This commit is contained in:
9
react/features/noise-suppression/actionTypes.ts
Normal file
9
react/features/noise-suppression/actionTypes.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Type of action which sets the current state of noise suppression.
|
||||
*
|
||||
* {
|
||||
* type: SET_NOISE_SUPPRESSION_ENABLED,
|
||||
* enabled: boolean
|
||||
* }
|
||||
*/
|
||||
export const SET_NOISE_SUPPRESSION_ENABLED = 'SET_NOISE_SUPPRESSION_ENABLED';
|
||||
98
react/features/noise-suppression/actions.ts
Normal file
98
react/features/noise-suppression/actions.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
import { IStore } from '../app/types';
|
||||
import { getLocalJitsiAudioTrack } from '../base/tracks/functions';
|
||||
import { showErrorNotification } from '../notifications/actions';
|
||||
import { NoiseSuppressionEffect } from '../stream-effects/noise-suppression/NoiseSuppressionEffect';
|
||||
|
||||
import { SET_NOISE_SUPPRESSION_ENABLED } from './actionTypes';
|
||||
import { canEnableNoiseSuppression, isNoiseSuppressionEnabled } from './functions';
|
||||
import logger from './logger';
|
||||
|
||||
/**
|
||||
* Updates the noise suppression active state.
|
||||
*
|
||||
* @param {boolean} enabled - Is noise suppression enabled.
|
||||
* @returns {{
|
||||
* type: SET_NOISE_SUPPRESSION_STATE,
|
||||
* enabled: boolean
|
||||
* }}
|
||||
*/
|
||||
export function setNoiseSuppressionEnabledState(enabled: boolean): any {
|
||||
return {
|
||||
type: SET_NOISE_SUPPRESSION_ENABLED,
|
||||
enabled
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Enabled/disable noise suppression depending on the current state.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function toggleNoiseSuppression(): any {
|
||||
return (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
if (isNoiseSuppressionEnabled(getState())) {
|
||||
dispatch(setNoiseSuppressionEnabled(false));
|
||||
} else {
|
||||
dispatch(setNoiseSuppressionEnabled(true));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to enable or disable noise suppression using the {@link NoiseSuppressionEffect}.
|
||||
*
|
||||
* @param {boolean} enabled - Enable or disable noise suppression.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
export function setNoiseSuppressionEnabled(enabled: boolean): any {
|
||||
return async (dispatch: IStore['dispatch'], getState: IStore['getState']) => {
|
||||
const state = getState();
|
||||
|
||||
const { noiseSuppression: nsOptions } = state['features/base/config'];
|
||||
const localAudio = getLocalJitsiAudioTrack(state);
|
||||
const noiseSuppressionEnabled = isNoiseSuppressionEnabled(state);
|
||||
|
||||
logger.info(`Attempting to set noise suppression enabled state: ${enabled}`);
|
||||
|
||||
if (enabled === noiseSuppressionEnabled) {
|
||||
logger.warn(`Noise suppression enabled state already: ${enabled}`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is no local audio, simply set the enabled state. Once an audio track is created
|
||||
// the effects list will be applied.
|
||||
if (!localAudio) {
|
||||
dispatch(setNoiseSuppressionEnabledState(enabled));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (enabled) {
|
||||
if (!canEnableNoiseSuppression(state, dispatch, localAudio)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await localAudio.setEffect(new NoiseSuppressionEffect(nsOptions));
|
||||
dispatch(setNoiseSuppressionEnabledState(true));
|
||||
logger.info('Noise suppression enabled.');
|
||||
|
||||
} else {
|
||||
await localAudio.setEffect(undefined);
|
||||
dispatch(setNoiseSuppressionEnabledState(false));
|
||||
logger.info('Noise suppression disabled.');
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to set noise suppression enabled to: ${enabled}`,
|
||||
error
|
||||
);
|
||||
|
||||
dispatch(showErrorNotification({
|
||||
titleKey: 'notify.noiseSuppressionFailedTitle'
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import { IReduxState } from '../../app/types';
|
||||
import { translate } from '../../base/i18n/functions';
|
||||
import {
|
||||
IconNoiseSuppressionOff,
|
||||
IconNoiseSuppressionOn
|
||||
} from '../../base/icons/svg';
|
||||
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
|
||||
import { setOverflowMenuVisible } from '../../toolbox/actions';
|
||||
import { toggleNoiseSuppression } from '../actions';
|
||||
import { isNoiseSuppressionEnabled } from '../functions';
|
||||
|
||||
interface IProps extends AbstractButtonProps {
|
||||
_isNoiseSuppressionEnabled?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component that renders a toolbar button for toggling noise suppression.
|
||||
*/
|
||||
class NoiseSuppressionButton extends AbstractButton<IProps> {
|
||||
override accessibilityLabel = 'toolbar.accessibilityLabel.noiseSuppression';
|
||||
override icon = IconNoiseSuppressionOn;
|
||||
override label = 'toolbar.noiseSuppression';
|
||||
override tooltip = 'toolbar.noiseSuppression';
|
||||
override toggledIcon = IconNoiseSuppressionOff;
|
||||
override toggledLabel = 'toolbar.disableNoiseSuppression';
|
||||
|
||||
/**
|
||||
* Handles clicking / pressing the button.
|
||||
*
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
override _handleClick() {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(toggleNoiseSuppression());
|
||||
dispatch(setOverflowMenuVisible(false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this button is in toggled state or not.
|
||||
*
|
||||
* @override
|
||||
* @protected
|
||||
* @returns {boolean}
|
||||
*/
|
||||
override _isToggled() {
|
||||
return this.props._isNoiseSuppressionEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps part of the Redux state to the props of this component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @private
|
||||
* @returns {IProps}
|
||||
*/
|
||||
function _mapStateToProps(state: IReduxState) {
|
||||
return {
|
||||
_isNoiseSuppressionEnabled: isNoiseSuppressionEnabled(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default translate(connect(_mapStateToProps)(NoiseSuppressionButton));
|
||||
49
react/features/noise-suppression/functions.ts
Normal file
49
react/features/noise-suppression/functions.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { IReduxState, IStore } from '../app/types';
|
||||
import { showWarningNotification } from '../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants';
|
||||
import { isScreenAudioShared } from '../screen-share/functions';
|
||||
|
||||
/**
|
||||
* Is noise suppression currently enabled.
|
||||
*
|
||||
* @param {IReduxState} state - The state of the application.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isNoiseSuppressionEnabled(state: IReduxState): boolean {
|
||||
return state['features/noise-suppression'].enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify if noise suppression can be enabled in the current state.
|
||||
*
|
||||
* @param {*} state - Redux state.
|
||||
* @param {*} dispatch - Redux dispatch.
|
||||
* @param {*} localAudio - Current local audio track.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function canEnableNoiseSuppression(state: IReduxState, dispatch: IStore['dispatch'], localAudio: any): boolean {
|
||||
const { channelCount } = localAudio.track.getSettings();
|
||||
|
||||
// Sharing screen audio implies an effect being applied to the local track, because currently we don't support
|
||||
// more then one effect at a time the user has to choose between sharing audio or having noise suppression active.
|
||||
if (isScreenAudioShared(state)) {
|
||||
dispatch(showWarningNotification({
|
||||
titleKey: 'notify.noiseSuppressionFailedTitle',
|
||||
descriptionKey: 'notify.noiseSuppressionDesktopAudioDescription'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stereo audio tracks aren't currently supported, make sure the current local track is mono
|
||||
if (channelCount > 1) {
|
||||
dispatch(showWarningNotification({
|
||||
titleKey: 'notify.noiseSuppressionFailedTitle',
|
||||
descriptionKey: 'notify.noiseSuppressionStereoDescription'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.MEDIUM));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
3
react/features/noise-suppression/logger.ts
Normal file
3
react/features/noise-suppression/logger.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { getLogger } from '../base/logging/functions';
|
||||
|
||||
export default getLogger('features/noise-suppression');
|
||||
36
react/features/noise-suppression/reducer.ts
Normal file
36
react/features/noise-suppression/reducer.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import PersistenceRegistry from '../base/redux/PersistenceRegistry';
|
||||
import ReducerRegistry from '../base/redux/ReducerRegistry';
|
||||
|
||||
import {
|
||||
SET_NOISE_SUPPRESSION_ENABLED
|
||||
} from './actionTypes';
|
||||
|
||||
export interface INoiseSuppressionState {
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
const STORE_NAME = 'features/noise-suppression';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
enabled: false
|
||||
};
|
||||
|
||||
PersistenceRegistry.register(STORE_NAME);
|
||||
|
||||
/**
|
||||
* Reduces the Redux actions of the feature features/noise-suppression.
|
||||
*/
|
||||
ReducerRegistry.register<INoiseSuppressionState>(STORE_NAME,
|
||||
(state = DEFAULT_STATE, action): INoiseSuppressionState => {
|
||||
const { enabled } = action;
|
||||
|
||||
switch (action.type) {
|
||||
case SET_NOISE_SUPPRESSION_ENABLED:
|
||||
return {
|
||||
...state,
|
||||
enabled
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user