ref(large-video): combine selectParticipant logic from web (#3266)

* ref(large-video): combine selectParticipant logic from web

Currently native/middleware/redux has its own logic for selecting a participant
on the bridge. To have the logic web respect that logic, a few changes are
needed.
- Web no longer has its own call to selectParticipant.
- To keep in line with web logic selectParticipant action should act even when
  there is no track. This makes it so that when a participant does get a track
  that the bridge will send high quality. The bridge can already handle when the
  selected participant does not have a video track.
- The timing of web is such that on joining an existing conference, a
  participant joins and the participant's tracks get updated and then the
  conference is joined. The result is selectParticipant does not get fired
  because it no-ops when there is no conference. To avoid having to make
  uncertain changes (to be lazy), update the selected participant on conference
  join as well.

* squash: update comment, pass message to error handler
This commit is contained in:
virtuacoplenny 2018-07-20 11:19:26 -07:00 committed by yanas
parent c62f761d67
commit afd2aea79c
5 changed files with 28 additions and 36 deletions

View File

@ -7,8 +7,6 @@ import Recorder from './modules/recorder/Recorder';
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper'; import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
import { reportError } from './modules/util/helpers';
import * as RemoteControlEvents import * as RemoteControlEvents
from './service/remotecontrol/RemoteControlEvents'; from './service/remotecontrol/RemoteControlEvents';
import UIEvents from './service/UI/UIEvents'; import UIEvents from './service/UI/UIEvents';
@ -18,7 +16,6 @@ import * as JitsiMeetConferenceEvents from './ConferenceEvents';
import { import {
createDeviceChangedEvent, createDeviceChangedEvent,
createScreenSharingEvent, createScreenSharingEvent,
createSelectParticipantFailedEvent,
createStreamSwitchDelayEvent, createStreamSwitchDelayEvent,
createTrackMutedEvent, createTrackMutedEvent,
sendAnalytics sendAnalytics
@ -1813,24 +1810,6 @@ export default {
room.sendTextMessage(message); room.sendTextMessage(message);
}); });
} }
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, id => {
APP.API.notifyOnStageParticipantChanged(id);
try {
// do not try to select participant if there is none (we
// are alone in the room), otherwise an error will be
// thrown cause reporting mechanism is not available
// (datachannels currently)
if (room.getParticipants().length === 0) {
return;
}
room.selectParticipant(id);
} catch (e) {
sendAnalytics(createSelectParticipantFailedEvent(e));
reportError(e);
}
});
} }
room.on(JitsiConferenceEvents.CONNECTION_INTERRUPTED, () => { room.on(JitsiConferenceEvents.CONNECTION_INTERRUPTED, () => {

View File

@ -960,7 +960,7 @@ const VideoLayout = {
// FIXME video type is not the same thing as container type // FIXME video type is not the same thing as container type
if (id !== currentId && videoType === VIDEO_CONTAINER_TYPE) { if (id !== currentId && videoType === VIDEO_CONTAINER_TYPE) {
eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, id); APP.API.notifyOnStageParticipantChanged(id);
} }
let oldSmallVideo; let oldSmallVideo;

View File

@ -1,14 +1,19 @@
// @flow // @flow
import {
createSelectParticipantFailedEvent,
sendAnalytics
} from '../analytics';
import { _handleParticipantError } from '../base/conference'; import { _handleParticipantError } from '../base/conference';
import { MEDIA_TYPE, VIDEO_TYPE } from '../base/media'; import { MEDIA_TYPE } from '../base/media';
import { getTrackByMediaTypeAndParticipant } from '../base/tracks';
import { import {
SELECT_LARGE_VIDEO_PARTICIPANT, SELECT_LARGE_VIDEO_PARTICIPANT,
UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION UPDATE_KNOWN_LARGE_VIDEO_RESOLUTION
} from './actionTypes'; } from './actionTypes';
declare var APP: Object;
/** /**
* Signals conference to select a participant. * Signals conference to select a participant.
* *
@ -21,22 +26,23 @@ export function selectParticipant() {
if (conference) { if (conference) {
const largeVideo = state['features/large-video']; const largeVideo = state['features/large-video'];
const tracks = state['features/base/tracks'];
const id = largeVideo.participantId; const id = largeVideo.participantId;
const videoTrack
= getTrackByMediaTypeAndParticipant(
tracks,
MEDIA_TYPE.VIDEO,
id);
try { try {
conference.selectParticipant( conference.selectParticipant(id);
videoTrack && videoTrack.videoType === VIDEO_TYPE.CAMERA
? id
: null);
} catch (err) { } catch (err) {
_handleParticipantError(err); _handleParticipantError(err);
sendAnalytics(createSelectParticipantFailedEvent(err));
if (typeof APP === 'object' && window.onerror) {
window.onerror(
`Failed to select participant ${id}`,
null, // source
null, // lineno
null, // colno
err);
}
} }
} }
}; };

View File

@ -1,5 +1,6 @@
// @flow // @flow
import { CONFERENCE_JOINED } from '../base/conference';
import { import {
DOMINANT_SPEAKER_CHANGED, DOMINANT_SPEAKER_CHANGED,
PARTICIPANT_JOINED, PARTICIPANT_JOINED,
@ -46,6 +47,13 @@ MiddlewareRegistry.register(store => next => action => {
store.dispatch(selectParticipantInLargeVideo()); store.dispatch(selectParticipantInLargeVideo());
break; break;
case CONFERENCE_JOINED:
// Ensure a participant is selected on conference join. This addresses
// the case where video tracks were received before CONFERENCE_JOINED
// fired; without the conference selection may not happen.
store.dispatch(selectParticipant());
break;
case TRACK_UPDATED: case TRACK_UPDATED:
// In order to minimize re-calculations, we need to select participant // In order to minimize re-calculations, we need to select participant
// only if the videoType of the current participant rendered in // only if the videoType of the current participant rendered in

View File

@ -1,6 +1,5 @@
export default { export default {
NICKNAME_CHANGED: 'UI.nickname_changed', NICKNAME_CHANGED: 'UI.nickname_changed',
SELECTED_ENDPOINT: 'UI.selected_endpoint',
PINNED_ENDPOINT: 'UI.pinned_endpoint', PINNED_ENDPOINT: 'UI.pinned_endpoint',
/** /**