diff --git a/react/features/base/lib-jitsi-meet/actions.js b/react/features/base/lib-jitsi-meet/actions.js
index 734bb55f7..aa97ae36d 100644
--- a/react/features/base/lib-jitsi-meet/actions.js
+++ b/react/features/base/lib-jitsi-meet/actions.js
@@ -34,7 +34,7 @@ export function disposeLib() {
*/
export function initLib() {
return (dispatch, getState) => {
- const config = getState()['features/base/lib'].config;
+ const config = getState()['features/base/lib-jitsi-meet'].config;
if (!config) {
throw new Error('Cannot initialize lib-jitsi-meet without config');
diff --git a/react/features/base/lib-jitsi-meet/middleware.js b/react/features/base/lib-jitsi-meet/middleware.js
index cd8674d94..05ec87da6 100644
--- a/react/features/base/lib-jitsi-meet/middleware.js
+++ b/react/features/base/lib-jitsi-meet/middleware.js
@@ -19,26 +19,23 @@ import { SET_CONFIG } from './actionTypes';
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case PARTICIPANT_LEFT:
- if (action.participant.local) {
- store.dispatch(disposeLib());
- }
+ action.participant.local && store.dispatch(disposeLib());
break;
case SET_CONFIG: {
const { dispatch, getState } = store;
- const libInitialized = getState()['features/base/lib'].initialized;
+ const initialized
+ = getState()['features/base/lib-jitsi-meet'].initialized;
// XXX If we already have config, that means new config is coming, which
// means that we should dispose instance of lib initialized with
// previous config first.
// TODO Currently 'disposeLib' actually does not dispose lib-jitsi-meet.
// This functionality should be implemented.
- const promise = libInitialized
- ? dispatch(disposeLib())
- : Promise.resolve();
+ const promise
+ = initialized ? dispatch(disposeLib()) : Promise.resolve();
- promise
- .then(dispatch(initLib()));
+ promise.then(dispatch(initLib()));
break;
}
diff --git a/react/features/base/lib-jitsi-meet/reducer.js b/react/features/base/lib-jitsi-meet/reducer.js
index 995d6f65d..0a7304561 100644
--- a/react/features/base/lib-jitsi-meet/reducer.js
+++ b/react/features/base/lib-jitsi-meet/reducer.js
@@ -8,7 +8,7 @@ import {
} from './actionTypes';
/**
- * Initial state of 'features/base/lib'.
+ * Initial state of 'features/base/lib-jitsi-meet'.
*
* @type {{
* initializationError: null,
@@ -31,7 +31,7 @@ const INITIAL_STATE = {
};
ReducerRegistry.register(
- 'features/base/lib',
+ 'features/base/lib-jitsi-meet',
(state = INITIAL_STATE, action) => {
switch (action.type) {
case LIB_DISPOSED:
diff --git a/react/features/base/media/middleware.js b/react/features/base/media/middleware.js
index 51dec59fb..6b88d4f52 100644
--- a/react/features/base/media/middleware.js
+++ b/react/features/base/media/middleware.js
@@ -42,15 +42,10 @@ function resetInitialMediaState(store) {
const { dispatch, getState } = store;
const state = getState()['features/base/media'];
- if (state.audio.muted) {
- dispatch(audioMutedChanged(false));
- }
- if (state.video.facingMode !== CAMERA_FACING_MODE.USER) {
- dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
- }
- if (state.video.muted) {
- dispatch(videoMutedChanged(false));
- }
+ state.audio.muted && dispatch(audioMutedChanged(false));
+ (state.video.facingMode !== CAMERA_FACING_MODE.USER)
+ && dispatch(cameraFacingModeChanged(CAMERA_FACING_MODE.USER));
+ state.video.muted && dispatch(videoMutedChanged(false));
}
/**
diff --git a/react/features/base/tracks/functions.js b/react/features/base/tracks/functions.js
index 29fdb39be..f92a5aade 100644
--- a/react/features/base/tracks/functions.js
+++ b/react/features/base/tracks/functions.js
@@ -72,14 +72,18 @@ export function getTracksByMediaType(tracks, mediaType) {
}
/**
- * Mute or unmute local track if any.
+ * Mutes or unmutes a specific JitsiLocalTrack. If the muted state of
+ * the specified track is already in accord with the specified
+ * muted value, then does nothing.
*
- * @param {JitsiLocalTrack} track - Track instance.
- * @param {boolean} muted - If audio stream should be muted or unmuted.
+ * @param {JitsiLocalTrack} track - The JitsiLocalTrack to mute or
+ * unmute.
+ * @param {boolean} muted - If the specified track is to be muted, then
+ * true; otherwise, false.
* @returns {Promise}
*/
export function setTrackMuted(track, muted) {
- if (!track) {
+ if (track.isMuted() === muted) {
return Promise.resolve();
}
diff --git a/react/features/base/tracks/middleware.js b/react/features/base/tracks/middleware.js
index 90c5ecea3..75a871c37 100644
--- a/react/features/base/tracks/middleware.js
+++ b/react/features/base/tracks/middleware.js
@@ -4,9 +4,11 @@ import {
} from '../lib-jitsi-meet';
import {
AUDIO_MUTED_CHANGED,
+ audioMutedChanged,
CAMERA_FACING_MODE_CHANGED,
MEDIA_TYPE,
- VIDEO_MUTED_CHANGED
+ VIDEO_MUTED_CHANGED,
+ videoMutedChanged
} from '../media';
import { MiddlewareRegistry } from '../redux';
@@ -14,6 +16,7 @@ import {
createLocalTracks,
destroyLocalTracks
} from './actions';
+import { TRACK_UPDATED } from './actionTypes';
import {
getLocalTrack,
setTrackMuted
@@ -50,6 +53,9 @@ MiddlewareRegistry.register(store => next => action => {
store.dispatch(destroyLocalTracks());
break;
+ case TRACK_UPDATED:
+ return _trackUpdated(store, next, action);
+
case VIDEO_MUTED_CHANGED:
_mutedChanged(store, action, MEDIA_TYPE.VIDEO);
break;
@@ -58,6 +64,22 @@ MiddlewareRegistry.register(store => next => action => {
return next(action);
});
+/**
+ * Gets the local track associated with a specific MEDIA_TYPE in a
+ * specific Redux store.
+ *
+ * @param {Store} store - The Redux store from which the local track associated
+ * with the specified mediaType is to be retrieved.
+ * @param {MEDIA_TYPE} mediaType - The MEDIA_TYPE of the local track to
+ * be retrieved from the specified store.
+ * @private
+ * @returns {Track} The local Track associated with the specified
+ * mediaType in the specified store.
+ */
+function _getLocalTrack(store, mediaType) {
+ return getLocalTrack(store.getState()['features/base/tracks'], mediaType);
+}
+
/**
* Mutes or unmutes a local track with a specific media type.
*
@@ -70,8 +92,67 @@ MiddlewareRegistry.register(store => next => action => {
* @returns {void}
*/
function _mutedChanged(store, action, mediaType) {
- const tracks = store.getState()['features/base/tracks'];
- const localTrack = getLocalTrack(tracks, mediaType);
+ const localTrack = _getLocalTrack(store, mediaType);
localTrack && setTrackMuted(localTrack.jitsiTrack, action.muted);
}
+
+/**
+ * Intercepts the action TRACK_UPDATED in order to synchronize the
+ * muted states of the local tracks of features/base/tracks with the muted
+ * states of features/base/media.
+ *
+ * @param {Store} store - The Redux store in which the specified action
+ * is being dispatched.
+ * @param {Dispatch} next - The Redux dispatch function to dispatch the
+ * specified action to the specified store.
+ * @param {Action} action - The Redux action TRACK_UPDATED which is
+ * being dispatched in the specified store.
+ * @private
+ * @returns {void}
+ */
+function _trackUpdated(store, next, action) {
+ // Determine the muted state of the local track before the update.
+ const track = action.track;
+ let mediaType;
+ let oldMuted;
+
+ if ('muted' in track) {
+ // XXX The return value of JitsiTrack.getType() is of type MEDIA_TYPE
+ // that happens to be compatible with the type MEDIA_TYPE defined by
+ // jitsi-meet-react.
+ mediaType = track.jitsiTrack.getType();
+
+ const localTrack = _getLocalTrack(store, mediaType);
+
+ if (localTrack) {
+ oldMuted = localTrack.muted;
+ }
+ }
+
+ const result = next(action);
+
+ if (typeof oldMuted !== 'undefined') {
+ // Determine the muted state of the local track after the update. If the
+ // muted states before and after the update differ, then the respective
+ // media state should by synchronized.
+ const localTrack = _getLocalTrack(store, mediaType);
+
+ if (localTrack) {
+ const newMuted = localTrack.muted;
+
+ if (oldMuted !== newMuted) {
+ switch (mediaType) {
+ case MEDIA_TYPE.AUDIO:
+ store.dispatch(audioMutedChanged(newMuted));
+ break;
+ case MEDIA_TYPE.VIDEO:
+ store.dispatch(videoMutedChanged(newMuted));
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
diff --git a/react/features/largeVideo/middleware.js b/react/features/largeVideo/middleware.js
index 2c91237fd..374428096 100644
--- a/react/features/largeVideo/middleware.js
+++ b/react/features/largeVideo/middleware.js
@@ -49,9 +49,8 @@ MiddlewareRegistry.register(store => next => action => {
action.track.jitsiTrack);
const participantId = state['features/largeVideo'].participantId;
- if (track.participantId === participantId) {
- store.dispatch(selectParticipant());
- }
+ (track.participantId === participantId)
+ && store.dispatch(selectParticipant());
}
break;
}