|
|
|
@ -90,6 +90,17 @@ class AgentController extends GetxController { |
|
|
|
_loadTtsPreference(); //加载TTS偏好设置 |
|
|
|
_loadChatHistory(); //加载聊天历史记录 |
|
|
|
_subscribeToEvents(); //订阅代理服务事件 |
|
|
|
_initMusicStatus(); //初始化音乐状态 |
|
|
|
} |
|
|
|
|
|
|
|
// 初始化音乐播放状态 |
|
|
|
Future<void> _initMusicStatus() async { |
|
|
|
try { |
|
|
|
await musicStatus(); |
|
|
|
Logger.d('AgentController', '音乐状态初始化完成'); |
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '音乐状态初始化失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
@ -807,85 +818,156 @@ class AgentController extends GetxController { |
|
|
|
useImagePrompt('请翻译这张图片中的文字'); |
|
|
|
} |
|
|
|
|
|
|
|
// 播放音乐 |
|
|
|
void musicStatus() async { |
|
|
|
var status = await _musiceManager.getStatus(); |
|
|
|
// debugPrint('获取当前音乐播放状态 $status'); |
|
|
|
isPlaying.value = status['isPlaying']; |
|
|
|
currentUrl.value = status['url']; |
|
|
|
// 获取音乐播放状态 |
|
|
|
Future<void> musicStatus() async { |
|
|
|
try { |
|
|
|
var status = await _musiceManager.getStatus(); |
|
|
|
isPlaying.value = status['isPlaying'] ?? false; |
|
|
|
currentUrl.value = status['url'] ?? ''; |
|
|
|
Logger.d('AgentController', '音乐状态更新: playing=${isPlaying.value}, url=${currentUrl.value}'); |
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '获取音乐状态失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 播放音乐 |
|
|
|
void musicPlay(Map<String, dynamic> song) async { |
|
|
|
final id = song['id'] ?? ""; |
|
|
|
final timestampMs = song['ts'] ?? 0; |
|
|
|
// 当前时间 |
|
|
|
final now = DateTime.now(); |
|
|
|
// 将时间戳转换为 DateTime |
|
|
|
final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add( |
|
|
|
const Duration(minutes: 10), // 转换为北京时间 |
|
|
|
); |
|
|
|
// 判断是否过期 |
|
|
|
if (tsTime.isBefore(now)) { |
|
|
|
//获取新的连接 |
|
|
|
var response = await Api.getMusicUrl({ |
|
|
|
"ids": [id] |
|
|
|
}); |
|
|
|
// 2. 将响应数据转换为User对象 |
|
|
|
try { |
|
|
|
print('getMusicUrl 响应数据: ${response.toString()}'); // 调试输出原始数据 |
|
|
|
final urldata = response['urls'][0] as Map<String, dynamic>; |
|
|
|
song["url"] = urldata['url'] ?? ''; |
|
|
|
} catch (e) { |
|
|
|
Logger.e(TAG, '转换响应数据失败: $e'); |
|
|
|
return; |
|
|
|
Future<void> musicPlay(Map<String, dynamic> song) async { |
|
|
|
try { |
|
|
|
Logger.d('AgentController', '开始播放音乐: ${song['title'] ?? song['name']}'); |
|
|
|
|
|
|
|
// 立即更新UI状态,提供即时反馈 |
|
|
|
isPlaying.value = true; |
|
|
|
currentUrl.value = song['url'] ?? ''; |
|
|
|
|
|
|
|
// 重置进度状态 |
|
|
|
currentPosition.value = 0; |
|
|
|
duration.value = 0; |
|
|
|
progress.value = 0.0; |
|
|
|
|
|
|
|
final id = song['id'] ?? ""; |
|
|
|
final timestampMs = song['ts'] ?? 0; |
|
|
|
|
|
|
|
// 检查URL是否需要刷新(只有当有时间戳时才检查) |
|
|
|
if (timestampMs > 0) { |
|
|
|
final now = DateTime.now(); |
|
|
|
final tsTime = DateTime.fromMillisecondsSinceEpoch(timestampMs).add( |
|
|
|
const Duration(minutes: 10), // 转换为北京时间 |
|
|
|
); |
|
|
|
|
|
|
|
// 判断是否过期 |
|
|
|
if (tsTime.isBefore(now)) { |
|
|
|
Logger.d('AgentController', '音乐URL已过期,正在获取新URL...'); |
|
|
|
try { |
|
|
|
var response = await Api.getMusicUrl({"ids": [id]}); |
|
|
|
final urldata = response['urls'][0] as Map<String, dynamic>; |
|
|
|
song["url"] = urldata['url'] ?? ''; |
|
|
|
currentUrl.value = song['url'] ?? ''; |
|
|
|
Logger.d('AgentController', '获取新URL成功'); |
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '获取新URL失败: $e'); |
|
|
|
// 如果获取新URL失败,尝试使用原URL |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
_musiceManager.play(song); |
|
|
|
isPlaying.value = true; |
|
|
|
currentUrl.value = song['url'] ?? ''; |
|
|
|
_startProgressTimer(); |
|
|
|
// 转换为MusicManager期望的格式 |
|
|
|
final musicData = <String, String>{ |
|
|
|
'id': song['id']?.toString() ?? '', |
|
|
|
'url': song['url']?.toString() ?? '', |
|
|
|
'title': song['title']?.toString() ?? song['name']?.toString() ?? '', |
|
|
|
'artist': song['artist']?.toString() ?? song['sgener']?.toString() ?? '', |
|
|
|
'coverUrl': song['coverUrl']?.toString() ?? song['image']?.toString() ?? '', |
|
|
|
}; |
|
|
|
|
|
|
|
// 调用音乐管理器播放 |
|
|
|
await _musiceManager.play(musicData); |
|
|
|
|
|
|
|
// 启动进度定时器 |
|
|
|
_startProgressTimer(); |
|
|
|
|
|
|
|
Logger.d('AgentController', '音乐播放启动成功'); |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '播放音乐失败: $e'); |
|
|
|
// 发生错误时重置状态 |
|
|
|
isPlaying.value = false; |
|
|
|
currentUrl.value = ''; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 播放音乐 |
|
|
|
void musicPause() { |
|
|
|
_musiceManager.pause(); |
|
|
|
isPlaying.value = false; |
|
|
|
_stopProgressTimer(); |
|
|
|
// 暂停音乐 |
|
|
|
Future<void> musicPause() async { |
|
|
|
try { |
|
|
|
Logger.d('AgentController', '暂停音乐播放'); |
|
|
|
await _musiceManager.pause(); |
|
|
|
isPlaying.value = false; |
|
|
|
_stopProgressTimer(); |
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '暂停音乐失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void musicResume() { |
|
|
|
_musiceManager.resume(); |
|
|
|
isPlaying.value = true; |
|
|
|
_startProgressTimer(); |
|
|
|
// 恢复音乐播放 |
|
|
|
Future<void> musicResume() async { |
|
|
|
try { |
|
|
|
Logger.d('AgentController', '恢复音乐播放'); |
|
|
|
await _musiceManager.resume(); |
|
|
|
isPlaying.value = true; |
|
|
|
_startProgressTimer(); |
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '恢复音乐失败: $e'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 启动进度更新定时器 |
|
|
|
void _startProgressTimer() { |
|
|
|
_stopProgressTimer(); // 先停止现有定时器 |
|
|
|
_progressTimer = Timer.periodic(const Duration(seconds: 1), (timer) { |
|
|
|
if (isPlaying.value) { |
|
|
|
|
|
|
|
Logger.d('AgentController', '启动播放进度定时器'); |
|
|
|
_progressTimer = Timer.periodic(const Duration(milliseconds: 500), (timer) { |
|
|
|
if (isPlaying.value && currentUrl.value.isNotEmpty) { |
|
|
|
updateMusicProgress(); |
|
|
|
} else { |
|
|
|
} else if (!isPlaying.value) { |
|
|
|
// 如果不在播放状态,停止定时器 |
|
|
|
timer.cancel(); |
|
|
|
_progressTimer = null; |
|
|
|
Logger.d('AgentController', '播放已停止,取消进度定时器'); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
// 停止进度更新定时器 |
|
|
|
void _stopProgressTimer() { |
|
|
|
_progressTimer?.cancel(); |
|
|
|
_progressTimer = null; |
|
|
|
if (_progressTimer != null) { |
|
|
|
Logger.d('AgentController', '停止播放进度定时器'); |
|
|
|
_progressTimer?.cancel(); |
|
|
|
_progressTimer = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 获取播放进度 |
|
|
|
Future<void> updateMusicProgress() async { |
|
|
|
try { |
|
|
|
if (!isPlaying.value || currentUrl.value.isEmpty) { |
|
|
|
return; // 如果没有在播放,直接返回 |
|
|
|
} |
|
|
|
|
|
|
|
var progressInfo = await _musiceManager.getProgress(); |
|
|
|
currentPosition.value = progressInfo['currentPosition'] ?? 0; |
|
|
|
duration.value = progressInfo['duration'] ?? 0; |
|
|
|
progress.value = progressInfo['progress'] ?? 0.0; |
|
|
|
final newPosition = progressInfo['currentPosition'] ?? 0; |
|
|
|
final newDuration = progressInfo['duration'] ?? 0; |
|
|
|
final newProgress = progressInfo['progress'] ?? 0.0; |
|
|
|
|
|
|
|
// 只有当值发生变化时才更新,避免不必要的UI刷新 |
|
|
|
if (currentPosition.value != newPosition) { |
|
|
|
currentPosition.value = newPosition; |
|
|
|
} |
|
|
|
if (duration.value != newDuration) { |
|
|
|
duration.value = newDuration; |
|
|
|
} |
|
|
|
if ((progress.value - newProgress).abs() > 0.001) { // 避免浮点数精度问题 |
|
|
|
progress.value = newProgress; |
|
|
|
} |
|
|
|
|
|
|
|
} catch (e) { |
|
|
|
Logger.e('AgentController', '获取播放进度失败: $e'); |
|
|
|
} |
|
|
|
|