import {_connection} from "./ServerConnection"; import {_audio as _recorder} from "../audio/AudioRecorder"; import { NativeVoiceConnection, NativeVoiceClient } from "teaclient_connection"; export namespace _audio { export namespace native { import ServerConnection = _connection.native.ServerConnection; export class VoiceConnection extends connection.voice.AbstractVoiceConnection { readonly connection: ServerConnection; readonly handle: NativeVoiceConnection; private _audio_source: RecorderProfile; constructor(connection: ServerConnection, voice: NativeVoiceConnection) { super(connection); this.connection = connection; this.handle = voice; } setup() { } async acquire_voice_recorder(recorder: RecorderProfile | undefined, enforce?: boolean) { if(this._audio_source === recorder && !enforce) return; if(this._audio_source) await this._audio_source.unmount(); if(recorder) { if(!(recorder.input instanceof _recorder.recorder.NativeInput)) throw "Recorder input must be an instance of NativeInput!"; await recorder.unmount(); } this.handleVoiceEnded(); this._audio_source = recorder; if(recorder) { recorder.current_handler = this.connection.client; recorder.callback_unmount = () => { this._audio_source = undefined; this.handle.set_audio_source(undefined); this.connection.client.update_voice_status(undefined); }; recorder.callback_start = this.on_voice_started.bind(this); recorder.callback_stop = this.handleVoiceEnded.bind(this); recorder.callback_support_change = () => { this.connection.client.update_voice_status(undefined); }; this.handle.set_audio_source((recorder.input as _recorder.recorder.NativeInput).consumer); } this.connection.client.update_voice_status(undefined); } voice_playback_support() : boolean { return this.connection.connected(); } voice_send_support() : boolean { return this.connection.connected(); } private current_channel_codec() : number { const chandler = this.connection.client; return (chandler.getClient().currentChannel() || {properties: { channel_codec: 4}}).properties.channel_codec; } private handleVoiceEnded() { const chandler = this.connection.client; chandler.getClient().speaking = false; if(!chandler.connected) return false; if(chandler.client_status.input_muted) return false; console.log(tr("Local voice ended")); //TODO } private on_voice_started() { const chandler = this.connection.client; if(chandler.client_status.input_muted) { /* evil hack due to the settings :D */ log.warn(LogCategory.VOICE, tr("Received local voice started event, even thou we're muted! Do not send any voice.")); if(this.handle) { this.handle.enable_voice_send(false); } return; } log.info(LogCategory.VOICE, tr("Local voice started")); this.handle.enable_voice_send(true); const ch = chandler.getClient(); if(ch) ch.speaking = true; } connected(): boolean { return true; /* we cant be disconnected at any time! */ } voice_recorder(): RecorderProfile { return this._audio_source; } available_clients(): connection.voice.VoiceClient[] { return this.handle.available_clients(); } find_client(client_id: number) : connection.voice.VoiceClient | undefined { for(const client of this.available_clients()) if(client.client_id === client_id) return client; return undefined; } unregister_client(client: connection.voice.VoiceClient): Promise { this.handle.unregister_client(client.client_id); return Promise.resolve(); } register_client(client_id: number): connection.voice.VoiceClient { const client = this.handle.register_client(client_id); if(!client) return client; const stream = client.get_stream(); stream.set_buffer_latency(0.02); stream.set_buffer_max_latency(0.2); return client; } decoding_supported(codec: number): boolean { return this.handle.decoding_supported(codec); } encoding_supported(codec: number): boolean { return this.handle.encoding_supported(codec); } get_encoder_codec(): number { return this.handle.get_encoder_codec(); } set_encoder_codec(codec: number) { return this.handle.set_encoder_codec(codec); } } } }