Pārlūkot izejas kodu

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.

master
damencho 9 gadus atpakaļ
vecāks
revīzija
0531daf541

+ 1
- 1
conference.js Parādīt failu

@@ -246,6 +246,7 @@ export default {
246 246
     _createRoom () {
247 247
         room = connection.initJitsiConference(APP.conference.roomName,
248 248
             this._getConferenceOptions());
249
+        this.localId = room.myUserId();
249 250
         localTracks.forEach((track) => {
250 251
             if(track.isAudioTrack()) {
251 252
                 localAudio = track;
@@ -258,7 +259,6 @@ export default {
258 259
         });
259 260
         roomLocker = createRoomLocker(room);
260 261
         this._room = room; // FIXME do not use this
261
-        this.localId = room.myUserId();
262 262
 
263 263
         let email = APP.settings.getEmail();
264 264
         email && sendEmail(email);

+ 23
- 20
libs/lib-jitsi-meet.js Parādīt failu

@@ -258,20 +258,12 @@ JitsiConference.prototype.addTrack = function (track) {
258 258
         if (track.startMuted) {
259 259
             track.mute();
260 260
         }
261
-        var muteHandler = this._fireMuteChangeEvent.bind(this, track);
262
-        var stopHandler = this.removeTrack.bind(this, track);
263
-        var audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
264
-        track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler);
265
-        track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler);
266
-        track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler);
267
-        this.addEventListener(JitsiConferenceEvents.TRACK_REMOVED, function (someTrack) {
268
-            if (someTrack !== track) {
269
-                return;
270
-            }
271
-            track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, muteHandler);
272
-            track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED, stopHandler);
273
-            track.removeEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, audioLevelHandler);
274
-        });
261
+        track.muteHandler = this._fireMuteChangeEvent.bind(this, track);
262
+        track.stopHandler = this.removeTrack.bind(this, track);
263
+        track.audioLevelHandler = this._fireAudioLevelChangeEvent.bind(this);
264
+        track.addEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, track.muteHandler);
265
+        track.addEventListener(JitsiTrackEvents.TRACK_STOPPED, track.stopHandler);
266
+        track.addEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, track.audioLevelHandler);
275 267
         this.eventEmitter.emit(JitsiConferenceEvents.TRACK_ADDED, track);
276 268
     }.bind(this));
277 269
 };
@@ -306,6 +298,9 @@ JitsiConference.prototype.removeTrack = function (track) {
306 298
     }
307 299
     this.room.removeStream(track.getOriginalStream(), function(){
308 300
         this.rtc.removeLocalStream(track);
301
+        track.removeEventListener(JitsiTrackEvents.TRACK_MUTE_CHANGED, track.muteHandler);
302
+        track.removeEventListener(JitsiTrackEvents.TRACK_STOPPED, track.stopHandler);
303
+        track.removeEventListener(JitsiTrackEvents.TRACK_AUDIO_LEVEL_CHANGED, track.audioLevelHandler);
309 304
         this.eventEmitter.emit(JitsiConferenceEvents.TRACK_REMOVED, track);
310 305
     }.bind(this));
311 306
 };
@@ -1303,7 +1298,6 @@ var LibJitsiMeet = {
1303 1298
     }
1304 1299
 };
1305 1300
 
1306
-require("es6-promise").polyfill()
1307 1301
 //Setups the promise object.
1308 1302
 window.Promise = window.Promise || require("es6-promise").Promise;
1309 1303
 
@@ -1601,7 +1595,7 @@ DataChannels.prototype.onDataChannel = function (event) {
1601 1595
         // selections so that it can do adaptive simulcast,
1602 1596
         // we want the notification to trigger even if userJid is undefined,
1603 1597
         // or null.
1604
-        this.handleSelectedEndpointEvent(this.lastSelectedEndpoint);
1598
+        self.handleSelectedEndpointEvent(self.lastSelectedEndpoint);
1605 1599
     };
1606 1600
 
1607 1601
     dataChannel.onerror = function (error) {
@@ -1959,6 +1953,10 @@ JitsiRemoteTrack.prototype.constructor = JitsiRemoteTrack;
1959 1953
  * @param value the muted status.
1960 1954
  */
1961 1955
 JitsiRemoteTrack.prototype.setMute = function (value) {
1956
+
1957
+    if(this.muted === value)
1958
+        return;
1959
+
1962 1960
     this.stream.muted = value;
1963 1961
     this.muted = value;
1964 1962
     this.eventEmitter.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED);
@@ -5187,6 +5185,14 @@ var WEBAUDIO_ANALYZER_FFT_SIZE = 2048;
5187 5185
  */
5188 5186
 var WEBAUDIO_ANALYZER_SMOOTING_TIME = 0.8;
5189 5187
 
5188
+window.AudioContext = window.AudioContext || window.webkitAudioContext;
5189
+
5190
+var context = null;
5191
+
5192
+if(window.AudioContext) {
5193
+    context = new AudioContext();
5194
+}
5195
+
5190 5196
 /**
5191 5197
  * Converts time domain data array to audio level.
5192 5198
  * @param samples the time domain data array.
@@ -5238,7 +5244,6 @@ function animateLevel(newLevel, lastLevel) {
5238 5244
  * @constructor
5239 5245
  */
5240 5246
 function LocalStatsCollector(stream, interval, callback) {
5241
-    window.AudioContext = window.AudioContext || window.webkitAudioContext;
5242 5247
     this.stream = stream;
5243 5248
     this.intervalId = null;
5244 5249
     this.intervalMilis = interval;
@@ -5250,16 +5255,14 @@ function LocalStatsCollector(stream, interval, callback) {
5250 5255
  * Starts the collecting the statistics.
5251 5256
  */
5252 5257
 LocalStatsCollector.prototype.start = function () {
5253
-    if (!window.AudioContext ||
5258
+    if (!context ||
5254 5259
         RTCBrowserType.isTemasysPluginUsed())
5255 5260
         return;
5256 5261
 
5257
-    var context = new AudioContext();
5258 5262
     var analyser = context.createAnalyser();
5259 5263
     analyser.smoothingTimeConstant = WEBAUDIO_ANALYZER_SMOOTING_TIME;
5260 5264
     analyser.fftSize = WEBAUDIO_ANALYZER_FFT_SIZE;
5261 5265
 
5262
-
5263 5266
     var source = context.createMediaStreamSource(this.stream);
5264 5267
     source.connect(analyser);
5265 5268
 

+ 2
- 1
modules/UI/videolayout/LargeVideo.js Parādīt failu

@@ -341,7 +341,7 @@ export default class LargeVideoManager {
341 341
         return this.videoContainer.id;
342 342
     }
343 343
 
344
-    updateLargeVideo (stream, videoType) {
344
+    updateLargeVideo (stream, videoType, largeVideoUpdatedCallBack) {
345 345
         let id = getStreamId(stream);
346 346
 
347 347
         let container = this.getContainer(this.state);
@@ -351,6 +351,7 @@ export default class LargeVideoManager {
351 351
             this.state = VideoContainerType;
352 352
             this.videoContainer.setStream(stream, videoType);
353 353
             this.videoContainer.show();
354
+            largeVideoUpdatedCallBack();
354 355
         });
355 356
     }
356 357
 

+ 1
- 0
modules/UI/videolayout/LocalVideo.js Parādīt failu

@@ -17,6 +17,7 @@ function LocalVideo(VideoLayout, emitter) {
17 17
     this.flipX = true;
18 18
     this.isLocal = true;
19 19
     this.emitter = emitter;
20
+    SmallVideo.call(this);
20 21
 }
21 22
 
22 23
 LocalVideo.prototype = Object.create(SmallVideo.prototype);

+ 3
- 2
modules/UI/videolayout/RemoteVideo.js Parādīt failu

@@ -24,6 +24,7 @@ function RemoteVideo(id, VideoLayout, emitter) {
24 24
     this.bindHoverHandler();
25 25
     this.flipX = false;
26 26
     this.isLocal = false;
27
+    SmallVideo.call(this);
27 28
 }
28 29
 
29 30
 RemoteVideo.prototype = Object.create(SmallVideo.prototype);
@@ -274,10 +275,10 @@ RemoteVideo.prototype.showPeerContainer = function (state) {
274 275
             resizeThumbnails = true;
275 276
             $(this.container).show();
276 277
         }
277
-        // Call showAvatar with undefined, so that we'll figure out if avatar
278
+        // Call updateView, so that we'll figure out if avatar
278 279
         // should be displayed based on video muted status and whether or not
279 280
         // it's in the lastN set
280
-        this.showAvatar(undefined);
281
+        this.updateView();
281 282
     }
282 283
     else if ($(this.container).is(':visible') && isHide)
283 284
     {

+ 36
- 57
modules/UI/videolayout/SmallVideo.js Parādīt failu

@@ -2,13 +2,13 @@
2 2
 /* jshint -W101 */
3 3
 import Avatar from "../avatar/Avatar";
4 4
 import UIUtil from "../util/UIUtil";
5
-import LargeVideo from "./LargeVideo";
6 5
 
7 6
 var RTCBrowserType = require("../../RTC/RTCBrowserType");
8 7
 
9 8
 function SmallVideo() {
10 9
     this.isMuted = false;
11 10
     this.hasAvatar = false;
11
+    this.isVideoMuted = false;
12 12
     this.stream = null;
13 13
 }
14 14
 
@@ -203,10 +203,12 @@ SmallVideo.prototype.showAudioIndicator = function(isMuted) {
203 203
 };
204 204
 
205 205
 /**
206
- * Shows video muted indicator over small videos.
206
+ * Shows video muted indicator over small videos and disables/enables avatar
207
+ * if video muted.
207 208
  */
208
-SmallVideo.prototype.showVideoIndicator = function(isMuted) {
209
-    this.showAvatar(isMuted);
209
+SmallVideo.prototype.setMutedView = function(isMuted) {
210
+    this.isVideoMuted = isMuted;
211
+    this.updateView();
210 212
 
211 213
     var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
212 214
 
@@ -233,34 +235,7 @@ SmallVideo.prototype.showVideoIndicator = function(isMuted) {
233 235
         }
234 236
 
235 237
         this.updateIconPositions();
236
-
237
-    }
238
-};
239
-
240
-SmallVideo.prototype.enableDominantSpeaker = function (isEnable) {
241
-    var displayName = this.id;
242
-    var nameSpan = $('#' + this.videoSpanId + '>span.displayname');
243
-    if (nameSpan.length > 0)
244
-        displayName = nameSpan.html();
245
-
246
-    console.log("UI enable dominant speaker",
247
-        displayName,
248
-        this.id,
249
-        isEnable);
250
-
251
-
252
-    if (!this.container) {
253
-        return;
254
-    }
255
-
256
-    if (isEnable) {
257
-        this.showDisplayName(this.VideoLayout.isLargeVideoVisible());
258
-    }
259
-    else {
260
-        this.showDisplayName(false);
261 238
     }
262
-
263
-    this.showAvatar();
264 239
 };
265 240
 
266 241
 SmallVideo.prototype.updateIconPositions = function () {
@@ -310,15 +285,15 @@ SmallVideo.prototype.createModeratorIndicatorElement = function () {
310 285
 };
311 286
 
312 287
 SmallVideo.prototype.selectVideoElement = function () {
313
-    return $('#' + this.videoSpanId).find(videoElem);
314
-    // FIXME maybe move this to the library?
315
-    var videoElem = APP.RTC.getVideoElementName();
288
+    var videoElemName;
316 289
     if (!RTCBrowserType.isTemasysPluginUsed()) {
317
-        return $('#' + this.videoSpanId).find(videoElem);
290
+        videoElemName = 'video';
291
+        return $('#' + this.videoSpanId).find(videoElemName);
318 292
     } else {
293
+        videoElemName = 'object';
319 294
         var matching = $('#' + this.videoSpanId +
320 295
                          (this.isLocal ? '>>' : '>') +
321
-                         videoElem + '>param[value="video"]');
296
+                         videoElemName + '>param[value="video"]');
322 297
         if (matching.length < 2) {
323 298
             return matching.parent();
324 299
         }
@@ -352,11 +327,12 @@ SmallVideo.prototype.hasVideo = function () {
352 327
 };
353 328
 
354 329
 /**
355
- * Hides or shows the user's avatar
330
+ * Hides or shows the user's avatar.
331
+ *
356 332
  * @param show whether we should show the avatar or not
357 333
  * video because there is no dominant speaker and no focused speaker
358 334
  */
359
-SmallVideo.prototype.showAvatar = function (show) {
335
+SmallVideo.prototype.updateView = function () {
360 336
     if (!this.hasAvatar) {
361 337
         if (this.id) {
362 338
             // Init avatar
@@ -371,28 +347,31 @@ SmallVideo.prototype.showAvatar = function (show) {
371 347
 
372 348
     let avatar = $(`#avatar_${this.id}`);
373 349
 
374
-    if (show === undefined || show === null) {
375
-        if (!this.isLocal &&
376
-            !this.VideoLayout.isInLastN(this.id)) {
377
-            show = true;
378
-        } else {
379
-            // We want to show the avatar when the video is muted or not exists
380
-            // that is when 'true' or 'null' is returned
381
-            show = !this.stream || this.stream.isMuted();
382
-        }
350
+    var showVideo = !this.isVideoMuted
351
+                        && !this.VideoLayout.isCurrentlyOnLarge(this.id);
352
+    var showAvatar;
353
+    if ((!this.isLocal &&
354
+        !this.VideoLayout.isInLastN(this.id)) ||
355
+        this.isVideoMuted) {
356
+        showAvatar = true;
357
+    } else {
358
+        // We want to show the avatar when the video is muted or not exists
359
+        // that is when 'true' or 'null' is returned
360
+        showAvatar = !this.stream || this.stream.isMuted();
361
+    }
362
+
363
+    if (video && video.length > 0) {
364
+        setVisibility(video, showVideo);
383 365
     }
366
+    setVisibility(avatar, showAvatar);
384 367
 
385
-    if (this.VideoLayout.isCurrentlyOnLarge(this.id)
386
-        && this.VideoLayout.isLargeVideoVisible()) {
368
+    var showDisplayName = !showVideo && !showAvatar;
387 369
 
388
-        this.VideoLayout.showLargeVideoAvatar(show);
389
-        setVisibility(avatar, false);
390
-        setVisibility(video, false);
391
-    } else {
392
-        if (video && video.length > 0) {
393
-            setVisibility(video, !show);
394
-        }
395
-        setVisibility(avatar, show);
370
+    if (showDisplayName) {
371
+        this.showDisplayName(this.VideoLayout.isLargeVideoVisible());
372
+    }
373
+    else {
374
+        this.showDisplayName(false);
396 375
     }
397 376
 };
398 377
 

+ 31
- 11
modules/UI/videolayout/VideoLayout.js Parādīt failu

@@ -2,6 +2,7 @@
2 2
 /* jshint -W101 */
3 3
 
4 4
 import AudioLevels from "../audio_levels/AudioLevels";
5
+import Avatar from "../avatar/Avatar";
5 6
 import BottomToolbar from "../toolbars/BottomToolbar";
6 7
 
7 8
 import UIEvents from "../../../service/UI/UIEvents";
@@ -262,6 +263,15 @@ var VideoLayout = {
262 263
     onRemoteStreamAdded (stream) {
263 264
         let id = stream.getParticipantId();
264 265
         remoteVideos[id].addRemoteStreamElement(stream);
266
+
267
+        // if track is muted make sure we reflect that
268
+        if(stream.isMuted())
269
+        {
270
+            if(stream.getType() === "audio")
271
+                this.onAudioMute(stream.getParticipantId(), true);
272
+            else
273
+                this.onVideoMute(stream.getParticipantId(), true);
274
+        }
265 275
     },
266 276
 
267 277
     /**
@@ -499,10 +509,10 @@ var VideoLayout = {
499 509
      */
500 510
     onVideoMute (id, value) {
501 511
         if (APP.conference.isLocalId(id)) {
502
-            localVideoThumbnail.showVideoIndicator(value);
512
+            localVideoThumbnail.setMutedView(value);
503 513
         } else {
504 514
             var remoteVideo = remoteVideos[id];
505
-            remoteVideo.showVideoIndicator(value);
515
+            remoteVideo.setMutedView(value);
506 516
 
507 517
             var el = remoteVideo.selectVideoElement();
508 518
             if (!value)
@@ -510,6 +520,9 @@ var VideoLayout = {
510 520
             else
511 521
                 el.hide();
512 522
         }
523
+
524
+        if(this.isCurrentlyOnLarge(id))
525
+            largeVideo.showAvatar(value);
513 526
     },
514 527
 
515 528
     /**
@@ -960,26 +973,33 @@ var VideoLayout = {
960 973
                 eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, id);
961 974
             }
962 975
             if (currentId) {
963
-                let currentSmallVideo = this.getSmallVideo(currentId);
964
-                currentSmallVideo && currentSmallVideo.enableDominantSpeaker(false);
976
+                var oldSmallVideo = this.getSmallVideo(currentId);
965 977
             }
966 978
 
967 979
             let smallVideo = this.getSmallVideo(id);
968 980
 
969 981
             let videoType = this.getRemoteVideoType(id);
970
-            largeVideo.updateLargeVideo(smallVideo.stream, videoType);
982
+            largeVideo.updateLargeVideo(
983
+                smallVideo.stream,
984
+                videoType,
985
+                // LargeVideoUpdatedCallBack
986
+                function() {
987
+                    // update current small video and the old one
988
+                    smallVideo.updateView();
989
+                    oldSmallVideo && oldSmallVideo.updateView();
990
+
991
+                    // change the avatar url on large
992
+                    largeVideo.updateAvatar(Avatar.getThumbUrl(smallVideo.id));
993
+                    // show the avatar on large if needed
994
+                    largeVideo.showAvatar(show);
995
+                });
971 996
 
972
-            smallVideo.enableDominantSpeaker(true);
973 997
         } else if (currentId) {
974 998
             let currentSmallVideo = this.getSmallVideo(currentId);
975
-            currentSmallVideo.showAvatar();
999
+            currentSmallVideo.updateView();
976 1000
         }
977 1001
     },
978 1002
 
979
-    showLargeVideoAvatar (show) {
980
-        largeVideo && largeVideo.showAvatar(show);
981
-    },
982
-
983 1003
     addLargeVideoContainer (type, container) {
984 1004
         largeVideo && largeVideo.addContainer(type, container);
985 1005
     },

Notiek ielāde…
Atcelt
Saglabāt