引入播放列表库,同时引入全新的播放控制器,以控制读库与播放模式的动作,但是功能仍在完善,需要确认部分边界问题

This commit is contained in:
2026-08-27 22:29:20 +08:00
parent ad6617592e
commit e58be9c17f
6 changed files with 677 additions and 126 deletions
+131
View File
@@ -0,0 +1,131 @@
// lib/controllers/playback_controller.dart
import '../services/audio_service.dart';
import '../services/webdav_service.dart';
import '../database/song_database.dart';
class PlaybackController {
static final PlaybackController _instance = PlaybackController._internal();
factory PlaybackController() => _instance;
PlaybackController._internal();
final AudioService _audioService = AudioService();
final SongDatabase _db = SongDatabase();
// ════════════════════════════════════════════════════════════
// 播放 WebDAV 目录中的歌曲(从点击歌曲开始)
// ════════════════════════════════════════════════════════════
Future<void> playFromWebDAV({
required String directoryPath,
required String clickedSongPath,
required List<WebDAVItem> allItems,
}) async {
final musicFiles = allItems.where((item) => !item.isDirectory).toList();
if (musicFiles.isEmpty) return;
final clickedIndex =
musicFiles.indexWhere((item) => item.path == clickedSongPath);
if (clickedIndex == -1) {
await _playSingleSong(clickedSongPath);
return;
}
final queue = await _buildSongQueue(musicFiles);
final playMode = _audioService.playMode;
// ⭐ 修复:显式指定类型
List<Song> finalQueue = List<Song>.from(queue);
int startIndex = clickedIndex;
if (playMode == PlayMode.shuffle) {
final shuffled = List<Song>.from(queue)..shuffle();
startIndex = shuffled.indexWhere((s) => s.id == clickedSongPath);
if (startIndex == -1) startIndex = 0;
finalQueue = shuffled;
}
_audioService.setQueue(finalQueue, startIndex: startIndex);
}
// ════════════════════════════════════════════════════════════
// 播放整个目录(从第一首开始)
// ════════════════════════════════════════════════════════════
Future<void> playAllFromWebDAV({
required String directoryPath,
required List<WebDAVItem> allItems,
}) async {
final musicFiles = allItems.where((item) => !item.isDirectory).toList();
if (musicFiles.isEmpty) return;
final queue = await _buildSongQueue(musicFiles);
final playMode = _audioService.playMode;
// ⭐ 修复:显式指定类型
List<Song> finalQueue = List<Song>.from(queue);
if (playMode == PlayMode.shuffle) {
finalQueue = List<Song>.from(queue)..shuffle();
}
_audioService.setQueue(finalQueue, startIndex: 0);
}
// ════════════════════════════════════════════════════════════
// 播放单曲(fallback
// ════════════════════════════════════════════════════════════
Future<void> _playSingleSong(String songPath) async {
final url = WebDAVService.instance.getFileUrl(songPath);
final dbSong = await _db.getSongByPath(songPath);
final song = Song(
id: songPath,
title: dbSong?['title'] as String? ??
songPath.split('/').last.replaceAll(RegExp(r'\.[^.]*$'), ''),
artist: dbSong?['artist'] as String? ?? '未知艺术家',
url: url,
);
_audioService.playSong(song);
}
// ════════════════════════════════════════════════════════════
// 辅助方法:从音乐文件列表构建 Song 队列
// ════════════════════════════════════════════════════════════
Future<List<Song>> _buildSongQueue(List<WebDAVItem> musicFiles) async {
final queue = <Song>[];
for (final item in musicFiles) {
final dbSong = await _db.getSongByPath(item.path);
final url = WebDAVService.instance.getFileUrl(item.path);
if (dbSong != null) {
queue.add(Song(
id: item.path,
title: dbSong['title'] as String? ??
item.name.replaceAll(RegExp(r'\.[^.]*$'), ''),
artist: dbSong['artist'] as String? ?? '未知艺术家',
url: url,
));
} else {
queue.add(Song(
id: item.path,
title: item.name.replaceAll(RegExp(r'\.[^.]*$'), ''),
artist: '未知艺术家',
url: url,
));
}
}
return queue;
}
// ════════════════════════════════════════════════════════════
// 播放控制(透传到 AudioService
// ════════════════════════════════════════════════════════════
void next() {
_audioService.next();
}
void previous() {
_audioService.previous();
}
void togglePlayMode() {
_audioService.togglePlayMode();
}
PlayMode get playMode => _audioService.playMode;
}