import 'package:flutter/material.dart'; import 'package:audioplayers/audioplayers.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/prank_sound.dart'; class SoundManager { static final SoundManager _instance = SoundManager._internal(); factory SoundManager() => _instance; SoundManager._internal(); final AudioPlayer audioPlayer = AudioPlayer(); // 播放状态 Notifiers final ValueNotifier currentSoundNotifier = ValueNotifier(null); final ValueNotifier isPlayingNotifier = ValueNotifier(false); final ValueNotifier positionNotifier = ValueNotifier(Duration.zero); final ValueNotifier durationNotifier = ValueNotifier(Duration.zero); // 设置状态 Notifiers (支持 UI 监听) final ValueNotifier volumeNotifier = ValueNotifier(1.0); // 默认 100% final ValueNotifier loopNotifier = ValueNotifier(false); // 默认不循环 static const String KEY_VOLUME = 'app_volume'; static const String KEY_LOOP = 'app_loop'; Future init() async { // 监听播放器事件 audioPlayer.onPlayerStateChanged.listen((state) { isPlayingNotifier.value = state == PlayerState.playing; }); audioPlayer.onDurationChanged.listen((d) { durationNotifier.value = d; }); audioPlayer.onPositionChanged.listen((p) { positionNotifier.value = p; }); audioPlayer.onPlayerComplete.listen((_) { // 只有在非循环模式下,播放结束才停止 if (!loopNotifier.value) { isPlayingNotifier.value = false; positionNotifier.value = Duration.zero; } }); // 加载本地设置 final prefs = await SharedPreferences.getInstance(); final double savedVolume = prefs.getDouble(KEY_VOLUME) ?? 1.0; final bool savedLoop = prefs.getBool(KEY_LOOP) ?? false; // 更新内存状态 volumeNotifier.value = savedVolume; loopNotifier.value = savedLoop; // 应用到播放器 await audioPlayer.setVolume(savedVolume); await audioPlayer.setReleaseMode(savedLoop ? ReleaseMode.loop : ReleaseMode.stop); } // 设置音量并保存 Future setVolume(double volume) async { volumeNotifier.value = volume; await audioPlayer.setVolume(volume); final prefs = await SharedPreferences.getInstance(); await prefs.setDouble(KEY_VOLUME, volume); } // 设置循环并保存 Future setLooping(bool loop) async { loopNotifier.value = loop; await audioPlayer.setReleaseMode(loop ? ReleaseMode.loop : ReleaseMode.stop); final prefs = await SharedPreferences.getInstance(); await prefs.setBool(KEY_LOOP, loop); } Future play(PrankSound sound) async { try { if (currentSoundNotifier.value == sound) { if (isPlayingNotifier.value) { await audioPlayer.pause(); } else { await audioPlayer.resume(); } } else { await audioPlayer.stop(); currentSoundNotifier.value = sound; // 播放前确保应用了当前的设置 await audioPlayer.setVolume(volumeNotifier.value); await audioPlayer.setReleaseMode(loopNotifier.value ? ReleaseMode.loop : ReleaseMode.stop); if (sound.mp3Url.isNotEmpty) { await audioPlayer.play(UrlSource(sound.mp3Url)); } } } catch (e) { debugPrint("Play Error: $e"); } } Future stop() async { await audioPlayer.stop(); currentSoundNotifier.value = null; isPlayingNotifier.value = false; positionNotifier.value = Duration.zero; } }