Adds new persistent state for devices user selection.
The state about currently opened devices is filtered and not stored, where we only store when user selects a device preferences. Also allow changing input devices for Firefox when we are not in a conference.
This commit is contained in:
parent
2d45709a6a
commit
740c1eb84f
|
@ -2394,7 +2394,15 @@ export default {
|
|||
: this.useVideoStream.bind(this);
|
||||
|
||||
// Use the new stream or null if we failed to obtain it.
|
||||
return useStream(tracks.find(track => track.getType() === mediaType) || null);
|
||||
return useStream(tracks.find(track => track.getType() === mediaType) || null)
|
||||
.then(() => {
|
||||
const settings
|
||||
= mediaType === 'audio'
|
||||
? { micDeviceId: newDevices.audioinput }
|
||||
: { cameraDeviceId: newDevices.videoinput };
|
||||
|
||||
APP.store.dispatch(updateSettings(settings));
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
|
|
|
@ -39,7 +39,7 @@ function getNewAudioInputDevice(newDevices, localAudio) {
|
|||
const availableAudioInputDevices = newDevices.filter(
|
||||
d => d.kind === 'audioinput');
|
||||
const settings = APP.store.getState()['features/base/settings'];
|
||||
const selectedAudioInputDeviceId = settings.micDeviceId;
|
||||
const selectedAudioInputDeviceId = settings.userSelectedMicDeviceId;
|
||||
const selectedAudioInputDevice = availableAudioInputDevices.find(
|
||||
d => d.deviceId === selectedAudioInputDeviceId);
|
||||
|
||||
|
@ -78,7 +78,7 @@ function getNewVideoInputDevice(newDevices, localVideo) {
|
|||
const availableVideoInputDevices = newDevices.filter(
|
||||
d => d.kind === 'videoinput');
|
||||
const settings = APP.store.getState()['features/base/settings'];
|
||||
const selectedVideoInputDeviceId = settings.cameraDeviceId;
|
||||
const selectedVideoInputDeviceId = settings.userSelectedCameraDeviceId;
|
||||
const selectedVideoInputDevice = availableVideoInputDevices.find(
|
||||
d => d.deviceId === selectedVideoInputDeviceId);
|
||||
|
||||
|
|
|
@ -90,10 +90,10 @@ export function configureInitialDevices() {
|
|||
|
||||
return updateSettingsPromise
|
||||
.then(() => {
|
||||
const { audioOutputDeviceId }
|
||||
const { userSelectedAudioOutputDeviceId }
|
||||
= getState()['features/base/settings'];
|
||||
|
||||
return setAudioOutputDeviceId(audioOutputDeviceId, dispatch)
|
||||
return setAudioOutputDeviceId(userSelectedAudioOutputDeviceId, dispatch)
|
||||
.catch(ex => logger.warn(`Failed to set audio output device.
|
||||
Default audio output device will be used instead ${ex}`));
|
||||
});
|
||||
|
|
|
@ -117,14 +117,27 @@ export function groupDevicesByKind(devices: Object[]): Object {
|
|||
*
|
||||
* @param {string} newId - New audio output device id.
|
||||
* @param {Function} dispatch - The Redux dispatch function.
|
||||
* @param {boolean} userSelection - Whether this is a user selection update.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
export function setAudioOutputDeviceId(
|
||||
newId: string = 'default',
|
||||
dispatch: Function): Promise<*> {
|
||||
dispatch: Function,
|
||||
userSelection: boolean = false): Promise<*> {
|
||||
return JitsiMeetJS.mediaDevices.setAudioOutputDevice(newId)
|
||||
.then(() =>
|
||||
dispatch(updateSettings({
|
||||
audioOutputDeviceId: newId
|
||||
})));
|
||||
.then(() => {
|
||||
const newSettings = {
|
||||
audioOutputDeviceId: newId,
|
||||
userSelectedAudioOutputDeviceId: undefined
|
||||
};
|
||||
|
||||
if (userSelection) {
|
||||
newSettings.userSelectedAudioOutputDeviceId = newId;
|
||||
} else {
|
||||
// a flow workaround, I needed to add 'userSelectedAudioOutputDeviceId: undefined'
|
||||
delete newSettings.userSelectedAudioOutputDeviceId;
|
||||
}
|
||||
|
||||
return dispatch(updateSettings(newSettings));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -30,7 +30,10 @@ const DEFAULT_STATE = {
|
|||
serverURL: undefined,
|
||||
startAudioOnly: false,
|
||||
startWithAudioMuted: false,
|
||||
startWithVideoMuted: false
|
||||
startWithVideoMuted: false,
|
||||
userSelectedAudioOutputDeviceId: undefined,
|
||||
userSelectedCameraDeviceId: undefined,
|
||||
userSelectedMicDeviceId: undefined
|
||||
};
|
||||
|
||||
const STORE_NAME = 'features/base/settings';
|
||||
|
@ -38,7 +41,20 @@ const STORE_NAME = 'features/base/settings';
|
|||
/**
|
||||
* Sets up the persistence of the feature {@code base/settings}.
|
||||
*/
|
||||
PersistenceRegistry.register(STORE_NAME);
|
||||
const filterSubtree = {};
|
||||
|
||||
// start with the default state
|
||||
Object.keys(DEFAULT_STATE).forEach(key => {
|
||||
filterSubtree[key] = true;
|
||||
});
|
||||
|
||||
// we want to filter these props, to not be stored as they represent
|
||||
// what is currently opened/used as devices
|
||||
filterSubtree.audioOutputDeviceId = false;
|
||||
filterSubtree.cameraDeviceId = false;
|
||||
filterSubtree.micDeviceId = false;
|
||||
|
||||
PersistenceRegistry.register(STORE_NAME, filterSubtree);
|
||||
|
||||
ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
|
|
|
@ -40,10 +40,10 @@ export function createLocalTracksF(
|
|||
const settings = store.getState()['features/base/settings'];
|
||||
|
||||
if (typeof cameraDeviceId === 'undefined' || cameraDeviceId === null) {
|
||||
cameraDeviceId = settings.cameraDeviceId;
|
||||
cameraDeviceId = settings.userSelectedCameraDeviceId;
|
||||
}
|
||||
if (typeof micDeviceId === 'undefined' || micDeviceId === null) {
|
||||
micDeviceId = settings.micDeviceId;
|
||||
micDeviceId = settings.userSelectedMicDeviceId;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -112,7 +112,8 @@ export function submitDeviceSelectionTab(newState) {
|
|||
&& newState.selectedVideoInputId
|
||||
!== currentState.selectedVideoInputId) {
|
||||
dispatch(updateSettings({
|
||||
cameraDeviceId: newState.selectedVideoInputId
|
||||
cameraDeviceId: newState.selectedVideoInputId,
|
||||
userSelectedCameraDeviceId: newState.selectedVideoInputId
|
||||
}));
|
||||
|
||||
dispatch(
|
||||
|
@ -123,7 +124,8 @@ export function submitDeviceSelectionTab(newState) {
|
|||
&& newState.selectedAudioInputId
|
||||
!== currentState.selectedAudioInputId) {
|
||||
dispatch(updateSettings({
|
||||
micDeviceId: newState.selectedAudioInputId
|
||||
micDeviceId: newState.selectedAudioInputId,
|
||||
userSelectedMicDeviceId: newState.selectedAudioInputId
|
||||
}));
|
||||
|
||||
dispatch(
|
||||
|
@ -137,7 +139,8 @@ export function submitDeviceSelectionTab(newState) {
|
|||
|
||||
setAudioOutputDeviceId(
|
||||
newState.selectedAudioOutputId,
|
||||
dispatch)
|
||||
dispatch,
|
||||
true)
|
||||
.then(() => logger.log('changed audio output device'))
|
||||
.catch(err => {
|
||||
logger.warn(
|
||||
|
|
|
@ -26,20 +26,37 @@ import { toState } from '../base/redux';
|
|||
export function getDeviceSelectionDialogProps(stateful: Object | Function) {
|
||||
const state = toState(stateful);
|
||||
const settings = state['features/base/settings'];
|
||||
const { conference } = state['features/base/conference'];
|
||||
let disableAudioInputChange = !JitsiMeetJS.mediaDevices.isMultipleAudioInputSupported();
|
||||
let selectedAudioInputId = settings.micDeviceId;
|
||||
let selectedAudioOutputId = getAudioOutputDeviceId();
|
||||
let selectedVideoInputId = settings.cameraDeviceId;
|
||||
|
||||
// audio input change will be a problem only when we are in a
|
||||
// conference and this is not supported, when we open device selection on
|
||||
// welcome page changing input devices will not be a problem
|
||||
// on welcome page we also show only what we have saved as user selected devices
|
||||
if (!conference) {
|
||||
disableAudioInputChange = false;
|
||||
selectedAudioInputId = settings.userSelectedMicDeviceId;
|
||||
selectedAudioOutputId = settings.userSelectedAudioOutputDeviceId;
|
||||
selectedVideoInputId = settings.userSelectedCameraDeviceId;
|
||||
}
|
||||
|
||||
// we fill the device selection dialog with the devices that are currently
|
||||
// used or if none are currently used with what we have in settings(user selected)
|
||||
return {
|
||||
availableDevices: state['features/base/devices'].availableDevices,
|
||||
disableAudioInputChange:
|
||||
!JitsiMeetJS.isMultipleAudioInputSupported(),
|
||||
disableAudioInputChange,
|
||||
disableDeviceChange:
|
||||
!JitsiMeetJS.mediaDevices.isDeviceChangeAvailable(),
|
||||
hideAudioInputPreview:
|
||||
!JitsiMeetJS.isCollectingLocalStats(),
|
||||
hideAudioOutputSelect: !JitsiMeetJS.mediaDevices
|
||||
.isDeviceChangeAvailable('output'),
|
||||
selectedAudioInputId: settings.micDeviceId,
|
||||
selectedAudioOutputId: getAudioOutputDeviceId(),
|
||||
selectedVideoInputId: settings.cameraDeviceId
|
||||
selectedAudioInputId,
|
||||
selectedAudioOutputId,
|
||||
selectedVideoInputId
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue