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>
environments/review-docs-fix-d-jlladr/deployments/17321
Kasper Seweryn 2023-03-07 22:25:44 +01:00 zatwierdzone przez Georg krause
rodzic d28f6f7873
commit 81425d930b
5 zmienionych plików z 34 dodań i 4 usunięć

Wyświetl plik

@ -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,

Wyświetl plik

@ -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)

Wyświetl plik

@ -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

Wyświetl plik

@ -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())

Wyświetl plik

@ -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