diff --git a/lib/provider/audio_player/audio_player.dart b/lib/provider/audio_player/audio_player.dart index e5db78c0..9dfc2c0a 100644 --- a/lib/provider/audio_player/audio_player.dart +++ b/lib/provider/audio_player/audio_player.dart @@ -86,6 +86,7 @@ class AudioPlayerNotifier extends Notifier { ) .toList(), initialIndex: playlist.index, + autoPlay: false, ); } } @@ -270,17 +271,18 @@ class AudioPlayerNotifier extends Notifier { int initialIndex = 0, bool autoPlay = false, }) async { - tracks = _blacklist.filter(tracks).toList() as List; + final medias = + (_blacklist.filter(tracks).toList() as List).asMediaList(); // Giving the initial track a boost so MediaKit won't skip // because of timeout - final intendedActiveTrack = tracks.elementAt(initialIndex); + final intendedActiveTrack = medias.elementAt(initialIndex); if (intendedActiveTrack is! LocalTrack) { await ref.read(sourcedTrackProvider(intendedActiveTrack).future); } await audioPlayer.openPlaylist( - tracks.asMediaList(), + medias, initialIndex: initialIndex, autoPlay: autoPlay, ); diff --git a/lib/provider/audio_player/audio_player_streams.dart b/lib/provider/audio_player/audio_player_streams.dart index d5473dd5..42944075 100644 --- a/lib/provider/audio_player/audio_player_streams.dart +++ b/lib/provider/audio_player/audio_player_streams.dart @@ -128,15 +128,17 @@ class AudioPlayerStreamListeners { audioPlayerState.tracks.length - 1) { return; } - final nextTrack = audioPlayerState.tracks - .elementAt(audioPlayerState.playlist.index + 1); + final nextTrack = SpotubeMedia.fromMedia(audioPlayerState.playlist.medias + .elementAt(audioPlayerState.playlist.index + 1)); - if (lastTrack == nextTrack.id || nextTrack is LocalTrack) return; + if (lastTrack == nextTrack.track.id || nextTrack.track is LocalTrack) { + return; + } try { await ref.read(sourcedTrackProvider(nextTrack).future); } finally { - lastTrack = nextTrack.id!; + lastTrack = nextTrack.track.id!; } }); } diff --git a/lib/provider/audio_player/querying_track_info.dart b/lib/provider/audio_player/querying_track_info.dart index f03efd9e..55590d48 100644 --- a/lib/provider/audio_player/querying_track_info.dart +++ b/lib/provider/audio_player/querying_track_info.dart @@ -4,17 +4,21 @@ import 'package:spotube/provider/server/sourced_track.dart'; import 'package:spotube/services/audio_player/audio_player.dart'; final queryingTrackInfoProvider = Provider((ref) { - final media = audioPlayer.playlist.index == -1 + final media = audioPlayer.playlist.index == -1 || + audioPlayer.playlist.medias.isEmpty ? null : audioPlayer.playlist.medias.elementAtOrNull(audioPlayer.playlist.index); final audioPlayerActiveTrack = - media == null ? null : SpotubeMedia.fromMedia(media).track; + media == null ? null : SpotubeMedia.fromMedia(media); - final activeTrack = - ref.watch(audioPlayerProvider.select((s) => s.activeTrack)) ?? - audioPlayerActiveTrack; + final activeMedia = ref.watch(audioPlayerProvider.select( + (s) => s.activeMedia == null + ? null + : SpotubeMedia.fromMedia(s.activeMedia!), + )) ?? + audioPlayerActiveTrack; - if (activeTrack == null) return false; + if (activeMedia == null) return false; - return ref.watch(sourcedTrackProvider(activeTrack)).isLoading; + return ref.watch(sourcedTrackProvider(activeMedia)).isLoading; }); diff --git a/lib/provider/audio_player/state.dart b/lib/provider/audio_player/state.dart index 3572e289..387c2e30 100644 --- a/lib/provider/audio_player/state.dart +++ b/lib/provider/audio_player/state.dart @@ -88,6 +88,11 @@ class AudioPlayerState { return tracks.elementAtOrNull(playlist.index); } + Media? get activeMedia { + if (playlist.index == -1 || playlist.medias.isEmpty) return null; + return playlist.medias.elementAt(playlist.index); + } + bool containsTrack(Track track) { return tracks.any((t) => t.id == track.id); } diff --git a/lib/provider/server/routes/playback.dart b/lib/provider/server/routes/playback.dart index f29aecf4..aa380d01 100644 --- a/lib/provider/server/routes/playback.dart +++ b/lib/provider/server/routes/playback.dart @@ -7,6 +7,7 @@ import 'package:spotube/provider/audio_player/state.dart'; import 'package:spotube/provider/server/active_sourced_track.dart'; import 'package:spotube/provider/server/sourced_track.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; +import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/logger/logger.dart'; class ServerPlaybackRoutes { @@ -25,7 +26,7 @@ class ServerPlaybackRoutes { final activeSourcedTrack = ref.read(activeSourcedTrackProvider); final sourcedTrack = activeSourcedTrack?.id == track.id ? activeSourcedTrack - : await ref.read(sourcedTrackProvider(track).future); + : await ref.read(sourcedTrackProvider(SpotubeMedia(track)).future); ref.read(activeSourcedTrackProvider.notifier).update(sourcedTrack); diff --git a/lib/provider/server/sourced_track.dart b/lib/provider/server/sourced_track.dart index 37c889b0..53a04023 100644 --- a/lib/provider/server/sourced_track.dart +++ b/lib/provider/server/sourced_track.dart @@ -1,12 +1,13 @@ import 'package:collection/collection.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:spotify/spotify.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/provider/audio_player/audio_player.dart'; +import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/sourced_track/sourced_track.dart'; final sourcedTrackProvider = - FutureProvider.family((ref, track) async { + FutureProvider.family((ref, media) async { + final track = media?.track; if (track == null || track is LocalTrack) { return null; } diff --git a/lib/services/audio_player/audio_player.dart b/lib/services/audio_player/audio_player.dart index 0b62c068..bb1a6203 100644 --- a/lib/services/audio_player/audio_player.dart +++ b/lib/services/audio_player/audio_player.dart @@ -54,6 +54,21 @@ class SpotubeMedia extends mk.Media { httpHeaders: media.httpHeaders, ); } + + @override + operator ==(Object other) { + if (other is! SpotubeMedia) return false; + + final isLocal = track is LocalTrack && other.track is LocalTrack; + return isLocal + ? (other.track as LocalTrack).path == (track as LocalTrack).path + : other.track.id == track.id; + } + + @override + int get hashCode => track is LocalTrack + ? (track as LocalTrack).path.hashCode + : track.id.hashCode; } abstract class AudioPlayerInterface {