ToneSnap_FSX_Flutter/lib/modules/sideb/controllers/music_player_controller.dart
fengshengxiong 7611e78244 1.变声加入广告和Firebase
2.音乐播放器首页完成数据加载展示
2024-06-26 15:32:21 +08:00

224 lines
6.2 KiB
Dart

// 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<Duration>? _bufferedSubscription;
StreamSubscription<Duration?>? _durationSubscription;
StreamSubscription<Duration>? _positionSubscription;
StreamSubscription<PlayerState>? _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<void> playNewUrl(String newUrl, String videoId) async {
await _initializePlayer(newUrl, videoId);
_player.play();
// 使用的 music_$videoId 作为唯一的 key
cacheKey = 'music_$videoId';
}
/// 设置 url 和监听器
Future<void> _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<void> 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<void> 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<bool> _fileExists(String path) async {
if (await File(path).exists()) {
return true;
} else {
BaseEasyLoading.toast('Local resource does not exist');
return false;
}
}
}