Updates the way we update large/small video, avatars and displayname. Fixes issue with not displying avatars in local or remote video when video muted. Fixes if pinned participant turns off video and when unpin we return to the correct dominant speaker.
This commit is contained in:
parent
cb40ab5420
commit
0531daf541
|
@ -246,6 +246,7 @@ export default {
|
|||
_createRoom () {
|
||||
room = connection.initJitsiConference(APP.conference.roomName,
|
||||
this._getConferenceOptions());
|
||||
this.localId = room.myUserId();
|
||||
localTracks.forEach((track) => {
|
||||
if(track.isAudioTrack()) {
|
||||
localAudio = track;
|
||||
|
@ -258,7 +259,6 @@ export default {
|
|||
});
|
||||
roomLocker = createRoomLocker(room);
|
||||
this._room = room; // FIXME do not use this
|
||||
this.localId = room.myUserId();
|
||||
|
||||
let email = APP.settings.getEmail();
|
||||
email && sendEmail(email);
|
||||
|
|
|
@ -258,20 +258,12 @@ JitsiConference.prototype.addTrack = function (track) {
|
|||
if (track.startMuted) {
|
||||
track.mute();
|
||||
}
|
||||
var muteHandler = this._fireMuteChangeEvent.bind(this, track);
|
||||
var stopHandler = this.removeTrack.bind(this, track);
|
||||
var audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
|
||||
track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler);
|
||||
track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler);
|
||||
track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler);
|
||||
this.addEventListener(JitsiConferenceEvents.TRACK_REMOVED, function (someTrack) {
|
||||
if (someTrack !== track) {
|
||||
return;
|
||||
}
|
||||
track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler);
|
||||
track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler);
|
||||
track.removeEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler);
|
||||
});
|
||||
track.muteHandler = this._fireMuteChangeEvent.bind(this, track);
|
||||
track.stopHandler = this.removeTrack.bind(this, track);
|
||||
track.audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
|
||||
track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, track.muteHandler);
|
||||
track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, track.stopHandler);
|
||||
track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, track.audioLevelHandler);
|
||||
this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);
|
||||
}.bind(this));
|
||||
};
|
||||
|
@ -306,6 +298,9 @@ JitsiConference.prototype.removeTrack = function (track) {
|
|||
}
|
||||
this.room.removeStream(track.getOriginalStream(), function(){
|
||||
this.rtc.removeLocalStream(track);
|
||||
track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, track.muteHandler);
|
||||
track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED, track.stopHandler);
|
||||
track.removeEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, track.audioLevelHandler);
|
||||
this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
|
||||
}.bind(this));
|
||||
};
|
||||
|
@ -1303,7 +1298,6 @@ var LibJitsiMeet = {
|
|||
}
|
||||
};
|
||||
|
||||
require("es6-promise").polyfill()
|
||||
//Setups the promise object.
|
||||
window.Promise = window.Promise || require("es6-promise").Promise;
|
||||
|
||||
|
@ -1601,7 +1595,7 @@ DataChannels.prototype.onDataChannel = function (event) {
|
|||
// selections so that it can do adaptive simulcast,
|
||||
// we want the notification to trigger even if userJid is undefined,
|
||||
// or null.
|
||||
this.handleSelectedEndpointEvent(this.lastSelectedEndpoint);
|
||||
self.handleSelectedEndpointEvent(self.lastSelectedEndpoint);
|
||||
};
|
||||
|
||||
dataChannel.onerror = function (error) {
|
||||
|
@ -1959,6 +1953,10 @@ JitsiRemoteTrack.prototype.constructor = JitsiRemoteTrack;
|
|||
* @param value the muted status.
|
||||
*/
|
||||
JitsiRemoteTrack.prototype.setMute = function (value) {
|
||||
|
||||
if(this.muted === value)
|
||||
return;
|
||||
|
||||
this.stream.muted = value;
|
||||
this.muted = value;
|
||||
this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
|
||||
|
@ -5187,6 +5185,14 @@ var WEBAUDIO_ANALYZER_FFT_SIZE = 2048;
|
|||
*/
|
||||
var WEBAUDIO_ANALYZER_SMOOTING_TIME = 0.8;
|
||||
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
|
||||
var context = null;
|
||||
|
||||
if(window.AudioContext) {
|
||||
context = new AudioContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts time domain data array to audio level.
|
||||
* @param samples the time domain data array.
|
||||
|
@ -5238,7 +5244,6 @@ function animateLevel(newLevel, lastLevel) {
|
|||
* @constructor
|
||||
*/
|
||||
function LocalStatsCollector(stream, interval, callback) {
|
||||
window.AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
this.stream = stream;
|
||||
this.intervalId = null;
|
||||
this.intervalMilis = interval;
|
||||
|
@ -5250,16 +5255,14 @@ function LocalStatsCollector(stream, interval, callback) {
|
|||
* Starts the collecting the statistics.
|
||||
*/
|
||||
LocalStatsCollector.prototype.start = function () {
|
||||
if (!window.AudioContext ||
|
||||
if (!context ||
|
||||
RTCBrowserType.isTemasysPluginUsed())
|
||||
return;
|
||||
|
||||
var context = new AudioContext();
|
||||
var analyser = context.createAnalyser();
|
||||
analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;
|
||||
analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;
|
||||
|
||||
|
||||
var source = context.createMediaStreamSource(this.stream);
|
||||
source.connect(analyser);
|
||||
|
||||
|
|
|
@ -341,7 +341,7 @@ export default class LargeVideoManager {
|
|||
return this.videoContainer.id;
|
||||
}
|
||||
|
||||
updateLargeVideo (stream, videoType) {
|
||||
updateLargeVideo (stream, videoType, largeVideoUpdatedCallBack) {
|
||||
let id = getStreamId(stream);
|
||||
|
||||
let container = this.getContainer(this.state);
|
||||
|
@ -351,6 +351,7 @@ export default class LargeVideoManager {
|
|||
this.state = VideoContainerType;
|
||||
this.videoContainer.setStream(stream, videoType);
|
||||
this.videoContainer.show();
|
||||
largeVideoUpdatedCallBack();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ function LocalVideo(VideoLayout, emitter) {
|
|||
this.flipX = true;
|
||||
this.isLocal = true;
|
||||
this.emitter = emitter;
|
||||
SmallVideo.call(this);
|
||||
}
|
||||
|
||||
LocalVideo.prototype = Object.create(SmallVideo.prototype);
|
||||
|
|
|
@ -24,6 +24,7 @@ function RemoteVideo(id, VideoLayout, emitter) {
|
|||
this.bindHoverHandler();
|
||||
this.flipX = false;
|
||||
this.isLocal = false;
|
||||
SmallVideo.call(this);
|
||||
}
|
||||
|
||||
RemoteVideo.prototype = Object.create(SmallVideo.prototype);
|
||||
|
@ -274,10 +275,10 @@ RemoteVideo.prototype.showPeerContainer = function (state) {
|
|||
resizeThumbnails = true;
|
||||
$(this.container).show();
|
||||
}
|
||||
// Call showAvatar with undefined, so that we'll figure out if avatar
|
||||
// Call updateView, so that we'll figure out if avatar
|
||||
// should be displayed based on video muted status and whether or not
|
||||
// it's in the lastN set
|
||||
this.showAvatar(undefined);
|
||||
this.updateView();
|
||||
}
|
||||
else if ($(this.container).is(':visible') && isHide)
|
||||
{
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
/* jshint -W101 */
|
||||
import Avatar from "../avatar/Avatar";
|
||||
import UIUtil from "../util/UIUtil";
|
||||
import LargeVideo from "./LargeVideo";
|
||||
|
||||
var RTCBrowserType = require("../../RTC/RTCBrowserType");
|
||||
|
||||
function SmallVideo() {
|
||||
this.isMuted = false;
|
||||
this.hasAvatar = false;
|
||||
this.isVideoMuted = false;
|
||||
this.stream = null;
|
||||
}
|
||||
|
||||
|
@ -203,10 +203,12 @@ SmallVideo.prototype.showAudioIndicator = function(isMuted) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Shows video muted indicator over small videos.
|
||||
* Shows video muted indicator over small videos and disables/enables avatar
|
||||
* if video muted.
|
||||
*/
|
||||
SmallVideo.prototype.showVideoIndicator = function(isMuted) {
|
||||
this.showAvatar(isMuted);
|
||||
SmallVideo.prototype.setMutedView = function(isMuted) {
|
||||
this.isVideoMuted = isMuted;
|
||||
this.updateView();
|
||||
|
||||
var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
|
||||
|
||||
|
@ -233,36 +235,9 @@ SmallVideo.prototype.showVideoIndicator = function(isMuted) {
|
|||
}
|
||||
|
||||
this.updateIconPositions();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
SmallVideo.prototype.enableDominantSpeaker = function (isEnable) {
|
||||
var displayName = this.id;
|
||||
var nameSpan = $('#' + this.videoSpanId + '>span.displayname');
|
||||
if (nameSpan.length > 0)
|
||||
displayName = nameSpan.html();
|
||||
|
||||
console.log("UI enable dominant speaker",
|
||||
displayName,
|
||||
this.id,
|
||||
isEnable);
|
||||
|
||||
|
||||
if (!this.container) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isEnable) {
|
||||
this.showDisplayName(this.VideoLayout.isLargeVideoVisible());
|
||||
}
|
||||
else {
|
||||
this.showDisplayName(false);
|
||||
}
|
||||
|
||||
this.showAvatar();
|
||||
};
|
||||
|
||||
SmallVideo.prototype.updateIconPositions = function () {
|
||||
var audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');
|
||||
var connectionIndicator = $('#' + this.videoSpanId + '>div.connectionindicator');
|
||||
|
@ -310,15 +285,15 @@ SmallVideo.prototype.createModeratorIndicatorElement = function () {
|
|||
};
|
||||
|
||||
SmallVideo.prototype.selectVideoElement = function () {
|
||||
return $('#' + this.videoSpanId).find(videoElem);
|
||||
// FIXME maybe move this to the library?
|
||||
var videoElem = APP.RTC.getVideoElementName();
|
||||
var videoElemName;
|
||||
if (!RTCBrowserType.isTemasysPluginUsed()) {
|
||||
return $('#' + this.videoSpanId).find(videoElem);
|
||||
videoElemName = 'video';
|
||||
return $('#' + this.videoSpanId).find(videoElemName);
|
||||
} else {
|
||||
videoElemName = 'object';
|
||||
var matching = $('#' + this.videoSpanId +
|
||||
(this.isLocal ? '>>' : '>') +
|
||||
videoElem + '>param[value="video"]');
|
||||
videoElemName + '>param[value="video"]');
|
||||
if (matching.length < 2) {
|
||||
return matching.parent();
|
||||
}
|
||||
|
@ -352,11 +327,12 @@ SmallVideo.prototype.hasVideo = function () {
|
|||
};
|
||||
|
||||
/**
|
||||
* Hides or shows the user's avatar
|
||||
* Hides or shows the user's avatar.
|
||||
*
|
||||
* @param show whether we should show the avatar or not
|
||||
* video because there is no dominant speaker and no focused speaker
|
||||
*/
|
||||
SmallVideo.prototype.showAvatar = function (show) {
|
||||
SmallVideo.prototype.updateView = function () {
|
||||
if (!this.hasAvatar) {
|
||||
if (this.id) {
|
||||
// Init avatar
|
||||
|
@ -371,28 +347,31 @@ SmallVideo.prototype.showAvatar = function (show) {
|
|||
|
||||
let avatar = $(`#avatar_${this.id}`);
|
||||
|
||||
if (show === undefined || show === null) {
|
||||
if (!this.isLocal &&
|
||||
!this.VideoLayout.isInLastN(this.id)) {
|
||||
show = true;
|
||||
} else {
|
||||
// We want to show the avatar when the video is muted or not exists
|
||||
// that is when 'true' or 'null' is returned
|
||||
show = !this.stream || this.stream.isMuted();
|
||||
}
|
||||
var showVideo = !this.isVideoMuted
|
||||
&& !this.VideoLayout.isCurrentlyOnLarge(this.id);
|
||||
var showAvatar;
|
||||
if ((!this.isLocal &&
|
||||
!this.VideoLayout.isInLastN(this.id)) ||
|
||||
this.isVideoMuted) {
|
||||
showAvatar = true;
|
||||
} else {
|
||||
// We want to show the avatar when the video is muted or not exists
|
||||
// that is when 'true' or 'null' is returned
|
||||
showAvatar = !this.stream || this.stream.isMuted();
|
||||
}
|
||||
|
||||
if (this.VideoLayout.isCurrentlyOnLarge(this.id)
|
||||
&& this.VideoLayout.isLargeVideoVisible()) {
|
||||
if (video && video.length > 0) {
|
||||
setVisibility(video, showVideo);
|
||||
}
|
||||
setVisibility(avatar, showAvatar);
|
||||
|
||||
this.VideoLayout.showLargeVideoAvatar(show);
|
||||
setVisibility(avatar, false);
|
||||
setVisibility(video, false);
|
||||
} else {
|
||||
if (video && video.length > 0) {
|
||||
setVisibility(video, !show);
|
||||
}
|
||||
setVisibility(avatar, show);
|
||||
var showDisplayName = !showVideo && !showAvatar;
|
||||
|
||||
if (showDisplayName) {
|
||||
this.showDisplayName(this.VideoLayout.isLargeVideoVisible());
|
||||
}
|
||||
else {
|
||||
this.showDisplayName(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/* jshint -W101 */
|
||||
|
||||
import AudioLevels from "../audio_levels/AudioLevels";
|
||||
import Avatar from "../avatar/Avatar";
|
||||
import BottomToolbar from "../toolbars/BottomToolbar";
|
||||
|
||||
import UIEvents from "../../../service/UI/UIEvents";
|
||||
|
@ -262,6 +263,15 @@ var VideoLayout = {
|
|||
onRemoteStreamAdded (stream) {
|
||||
let id = stream.getParticipantId();
|
||||
remoteVideos[id].addRemoteStreamElement(stream);
|
||||
|
||||
// if track is muted make sure we reflect that
|
||||
if(stream.isMuted())
|
||||
{
|
||||
if(stream.getType() === "audio")
|
||||
this.onAudioMute(stream.getParticipantId(), true);
|
||||
else
|
||||
this.onVideoMute(stream.getParticipantId(), true);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -499,10 +509,10 @@ var VideoLayout = {
|
|||
*/
|
||||
onVideoMute (id, value) {
|
||||
if (APP.conference.isLocalId(id)) {
|
||||
localVideoThumbnail.showVideoIndicator(value);
|
||||
localVideoThumbnail.setMutedView(value);
|
||||
} else {
|
||||
var remoteVideo = remoteVideos[id];
|
||||
remoteVideo.showVideoIndicator(value);
|
||||
remoteVideo.setMutedView(value);
|
||||
|
||||
var el = remoteVideo.selectVideoElement();
|
||||
if (!value)
|
||||
|
@ -510,6 +520,9 @@ var VideoLayout = {
|
|||
else
|
||||
el.hide();
|
||||
}
|
||||
|
||||
if(this.isCurrentlyOnLarge(id))
|
||||
largeVideo.showAvatar(value);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -960,26 +973,33 @@ var VideoLayout = {
|
|||
eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, id);
|
||||
}
|
||||
if (currentId) {
|
||||
let currentSmallVideo = this.getSmallVideo(currentId);
|
||||
currentSmallVideo && currentSmallVideo.enableDominantSpeaker(false);
|
||||
var oldSmallVideo = this.getSmallVideo(currentId);
|
||||
}
|
||||
|
||||
let smallVideo = this.getSmallVideo(id);
|
||||
|
||||
let videoType = this.getRemoteVideoType(id);
|
||||
largeVideo.updateLargeVideo(smallVideo.stream, videoType);
|
||||
largeVideo.updateLargeVideo(
|
||||
smallVideo.stream,
|
||||
videoType,
|
||||
// LargeVideoUpdatedCallBack
|
||||
function() {
|
||||
// update current small video and the old one
|
||||
smallVideo.updateView();
|
||||
oldSmallVideo && oldSmallVideo.updateView();
|
||||
|
||||
// change the avatar url on large
|
||||
largeVideo.updateAvatar(Avatar.getThumbUrl(smallVideo.id));
|
||||
// show the avatar on large if needed
|
||||
largeVideo.showAvatar(show);
|
||||
});
|
||||
|
||||
smallVideo.enableDominantSpeaker(true);
|
||||
} else if (currentId) {
|
||||
let currentSmallVideo = this.getSmallVideo(currentId);
|
||||
currentSmallVideo.showAvatar();
|
||||
currentSmallVideo.updateView();
|
||||
}
|
||||
},
|
||||
|
||||
showLargeVideoAvatar (show) {
|
||||
largeVideo && largeVideo.showAvatar(show);
|
||||
},
|
||||
|
||||
addLargeVideoContainer (type, container) {
|
||||
largeVideo && largeVideo.addContainer(type, container);
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue