diff --git a/shared/js/settings.ts b/shared/js/settings.ts index df36f6ef..6718b196 100644 --- a/shared/js/settings.ts +++ b/shared/js/settings.ts @@ -1,4 +1,3 @@ -import * as log from "./log"; import {LogCategory, logError, logTrace} from "./log"; import * as loader from "tc-loader"; import {Stage} from "tc-loader"; @@ -773,6 +772,12 @@ export class Settings { valueType: "boolean", }; + static readonly KEY_MICROPHONE_LEVEL_INDICATOR: RegistryKey = { + key: "microphone_level_indicator", + description: "Enable/disable the microphone level indicator when opening the microphone settings. The default is true, except for the linux native client.", + valueType: "boolean", + }; + static readonly FN_LOG_ENABLED: (category: string) => RegistryKey = category => { return { key: "log." + category.toLowerCase() + ".enabled", diff --git a/shared/js/ui/modal/settings/Microphone.tsx b/shared/js/ui/modal/settings/Microphone.tsx index 1fe07c87..313c3fa5 100644 --- a/shared/js/ui/modal/settings/Microphone.tsx +++ b/shared/js/ui/modal/settings/Microphone.tsx @@ -6,6 +6,8 @@ import {LogCategory, logTrace, logWarn} from "tc-shared/log"; import {defaultRecorder} from "tc-shared/voice/RecorderProfile"; import {DeviceListState, getRecorderBackend, IDevice} from "tc-shared/audio/recorder"; import {Settings, settings} from "tc-shared/settings"; +import {getBackend} from "tc-shared/backend"; +import * as _ from "lodash"; export type MicrophoneSetting = "volume" @@ -48,8 +50,6 @@ export interface MicrophoneSettingsEvents { "action_request_permissions": {}, "action_set_selected_device": { target: SelectedMicrophone }, "action_set_selected_device_result": { - status: "success", - } | { status: "error", reason: string }, @@ -96,6 +96,7 @@ export function initialize_audio_microphone_controller(events: Registry } = {}; const deviceLevelInfo: { [key: string]: any } = {}; let deviceLevelUpdateTask; + let selectedDevice: SelectedMicrophone = { type: "none" }; const destroyLevelIndicators = () => { Object.keys(levelMeterInitializePromises).forEach(e => { @@ -110,39 +111,77 @@ export function initialize_audio_microphone_controller(events: Registry { destroyLevelIndicators(); + let levelMeterEnabled; + { + let defaultValue = true; + if(__build.target === "client" && getBackend("native").getVersionInfo().os_platform === "linux") { + defaultValue = false; + } + + levelMeterEnabled = settings.getValue(Settings.KEY_MICROPHONE_LEVEL_INDICATOR, defaultValue); + } deviceLevelInfo["none"] = {deviceId: "none", status: "success", level: 0}; + const defaultDeviceId = recorderBackend.getDeviceList().getDefaultDeviceId(); for (const device of recorderBackend.getDeviceList().getDevices()) { - let promise = recorderBackend.createLevelMeter(device).then(meter => { - meter.setObserver(level => { + let createLevelMeter; + if(!levelMeterEnabled) { + switch (selectedDevice.type) { + case "default": + createLevelMeter = device.deviceId == defaultDeviceId; + break; + + case "device": + createLevelMeter = device.deviceId == selectedDevice.deviceId; + break; + + case "none": + createLevelMeter = false; + break; + } + } else { + createLevelMeter = true; + } + + if(createLevelMeter) { + let promise = recorderBackend.createLevelMeter(device).then(meter => { + meter.setObserver(level => { + if (levelMeterInitializePromises[device.deviceId] !== promise) { + /* old level meter */ + return; + } + + deviceLevelInfo[device.deviceId] = { + deviceId: device.deviceId, + status: "success", + level: level + }; + }); + return Promise.resolve(meter); + }).catch(error => { if (levelMeterInitializePromises[device.deviceId] !== promise) { /* old level meter */ return; } - deviceLevelInfo[device.deviceId] = { deviceId: device.deviceId, - status: "success", - level: level + status: "error", + + error: error }; + + logWarn(LogCategory.AUDIO, tr("Failed to initialize a level meter for device %s (%s): %o"), device.deviceId, device.driver + ":" + device.name, error); + return Promise.reject(error); }); - return Promise.resolve(meter); - }).catch(error => { - if (levelMeterInitializePromises[device.deviceId] !== promise) { - /* old level meter */ - return; - } + levelMeterInitializePromises[device.deviceId] = promise; + } else { deviceLevelInfo[device.deviceId] = { deviceId: device.deviceId, status: "error", - error: error + error: tr("level meter disabled") }; - - logWarn(LogCategory.AUDIO, tr("Failed to initialize a level meter for device %s (%s): %o"), device.deviceId, device.driver + ":" + device.name, error); - return Promise.reject(error); - }); - levelMeterInitializePromises[device.deviceId] = promise; + } } }; @@ -160,6 +199,7 @@ export function initialize_audio_microphone_controller(events: Registry { + if(_.isEqual(selectedDevice, event.device)) { + return; + } + + selectedDevice = event.device; + updateLevelMeter(); + }); } /* device list */ diff --git a/shared/js/ui/modal/settings/MicrophoneRenderer.tsx b/shared/js/ui/modal/settings/MicrophoneRenderer.tsx index c264d12b..6837513e 100644 --- a/shared/js/ui/modal/settings/MicrophoneRenderer.tsx +++ b/shared/js/ui/modal/settings/MicrophoneRenderer.tsx @@ -52,6 +52,7 @@ const ActivityBar = (props: { events: Registry, device } props.events.reactUse("notify_device_level", event => { + refHider.current.style.width = "100%"; if (event.status === "uninitialized") { if (status.mode === "uninitialized") { return;