From 81425d930b95a1e0eb0445de7bfd2bd17ba7e375 Mon Sep 17 00:00:00 2001 From: Kasper Seweryn Date: Tue, 7 Mar 2023 22:25:44 +0100 Subject: [PATCH] fix(radio): pausing when current song ended and new song data hasn't been fetched yet Part-of: --- front/src/composables/audio/player.ts | 16 ++++++++++++++++ front/src/composables/audio/queue.ts | 5 +++++ front/src/composables/audio/tracks.ts | 3 ++- front/src/init/mediaSession.ts | 7 +++++-- front/src/store/radios.ts | 7 ++++++- 5 files changed, 34 insertions(+), 4 deletions(-) diff --git a/front/src/composables/audio/player.ts b/front/src/composables/audio/player.ts index 71564fb96..d2704e9e4 100644 --- a/front/src/composables/audio/player.ts +++ b/front/src/composables/audio/player.ts @@ -16,6 +16,16 @@ export enum LoopingMode { LoopQueue } +// Pausing + +export enum PauseReason { + UserInput, + EndOfQueue, + MediaSession, + Errored, + EndOfRadio +} + const MODE_MAX = 1 + Math.max(...Object.values(LoopingMode).filter(mode => typeof mode === 'number') as number[]) export const looping: Ref = useStorage('player:looping', LoopingMode.None) @@ -32,6 +42,8 @@ export const usePlayer = createGlobalState(() => { const { currentSound } = useTracks() const { playNext } = useQueue() + const pauseReason = ref(PauseReason.UserInput) + watchEffect(() => { const sound = currentSound.value if (!sound) return @@ -40,6 +52,7 @@ export const usePlayer = createGlobalState(() => { return sound.play() } + pauseReason.value = PauseReason.UserInput return sound.pause() }) @@ -206,6 +219,7 @@ export const usePlayer = createGlobalState(() => { } isPlaying.value = false + pauseReason.value = PauseReason.Errored }, 3000, { immediate: false }) watch(currentIndex, stopErrorTimeout) @@ -214,6 +228,8 @@ export const usePlayer = createGlobalState(() => { return { initializeFirstTrack, isPlaying, + pauseReason, + PauseReason, volume, mute, looping, diff --git a/front/src/composables/audio/queue.ts b/front/src/composables/audio/queue.ts index 209965960..4b733dc80 100644 --- a/front/src/composables/audio/queue.ts +++ b/front/src/composables/audio/queue.ts @@ -233,10 +233,15 @@ export const useQueue = createGlobalState(() => { if (looping.value === LoopingMode.LoopQueue && force !== true) { // Loop track programmatically if it is the only track in the queue if (tracks.value.length === 1) return playTrack(currentIndex.value, true) + + // Loop entire queue return playTrack(0) } isPlaying.value = false + + const { pauseReason, PauseReason } = usePlayer() + pauseReason.value = PauseReason.EndOfQueue } return playTrack(currentIndex.value + 1) diff --git a/front/src/composables/audio/tracks.ts b/front/src/composables/audio/tracks.ts index 48f3624b1..b552f69c3 100644 --- a/front/src/composables/audio/tracks.ts +++ b/front/src/composables/audio/tracks.ts @@ -114,7 +114,7 @@ export const useTracks = createGlobalState(() => { // Skip when errored const { start: soundUnplayable, stop: abortSoundUnplayableTimeout } = useTimeoutFn(() => { - const { isPlaying, looping, LoopingMode } = usePlayer() + const { isPlaying, looping, LoopingMode, pauseReason, PauseReason } = usePlayer() const { playNext } = useQueue() if (looping.value !== LoopingMode.LoopTrack) { @@ -122,6 +122,7 @@ export const useTracks = createGlobalState(() => { } isPlaying.value = false + pauseReason.value = PauseReason.Errored }, 3000, { immediate: false }) // Preload next track diff --git a/front/src/init/mediaSession.ts b/front/src/init/mediaSession.ts index f7677527d..4c0592587 100644 --- a/front/src/init/mediaSession.ts +++ b/front/src/init/mediaSession.ts @@ -6,12 +6,15 @@ import { usePlayer } from '~/composables/audio/player' export const install: InitModule = ({ app }) => { const { currentTrack, playNext, playPrevious } = useQueue() - const { isPlaying, seekBy } = usePlayer() + const { isPlaying, seekBy, pauseReason, PauseReason } = usePlayer() // Add controls for notification drawer if ('mediaSession' in navigator) { navigator.mediaSession.setActionHandler('play', () => (isPlaying.value = true)) - navigator.mediaSession.setActionHandler('pause', () => (isPlaying.value = false)) + navigator.mediaSession.setActionHandler('pause', () => { + isPlaying.value = false + pauseReason.value = PauseReason.MediaSession + }) navigator.mediaSession.setActionHandler('seekforward', () => seekBy(5)) navigator.mediaSession.setActionHandler('seekbackward', () => seekBy(-5)) navigator.mediaSession.setActionHandler('nexttrack', () => playNext()) diff --git a/front/src/store/radios.ts b/front/src/store/radios.ts index 8ee983d40..4d92a206e 100644 --- a/front/src/store/radios.ts +++ b/front/src/store/radios.ts @@ -132,7 +132,7 @@ const store: Module = { state.populating = true const { enqueue, playTrack, tracks } = useQueue() - const { isPlaying } = usePlayer() + const { isPlaying, pauseReason, PauseReason } = usePlayer() const params = { session: state.current?.session } @@ -147,11 +147,16 @@ const store: Module = { if (track === undefined) { isPlaying.value = false + pauseReason.value = PauseReason.EndOfRadio return } await enqueue(track) + if (isPlaying.value === false && pauseReason.value === PauseReason.EndOfQueue) { + playNow = true + } + if (playNow) { await playTrack(tracks.value.length - 1) isPlaying.value = true