| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 |
- import { Audio, type AudioErrorContext, type AudioPlayOptions, type AudioSound, type AudioVoice } from "@opentui/core"
- import { readFile } from "node:fs/promises"
- let audio: Audio | null | undefined
- const sounds = new Map<string, Promise<AudioSound | null>>()
- function getAudio() {
- if (audio !== undefined) return audio
- try {
- const next = Audio.create({ autoStart: false })
- next.on("error", (error: Error, context: AudioErrorContext) => {
- console.debug("tui audio error", { error, context })
- })
- audio = next
- return next
- } catch (error) {
- console.debug("failed to create tui audio", { error })
- audio = null
- return null
- }
- }
- export function loadSoundFile(file: string) {
- const current = getAudio()
- if (!current) return Promise.resolve(null)
- const cached = sounds.get(file)
- if (cached) return cached
- const task = readFile(file)
- .then((bytes) => current.loadSound(bytes))
- .catch((error) => {
- console.debug("failed to load tui sound", { file, error })
- return null
- })
- sounds.set(file, task)
- return task
- }
- export function play(sound: AudioSound, options?: AudioPlayOptions) {
- const current = getAudio()
- if (!current) return null
- if (!current.isStarted() && !current.start()) return null
- return current.play(sound, options)
- }
- export function stopVoice(voice: AudioVoice) {
- return audio?.stopVoice(voice) ?? false
- }
- export function dispose() {
- audio?.dispose()
- audio = undefined
- sounds.clear()
- }
|