From f870e12011094e78addddadb939946f71219003c Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Fri, 5 Sep 2025 11:03:56 +0600 Subject: [PATCH] fix(playback): skip network requests if cached file already exists --- lib/provider/server/routes/playback.dart | 106 ++++++++++------------- 1 file changed, 47 insertions(+), 59 deletions(-) diff --git a/lib/provider/server/routes/playback.dart b/lib/provider/server/routes/playback.dart index a158c86c..f31de9cb 100644 --- a/lib/provider/server/routes/playback.dart +++ b/lib/provider/server/routes/playback.dart @@ -48,6 +48,7 @@ class ServerPlaybackRoutes { Future<({dio_lib.Response response, Uint8List? bytes})> streamTrack( + Request request, SourcedTrack track, Map headers, ) async { @@ -59,35 +60,6 @@ class ServerPlaybackRoutes { ), ), ); - final trackPartialCacheFile = File("${trackCacheFile.path}.part"); - - String? url = track.url; - - url ??= await ref - .read(trackSourcesProvider(track.query).notifier) - .swapWithNextSibling() - .then((track) => track.url!); - - var options = Options( - headers: { - ...headers, - "user-agent": _randomUserAgent, - "Cache-Control": "max-age=3600", - "Connection": "keep-alive", - "host": Uri.parse(url!).host, - }, - responseType: ResponseType.bytes, - validateStatus: (status) => status! < 400, - ); - - final headersRes = await Future.value( - dio.head( - url, - options: options, - ), - ).catchError((_) async => null); - - final contentLength = headersRes?.headers.value("content-length"); if (await trackCacheFile.exists() && userPreferences.cacheMusic) { final bytes = await trackCacheFile.readAsBytes(); @@ -102,12 +74,51 @@ class ServerPlaybackRoutes { "accept-ranges": ["bytes"], "content-range": ["bytes 0-$cachedFileLength/$cachedFileLength"], }), - requestOptions: RequestOptions(path: url), + requestOptions: RequestOptions(path: request.requestedUri.toString()), ), bytes: bytes, ); } + final trackPartialCacheFile = File("${trackCacheFile.path}.part"); + + String url = track.url ?? + await ref + .read(trackSourcesProvider(track.query).notifier) + .swapWithNextSibling() + .then((track) => track.url!); + + var options = Options( + headers: { + ...headers, + "user-agent": _randomUserAgent, + "Cache-Control": "max-age=3600", + "Connection": "keep-alive", + "host": Uri.parse(url).host, + }, + responseType: ResponseType.bytes, + validateStatus: (status) => status! < 400, + ); + + final contentLengthRes = await Future.value( + dio.head( + url, + options: options, + ), + ).catchError((e, stack) async { + AppLogger.reportError(e, stack); + + final sourcedTrack = await ref + .read(trackSourcesProvider(track.query).notifier) + .refreshStreamingUrl(); + + url = sourcedTrack.url!; + + return dio.head(url, options: options); + }); + + final contentLength = contentLengthRes?.headers.value("content-length"); + /// Forcing partial content range as mpv sometimes greedily wants /// everything at one go. Slows down overall streaming. final range = RangeHeader.parse(headers["range"] ?? ""); @@ -123,33 +134,7 @@ class ServerPlaybackRoutes { ); } - final res = await dio - .get( - url, - options: options.copyWith(headers: { - ...?options.headers, - "user-agent": _randomUserAgent, - }), - ) - .catchError((e, stack) async { - AppLogger.reportError(e, stack); - final sourcedTrack = await ref - .read(trackSourcesProvider(track.query).notifier) - .refreshStreamingUrl(); - - // It gets updated by itself. - // if (playlist.activeTrack?.id == sourcedTrack.query.id) { - // ref.read(activeTrackSourcesProvider.notifier).update(sourcedTrack); - // } - - return await dio.get( - sourcedTrack.url!, - options: options.copyWith(headers: { - ...?options.headers, - "user-agent": _randomUserAgent, - }), - ); - }); + final res = await dio.get(url, options: options); final bytes = res.data; @@ -228,8 +213,11 @@ class ServerPlaybackRoutes { ).future, ); - final (bytes: audioBytes, response: res) = - await streamTrack(sourcedTrack!, request.headers); + final (bytes: audioBytes, response: res) = await streamTrack( + request, + sourcedTrack!, + request.headers, + ); return Response( res.statusCode!,