ref(video-quality): update video quality post redux update
Move away from middleware and instead update video quality when the selected video quality updates in redux. This also lead to removing of automatically exiting audio only because with the change it's not so readily possible to tell if the user switched off audio only by re-selecting the already preferred video quality. Removing this automagic removed some additional checking done for mobile.
This commit is contained in:
parent
ee7d180cbb
commit
0b1224495b
|
@ -17,7 +17,7 @@ import {
|
||||||
getPinnedParticipant,
|
getPinnedParticipant,
|
||||||
PIN_PARTICIPANT
|
PIN_PARTICIPANT
|
||||||
} from '../participants';
|
} from '../participants';
|
||||||
import { MiddlewareRegistry } from '../redux';
|
import { MiddlewareRegistry, StateListenerRegistry } from '../redux';
|
||||||
import UIEvents from '../../../../service/UI/UIEvents';
|
import UIEvents from '../../../../service/UI/UIEvents';
|
||||||
import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';
|
import { TRACK_ADDED, TRACK_REMOVED } from '../tracks';
|
||||||
|
|
||||||
|
@ -25,8 +25,7 @@ import {
|
||||||
conferenceFailed,
|
conferenceFailed,
|
||||||
conferenceLeft,
|
conferenceLeft,
|
||||||
createConference,
|
createConference,
|
||||||
setLastN,
|
setLastN
|
||||||
toggleAudioOnly
|
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import {
|
import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
|
@ -34,8 +33,6 @@ import {
|
||||||
DATA_CHANNEL_OPENED,
|
DATA_CHANNEL_OPENED,
|
||||||
SET_AUDIO_ONLY,
|
SET_AUDIO_ONLY,
|
||||||
SET_LASTN,
|
SET_LASTN,
|
||||||
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
|
||||||
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
|
||||||
SET_ROOM
|
SET_ROOM
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import {
|
import {
|
||||||
|
@ -81,12 +78,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case SET_LASTN:
|
case SET_LASTN:
|
||||||
return _setLastN(store, next, action);
|
return _setLastN(store, next, action);
|
||||||
|
|
||||||
case SET_MAX_RECEIVER_VIDEO_QUALITY:
|
|
||||||
return _setMaximumReceiverVideoQuality(store, next, action);
|
|
||||||
|
|
||||||
case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
|
|
||||||
return _setPreferredReceiverVideoQuality(store, next, action);
|
|
||||||
|
|
||||||
case SET_ROOM:
|
case SET_ROOM:
|
||||||
return _setRoom(store, next, action);
|
return _setRoom(store, next, action);
|
||||||
|
|
||||||
|
@ -98,6 +89,32 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
return next(action);
|
return next(action);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a change handler for state['features/base/conference'] to update
|
||||||
|
* the preferred video quality levels based on user preferred and internal
|
||||||
|
* settings.
|
||||||
|
*/
|
||||||
|
StateListenerRegistry.register(
|
||||||
|
/* selector */ state => state['features/base/conference'],
|
||||||
|
/* listener */ (currentState, store, previousState = {}) => {
|
||||||
|
const {
|
||||||
|
conference,
|
||||||
|
maxReceiverVideoQuality,
|
||||||
|
preferredReceiverVideoQuality
|
||||||
|
} = currentState;
|
||||||
|
const changedPreferredVideoQuality = preferredReceiverVideoQuality
|
||||||
|
!== previousState.preferredReceiverVideoQuality;
|
||||||
|
const changedMaxVideoQuality = maxReceiverVideoQuality
|
||||||
|
!== previousState.maxReceiverVideoQuality;
|
||||||
|
|
||||||
|
if (changedPreferredVideoQuality || changedMaxVideoQuality) {
|
||||||
|
_setReceiverVideoConstraint(
|
||||||
|
conference,
|
||||||
|
preferredReceiverVideoQuality,
|
||||||
|
maxReceiverVideoQuality);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure to leave a failed conference in order to release any allocated
|
* Makes sure to leave a failed conference in order to release any allocated
|
||||||
* resources like peer connections, emit participant left events, etc.
|
* resources like peer connections, emit participant left events, etc.
|
||||||
|
@ -438,73 +455,22 @@ function _setLastN({ getState }, next, action) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets an internal maximum for the video frame height to receive from remote
|
* Helper function for updating the preferred receiver video constraint, based
|
||||||
* videos. This maximum acts as a cap so user preferences cannot exceed a
|
* on the user preference and the internal maximum.
|
||||||
* specified frame height.
|
|
||||||
*
|
*
|
||||||
* @private
|
* @param {JitsiConference} conference - The JitsiConference instance for the
|
||||||
* @param {Store} store - The redux store in which the specified {@code action}
|
* current call.
|
||||||
* is being dispatched.
|
* @param {number} preferred - The user preferred max frame height.
|
||||||
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
* @param {number} max - The maximum frame height the application should
|
||||||
* specified {@code action} to the specified {@code store}.
|
* receive.
|
||||||
* @param {Action} action - The redux action
|
* @returns {void}
|
||||||
* {@code SET_MAXIMUM_RECEIVER_VIDEO_QUALITY} which is being dispatched in the
|
|
||||||
* specified {@code store}.
|
|
||||||
* @private
|
|
||||||
* @returns {Object} The value returned by {@code next(action)}.
|
|
||||||
*/
|
*/
|
||||||
function _setMaximumReceiverVideoQuality({ getState }, next, action) {
|
function _setReceiverVideoConstraint(conference, preferred, max) {
|
||||||
const { conference, preferredReceiverVideoQuality }
|
|
||||||
= getState()['features/base/conference'];
|
|
||||||
|
|
||||||
if (conference) {
|
if (conference) {
|
||||||
if (typeof preferredReceiverVideoQuality === 'undefined'
|
conference.setReceiverVideoConstraint(Math.min(preferred, max));
|
||||||
|| preferredReceiverVideoQuality > action.maxReceiverVideoQuality) {
|
|
||||||
conference.setReceiverVideoConstraint(
|
|
||||||
action.maxReceiverVideoQuality);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the preferred receive video quality and will turn off audio only mode if
|
|
||||||
* enabled.
|
|
||||||
*
|
|
||||||
* @param {Store} store - The redux store in which the specified {@code action}
|
|
||||||
* is being dispatched.
|
|
||||||
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
|
||||||
* specified {@code action} to the specified {@code store}.
|
|
||||||
* @param {Action} action - The redux action
|
|
||||||
* {@code SET_PREFERRED_RECEIVER_VIDEO_QUALITY} which is being dispatched in the
|
|
||||||
* specified {@code store}.
|
|
||||||
* @private
|
|
||||||
* @returns {Object} The value returned by {@code next(action)}.
|
|
||||||
*/
|
|
||||||
function _setPreferredReceiverVideoQuality(
|
|
||||||
{ dispatch, getState },
|
|
||||||
next,
|
|
||||||
action) {
|
|
||||||
const {
|
|
||||||
audioOnly,
|
|
||||||
conference,
|
|
||||||
maxReceiverVideoQuality
|
|
||||||
} = getState()['features/base/conference'];
|
|
||||||
|
|
||||||
if (conference) {
|
|
||||||
const { preferredReceiverVideoQuality } = action;
|
|
||||||
const targetQuality = typeof maxReceiverVideoQuality === 'undefined'
|
|
||||||
? preferredReceiverVideoQuality
|
|
||||||
: Math.min(maxReceiverVideoQuality, preferredReceiverVideoQuality);
|
|
||||||
|
|
||||||
conference.setReceiverVideoConstraint(targetQuality);
|
|
||||||
audioOnly && dispatch(toggleAudioOnly());
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the feature {@code base/conference} that the redix action
|
* Notifies the feature {@code base/conference} that the redix action
|
||||||
* {@link SET_ROOM} is being dispatched within a specific redux store.
|
* {@link SET_ROOM} is being dispatched within a specific redux store.
|
||||||
|
@ -592,10 +558,16 @@ function _syncConferenceLocalTracksWithState({ getState }, action) {
|
||||||
* @returns {Object} The value returned by {@code next(action)}.
|
* @returns {Object} The value returned by {@code next(action)}.
|
||||||
*/
|
*/
|
||||||
function _syncReceiveVideoQuality({ getState }, next, action) {
|
function _syncReceiveVideoQuality({ getState }, next, action) {
|
||||||
const state = getState()['features/base/conference'];
|
const {
|
||||||
|
conference,
|
||||||
|
maxReceiverVideoQuality,
|
||||||
|
preferredReceiverVideoQuality
|
||||||
|
} = getState()['features/base/conference'];
|
||||||
|
|
||||||
state.conference.setReceiverVideoConstraint(
|
_setReceiverVideoConstraint(
|
||||||
state.preferredReceiverVideoQuality);
|
conference,
|
||||||
|
preferredReceiverVideoQuality,
|
||||||
|
maxReceiverVideoQuality);
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,19 @@ import {
|
||||||
import { VIDEO_QUALITY_LEVELS } from './constants';
|
import { VIDEO_QUALITY_LEVELS } from './constants';
|
||||||
import { isRoomValid } from './functions';
|
import { isRoomValid } from './functions';
|
||||||
|
|
||||||
|
const DEFAULT_STATE = {
|
||||||
|
joining: undefined,
|
||||||
|
maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH,
|
||||||
|
preferredReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listen for actions that contain the conference object, so that it can be
|
* Listen for actions that contain the conference object, so that it can be
|
||||||
* stored for use by other action creators.
|
* stored for use by other action creators.
|
||||||
*/
|
*/
|
||||||
ReducerRegistry.register('features/base/conference', (state = {}, action) => {
|
ReducerRegistry.register(
|
||||||
|
'features/base/conference',
|
||||||
|
(state = DEFAULT_STATE, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case AUTH_STATUS_CHANGED:
|
case AUTH_STATUS_CHANGED:
|
||||||
return _authStatusChanged(state, action);
|
return _authStatusChanged(state, action);
|
||||||
|
@ -80,7 +88,10 @@ ReducerRegistry.register('features/base/conference', (state = {}, action) => {
|
||||||
return _setPassword(state, action);
|
return _setPassword(state, action);
|
||||||
|
|
||||||
case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
|
case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
|
||||||
return _setPreferredReceiverVideoQuality(state, action);
|
return set(
|
||||||
|
state,
|
||||||
|
'preferredReceiverVideoQuality',
|
||||||
|
action.preferredReceiverVideoQuality);
|
||||||
|
|
||||||
case SET_ROOM:
|
case SET_ROOM:
|
||||||
return _setRoom(state, action);
|
return _setRoom(state, action);
|
||||||
|
@ -210,15 +221,7 @@ function _conferenceJoined(state, { conference }) {
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
locked,
|
locked,
|
||||||
passwordRequired: undefined,
|
passwordRequired: undefined
|
||||||
|
|
||||||
/**
|
|
||||||
* The current resolution restraint on receiving remote video. By
|
|
||||||
* default the conference will send the highest level possible.
|
|
||||||
*
|
|
||||||
* @type number
|
|
||||||
*/
|
|
||||||
preferredReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,24 +412,6 @@ function _setPassword(state, { conference, method, password }) {
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reduces a specific Redux action {@code SET_PREFERRED_RECEIVER_VIDEO_QUALITY}
|
|
||||||
* of the feature base/conference.
|
|
||||||
*
|
|
||||||
* @param {Object} state - The Redux state of the feature base/conference.
|
|
||||||
* @param {Action} action - The Redux action of type
|
|
||||||
* {@code SET_PREFERRED_RECEIVER_VIDEO_QUALITY} to reduce.
|
|
||||||
* @private
|
|
||||||
* @returns {Object} The new state of the feature base/conference after the
|
|
||||||
* reduction of the specified action.
|
|
||||||
*/
|
|
||||||
function _setPreferredReceiverVideoQuality(state, action) {
|
|
||||||
return set(
|
|
||||||
state,
|
|
||||||
'preferredReceiverVideoQuality',
|
|
||||||
action.preferredReceiverVideoQuality);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces a specific Redux action SET_ROOM of the feature base/conference.
|
* Reduces a specific Redux action SET_ROOM of the feature base/conference.
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,16 +22,12 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case SET_REDUCED_UI: {
|
case SET_REDUCED_UI: {
|
||||||
const { dispatch, getState } = store;
|
const { dispatch, getState } = store;
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { audioOnly } = state['features/base/conference'];
|
|
||||||
const { reducedUI } = state['features/base/responsive-ui'];
|
const { reducedUI } = state['features/base/responsive-ui'];
|
||||||
|
|
||||||
dispatch(setToolboxEnabled(!reducedUI));
|
dispatch(setToolboxEnabled(!reducedUI));
|
||||||
dispatch(setFilmstripEnabled(!reducedUI));
|
dispatch(setFilmstripEnabled(!reducedUI));
|
||||||
|
|
||||||
// XXX: Currently setting the received video quality will disable
|
dispatch(
|
||||||
// audio-only mode if engaged, that's why we check for it here.
|
|
||||||
audioOnly
|
|
||||||
|| dispatch(
|
|
||||||
setPreferredReceiverVideoQuality(
|
setPreferredReceiverVideoQuality(
|
||||||
reducedUI
|
reducedUI
|
||||||
? VIDEO_QUALITY_LEVELS.LOW
|
? VIDEO_QUALITY_LEVELS.LOW
|
||||||
|
|
|
@ -284,7 +284,7 @@ class VideoQualitySlider extends Component {
|
||||||
_enableHighDefinition() {
|
_enableHighDefinition() {
|
||||||
sendAnalytics(createEvent('high'));
|
sendAnalytics(createEvent('high'));
|
||||||
logger.log('Video quality: high enabled');
|
logger.log('Video quality: high enabled');
|
||||||
this.props.dispatch(setPreferredReceiverVideoQuality(HIGH));
|
this._setPreferredVideoQuality(HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -297,7 +297,7 @@ class VideoQualitySlider extends Component {
|
||||||
_enableLowDefinition() {
|
_enableLowDefinition() {
|
||||||
sendAnalytics(createEvent('low'));
|
sendAnalytics(createEvent('low'));
|
||||||
logger.log('Video quality: low enabled');
|
logger.log('Video quality: low enabled');
|
||||||
this.props.dispatch(setPreferredReceiverVideoQuality(LOW));
|
this._setPreferredVideoQuality(LOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,7 +310,7 @@ class VideoQualitySlider extends Component {
|
||||||
_enableStandardDefinition() {
|
_enableStandardDefinition() {
|
||||||
sendAnalytics(createEvent('standard'));
|
sendAnalytics(createEvent('standard'));
|
||||||
logger.log('Video quality: standard enabled');
|
logger.log('Video quality: standard enabled');
|
||||||
this.props.dispatch(setPreferredReceiverVideoQuality(STANDARD));
|
this._setPreferredVideoQuality(STANDARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -361,6 +361,23 @@ class VideoQualitySlider extends Component {
|
||||||
|
|
||||||
onSelect();
|
onSelect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper for changing the preferred maximum video quality to receive and
|
||||||
|
* disable audio only.
|
||||||
|
*
|
||||||
|
* @param {number} qualityLevel - The new maximum video quality. Should be
|
||||||
|
* a value enumerated in {@code VIDEO_QUALITY_LEVELS}.
|
||||||
|
* @private
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
_setPreferredVideoQuality(qualityLevel) {
|
||||||
|
this.props.dispatch(setPreferredReceiverVideoQuality(qualityLevel));
|
||||||
|
|
||||||
|
if (this.props._audioOnly) {
|
||||||
|
this.props.dispatch(setAudioOnly(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue