Fixed linux client start crash when opening too many devices
This commit is contained in:
parent
d8ecb013c2
commit
6e93b76089
3 changed files with 75 additions and 20 deletions
|
@ -1,4 +1,3 @@
|
||||||
import * as log from "./log";
|
|
||||||
import {LogCategory, logError, logTrace} from "./log";
|
import {LogCategory, logError, logTrace} from "./log";
|
||||||
import * as loader from "tc-loader";
|
import * as loader from "tc-loader";
|
||||||
import {Stage} from "tc-loader";
|
import {Stage} from "tc-loader";
|
||||||
|
@ -773,6 +772,12 @@ export class Settings {
|
||||||
valueType: "boolean",
|
valueType: "boolean",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static readonly KEY_MICROPHONE_LEVEL_INDICATOR: RegistryKey<boolean> = {
|
||||||
|
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<boolean> = category => {
|
static readonly FN_LOG_ENABLED: (category: string) => RegistryKey<boolean> = category => {
|
||||||
return {
|
return {
|
||||||
key: "log." + category.toLowerCase() + ".enabled",
|
key: "log." + category.toLowerCase() + ".enabled",
|
||||||
|
|
|
@ -6,6 +6,8 @@ import {LogCategory, logTrace, logWarn} from "tc-shared/log";
|
||||||
import {defaultRecorder} from "tc-shared/voice/RecorderProfile";
|
import {defaultRecorder} from "tc-shared/voice/RecorderProfile";
|
||||||
import {DeviceListState, getRecorderBackend, IDevice} from "tc-shared/audio/recorder";
|
import {DeviceListState, getRecorderBackend, IDevice} from "tc-shared/audio/recorder";
|
||||||
import {Settings, settings} from "tc-shared/settings";
|
import {Settings, settings} from "tc-shared/settings";
|
||||||
|
import {getBackend} from "tc-shared/backend";
|
||||||
|
import * as _ from "lodash";
|
||||||
|
|
||||||
export type MicrophoneSetting =
|
export type MicrophoneSetting =
|
||||||
"volume"
|
"volume"
|
||||||
|
@ -48,8 +50,6 @@ export interface MicrophoneSettingsEvents {
|
||||||
"action_request_permissions": {},
|
"action_request_permissions": {},
|
||||||
"action_set_selected_device": { target: SelectedMicrophone },
|
"action_set_selected_device": { target: SelectedMicrophone },
|
||||||
"action_set_selected_device_result": {
|
"action_set_selected_device_result": {
|
||||||
status: "success",
|
|
||||||
} | {
|
|
||||||
status: "error",
|
status: "error",
|
||||||
reason: string
|
reason: string
|
||||||
},
|
},
|
||||||
|
@ -96,6 +96,7 @@ export function initialize_audio_microphone_controller(events: Registry<Micropho
|
||||||
const levelMeterInitializePromises: { [key: string]: Promise<LevelMeter> } = {};
|
const levelMeterInitializePromises: { [key: string]: Promise<LevelMeter> } = {};
|
||||||
const deviceLevelInfo: { [key: string]: any } = {};
|
const deviceLevelInfo: { [key: string]: any } = {};
|
||||||
let deviceLevelUpdateTask;
|
let deviceLevelUpdateTask;
|
||||||
|
let selectedDevice: SelectedMicrophone = { type: "none" };
|
||||||
|
|
||||||
const destroyLevelIndicators = () => {
|
const destroyLevelIndicators = () => {
|
||||||
Object.keys(levelMeterInitializePromises).forEach(e => {
|
Object.keys(levelMeterInitializePromises).forEach(e => {
|
||||||
|
@ -110,39 +111,77 @@ export function initialize_audio_microphone_controller(events: Registry<Micropho
|
||||||
const updateLevelMeter = () => {
|
const updateLevelMeter = () => {
|
||||||
destroyLevelIndicators();
|
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};
|
deviceLevelInfo["none"] = {deviceId: "none", status: "success", level: 0};
|
||||||
|
|
||||||
|
const defaultDeviceId = recorderBackend.getDeviceList().getDefaultDeviceId();
|
||||||
for (const device of recorderBackend.getDeviceList().getDevices()) {
|
for (const device of recorderBackend.getDeviceList().getDevices()) {
|
||||||
let promise = recorderBackend.createLevelMeter(device).then(meter => {
|
let createLevelMeter;
|
||||||
meter.setObserver(level => {
|
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) {
|
if (levelMeterInitializePromises[device.deviceId] !== promise) {
|
||||||
/* old level meter */
|
/* old level meter */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
deviceLevelInfo[device.deviceId] = {
|
deviceLevelInfo[device.deviceId] = {
|
||||||
deviceId: device.deviceId,
|
deviceId: device.deviceId,
|
||||||
status: "success",
|
status: "error",
|
||||||
level: level
|
|
||||||
|
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);
|
levelMeterInitializePromises[device.deviceId] = promise;
|
||||||
}).catch(error => {
|
} else {
|
||||||
if (levelMeterInitializePromises[device.deviceId] !== promise) {
|
|
||||||
/* old level meter */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
deviceLevelInfo[device.deviceId] = {
|
deviceLevelInfo[device.deviceId] = {
|
||||||
deviceId: device.deviceId,
|
deviceId: device.deviceId,
|
||||||
status: "error",
|
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<Micropho
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectedDevice = event.selectedDevice;
|
||||||
updateLevelMeter();
|
updateLevelMeter();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -167,6 +207,15 @@ export function initialize_audio_microphone_controller(events: Registry<Micropho
|
||||||
destroyLevelIndicators();
|
destroyLevelIndicators();
|
||||||
clearInterval(deviceLevelUpdateTask);
|
clearInterval(deviceLevelUpdateTask);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
events.on("notify_device_selected", event => {
|
||||||
|
if(_.isEqual(selectedDevice, event.device)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedDevice = event.device;
|
||||||
|
updateLevelMeter();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* device list */
|
/* device list */
|
||||||
|
|
|
@ -52,6 +52,7 @@ const ActivityBar = (props: { events: Registry<MicrophoneSettingsEvents>, device
|
||||||
}
|
}
|
||||||
|
|
||||||
props.events.reactUse("notify_device_level", event => {
|
props.events.reactUse("notify_device_level", event => {
|
||||||
|
refHider.current.style.width = "100%";
|
||||||
if (event.status === "uninitialized") {
|
if (event.status === "uninitialized") {
|
||||||
if (status.mode === "uninitialized") {
|
if (status.mode === "uninitialized") {
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Add table
Reference in a new issue