fix(radio): pausing when current song ended and new song data hasn't been fetched yet
Part-of: <https://dev.funkwhale.audio/funkwhale/funkwhale/-/merge_requests/2346>
This commit is contained in:
parent
f961e3ff8c
commit
babd65e698
|
@ -16,6 +16,16 @@ export enum LoopingMode {
|
||||||
LoopQueue
|
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[])
|
const MODE_MAX = 1 + Math.max(...Object.values(LoopingMode).filter(mode => typeof mode === 'number') as number[])
|
||||||
|
|
||||||
export const looping: Ref<number> = useStorage('player:looping', LoopingMode.None)
|
export const looping: Ref<number> = useStorage('player:looping', LoopingMode.None)
|
||||||
|
@ -32,6 +42,8 @@ export const usePlayer = createGlobalState(() => {
|
||||||
const { currentSound } = useTracks()
|
const { currentSound } = useTracks()
|
||||||
const { playNext } = useQueue()
|
const { playNext } = useQueue()
|
||||||
|
|
||||||
|
const pauseReason = ref(PauseReason.UserInput)
|
||||||
|
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
const sound = currentSound.value
|
const sound = currentSound.value
|
||||||
if (!sound) return
|
if (!sound) return
|
||||||
|
@ -40,6 +52,7 @@ export const usePlayer = createGlobalState(() => {
|
||||||
return sound.play()
|
return sound.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pauseReason.value = PauseReason.UserInput
|
||||||
return sound.pause()
|
return sound.pause()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -206,6 +219,7 @@ export const usePlayer = createGlobalState(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlaying.value = false
|
isPlaying.value = false
|
||||||
|
pauseReason.value = PauseReason.Errored
|
||||||
}, 3000, { immediate: false })
|
}, 3000, { immediate: false })
|
||||||
|
|
||||||
watch(currentIndex, stopErrorTimeout)
|
watch(currentIndex, stopErrorTimeout)
|
||||||
|
@ -214,6 +228,8 @@ export const usePlayer = createGlobalState(() => {
|
||||||
return {
|
return {
|
||||||
initializeFirstTrack,
|
initializeFirstTrack,
|
||||||
isPlaying,
|
isPlaying,
|
||||||
|
pauseReason,
|
||||||
|
PauseReason,
|
||||||
volume,
|
volume,
|
||||||
mute,
|
mute,
|
||||||
looping,
|
looping,
|
||||||
|
|
|
@ -233,10 +233,15 @@ export const useQueue = createGlobalState(() => {
|
||||||
if (looping.value === LoopingMode.LoopQueue && force !== true) {
|
if (looping.value === LoopingMode.LoopQueue && force !== true) {
|
||||||
// Loop track programmatically if it is the only track in the queue
|
// Loop track programmatically if it is the only track in the queue
|
||||||
if (tracks.value.length === 1) return playTrack(currentIndex.value, true)
|
if (tracks.value.length === 1) return playTrack(currentIndex.value, true)
|
||||||
|
|
||||||
|
// Loop entire queue
|
||||||
return playTrack(0)
|
return playTrack(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlaying.value = false
|
isPlaying.value = false
|
||||||
|
|
||||||
|
const { pauseReason, PauseReason } = usePlayer()
|
||||||
|
pauseReason.value = PauseReason.EndOfQueue
|
||||||
}
|
}
|
||||||
|
|
||||||
return playTrack(currentIndex.value + 1)
|
return playTrack(currentIndex.value + 1)
|
||||||
|
|
|
@ -114,7 +114,7 @@ export const useTracks = createGlobalState(() => {
|
||||||
|
|
||||||
// Skip when errored
|
// Skip when errored
|
||||||
const { start: soundUnplayable, stop: abortSoundUnplayableTimeout } = useTimeoutFn(() => {
|
const { start: soundUnplayable, stop: abortSoundUnplayableTimeout } = useTimeoutFn(() => {
|
||||||
const { isPlaying, looping, LoopingMode } = usePlayer()
|
const { isPlaying, looping, LoopingMode, pauseReason, PauseReason } = usePlayer()
|
||||||
const { playNext } = useQueue()
|
const { playNext } = useQueue()
|
||||||
|
|
||||||
if (looping.value !== LoopingMode.LoopTrack) {
|
if (looping.value !== LoopingMode.LoopTrack) {
|
||||||
|
@ -122,6 +122,7 @@ export const useTracks = createGlobalState(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
isPlaying.value = false
|
isPlaying.value = false
|
||||||
|
pauseReason.value = PauseReason.Errored
|
||||||
}, 3000, { immediate: false })
|
}, 3000, { immediate: false })
|
||||||
|
|
||||||
// Preload next track
|
// Preload next track
|
||||||
|
|
|
@ -6,12 +6,15 @@ import { usePlayer } from '~/composables/audio/player'
|
||||||
|
|
||||||
export const install: InitModule = ({ app }) => {
|
export const install: InitModule = ({ app }) => {
|
||||||
const { currentTrack, playNext, playPrevious } = useQueue()
|
const { currentTrack, playNext, playPrevious } = useQueue()
|
||||||
const { isPlaying, seekBy } = usePlayer()
|
const { isPlaying, seekBy, pauseReason, PauseReason } = usePlayer()
|
||||||
|
|
||||||
// Add controls for notification drawer
|
// Add controls for notification drawer
|
||||||
if ('mediaSession' in navigator) {
|
if ('mediaSession' in navigator) {
|
||||||
navigator.mediaSession.setActionHandler('play', () => (isPlaying.value = true))
|
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('seekforward', () => seekBy(5))
|
||||||
navigator.mediaSession.setActionHandler('seekbackward', () => seekBy(-5))
|
navigator.mediaSession.setActionHandler('seekbackward', () => seekBy(-5))
|
||||||
navigator.mediaSession.setActionHandler('nexttrack', () => playNext())
|
navigator.mediaSession.setActionHandler('nexttrack', () => playNext())
|
||||||
|
|
|
@ -132,7 +132,7 @@ const store: Module<State, RootState> = {
|
||||||
state.populating = true
|
state.populating = true
|
||||||
|
|
||||||
const { enqueue, playTrack, tracks } = useQueue()
|
const { enqueue, playTrack, tracks } = useQueue()
|
||||||
const { isPlaying } = usePlayer()
|
const { isPlaying, pauseReason, PauseReason } = usePlayer()
|
||||||
|
|
||||||
const params = { session: state.current?.session }
|
const params = { session: state.current?.session }
|
||||||
|
|
||||||
|
@ -147,11 +147,16 @@ const store: Module<State, RootState> = {
|
||||||
|
|
||||||
if (track === undefined) {
|
if (track === undefined) {
|
||||||
isPlaying.value = false
|
isPlaying.value = false
|
||||||
|
pauseReason.value = PauseReason.EndOfRadio
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
await enqueue(track)
|
await enqueue(track)
|
||||||
|
|
||||||
|
if (isPlaying.value === false && pauseReason.value === PauseReason.EndOfQueue) {
|
||||||
|
playNow = true
|
||||||
|
}
|
||||||
|
|
||||||
if (playNow) {
|
if (playNow) {
|
||||||
await playTrack(tracks.value.length - 1)
|
await playTrack(tracks.value.length - 1)
|
||||||
isPlaying.value = true
|
isPlaying.value = true
|
||||||
|
|
Loading…
Reference in New Issue