import { State } from ".."; import { AbstractStore } from "."; export interface TypeVoice { preferredAudioInputDevice?: string; preferredAudioOutputDevice?: string; echoCancellation: boolean; noiseSupression: boolean; inputVolume: number; outputVolume: number; userVolumes: Record; userMutes: Record; } /** * Handles enabling and disabling client experiments. */ export class Voice extends AbstractStore<"voice", TypeVoice> { /** * Construct store * @param state State */ constructor(state: State) { super(state, "voice"); } /** * Hydrate external context */ hydrate(): void { /** nothing needs to be done */ } /** * Generate default values */ default(): TypeVoice { return { echoCancellation: true, noiseSupression: true, inputVolume: 1.0, outputVolume: 1.0, userVolumes: {}, userMutes: {}, }; } /** * Validate the given data to see if it is compliant and return a compliant object */ clean(input: Partial): TypeVoice { const data = this.default(); if (typeof input.preferredAudioInputDevice === "string") { data.preferredAudioInputDevice = input.preferredAudioInputDevice; } if (typeof input.preferredAudioOutputDevice === "string") { data.preferredAudioOutputDevice = input.preferredAudioOutputDevice; } if (typeof input.echoCancellation === "boolean") { data.echoCancellation = input.echoCancellation; } if (typeof input.noiseSupression === "boolean") { data.noiseSupression = input.noiseSupression; } if (typeof input.inputVolume === "number") { data.inputVolume = input.inputVolume; } if (typeof input.outputVolume === "number") { data.outputVolume = input.outputVolume; } if (typeof input.userVolumes === "object") { Object.entries(input.userVolumes) .filter( ([userId, volume]) => typeof userId === "string" && typeof volume === "number", ) .forEach(([k, v]) => (data.userVolumes[k] = v)); } if (typeof input.userMutes === "object") { Object.entries(input.userMutes) .filter( ([userId, muted]) => typeof userId === "string" && muted === true, ) .forEach(([k, v]) => (data.userMutes[k] = v)); } return data; } /** * Set a user's volume * @param userId User ID * @param volume Volume */ setUserVolume(userId: string, volume: number) { this.set("userVolumes", userId, volume); } /** * Get a user's volume * @param userId User ID * @returns Volume or default */ getUserVolume(userId: string): number { return this.get().userVolumes[userId] || 1.0; } /** * Set whether a user is muted * @param userId User ID * @param muted Whether they should be muted */ setUserMuted(userId: string, muted: boolean) { this.set("userMutes", userId, muted); } /** * Get whether a user is muted * @param userId User ID * @returns Whether muted */ getUserMuted(userId: string): boolean { return this.get().userMutes[userId] || false; } /** * Set the preferred audio input device */ set preferredAudioInputDevice(value: string) { this.set("preferredAudioInputDevice", value); } /** * Set the preferred audio output device */ set preferredAudioOutputDevice(value: string) { this.set("preferredAudioOutputDevice", value); } /** * Set echo cancellation */ set echoCancellation(value: boolean) { this.set("echoCancellation", value); } /** * Set noise cancellation */ set noiseSupression(value: boolean) { this.set("noiseSupression", value); } /** * Set input volume */ set inputVolume(value: number) { this.set("inputVolume", value); } /** * Set output volume */ set outputVolume(value: number) { this.set("outputVolume", value); } /** * Get the preferred audio input device */ get preferredAudioInputDevice(): string | undefined { return this.get().preferredAudioInputDevice; } /** * Get the preferred audio output device */ get preferredAudioOutputDevice(): string | undefined { return this.get().preferredAudioInputDevice; } /** * Get echo cancellation */ get echoCancellation(): boolean | undefined { return this.get().echoCancellation; } /** * Get noise supression */ get noiseSupression(): boolean | undefined { return this.get().noiseSupression; } /** * Get input volume */ get inputVolume(): number { return this.get().inputVolume; } /** * Get noise supression */ get outputVolume(): number { return this.get().outputVolume; } }