Resolve race condition

This commit is contained in:
wvffle 2022-10-28 14:31:50 +00:00 committed by Georg Krause
parent 0118fe0c63
commit 8c62d516b0
No known key found for this signature in database
GPG Key ID: 2970D504B2183D22
3 changed files with 33 additions and 27 deletions

View File

@ -1,5 +1,5 @@
import { createGlobalState, tryOnMounted, useIntervalFn, useRafFn, useStorage, useTimeoutFn, whenever } from '@vueuse/core'
import { computed, nextTick, ref, watch, watchEffect, type Ref } from 'vue'
import { computed, ref, watch, watchEffect, type Ref } from 'vue'
import { useTracks } from '~/composables/audio/tracks'
import { setGain } from './audio-api'
@ -28,7 +28,7 @@ export const isPlaying = ref(false)
// Use Player
export const usePlayer = createGlobalState(() => {
const { currentSound, createTrack } = useTracks()
const { currentSound } = useTracks()
const { playNext } = useQueue()
watchEffect(() => {
@ -43,12 +43,6 @@ export const usePlayer = createGlobalState(() => {
sound.pause()
})
const stop = async () => {
isPlaying.value = false
seekTo(0)
return nextTick()
}
// Create first track when we initalize the page
// NOTE: We want to have it called only once, hence we're using createGlobalState
const initializeFirstTrack = createGlobalState(() => tryOnMounted(() => {
@ -59,8 +53,6 @@ export const usePlayer = createGlobalState(() => {
trackRadioPopulating()
trackListenSubmissions()
createTrack(currentIndex.value)
}))
// Volume
@ -208,7 +200,6 @@ export const usePlayer = createGlobalState(() => {
return {
initializeFirstTrack,
isPlaying,
stop,
volume,
mute,
looping,

View File

@ -6,7 +6,7 @@ import { computed, ref, shallowReactive, watchEffect } from 'vue'
import { getMany, setMany } from 'idb-keyval'
import { useClamp } from '@vueuse/math'
import { looping, LoopingMode, isPlaying, usePlayer } from '~/composables/audio/player'
import { looping, LoopingMode, isPlaying } from '~/composables/audio/player'
import { useStore } from '~/store'
import { useTracks } from '~/composables/audio/tracks'
@ -166,13 +166,17 @@ export const useQueue = createGlobalState(() => {
}
// Play track
const playTrack = async (trackIndex: number, force = false) => {
const playTrack = async (trackIndex: number, forceRestartIfCurrent = false) => {
if (isPlaying.value) currentSound.value?.pause()
if (currentIndex.value !== trackIndex) currentSound.value?.seekTo(0)
if (force && currentIndex.value === trackIndex) {
const shouldRestart = forceRestartIfCurrent && currentIndex.value === trackIndex
const nextTrackIsTheSame = queue.value[trackIndex].id === currentTrack.value.id
if (shouldRestart || nextTrackIsTheSame) {
currentSound.value?.seekTo(0)
if (isPlaying.value) currentSound.value?.play()
return
if (shouldRestart) return
}
currentIndex.value = trackIndex
@ -270,8 +274,9 @@ export const useQueue = createGlobalState(() => {
// Clear
const clearRadio = ref(false)
const clear = async () => {
const { stop } = usePlayer()
await stop()
currentSound.value?.pause()
currentSound.value?.seekTo(0)
currentSound.value?.dispose()
clearRadio.value = true
tracks.value.length = 0
}

View File

@ -1,7 +1,7 @@
import type { QueueTrack, QueueTrackSource } from '~/composables/audio/queue'
import type { Sound } from '~/api/player'
import { createGlobalState, syncRef, whenever } from '@vueuse/core'
import { createGlobalState, syncRef, useTimeoutFn, whenever } from '@vueuse/core'
import { computed, ref } from 'vue'
import { connectAudioSource } from '~/composables/audio/audio-api'
@ -55,30 +55,40 @@ export const useTracks = createGlobalState(() => {
const createSoundPromise = async () => {
const sources = getTrackSources(track)
const { playNext, currentIndex } = useQueue()
const { playTrack, currentIndex } = useQueue()
const SoundImplementation = soundImplementation.value
const sound = new SoundImplementation(sources)
sound.onSoundEnd(() => {
console.log('TRACK ENDED, PLAYING NEXT')
createTrack(currentIndex.value + 1)
// NOTE: We push it to the end of the job queue
setTimeout(playNext, 0)
setTimeout(() => {
playTrack(currentIndex.value + 1)
}, 0)
})
soundCache.set(track.id, sound)
soundPromises.delete(track.id)
return sound
}
console.log('NO TRACK IN CACHE, CREATING')
console.log('NO TRACK IN CACHE, CREATING', track)
const soundPromise = createSoundPromise()
soundPromises.set(track.id, soundPromise)
return soundPromise
}
// Preload next track
const { start: startPreloadTimeout, stop: stopPreloadTimeout } = useTimeoutFn(async (index) => {
const { queue } = useQueue()
const sound = await createSound(queue.value[index as number])
await sound.preload()
}, 100, { immediate: false })
// Create track from queue
const createTrack = async (index: number) => {
stopPreloadTimeout()
const { queue, currentIndex } = useQueue()
if (queue.value.length <= index || index === -1) return
console.log('LOADING TRACK', index)
@ -97,10 +107,8 @@ export const useTracks = createGlobalState(() => {
// NOTE: Preload next track
if (index === currentIndex.value && index + 1 < queue.value.length) {
setTimeout(async () => {
const sound = await createSound(queue.value[index + 1])
await sound.preload()
}, 100)
// @ts-expect-error vueuse is wrongly typed?
startPreloadTimeout(index + 1)
}
}
@ -110,7 +118,9 @@ export const useTracks = createGlobalState(() => {
const initialize = createGlobalState(() => {
const { currentIndex, currentTrack: track } = useQueue()
whenever(track, () => createTrack(currentIndex.value))
whenever(track, () => {
createTrack(currentIndex.value)
}, { immediate: true })
syncRef(track, currentTrack, {
direction: 'ltr'
})