mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
fix: tracks doesn't change when ended
This commit is contained in:
parent
e3f4344ae9
commit
aa4ac8641a
@ -1,7 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:async/async.dart';
|
|
||||||
import 'package:catcher/catcher.dart';
|
import 'package:catcher/catcher.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@ -72,37 +71,45 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
|
|||||||
({String source, List<SkipSegment> segments})? currentSegments;
|
({String source, List<SkipSegment> segments})? currentSegments;
|
||||||
|
|
||||||
audioPlayer.activeSourceChangedStream.listen((newActiveSource) async {
|
audioPlayer.activeSourceChangedStream.listen((newActiveSource) async {
|
||||||
final newActiveTrack =
|
try {
|
||||||
mapSourcesToTracks([newActiveSource]).firstOrNull;
|
final newActiveTrack =
|
||||||
|
mapSourcesToTracks([newActiveSource]).firstOrNull;
|
||||||
|
|
||||||
if (newActiveTrack == null ||
|
if (newActiveTrack == null ||
|
||||||
newActiveTrack.id == state.activeTrack?.id) {
|
newActiveTrack.id == state.activeTrack?.id) {
|
||||||
return;
|
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) {
|
audioPlayer.shuffledStream.listen((event) {
|
||||||
final newlyOrderedTracks = mapSourcesToTracks(audioPlayer.sources);
|
try {
|
||||||
|
final newlyOrderedTracks = mapSourcesToTracks(audioPlayer.sources);
|
||||||
|
|
||||||
final newActiveIndex = newlyOrderedTracks.indexWhere(
|
final newActiveIndex = newlyOrderedTracks.indexWhere(
|
||||||
(element) => element.id == state.activeTrack?.id,
|
(element) => element.id == state.activeTrack?.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newActiveIndex == -1) return;
|
if (newActiveIndex == -1) return;
|
||||||
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
tracks: newlyOrderedTracks.toSet(),
|
tracks: newlyOrderedTracks.toSet(),
|
||||||
active: newActiveIndex,
|
active: newActiveIndex,
|
||||||
);
|
);
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
Catcher.reportCheckedError(e, stackTrace);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bool isPreSearching = false;
|
bool isPreSearching = false;
|
||||||
@ -130,6 +137,8 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
|
|||||||
track,
|
track,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
Catcher.reportCheckedError(e, stackTrace);
|
||||||
} finally {
|
} finally {
|
||||||
isPreSearching = false;
|
isPreSearching = false;
|
||||||
}
|
}
|
||||||
@ -140,37 +149,45 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
|
|||||||
bool isFetchingSegments = false;
|
bool isFetchingSegments = false;
|
||||||
|
|
||||||
audioPlayer.positionStream.listen((position) async {
|
audioPlayer.positionStream.listen((position) async {
|
||||||
// skipping in very first second breaks stream
|
try {
|
||||||
if ((preferences.youtubeApiType == YoutubeApiType.piped &&
|
if (state.activeTrack == null || state.activeTrack is LocalTrack) {
|
||||||
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 {
|
|
||||||
isFetchingSegments = false;
|
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!;
|
final notSameSegmentId =
|
||||||
if (segments.isEmpty || position < const Duration(seconds: 3)) return;
|
currentSegments?.source != audioPlayer.currentSource;
|
||||||
|
|
||||||
for (final segment in segments) {
|
if (currentSegments == null ||
|
||||||
if ((position.inSeconds >= segment.start &&
|
(notSameSegmentId && !isFetchingSegments)) {
|
||||||
position.inSeconds < segment.end)) {
|
isFetchingSegments = true;
|
||||||
await audioPlayer.seek(Duration(seconds: segment.end));
|
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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}();
|
}();
|
||||||
|
@ -20,7 +20,7 @@ abstract class AudioPlayerInterface {
|
|||||||
// _mkPlayer = _mkSupportedPlatform ? MkPlayerWithState() : null,
|
// _mkPlayer = _mkSupportedPlatform ? MkPlayerWithState() : null,
|
||||||
// _justAudio = !_mkSupportedPlatform ? ja.AudioPlayer() : null
|
// _justAudio = !_mkSupportedPlatform ? ja.AudioPlayer() : null
|
||||||
{
|
{
|
||||||
_mkPlayer.streams.error.listen((event) {
|
_mkPlayer.stream.error.listen((event) {
|
||||||
Catcher.reportCheckedError(event, StackTrace.current);
|
Catcher.reportCheckedError(event, StackTrace.current);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface {
|
|||||||
// stream getters
|
// stream getters
|
||||||
Stream<Duration> get durationStream {
|
Stream<Duration> get durationStream {
|
||||||
// if (mkSupportedPlatform) {
|
// if (mkSupportedPlatform) {
|
||||||
return _mkPlayer.streams.duration;
|
return _mkPlayer.stream.duration;
|
||||||
// } else {
|
// } else {
|
||||||
// return _justAudio!.durationStream
|
// return _justAudio!.durationStream
|
||||||
// .where((event) => event != null)
|
// .where((event) => event != null)
|
||||||
@ -15,7 +15,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface {
|
|||||||
|
|
||||||
Stream<Duration> get positionStream {
|
Stream<Duration> get positionStream {
|
||||||
// if (mkSupportedPlatform) {
|
// if (mkSupportedPlatform) {
|
||||||
return _mkPlayer.streams.position;
|
return _mkPlayer.stream.position;
|
||||||
// } else {
|
// } else {
|
||||||
// return _justAudio!.positionStream;
|
// return _justAudio!.positionStream;
|
||||||
// }
|
// }
|
||||||
@ -24,7 +24,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface {
|
|||||||
Stream<Duration> get bufferedPositionStream {
|
Stream<Duration> get bufferedPositionStream {
|
||||||
// if (mkSupportedPlatform) {
|
// if (mkSupportedPlatform) {
|
||||||
// audioplayers doesn't have the capability to get buffered position
|
// audioplayers doesn't have the capability to get buffered position
|
||||||
return _mkPlayer.streams.buffer;
|
return _mkPlayer.stream.buffer;
|
||||||
// } else {
|
// } else {
|
||||||
// return _justAudio!.bufferedPositionStream;
|
// return _justAudio!.bufferedPositionStream;
|
||||||
// }
|
// }
|
||||||
@ -32,7 +32,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface {
|
|||||||
|
|
||||||
Stream<void> get completedStream {
|
Stream<void> get completedStream {
|
||||||
// if (mkSupportedPlatform) {
|
// if (mkSupportedPlatform) {
|
||||||
return _mkPlayer.streams.completed;
|
return _mkPlayer.stream.completed;
|
||||||
// } else {
|
// } else {
|
||||||
// return _justAudio!.playerStateStream
|
// return _justAudio!.playerStateStream
|
||||||
// .where(
|
// .where(
|
||||||
@ -57,7 +57,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface {
|
|||||||
|
|
||||||
Stream<bool> get playingStream {
|
Stream<bool> get playingStream {
|
||||||
// if (mkSupportedPlatform) {
|
// if (mkSupportedPlatform) {
|
||||||
return _mkPlayer.streams.playing;
|
return _mkPlayer.stream.playing;
|
||||||
// } else {
|
// } else {
|
||||||
// return _justAudio!.playingStream;
|
// return _justAudio!.playingStream;
|
||||||
// }
|
// }
|
||||||
@ -83,7 +83,7 @@ mixin SpotubeAudioPlayersStreams on AudioPlayerInterface {
|
|||||||
|
|
||||||
Stream<double> get volumeStream {
|
Stream<double> get volumeStream {
|
||||||
// if (mkSupportedPlatform) {
|
// if (mkSupportedPlatform) {
|
||||||
return _mkPlayer.streams.volume.map((event) => event / 100);
|
return _mkPlayer.stream.volume.map((event) => event / 100);
|
||||||
// } else {
|
// } else {
|
||||||
// return _justAudio!.volumeStream;
|
// return _justAudio!.volumeStream;
|
||||||
// }
|
// }
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:catcher/catcher.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
// ignore: implementation_imports
|
// ignore: implementation_imports
|
||||||
@ -30,36 +31,40 @@ class MkPlayerWithState extends Player {
|
|||||||
_shuffled = false,
|
_shuffled = false,
|
||||||
_loopMode = PlaylistMode.none {
|
_loopMode = PlaylistMode.none {
|
||||||
_subscriptions = [
|
_subscriptions = [
|
||||||
streams.buffering.listen((event) {
|
stream.buffering.listen((event) {
|
||||||
_playerStateStream.add(AudioPlaybackState.buffering);
|
_playerStateStream.add(AudioPlaybackState.buffering);
|
||||||
}),
|
}),
|
||||||
streams.playing.listen((playing) {
|
stream.playing.listen((playing) {
|
||||||
if (playing) {
|
if (playing) {
|
||||||
_playerStateStream.add(AudioPlaybackState.playing);
|
_playerStateStream.add(AudioPlaybackState.playing);
|
||||||
} else {
|
} else {
|
||||||
_playerStateStream.add(AudioPlaybackState.paused);
|
_playerStateStream.add(AudioPlaybackState.paused);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
streams.position.listen((position) async {
|
stream.completed.listen((isCompleted) async {
|
||||||
final isComplete = state.duration != Duration.zero &&
|
try {
|
||||||
position != Duration.zero &&
|
if (!isCompleted) return;
|
||||||
state.duration.inSeconds == position.inSeconds;
|
|
||||||
|
|
||||||
if (!isComplete || _playlist == null) return;
|
_playerStateStream.add(AudioPlaybackState.completed);
|
||||||
_playerStateStream.add(AudioPlaybackState.completed);
|
|
||||||
|
|
||||||
if (loopMode == PlaylistMode.single) {
|
if (loopMode == PlaylistMode.single) {
|
||||||
await super.open(_playlist!.medias[_playlist!.index], play: true);
|
await super.open(_playlist!.medias[_playlist!.index], play: true);
|
||||||
} else {
|
} else {
|
||||||
await next();
|
await next();
|
||||||
await Future.delayed(const Duration(milliseconds: 250), play);
|
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) {
|
if (event.medias.isEmpty) {
|
||||||
_playerStateStream.add(AudioPlaybackState.stopped);
|
_playerStateStream.add(AudioPlaybackState.stopped);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
stream.error.listen((event) {
|
||||||
|
Catcher.reportCheckedError('[MediaKitError] \n$event', null);
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user