mirror of
https://github.com/KRTirtho/spotube.git
synced 2026-05-08 16:24:36 +00:00
feat: add source change support and re-add prefetching tracks
This commit is contained in:
parent
11964e588d
commit
ed079e3e15
@ -161,7 +161,7 @@ class PlayerQueue extends HookConsumerWidget {
|
||||
snap: false,
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
automaticallyImplyLeading: !isSearching.value,
|
||||
automaticallyImplyLeading: false,
|
||||
title: BackdropFilter(
|
||||
filter: ImageFilter.blur(
|
||||
sigmaX: 10,
|
||||
|
||||
@ -6,6 +6,7 @@ import 'package:catcher_2/catcher_2.dart';
|
||||
import 'package:spotube/models/local_track.dart';
|
||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||
import 'package:spotube/provider/proxy_playlist/skip_segments.dart';
|
||||
import 'package:spotube/provider/server/sourced_track.dart';
|
||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||
|
||||
extension ProxyPlaylistListeners on ProxyPlaylistNotifier {
|
||||
@ -63,6 +64,21 @@ extension ProxyPlaylistListeners on ProxyPlaylistNotifier {
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToPosition() {
|
||||
String lastTrack = ""; // used to prevent multiple calls to the same track
|
||||
return audioPlayer.positionStream.listen((event) async {
|
||||
if (event < const Duration(seconds: 3) ||
|
||||
state.active == null ||
|
||||
state.active == state.tracks.length - 1) return;
|
||||
final nextTrack = state.tracks.elementAt(state.active! + 1);
|
||||
|
||||
if (lastTrack == nextTrack.id) return;
|
||||
|
||||
await ref.read(sourcedTrackProvider(nextTrack).future);
|
||||
lastTrack = nextTrack.id!;
|
||||
});
|
||||
}
|
||||
|
||||
StreamSubscription subscribeToPlayerError() {
|
||||
return audioPlayer.errorStream.listen((event) {});
|
||||
}
|
||||
|
||||
@ -51,6 +51,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist> {
|
||||
// These are subscription methods from player_listeners.dart
|
||||
subscribeToPlaylist(),
|
||||
subscribeToSkipSponsor(),
|
||||
subscribeToPosition(),
|
||||
subscribeToScrobbleChanged(),
|
||||
];
|
||||
}
|
||||
|
||||
@ -13,9 +13,9 @@ import 'package:spotube/models/logger.dart';
|
||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist.dart';
|
||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.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/provider/user_preferences/user_preferences_state.dart';
|
||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
||||
|
||||
class PlaybackServer {
|
||||
final Ref ref;
|
||||
@ -38,7 +38,6 @@ class PlaybackServer {
|
||||
|
||||
if (kDebugMode) {
|
||||
pipeline.addMiddleware(logRequests());
|
||||
dio.interceptors.add(LogInterceptor());
|
||||
}
|
||||
|
||||
serve(pipeline.addHandler(router.call), InternetAddress.loopbackIPv4, port)
|
||||
@ -58,13 +57,15 @@ class PlaybackServer {
|
||||
try {
|
||||
final track =
|
||||
playlist.tracks.firstWhere((element) => element.id == trackId);
|
||||
final sourcedTrack =
|
||||
await SourcedTrack.fetchFromTrack(track: track, ref: ref);
|
||||
final activeSourcedTrack = ref.read(activeSourcedTrackProvider);
|
||||
final sourcedTrack = activeSourcedTrack?.id == track.id
|
||||
? activeSourcedTrack
|
||||
: await ref.read(sourcedTrackProvider(track).future);
|
||||
|
||||
ref.read(activeSourcedTrackProvider.notifier).update(sourcedTrack);
|
||||
|
||||
final res = await dio.get(
|
||||
sourcedTrack.url,
|
||||
sourcedTrack!.url,
|
||||
options: Options(
|
||||
headers: {
|
||||
...request.headers,
|
||||
@ -75,13 +76,14 @@ class PlaybackServer {
|
||||
"Connection": "keep-alive",
|
||||
},
|
||||
responseType: ResponseType.stream,
|
||||
validateStatus: (status) => status! < 500,
|
||||
),
|
||||
);
|
||||
|
||||
final audioStream = res.data?.stream as Stream<Uint8List>?;
|
||||
|
||||
return Response(
|
||||
200,
|
||||
res.statusCode!,
|
||||
body: audioStream,
|
||||
context: {
|
||||
"shelf.io.buffer_output": false,
|
||||
|
||||
27
lib/provider/server/sourced_track.dart
Normal file
27
lib/provider/server/sourced_track.dart
Normal file
@ -0,0 +1,27 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
|
||||
import 'package:spotube/services/sourced_track/sourced_track.dart';
|
||||
|
||||
final sourcedTrackProvider =
|
||||
FutureProvider.family<SourcedTrack?, Track?>((ref, track) async {
|
||||
if (track == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ref.listen(
|
||||
ProxyPlaylistNotifier.provider,
|
||||
(old, next) {
|
||||
if (next.tracks.isEmpty ||
|
||||
next.tracks.none((element) => element.id == track.id)) {
|
||||
ref.invalidateSelf();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
final sourcedTrack =
|
||||
await SourcedTrack.fetchFromTrack(track: track, ref: ref);
|
||||
|
||||
return sourcedTrack;
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user