From fd750c4584d51fe4bcc208f6442b011cbb5ebd40 Mon Sep 17 00:00:00 2001 From: Nils Knappmeier Date: Sat, 6 Apr 2024 03:08:54 +0200 Subject: [PATCH] player POC --- .../solid/organisms/Reader/Reader.tsx | 41 ++++++++++++++----- src/core/SpeechPackPlayer/Player.ts | 16 ++++++-- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/components/solid/organisms/Reader/Reader.tsx b/src/components/solid/organisms/Reader/Reader.tsx index a892a26..2933546 100644 --- a/src/components/solid/organisms/Reader/Reader.tsx +++ b/src/components/solid/organisms/Reader/Reader.tsx @@ -8,47 +8,66 @@ import speechPack from "@/data/speechpacks/default"; import { SINGLE_DIRECTION, type Technique } from "$core/model"; import { SimpleButton } from "@/components/solid/atoms/SimpleButton.tsx"; import { ExamScroll } from "@/components/solid/organisms/Reader/ExamScroll.tsx"; -import { IconAutoMode, IconPlay, IconSkipNext, IconSkipPrevious } from "@/icons"; +import { IconAutoMode, IconPause, IconPlay, IconSkipNext, IconSkipPrevious } from "@/icons"; import { CheckButton } from "@/components/solid/atoms/CheckButton.tsx"; import { type Speed, SpeedButton } from "@/components/solid/organisms/Reader/SpeedButton.tsx"; export const Reader: Component<{ dojoInfo: DojoInfo }> = (props) => { const techniqueStore = createTechniqueStore(props.dojoInfo.id); const [techniques] = createResource(techniqueStore.load, { initialValue: [] }); + const [playing, setPlaying] = createSignal(false); const [player] = createResource( async () => { const speechPackPlayer = await loadSpeechPackPlayer(speechPack, playArrayBuffer); - return (technique: Technique) => { - if (technique.direction === SINGLE_DIRECTION) { - return speechPackPlayer.play([technique.execution, technique.attack, technique.defence]); - } else { - return speechPackPlayer.play([technique.execution, technique.attack, technique.defence, technique.direction]); - } + return { + play: async (technique: Technique) => { + setPlaying(true); + if (technique.direction === SINGLE_DIRECTION) { + await speechPackPlayer.play([technique.execution, technique.attack, technique.defence]); + } else { + await speechPackPlayer.play([ + technique.execution, + technique.attack, + technique.defence, + technique.direction, + ]); + } + setPlaying(false); + }, + stop: async () => speechPackPlayer.stop(), }; }, { - initialValue: async () => {}, + initialValue: { play: async () => {}, stop: async () => {} }, }, ); return (
- +
); }; -const Player: Component<{ player: (technique: Technique) => Promise; techniques: Technique[] }> = (props) => { +const Player: Component<{ + player: { play: (technique: Technique) => Promise; stop: () => Promise }; + techniques: Technique[]; + playing: boolean; +}> = (props) => { const [autoPlay, setAutoPlay] = createSignal(false); const [speed, setSpeed] = createSignal("normal"); return ( <>
- props.player(props.techniques[0])} icon={IconPlay} /> + (props.playing ? props.player.stop() : props.player.play(props.techniques[0]))} + icon={props.playing ? IconPause : IconPlay} + />
diff --git a/src/core/SpeechPackPlayer/Player.ts b/src/core/SpeechPackPlayer/Player.ts index 09e122c..f6a1815 100644 --- a/src/core/SpeechPackPlayer/Player.ts +++ b/src/core/SpeechPackPlayer/Player.ts @@ -8,19 +8,29 @@ export async function loadSpeechPackPlayer(speechPack: SpeechPack, playArrayBuff class SpeechPackPlayer { private readonly speechPack: Promise; private readonly playArrayBuffer: PlayArrayBuffer; + private abortController: AbortController; constructor(speechPack: Promise, playArrayBuffer: PlayArrayBuffer) { + this.abortController = new AbortController(); this.speechPack = speechPack; this.playArrayBuffer = playArrayBuffer; } async play(audioFiles: SpeechFile[]): Promise { + this.abortController.abort(); + const abortController = new AbortController(); + this.abortController = abortController; for (const file of audioFiles) { - await this.playSingle(file); + if (abortController.signal.aborted) return; + await this.playSingle(file, abortController); } } - private async playSingle(audioFile: SpeechFile) { + async stop() { + this.abortController.abort(); + } + + private async playSingle(audioFile: SpeechFile, abortController: AbortController) { const loadedSpeechPack = await this.speechPack; - await this.playArrayBuffer(loadedSpeechPack[audioFile]); + await this.playArrayBuffer(loadedSpeechPack[audioFile], { abortSignal: abortController.signal }); } }