53 lines
1.8 KiB
TypeScript
53 lines
1.8 KiB
TypeScript
import type { AudioOutputInfo } from '../src/types/screen.js'
|
|
|
|
export class AudioOutput {
|
|
devices: AudioOutputInfo[] = []
|
|
notice = ''
|
|
private pending: Promise<unknown> = Promise.resolve()
|
|
constructor(
|
|
public selected: string,
|
|
private enumerate: () => Promise<AudioOutputInfo[]>,
|
|
private apply: (id: string) => Promise<void>,
|
|
private save: (id: string) => void,
|
|
) {}
|
|
private enqueue<T>(operation: () => Promise<T>): Promise<T> {
|
|
const result = this.pending.then(operation)
|
|
this.pending = result.catch(() => {})
|
|
return result
|
|
}
|
|
refresh() {
|
|
return this.enqueue(async () => {
|
|
this.devices = await this.enumerate()
|
|
if (this.selected && !this.devices.some((device) => device.id === this.selected)) {
|
|
await this.apply('')
|
|
this.selected = ''
|
|
this.notice = 'Устройство звука отключено. Используется устройство по умолчанию в системе.'
|
|
this.save('')
|
|
}
|
|
})
|
|
}
|
|
select(id: unknown) {
|
|
return this.enqueue(async () => {
|
|
if (typeof id !== 'string' || (id !== '' && !this.devices.some((d) => d.id === id)))
|
|
throw new Error('Устройство вывода звука недоступно')
|
|
const previous = this.selected
|
|
try {
|
|
await this.apply(id)
|
|
this.save(id)
|
|
} catch (error) {
|
|
try {
|
|
await this.apply(previous)
|
|
} catch {
|
|
this.notice = 'Не удалось восстановить устройство звука. Выберите устройство заново.'
|
|
}
|
|
throw error
|
|
}
|
|
this.selected = id
|
|
this.notice = ''
|
|
})
|
|
}
|
|
prepare(apply: (id: string) => Promise<void>) {
|
|
return this.enqueue(() => apply(this.selected))
|
|
}
|
|
}
|