// Author: fengshengxiong // Date: 2024/5/30 // Description: 音乐播放器控制器 import 'dart:async'; import 'dart:io'; import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:get/get.dart'; import 'package:just_audio/just_audio.dart'; import 'package:tone_snap/components/base_easyloading.dart'; import 'package:tone_snap/data/cache/music_cache_manager.dart'; import 'package:tone_snap/utils/audio_util.dart'; import 'package:tone_snap/utils/date_util.dart'; import 'package:tone_snap/utils/log_util.dart'; class MusicPlayerController extends GetxController { static MusicPlayerController get to => Get.put(MusicPlayerController(), permanent: true); final _player = AudioPlayer(); StreamSubscription? _bufferedSubscription; StreamSubscription? _durationSubscription; StreamSubscription? _positionSubscription; StreamSubscription? _playerStateSubscription; /// 缓存管理器 // final cacheManager = DefaultCacheManager(); final cacheManager = MusicCacheManager.instance; var cacheKey = ''; /// 是否正在从缓存播放中 var _isPlayingFromCache = false; /// 当前播放的url var currentUrl = ''; /// 是否正在播放 var isPlaying = false.obs; /// 总时长、已播放的时长、缓冲时长 var totalDuration = Duration.zero.obs; var positionDuration = Duration.zero.obs; var bufferedDuration = Duration.zero.obs; /// 记录进度条拖动前缓冲的位置 Duration? bufferedPosition; /// 拖动前是否是播放状态 var seekFrontPlaying = true; @override void onInit() { super.onInit(); AudioUtil.configAudioSession(); } @override void onClose() { _cancelListening(); _player.dispose(); super.onClose(); } /// 播放新的 url Future playNewUrl(String newUrl, String videoId) async { await _initializePlayer(newUrl, videoId); _player.play(); // 使用的 music_$videoId 作为唯一的 key cacheKey = 'music_$videoId'; } /// 设置 url 和监听器 Future _initializePlayer(String url, String videoId) async { try { currentUrl = url; // 检查是否有缓存 FileInfo? fileInfo = await cacheManager.getFileFromMemory(cacheKey); if (fileInfo != null) { LogUtil.d('有缓存,文件路径=${fileInfo.file.path}'); // 如果有缓存,使用缓存文件 await _player.setFilePath(fileInfo.file.path); _isPlayingFromCache = true; } else { // 如果没有缓存,通过 url 加载音源并开始播放,同时启动缓存下载 await _player.setUrl(currentUrl); _isPlayingFromCache = false; // 下载并缓存文件 cacheManager.downloadFile(currentUrl, key: cacheKey).then((fileInfo) { // 如果缓存下载完成且当前不是从缓存播放,切换到缓存文件 if (!_isPlayingFromCache) { LogUtil.d('新歌曲缓存路径=${fileInfo.file.path}'); _player.setFilePath(fileInfo.file.path); _isPlayingFromCache = true; } }); } _player.setLoopMode(LoopMode.off); _cancelListening(); _addListening(); } catch (e) { LogUtil.e('Error initializing player: $e'); BaseEasyLoading.toast('Error initializing player'); } } /// 播放/暂停 Future playPause() async { if (_player.playing) { _player.pause(); } else { if (_player.processingState == ProcessingState.idle) { BaseEasyLoading.loading(); await _player.load(); BaseEasyLoading.dismiss(); } _player.play(); } } /// 停止播放 void stopPlay() { _player.stop(); _player.seek(Duration.zero); positionDuration.value = Duration.zero; } /// 将播放器的播放位置设置为指定的时间 void seekToPosition(double value) { if (_player.processingState == ProcessingState.ready) { positionDuration.value = Duration(seconds: value.toInt()); _player.seek(positionDuration.value); } } /// 开始/结束拖动进度条 Future seekStartEnd(int value) async { bufferedPosition = _player.bufferedPosition; if (_player.processingState == ProcessingState.ready) { if (value == 0) { seekFrontPlaying = _player.playing; if (_player.playing) { _player.pause(); } } else { // 拖动前如果是播放状态,拖动完成后恢复播放,否则相反 if (seekFrontPlaying) { _player.play(); } } } } /// 上一首 void seekToPrevious() { _player.seekToPrevious(); } /// 下一首 void seekToNext() { _player.seekToNext(); } /// 监听 void _addListening() { _bufferedSubscription = _player.bufferedPositionStream.listen((bufferedPosition) { bufferedDuration.value = bufferedPosition; }); _durationSubscription = _player.durationStream.listen((duration) { totalDuration.value = duration ?? Duration.zero; }); _positionSubscription = _player.positionStream.listen((position) { positionDuration.value = position; }); _playerStateSubscription = _player.playerStateStream.listen((playerState) { isPlaying.value = _player.playing; switch (playerState.processingState) { case ProcessingState.idle: break; case ProcessingState.loading: break; case ProcessingState.buffering: break; case ProcessingState.ready: break; case ProcessingState.completed: stopPlay(); break; } }); } /// 取消监听 void _cancelListening() { _bufferedSubscription?.cancel(); _durationSubscription?.cancel(); _positionSubscription?.cancel(); _playerStateSubscription?.cancel(); } /// 返回格式化后的总时长 String getTotalDuration() { return DateUtil.playDuration(totalDuration.value); } /// 返回格式化后的已持续时间 String getPositionDuration() { return DateUtil.playDuration(positionDuration.value); } /// 文件是否存在 Future _fileExists(String path) async { if (await File(path).exists()) { return true; } else { BaseEasyLoading.toast('Local resource does not exist'); return false; } } }