diff --git a/lib/provider/proxy_playlist/proxy_playlist_provider.dart b/lib/provider/proxy_playlist/proxy_playlist_provider.dart index 151b04c2..0afc7046 100644 --- a/lib/provider/proxy_playlist/proxy_playlist_provider.dart +++ b/lib/provider/proxy_playlist/proxy_playlist_provider.dart @@ -1,7 +1,6 @@ import 'dart:async'; import 'dart:convert'; -import 'package:async/async.dart'; import 'package:catcher/catcher.dart'; import 'package:collection/collection.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -72,37 +71,45 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier ({String source, List segments})? currentSegments; audioPlayer.activeSourceChangedStream.listen((newActiveSource) async { - final newActiveTrack = - mapSourcesToTracks([newActiveSource]).firstOrNull; + try { + final newActiveTrack = + mapSourcesToTracks([newActiveSource]).firstOrNull; - if (newActiveTrack == null || - newActiveTrack.id == state.activeTrack?.id) { - return; + if (newActiveTrack == null || + newActiveTrack.id == state.activeTrack?.id) { + return; + } + + notificationService.addTrack(newActiveTrack); + state = state.copyWith( + active: state.tracks + .toList() + .indexWhere((element) => element.id == newActiveTrack.id), + ); + + updatePalette(); + } catch (e, stackTrace) { + Catcher.reportCheckedError(e, stackTrace); } - - notificationService.addTrack(newActiveTrack); - state = state.copyWith( - active: state.tracks - .toList() - .indexWhere((element) => element.id == newActiveTrack.id), - ); - - updatePalette(); }); audioPlayer.shuffledStream.listen((event) { - final newlyOrderedTracks = mapSourcesToTracks(audioPlayer.sources); + try { + final newlyOrderedTracks = mapSourcesToTracks(audioPlayer.sources); - final newActiveIndex = newlyOrderedTracks.indexWhere( - (element) => element.id == state.activeTrack?.id, - ); + final newActiveIndex = newlyOrderedTracks.indexWhere( + (element) => element.id == state.activeTrack?.id, + ); - if (newActiveIndex == -1) return; + if (newActiveIndex == -1) return; - state = state.copyWith( - tracks: newlyOrderedTracks.toSet(), - active: newActiveIndex, - ); + state = state.copyWith( + tracks: newlyOrderedTracks.toSet(), + active: newActiveIndex, + ); + } catch (e, stackTrace) { + Catcher.reportCheckedError(e, stackTrace); + } }); bool isPreSearching = false; @@ -130,6 +137,8 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier track, ); } + } catch (e, stackTrace) { + Catcher.reportCheckedError(e, stackTrace); } finally { isPreSearching = false; } @@ -140,37 +149,45 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier bool isFetchingSegments = false; audioPlayer.positionStream.listen((position) async { - // skipping in very first second breaks stream - if ((preferences.youtubeApiType == YoutubeApiType.piped && - preferences.searchMode == SearchMode.youtubeMusic) || - !preferences.skipNonMusic) return; - - final notSameSegmentId = - currentSegments?.source != audioPlayer.currentSource; - - if (currentSegments == null || - (notSameSegmentId && !isFetchingSegments)) { - isFetchingSegments = true; - try { - currentSegments = ( - source: audioPlayer.currentSource!, - segments: await getAndCacheSkipSegments( - (state.activeTrack as SpotubeTrack).ytTrack.id, - ), - ); - } finally { + try { + if (state.activeTrack == null || state.activeTrack is LocalTrack) { isFetchingSegments = false; + return; } - } + // skipping in very first second breaks stream + if ((preferences.youtubeApiType == YoutubeApiType.piped && + preferences.searchMode == SearchMode.youtubeMusic) || + !preferences.skipNonMusic) return; - final (source: _, :segments) = currentSegments!; - if (segments.isEmpty || position < const Duration(seconds: 3)) return; + final notSameSegmentId = + currentSegments?.source != audioPlayer.currentSource; - for (final segment in segments) { - if ((position.inSeconds >= segment.start && - position.inSeconds < segment.end)) { - await audioPlayer.seek(Duration(seconds: segment.end)); + if (currentSegments == null || + (notSameSegmentId && !isFetchingSegments)) { + isFetchingSegments = true; + try { + currentSegments = ( + source: audioPlayer.currentSource!, + segments: await getAndCacheSkipSegments( + (state.activeTrack as SpotubeTrack).ytTrack.id, + ), + ); + } finally { + isFetchingSegments = false; + } } + + final (source: _, :segments) = currentSegments!; + if (segments.isEmpty || position < const Duration(seconds: 3)) return; + + for (final segment in segments) { + if ((position.inSeconds >= segment.start && + position.inSeconds < segment.end)) { + await audioPlayer.seek(Duration(seconds: segment.end)); + } + } + } catch (e, stackTrace) { + Catcher.reportCheckedError(e, stackTrace); } }); }(); diff --git a/lib/services/audio_player/audio_player.dart b/lib/services/audio_player/audio_player.dart index fd0e5a5a..3a54f9ba 100644 --- a/lib/services/audio_player/audio_player.dart +++ b/lib/services/audio_player/audio_player.dart @@ -20,7 +20,7 @@ abstract class AudioPlayerInterface { // _mkPlayer = _mkSupportedPlatform ? MkPlayerWithState() : null, // _justAudio = !_mkSupportedPlatform ? ja.AudioPlayer() : null { - _mkPlayer.streams.error.listen((event) { + _mkPlayer.stream.error.listen((event) { Catcher.reportCheckedError(event, StackTrace.current); }); } diff --git a/lib/services/audio_player/audio_players_streams_mixin.dart b/lib/services/audio_player/audio_players_streams_mixin.dart index b3d43602..a736dc1c 100644 --- a/lib/services/audio_player/audio_players_streams_mixin.dart +++ b/lib/services/audio_player/audio_players_streams_mixin.dart @@ -4,7 +4,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface { // stream getters Stream get durationStream { // if (mkSupportedPlatform) { - return _mkPlayer.streams.duration; + return _mkPlayer.stream.duration; // } else { // return _justAudio!.durationStream // .where((event) => event != null) @@ -15,7 +15,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface { Stream get positionStream { // if (mkSupportedPlatform) { - return _mkPlayer.streams.position; + return _mkPlayer.stream.position; // } else { // return _justAudio!.positionStream; // } @@ -24,7 +24,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface { Stream get bufferedPositionStream { // if (mkSupportedPlatform) { // audioplayers doesn't have the capability to get buffered position - return _mkPlayer.streams.buffer; + return _mkPlayer.stream.buffer; // } else { // return _justAudio!.bufferedPositionStream; // } @@ -32,7 +32,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface { Stream get completedStream { // if (mkSupportedPlatform) { - return _mkPlayer.streams.completed; + return _mkPlayer.stream.completed; // } else { // return _justAudio!.playerStateStream // .where( @@ -57,7 +57,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface { Stream get playingStream { // if (mkSupportedPlatform) { - return _mkPlayer.streams.playing; + return _mkPlayer.stream.playing; // } else { // return _justAudio!.playingStream; // } @@ -83,7 +83,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface { Stream get volumeStream { // if (mkSupportedPlatform) { - return _mkPlayer.streams.volume.map((event) => event / 100); + return _mkPlayer.stream.volume.map((event) => event / 100); // } else { // return _justAudio!.volumeStream; // } diff --git a/lib/services/audio_player/mk_state_player.dart b/lib/services/audio_player/mk_state_player.dart index 5f1afe8b..84765727 100644 --- a/lib/services/audio_player/mk_state_player.dart +++ b/lib/services/audio_player/mk_state_player.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:catcher/catcher.dart'; import 'package:collection/collection.dart'; import 'package:media_kit/media_kit.dart'; // ignore: implementation_imports @@ -30,36 +31,40 @@ class MkPlayerWithState extends Player { _shuffled = false, _loopMode = PlaylistMode.none { _subscriptions = [ - streams.buffering.listen((event) { + stream.buffering.listen((event) { _playerStateStream.add(AudioPlaybackState.buffering); }), - streams.playing.listen((playing) { + stream.playing.listen((playing) { if (playing) { _playerStateStream.add(AudioPlaybackState.playing); } else { _playerStateStream.add(AudioPlaybackState.paused); } }), - streams.position.listen((position) async { - final isComplete = state.duration != Duration.zero && - position != Duration.zero && - state.duration.inSeconds == position.inSeconds; + stream.completed.listen((isCompleted) async { + try { + if (!isCompleted) return; - if (!isComplete || _playlist == null) return; - _playerStateStream.add(AudioPlaybackState.completed); + _playerStateStream.add(AudioPlaybackState.completed); - if (loopMode == PlaylistMode.single) { - await super.open(_playlist!.medias[_playlist!.index], play: true); - } else { - await next(); - await Future.delayed(const Duration(milliseconds: 250), play); + if (loopMode == PlaylistMode.single) { + await super.open(_playlist!.medias[_playlist!.index], play: true); + } else { + await next(); + await Future.delayed(const Duration(milliseconds: 250), play); + } + } catch (e, stackTrace) { + Catcher.reportCheckedError(e, stackTrace); } }), - streams.playlist.listen((event) { + stream.playlist.listen((event) { if (event.medias.isEmpty) { _playerStateStream.add(AudioPlaybackState.stopped); } }), + stream.error.listen((event) { + Catcher.reportCheckedError('[MediaKitError] \n$event', null); + }), ]; }