From 99e7d636b777639172a2cb2133d2f8f061ec2666 Mon Sep 17 00:00:00 2001 From: Vlad Piersec Date: Thu, 25 Jun 2020 13:31:14 +0300 Subject: [PATCH] fix(settings): Always show mic audio levels --- .../web/audio/AudioSettingsContent.js | 96 +++++++++---------- react/features/settings/functions.js | 47 +++++---- 2 files changed, 74 insertions(+), 69 deletions(-) diff --git a/react/features/settings/components/web/audio/AudioSettingsContent.js b/react/features/settings/components/web/audio/AudioSettingsContent.js index ac1d4bde7..a17a00240 100644 --- a/react/features/settings/components/web/audio/AudioSettingsContent.js +++ b/react/features/settings/components/web/audio/AudioSettingsContent.js @@ -4,7 +4,8 @@ import React, { Component } from 'react'; import { translate } from '../../../../base/i18n'; import { IconMicrophoneEmpty, IconVolumeEmpty } from '../../../../base/icons'; -import { createLocalAudioTrack } from '../../../functions'; +import { equals } from '../../../../base/redux'; +import { createLocalAudioTracks } from '../../../functions'; import AudioSettingsHeader from './AudioSettingsHeader'; import MicrophoneEntry from './MicrophoneEntry'; @@ -53,10 +54,10 @@ export type Props = { type State = { /** - * An object containing the jitsiTrack and the error (if the case) - * for the microphone that is in use. + * An list of objects, each containing the microphone label, audio track, device id + * and track error if the case. */ - currentMicData: Object + audioTracks: Object[] } /** @@ -81,10 +82,14 @@ class AudioSettingsContent extends Component { this._onSpeakerEntryClick = this._onSpeakerEntryClick.bind(this); this.state = { - currentMicData: { - error: false, - jitsiTrack: null - } + audioTracks: props.microphoneDevices.map(({ deviceId, label }) => { + return { + deviceId, + hasError: false, + jitsiTrack: null, + label + }; + }) }; } @@ -115,20 +120,13 @@ class AudioSettingsContent extends Component { /** * Renders a single microphone entry. * - * @param {Object} data - An object with the deviceId and label of the microphone. + * @param {Object} data - An object with the deviceId, jitsiTrack & label of the microphone. * @param {number} index - The index of the element, used for creating a key. * @returns {React$Node} */ _renderMicrophoneEntry(data, index) { - const { deviceId, label } = data; - const key = `me-${index}`; + const { deviceId, label, jitsiTrack, hasError } = data; const isSelected = deviceId === this.props.currentMicDeviceId; - let jitsiTrack = null; - let hasError = false; - - if (isSelected) { - ({ jitsiTrack, hasError } = this.state.currentMicData); - } return ( { hasError = { hasError } isSelected = { isSelected } jitsiTrack = { jitsiTrack } - key = { key } + key = { `me-${index}` } onClick = { this._onMicrophoneEntryClick }> {label} @@ -166,50 +164,36 @@ class AudioSettingsContent extends Component { } /** - * Disposes the audio track for a given micData object. - * - * @param {Object} micData - The object holding the track. - * @returns {Promise} - */ - _disposeTrack(micData) { - const { jitsiTrack } = micData; - - return jitsiTrack ? jitsiTrack.dispose() : Promise.resolve(); - } - - /** - * Updates the current microphone data. - * Disposes previously created track and creates a new one. + * Creates and updates the audio tracks. * * @returns {void} */ - async _updateCurrentMicData() { - await this._disposeTrack(this.state.currentMicData); + async _setTracks() { + this._disposeTracks(this.state.audioTracks); - const currentMicData = await createLocalAudioTrack( - this.props.currentMicDeviceId, + const audioTracks = await createLocalAudioTracks( + this.props.microphoneDevices ); - // In case the component gets unmounted before the track is created - // avoid a leak by not setting the state if (this._componentWasUnmounted) { - this._disposeTrack(currentMicData); + this._disposeTracks(audioTracks); } else { this.setState({ - currentMicData + audioTracks }); } } /** - * Implements React's {@link Component#componentDidUpdate}. + * Disposes the audio tracks. * - * @inheritdoc + * @param {Object} audioTracks - The object holding the audio tracks. + * @returns {void} */ - componentDidUpdate(prevProps) { - if (prevProps.currentMicDeviceId !== this.props.currentMicDeviceId) { - this._updateCurrentMicData(); - } + _disposeTracks(audioTracks) { + audioTracks.forEach(({ jitsiTrack }) => { + jitsiTrack && jitsiTrack.dispose(); + }); } /** @@ -218,7 +202,7 @@ class AudioSettingsContent extends Component { * @inheritdoc */ componentDidMount() { - this._updateCurrentMicData(); + this._setTracks(); } /** @@ -228,16 +212,28 @@ class AudioSettingsContent extends Component { */ componentWillUnmount() { this._componentWasUnmounted = true; - this._disposeTrack(this.state.currentMicData); + this._disposeTracks(this.state.audioTracks); } + /** + * Implements React's {@link Component#componentDidUpdate}. + * + * @inheritdoc + */ + componentDidUpdate(prevProps) { + if (!equals(this.props.microphoneDevices, prevProps.microphoneDevices)) { + this._setTracks(); + } + } + + /** * Implements React's {@link Component#render}. * * @inheritdoc */ render() { - const { microphoneDevices, outputDevices, t } = this.props; + const { outputDevices, t } = this.props; return (
@@ -245,7 +241,7 @@ class AudioSettingsContent extends Component { - {microphoneDevices.map((data, i) => + {this.state.audioTracks.map((data, i) => this._renderMicrophoneEntry(data, i), )} } + * @param {Object[]} devices - A list of microphone devices. + * @returns {Promise<{ + * deviceId: string, + * hasError: boolean, + * jitsiTrack: Object, + * label: string + * }[]>} */ -export function createLocalAudioTrack(deviceId: string) { - return createLocalTrack('audio', deviceId) - .then(jitsiTrack => { - return { - hasError: false, - jitsiTrack - }; - }) - .catch(() => { - return { - hasError: true, - jitsiTrack: null - }; - }); +export function createLocalAudioTracks(devices: Object[]) { + return Promise.all( + devices.map(async ({ deviceId, label }) => { + let jitsiTrack = null; + let hasError = false; + + try { + jitsiTrack = await createLocalTrack('audio', deviceId); + } catch (err) { + hasError = true; + } + + return { + deviceId, + hasError, + jitsiTrack, + label + }; + })); } /**