178 lines
4.8 KiB
TypeScript
Raw Normal View History

import * as native from "tc-native/connection";
import {AudioBackend, OutputDevice} from "tc-shared/audio/Player";
2019-10-26 01:51:40 +02:00
//FIXME: Native audio initialize handle!
export interface Device {
device_id: string;
name: string;
}
2020-02-08 16:50:48 +01:00
let _initialized_callbacks: (() => any)[] = [];
export let _initialized = false;
export let _initializing = false;
export let _current_device: native.audio.AudioDevice;
2020-02-08 16:50:48 +01:00
export function initialized() : boolean {
return _initialized;
}
export function on_ready(cb: () => any) {
if(_initialized)
cb();
else
_initialized_callbacks.push(cb);
}
2020-02-08 16:50:48 +01:00
export function initialize() {
if(_initializing) return;
_initializing = true;
native.audio.initialize(() => {
_initialized = true;
for(const callback of _initialized_callbacks)
callback();
_initialized_callbacks = [];
});
return true;
}
2020-02-08 16:50:48 +01:00
export async function available_devices() : Promise<Device[]> {
return native.audio.available_devices().filter(e => e.output_supported || e.output_default);
}
2019-10-26 01:51:40 +02:00
export async function set_device(device_id?: string) : Promise<void> {
const dev = native.audio.available_devices().filter(e => e.device_id == device_id);
if(dev.length == 0) {
console.warn("Missing audio device with is %s", device_id);
throw "invalid device id";
2019-10-26 01:51:40 +02:00
}
try {
native.audio.playback.set_device(dev[0].device_id);
} catch(error) {
if(error instanceof Error)
throw error.message;
throw error;
2019-10-26 01:51:40 +02:00
}
_current_device = dev[0];
}
2019-10-26 01:51:40 +02:00
export function current_device() : Device {
if(_current_device)
return _current_device;
2019-10-26 01:51:40 +02:00
const dev = native.audio.available_devices().filter(e => e.output_default);
if(dev.length > 0)
return dev[0];
return {device_id: "default", name: "default"} as Device;
2019-10-26 01:51:40 +02:00
}
export function get_master_volume() : number {
return native.audio.playback.get_master_volume();
}
export function set_master_volume(volume: number) {
native.audio.playback.set_master_volume(volume);
}
export class NativeAudioPlayer implements AudioBackend {
private readonly audioContext: AudioContext;
private initializedPromises: (() => void)[];
private currentDevice: native.audio.AudioDevice;
constructor() {
this.audioContext = new AudioContext();
this.initializedPromises = [];
native.audio.initialize(() => {
const promises = this.initializedPromises;
this.initializedPromises = undefined;
promises.forEach(callback => callback());
});
}
executeWhenInitialized(callback: () => void): any {
if(this.initializedPromises) {
this.initializedPromises.push(callback);
} else {
callback();
}
}
getMasterVolume(): number {
return native.audio.playback.get_master_volume();
}
setMasterVolume(volume: number): any {
native.audio.playback.set_master_volume(volume);
}
getAudioContext(): AudioContext | undefined {
return this.audioContext;
}
async getAvailableDevices(): Promise<OutputDevice[]> {
return native.audio.available_devices().filter(e => e.output_supported || e.output_default).map(entry => ({
device_id: entry.device_id,
driver: entry.driver,
name: entry.name
}));
}
getCurrentDevice(): OutputDevice {
if(this.currentDevice) {
return this.currentDevice;
}
const defaultDevice = native.audio.available_devices().find(entry => entry.output_default);
if(defaultDevice) {
return {
name: defaultDevice.name,
driver: defaultDevice.driver,
device_id: defaultDevice.device_id
};
}
return {
name: "Default device",
device_id: "default",
driver: "default driver"
};
}
async setCurrentDevice(targetId: string | undefined): Promise<void> {
const device = native.audio.available_devices().find(e => e.device_id == targetId);
if(!device) {
console.warn("Missing audio device with is %s", targetId);
throw "invalid device id";
}
try {
native.audio.playback.set_device(device.device_id);
} catch(error) {
if(error instanceof Error) {
throw error.message;
}
throw error;
}
this.currentDevice = device;
}
getDefaultDeviceId(): string {
return native.audio.available_devices().find(entry => entry.output_default).device_id;
}
isDeviceRefreshAvailable(): boolean {
return false;
}
isInitialized(): boolean {
return !this.initializedPromises;
}
refreshDevices(): Promise<void> {
return Promise.resolve(undefined);
}
}