Add track looping logic

environments/review-docs-renov-b1i8ag/deployments/15025
wvffle 2022-10-18 22:21:14 +00:00 zatwierdzone przez Georg Krause
rodzic e47dbc5ab5
commit 7c68fee276
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 2970D504B2183D22
2 zmienionych plików z 35 dodań i 2 usunięć

Wyświetl plik

@ -20,6 +20,7 @@ export interface Sound {
readonly currentTime: number
readonly duration: number
readonly buffered: number
looping: boolean
play(): void | Promise<void>
pause(): void | Promise<void>
@ -27,6 +28,7 @@ export interface Sound {
seekTo(seconds: number): void | Promise<void>
seekBy(seconds: number): void | Promise<void>
onSoundLoop: EventHookOn<Sound>
onSoundEnd: EventHookOn<Sound>
}
@ -41,11 +43,13 @@ export const registerSoundImplementation = <T extends Constructor<Sound>>(implem
@registerSoundImplementation
export class HTMLSound implements Sound {
#audio = new Audio()
#soundLoopEventHook = createEventHook<HTMLSound>()
#soundEndEventHook = createEventHook<HTMLSound>()
readonly isLoaded = ref(false)
audioNode = createAudioSource(this.#audio)
onSoundLoop: EventHookOn<HTMLSound>
onSoundEnd: EventHookOn<HTMLSound>
constructor (sources: SoundSource[]) {
@ -54,11 +58,18 @@ export class HTMLSound implements Sound {
this.#audio.preload = 'auto'
useEventListener(this.#audio, 'ended', () => this.#soundEndEventHook.trigger(this))
useEventListener(this.#audio, 'timeupdate', () => {
if (this.#audio.currentTime === 0) {
this.#soundLoopEventHook.trigger(this)
}
})
useEventListener(this.#audio, 'loadeddata', () => {
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
this.isLoaded.value = this.#audio.readyState >= 2
})
this.onSoundLoop = this.#soundLoopEventHook.on
this.onSoundEnd = this.#soundEndEventHook.on
}
@ -108,6 +119,14 @@ export class HTMLSound implements Sound {
get currentTime () {
return this.#audio.currentTime
}
get looping () {
return this.#audio.loop
}
set looping (value: boolean) {
this.#audio.loop = value
}
}
export const soundImplementation = refDefault(ref<Constructor<Sound>>(), HTMLSound)

Wyświetl plik

@ -62,11 +62,25 @@ export const toggleLooping = () => {
looping.value %= MODE_MAX
}
watchEffect(() => {
const sound = currentSound.value
if (!sound) return
sound.looping = looping.value === LoopingMode.LoopTrack
})
watch(currentSound, sound => {
sound?.onSoundLoop(() => {
currentTime.value = 0
})
})
// Duration
export const duration = ref(0)
watchEffect(() => {
if (currentSound.value?.isLoaded.value) {
duration.value = currentSound.value?.duration ?? 0
const sound = currentSound.value
if (sound?.isLoaded.value === true) {
duration.value = sound.duration ?? 0
currentTime.value = sound.currentTime
return
}