From de74ccb220012cdd079b677e82e6aa41a52ad0b7 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Thu, 9 Mar 2023 20:04:29 +0100 Subject: [PATCH] fix(player): ensure that current track lives despite enqueueing 3 tracks as 'next track' Part-of: --- front/src/composables/audio/tracks.ts | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/front/src/composables/audio/tracks.ts b/front/src/composables/audio/tracks.ts index b552f69c3..c759714e6 100644 --- a/front/src/composables/audio/tracks.ts +++ b/front/src/composables/audio/tracks.ts @@ -101,6 +101,33 @@ export const useTracks = createGlobalState(() => { setTimeout(() => playNext(), 0) }) + // NOTE: Bump current track to ensure that it lives despite enqueueing 3 tracks as next track: + // + // In every queue we have 3 tracks that are cached, in the order, they're being played: + // + // A B C + // ^ ^ ^______ C is the next track from the queue that has been preloaded in the 'Preload next track' code section + // \ \________ B is the currently played track + // \__________ A is the previous track + // + // Now, let's make an assumption that caching next tracks is more valueable than caching previous tracks. + // To prevent track B from being disposed from the cache after enqueueing D and E tracks as 'next track' twice, we can fetch the track from the cache and bump its counter + // The cache state would be as follows: + // + // A B C --(user enqueues D as next track)-> C B D --(user enqueues E as next track)-> D B E + // + // Note that the queue would be changed as follows: + // + // A B C -> A B D C -> A B E D C + // + // This means that the currently playing track (B) is never removed from the cache (and isn't disposed prematurely) during its playback. + // However, we end up in a situation where previous track isn't cached anymore but two next tracks are. + // That implies that when user changes to the previous track ( onlybefore track B ends), a new sound instance would be created, + // which means that there might be some network requests before playback. + if (currentTrack.value) { + soundCache.get(currentTrack.value.id) + } + soundCache.set(track.id, sound) soundPromises.delete(track.id) return sound