import 'dart:async'; import 'dart:convert'; import 'dart:math'; import 'package:agora_rtc_engine/agora_rtc_engine.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:aslan/chatvibe_managers/rtc_manager.dart'; import 'package:on_audio_query/on_audio_query.dart'; import 'package:provider/provider.dart'; import 'package:aslan/chatvibe_ui/components/at_tts.dart'; import 'package:aslan/chatvibe_data/sources/local/data_persistence.dart'; import 'package:aslan/chatvibe_data/models/at_music_mode.dart'; import '../chatvibe_features/room/music/control/at_room_music_control_page.dart'; typedef MixingCurrentPositionChange = Function(int currentValue, int maxValue); class AudioManager with ChangeNotifier { ATMusicMode? currentMusicMode; int playingIndex = -1; List localSongs = []; List addedSongs = []; Map addedMusicMap = {}; AudioMixingStateType state = AudioMixingStateType.audioMixingStateStopped; int playModel = 0; OnAudioQuery? _audioQuery; Timer? _timer; MixingCurrentPositionChange? changeCall; void startMixingCurrentPositionTimer(BuildContext context) { _timer?.cancel(); _timer = Timer.periodic(Duration(milliseconds: 550), (timer) async { int currentPos = await Provider.of( context, listen: false, ).engine!.getAudioMixingCurrentPosition(); // 获取音乐总时长 int duration = await Provider.of( context, listen: false, ).engine!.getAudioMixingDuration(); changeCall?.call(currentPos, duration); if (currentPos == duration) { if (currentPos > 0) { playFinished(context); } } }); } void stopTimer() { _timer?.cancel(); } Future getAtSongs() async { try { localSongs.clear(); _audioQuery ??= OnAudioQuery(); // 检查并请求存储权限 bool hasPermission = await _audioQuery!.checkAndRequest(); // 确保权限已授予后再进行查询 if (hasPermission) { // 查询设备上的所有歌曲 var ss = await _audioQuery!.querySongs(); for (var s in ss) { if ((s.duration ?? 0) > 10000) { localSongs.add(s); } } loadAtRoomMusics(); } else { // 用户拒绝了权限,需要进行处理(例如显示提示) ATTts.show("Failed to obtain permission"); return []; } } catch (e) {} } void addRoomMusic(ATMusicMode music) { try { List musics = []; String musicJson = DataPersistence.getUserRoomMusic(); if (musicJson.isNotEmpty) { musics = (jsonDecode(musicJson) as List) .map((e) => ATMusicMode.fromJson(e)) .toList(); } bool isHas = false; if (musics.isNotEmpty) { for (var m in musics) { if (m.title == music.title) { isHas = true; break; } } } if (!isHas) { musics.add(music); } String newMusicJson = jsonEncode(musics.map((v) => v.toJson()).toList()); DataPersistence.setUserRoomMusic(newMusicJson); addedMusicMap[music.title ?? ""] = music; notifyListeners(); } catch (e) {} } void deleteRoomMusic(BuildContext context, ATMusicMode music) { try { addedMusicMap.remove(music.title); List musics = []; String musicJson = DataPersistence.getUserRoomMusic(); if (musicJson.isNotEmpty) { musics = (jsonDecode(musicJson) as List) .map((e) => ATMusicMode.fromJson(e)) .toList(); } if (musics.isNotEmpty) { musics.removeWhere((m) => m.title == music.title); } String newMusicJson = jsonEncode(musics.map((v) => v.toJson()).toList()); DataPersistence.setUserRoomMusic(newMusicJson); if (music.title == currentMusicMode?.title) { currentMusicMode = null; Provider.of(context, listen: false).stopMusic(); SmartDialog.dismiss(tag: "showRoomMusicControl"); reset(); } } catch (e) {} notifyListeners(); } void loadAtRoomMusics() { try { addedSongs.clear(); String musicJson = DataPersistence.getUserRoomMusic(); if (musicJson.isNotEmpty) { addedSongs = (jsonDecode(musicJson) as List) .map((e) => ATMusicMode.fromJson(e)) .toList(); } } catch (e) {} if (addedSongs.isNotEmpty) { addedMusicMap = {for (var music in addedSongs) music.title ?? "": music}; } notifyListeners(); } void playMusic(BuildContext context, ATMusicMode music, int playingIndex) { if (this.playingIndex == playingIndex) { SmartDialog.show( tag: "showRoomMusicControl", alignment: Alignment.center, debounce: true, animationType: SmartAnimationType.fade, clickMaskDismiss: true, builder: (_) { return ATRoomMusicControlPage(); }, ); return; } currentMusicMode = music; this.playingIndex = playingIndex; Provider.of( context, listen: false, ).playMusic(music.localPath ?? "", playModel == 0 ? -1 : 1); notifyListeners(); SmartDialog.dismiss(tag: "showRoomMusic"); SmartDialog.show( tag: "showRoomMusicControl", alignment: Alignment.center, debounce: true, animationType: SmartAnimationType.fade, clickMaskDismiss: true, builder: (_) { return ATRoomMusicControlPage(); }, ); } void setPlayState(AudioMixingStateType state, BuildContext context) { if (state == AudioMixingStateType.audioMixingStatePlaying) { startMixingCurrentPositionTimer(context); } this.state = state; notifyListeners(); } void reset() { playingIndex = -1; playModel = 0; currentMusicMode = null; state = AudioMixingStateType.audioMixingStateStopped; stopTimer(); notifyListeners(); } ///暂停或者播放 void playOrPause(BuildContext context) { if (state == AudioMixingStateType.audioMixingStatePlaying) { Provider.of(context, listen: false).pauseMusic(); } else if (state == AudioMixingStateType.audioMixingStatePaused) { Provider.of(context, listen: false).resumeMusic(); } else { if (currentMusicMode != null) { Provider.of( context, listen: false, ).playMusic(currentMusicMode!.localPath ?? "", playModel == 0 ? -1 : 1); } } } void switchModel() { if (playModel == 0) { playModel = 1; } else if (playModel == 1) { playModel = 2; } else { playModel = 0; } notifyListeners(); } ///上一首 void previous(BuildContext context) { if (playingIndex == 0) { return; } else { playingIndex = playingIndex - 1; currentMusicMode = addedSongs[playingIndex]; Provider.of( context, listen: false, ).playMusic(currentMusicMode?.localPath ?? "", playModel == 0 ? -1 : 1); notifyListeners(); } } ///下一首 void playNext(BuildContext context) { if (playingIndex == addedSongs.length - 1) { return; } else { playingIndex = playingIndex + 1; currentMusicMode = addedSongs[playingIndex]; Provider.of( context, listen: false, ).playMusic(currentMusicMode?.localPath ?? "", playModel == 0 ? -1 : 1); notifyListeners(); } } ///随机播放一首 void playRandom(BuildContext context) { playingIndex = Random().nextInt(addedSongs.length + 1); currentMusicMode = addedSongs[playingIndex]; Provider.of( context, listen: false, ).playMusic(currentMusicMode?.localPath ?? "", playModel == 0 ? -1 : 1); notifyListeners(); } int sTime = 0; ///音乐播放完成 void playFinished(BuildContext context) { int nTime = DateTime.now().millisecondsSinceEpoch; if (nTime - sTime > 2000) { sTime = nTime; if (playModel == 1) { playRandom(context); } else { if (playingIndex == addedSongs.length - 1) { playingIndex = -1; } playNext(context); } } } ///置顶 void toUp(ATMusicMode s, int i) { if (addedSongs.contains(s)) { addedSongs.remove(s); addedSongs.insert(0, s); } int index = 0; for (var ms in addedSongs) { if (currentMusicMode?.title == ms.title) { playingIndex = index; break; } index = index + 1; } String newMusicJson = jsonEncode( addedSongs.map((v) => v.toJson()).toList(), ); DataPersistence.setUserRoomMusic(newMusicJson); notifyListeners(); } void selectAll() { try { Future(() { List musics = []; String musicJson = DataPersistence.getUserRoomMusic(); if (musicJson.isNotEmpty) { musics = (jsonDecode(musicJson) as List) .map((e) => ATMusicMode.fromJson(e)) .toList(); } List result = localSongs .where((p1) => musics.any((p2) => p2.title == p1.title)) .toList(); for (var song in localSongs) { if (!result.contains(song)) { var mode = ATMusicMode( title: song.title, artist: song.artist, duration: song.duration, localPath: song.uri, ); musics.add(mode); addedMusicMap[song.title] = mode; } } String newMusicJson = jsonEncode( musics.map((v) => v.toJson()).toList(), ); DataPersistence.setUserRoomMusic(newMusicJson); notifyListeners(); }); } catch (e) {} } }