diff --git a/lib/provider/proxy_playlist/next_fetcher_mixin.dart b/lib/provider/proxy_playlist/next_fetcher_mixin.dart index c3f440152..fce006b08 100644 --- a/lib/provider/proxy_playlist/next_fetcher_mixin.dart +++ b/lib/provider/proxy_playlist/next_fetcher_mixin.dart @@ -98,10 +98,10 @@ mixin NextFetcher on StateNotifier { return sources .map((source) { final track = state.tracks.firstWhereOrNull( - (track) { - final newSource = makeAppropriateSource(track); - return newSource == source; - }, + (track) => + trackToUnplayableSource(track) == source || + (track is SpotubeTrack && track.ytUri == source) || + (track is LocalTrack && track.path == source), ); return track; }) diff --git a/lib/provider/proxy_playlist/proxy_playlist_provider.dart b/lib/provider/proxy_playlist/proxy_playlist_provider.dart index 941951af1..7ab9293ab 100644 --- a/lib/provider/proxy_playlist/proxy_playlist_provider.dart +++ b/lib/provider/proxy_playlist/proxy_playlist_provider.dart @@ -1,5 +1,6 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:math'; import 'package:catcher/catcher.dart'; import 'package:collection/collection.dart'; @@ -129,6 +130,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier final oldTrack = mapSourcesToTracks([audioPlayer.nextSource!]).firstOrNull; + final track = await ensureSourcePlayable(audioPlayer.nextSource!); if (track != null) { @@ -439,13 +441,16 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier Future next() async { if (audioPlayer.nextSource == null) return; final oldTrack = mapSourcesToTracks([audioPlayer.nextSource!]).firstOrNull; + state = state.copyWith( active: state.tracks .toList() .indexWhere((element) => element.id == oldTrack?.id), ); + await audioPlayer.pause(); final track = await ensureSourcePlayable(audioPlayer.nextSource!); + if (track != null) { state = state.copyWith( tracks: mergeTracks([track], state.tracks), @@ -613,7 +618,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier final oldCollections = state.collections; await load( state.tracks, - initialIndex: state.active ?? 0, + initialIndex: max(state.active ?? 0, 0), autoPlay: false, ); state = state.copyWith(collections: oldCollections); diff --git a/lib/services/audio_player/audio_player.dart b/lib/services/audio_player/audio_player.dart index 3a54f9ba5..f468e87a6 100644 --- a/lib/services/audio_player/audio_player.dart +++ b/lib/services/audio_player/audio_player.dart @@ -111,7 +111,7 @@ abstract class AudioPlayerInterface { // } } - Future get loopMode async { + PlaybackLoopMode get loopMode { return PlaybackLoopMode.fromPlaylistMode(_mkPlayer.loopMode); // if (mkSupportedPlatform) { // return PlaybackLoopMode.fromPlaylistMode(_mkPlayer.loopMode); diff --git a/lib/services/audio_player/audio_player_impl.dart b/lib/services/audio_player/audio_player_impl.dart index cca8c36c5..417cf4b30 100644 --- a/lib/services/audio_player/audio_player_impl.dart +++ b/lib/services/audio_player/audio_player_impl.dart @@ -156,6 +156,12 @@ class SpotubeAudioPlayer extends AudioPlayerInterface String? get nextSource { // if (mkSupportedPlatform) { + + if (loopMode == PlaybackLoopMode.all && + _mkPlayer.playlist.index == _mkPlayer.playlist.medias.length - 1) { + return sources.first; + } + return _mkPlayer.playlist.medias .elementAtOrNull(_mkPlayer.playlist.index + 1) ?.uri; @@ -169,6 +175,10 @@ class SpotubeAudioPlayer extends AudioPlayerInterface } String? get previousSource { + if (loopMode == PlaybackLoopMode.all && _mkPlayer.playlist.index == 0) { + return sources.last; + } + // if (mkSupportedPlatform) { return _mkPlayer.playlist.medias .elementAtOrNull(_mkPlayer.playlist.index - 1) diff --git a/lib/services/audio_player/mk_state_player.dart b/lib/services/audio_player/mk_state_player.dart index c64f0095e..945b2ce07 100644 --- a/lib/services/audio_player/mk_state_player.dart +++ b/lib/services/audio_player/mk_state_player.dart @@ -170,6 +170,7 @@ class MkPlayerWithState extends Player { return super.open(_playlist!.medias[_playlist!.index], play: true); } else if (!isLast) { playlist = _playlist!.copyWith(index: _playlist!.index + 1); + return super.open(_playlist!.medias[_playlist!.index], play: true); } } @@ -233,30 +234,30 @@ class MkPlayerWithState extends Player { final isOldUrlPlaying = _playlist!.medias[_playlist!.index].uri == oldUrl; - for (var i = 0; i < _playlist!.medias.length - 1; i++) { - final media = _playlist!.medias[i]; - if (media.uri == oldUrl) { - if (isOldUrlPlaying) { - pause(); - } - final newMedias = _playlist!.medias.toList(); - newMedias[i] = Media(newUrl, extras: media.extras); - playlist = _playlist!.copyWith(medias: newMedias); - if (isOldUrlPlaying) { - super.open( - newMedias[i], - play: true, - ); - } + // ends the loop where match is found + // tends to be a bit more efficient than forEach + _playlist!.medias.firstWhereIndexedOrNull((i, media) { + if (media.uri != oldUrl) return false; + if (isOldUrlPlaying) { + pause(); + } + final copyMedias = [..._playlist!.medias]; + copyMedias[i] = Media(newUrl, extras: media.extras); + playlist = _playlist!.copyWith(medias: copyMedias); + if (isOldUrlPlaying) { + super.open( + copyMedias[i], + play: true, + ); + } - // replace in the _tempMedias if it's not null - if (shuffled && _tempMedias != null) { - final tempIndex = _tempMedias!.indexOf(media); - _tempMedias![tempIndex] = Media(newUrl, extras: media.extras); - } - break; + // replace in the _tempMedias if it's not null + if (shuffled && _tempMedias != null) { + final tempIndex = _tempMedias!.indexOf(media); + _tempMedias![tempIndex] = Media(newUrl, extras: media.extras); } - } + return true; + }); } @override