2026-07-01 18:25:58 +08:00

353 lines
10 KiB
Dart

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<SongModel> localSongs = [];
List<ATMusicMode> addedSongs = [];
Map<String, ATMusicMode> 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<RealTimeCommunicationManager>(
context,
listen: false,
).engine!.getAudioMixingCurrentPosition();
// 获取音乐总时长
int duration =
await Provider.of<RealTimeCommunicationManager>(
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<ATMusicMode> 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<ATMusicMode> 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<RealTimeCommunicationManager>(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<RealTimeCommunicationManager>(
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<RealTimeCommunicationManager>(context, listen: false).pauseMusic();
} else if (state == AudioMixingStateType.audioMixingStatePaused) {
Provider.of<RealTimeCommunicationManager>(context, listen: false).resumeMusic();
} else {
if (currentMusicMode != null) {
Provider.of<RealTimeCommunicationManager>(
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<RealTimeCommunicationManager>(
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<RealTimeCommunicationManager>(
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<RealTimeCommunicationManager>(
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<ATMusicMode> musics = [];
String musicJson = DataPersistence.getUserRoomMusic();
if (musicJson.isNotEmpty) {
musics =
(jsonDecode(musicJson) as List)
.map((e) => ATMusicMode.fromJson(e))
.toList();
}
List<SongModel> 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) {}
}
}