Resolve race condition
This commit is contained in:
parent
0118fe0c63
commit
8c62d516b0
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue