Bläddra i källkod

Active speaker user interface improvements and fixes.

j8
yanas 11 år sedan
förälder
incheckning
662287bf4a
3 ändrade filer med 134 tillägg och 84 borttagningar
  1. 24
    24
      app.js
  2. 1
    2
      css/videolayout_default.css
  3. 109
    58
      videolayout.js

+ 24
- 24
app.js Visa fil

309
         VideoLayout.checkChangeLargeVideo(vid.src);
309
         VideoLayout.checkChangeLargeVideo(vid.src);
310
     };
310
     };
311
 
311
 
312
-    // Add click handler
313
-    sel.click(function () {
314
-        VideoLayout.handleVideoThumbClicked(vid.src);
315
-    });
312
+    // Add click handler.
313
+    container.onclick = function (event) {
314
+        VideoLayout.handleVideoThumbClicked(
315
+                $('#' + container.id + '>video').get(0).src);
316
+        event.preventDefault();
317
+        return false;
318
+    };
319
+
316
     // Add hover handler
320
     // Add hover handler
317
     $(container).hover(
321
     $(container).hover(
318
         function() {
322
         function() {
327
 
331
 
328
             // If the video has been "pinned" by the user we want to keep the
332
             // If the video has been "pinned" by the user we want to keep the
329
             // display name on place.
333
             // display name on place.
330
-            if (focusedVideoSrc && focusedVideoSrc !== videoSrc
331
-                || (!focusedVideoSrc
332
-                    && container.id
333
-                        !== VideoLayout.getActiveSpeakerContainerId()))
334
+            if (!VideoLayout.isLargeVideoVisible()
335
+                    || videoSrc !== $('#largeVideo').attr('src'))
334
                 VideoLayout.showDisplayName(container.id, false);
336
                 VideoLayout.showDisplayName(container.id, false);
335
         }
337
         }
336
     );
338
     );
445
         var peerStats = statsCollector.jid2stats[jid];
447
         var peerStats = statsCollector.jid2stats[jid];
446
         Object.keys(peerStats.ssrc2AudioLevel).forEach(function (ssrc)
448
         Object.keys(peerStats.ssrc2AudioLevel).forEach(function (ssrc)
447
         {
449
         {
448
-            console.info(jid +  " audio level: " +
449
-                peerStats.ssrc2AudioLevel[ssrc] + " of ssrc: " + ssrc);
450
-//            VideoLayout.updateAudioLevel(   Strophe.getResourceFromJid(jid),
451
-//                                            peerStats.ssrc2AudioLevel[ssrc]);
450
+//            console.info(jid +  " audio level: " +
451
+//                peerStats.ssrc2AudioLevel[ssrc] + " of ssrc: " + ssrc);
452
         });
452
         });
453
     });
453
     });
454
 }
454
 }
460
  */
460
  */
461
 function localStatsUpdated(statsCollector)
461
 function localStatsUpdated(statsCollector)
462
 {
462
 {
463
-    console.info("Local audio level: " +  statsCollector.audioLevel);
463
+//    console.info("Local audio level: " +  statsCollector.audioLevel);
464
 }
464
 }
465
 
465
 
466
 /**
466
 /**
545
         videoelem.show();
545
         videoelem.show();
546
         VideoLayout.resizeThumbnails();
546
         VideoLayout.resizeThumbnails();
547
 
547
 
548
-        if (!focusedVideoSrc)
548
+        // Update the large video to the last added video only if there's no
549
+        // current active or focused speaker.
550
+        if (!focusedVideoSrc && !VideoLayout.getActiveSpeakerResourceJid())
549
             VideoLayout.updateLargeVideo(videoelem.attr('src'), 1);
551
             VideoLayout.updateLargeVideo(videoelem.attr('src'), 1);
550
 
552
 
551
         VideoLayout.showFocusIndicator();
553
         VideoLayout.showFocusIndicator();
740
         }
742
         }
741
     });
743
     });
742
 
744
 
743
-    if (info.displayName) {
744
-        if (jid === connection.emuc.myroomjid) {
745
-            VideoLayout.setDisplayName('localVideoContainer',
746
-                                        info.displayName + ' (me)');
747
-        } else {
748
-            VideoLayout.ensurePeerContainerExists(jid);
749
-            VideoLayout.setDisplayName(
750
-                    'participant_' + Strophe.getResourceFromJid(jid),
751
-                    info.displayName);
752
-        }
745
+    if (jid === connection.emuc.myroomjid) {
746
+        VideoLayout.setDisplayName('localVideoContainer',
747
+                                    info.displayName);
748
+    } else {
749
+        VideoLayout.ensurePeerContainerExists(jid);
750
+        VideoLayout.setDisplayName(
751
+                'participant_' + Strophe.getResourceFromJid(jid),
752
+                info.displayName);
753
     }
753
     }
754
 });
754
 });
755
 
755
 

+ 1
- 2
css/videolayout_default.css Visa fil

95
 }
95
 }
96
 
96
 
97
 .activespeaker {
97
 .activespeaker {
98
-    -webkit-filter: grayscale(1);
99
-    filter: grayscale(1);
98
+    background: #000 !important;
100
 }
99
 }
101
 
100
 
102
 #etherpad,
101
 #etherpad,

+ 109
- 58
videolayout.js Visa fil

27
         localVideoContainer.appendChild(localVideo);
27
         localVideoContainer.appendChild(localVideo);
28
 
28
 
29
         var localVideoSelector = $('#' + localVideo.id);
29
         var localVideoSelector = $('#' + localVideo.id);
30
-        // Add click handler
30
+        // Add click handler to both video and video wrapper elements in case
31
+        // there's no video.
31
         localVideoSelector.click(function () {
32
         localVideoSelector.click(function () {
32
             VideoLayout.handleVideoThumbClicked(localVideo.src);
33
             VideoLayout.handleVideoThumbClicked(localVideo.src);
33
         });
34
         });
35
+        $('#localVideoContainer').click(function () {
36
+            VideoLayout.handleVideoThumbClicked(localVideo.src);
37
+        });
38
+
34
         // Add hover handler
39
         // Add hover handler
35
         $('#localVideoContainer').hover(
40
         $('#localVideoContainer').hover(
36
             function() {
41
             function() {
37
                 VideoLayout.showDisplayName('localVideoContainer', true);
42
                 VideoLayout.showDisplayName('localVideoContainer', true);
38
             },
43
             },
39
             function() {
44
             function() {
40
-                if (focusedVideoSrc !== localVideo.src)
45
+                if (!VideoLayout.isLargeVideoVisible()
46
+                        || localVideo.src !== $('#largeVideo').attr('src'))
41
                     VideoLayout.showDisplayName('localVideoContainer', false);
47
                     VideoLayout.showDisplayName('localVideoContainer', false);
42
             }
48
             }
43
         );
49
         );
103
             var isVisible = $('#largeVideo').is(':visible');
109
             var isVisible = $('#largeVideo').is(':visible');
104
 
110
 
105
             $('#largeVideo').fadeOut(300, function () {
111
             $('#largeVideo').fadeOut(300, function () {
112
+                var oldSrc = $(this).attr('src');
113
+
106
                 $(this).attr('src', newSrc);
114
                 $(this).attr('src', newSrc);
107
 
115
 
108
                 // Screen stream is already rotated
116
                 // Screen stream is already rotated
129
                                     ? getDesktopVideoPosition
137
                                     ? getDesktopVideoPosition
130
                                     : getCameraVideoPosition;
138
                                     : getCameraVideoPosition;
131
 
139
 
132
-                if (isVisible)
140
+                if (isVisible) {
141
+                    // Only if the large video is currently visible.
142
+                    // Disable previous active speaker video.
143
+                    var oldJid = getJidFromVideoSrc(oldSrc);
144
+                    if (oldJid) {
145
+                        var oldResourceJid = Strophe.getResourceFromJid(oldJid);
146
+                        VideoLayout.enableActiveSpeaker(oldResourceJid, false);
147
+                    }
148
+
149
+                    // Enable new active speaker in the remote videos section.
150
+                    var userJid = getJidFromVideoSrc(newSrc);
151
+                    if (userJid)
152
+                    {
153
+                        var resourceJid = Strophe.getResourceFromJid(userJid);
154
+                        VideoLayout.enableActiveSpeaker(resourceJid, true);
155
+                    }
156
+
133
                     $(this).fadeIn(300);
157
                     $(this).fadeIn(300);
158
+                }
134
             });
159
             });
135
         }
160
         }
136
     };
161
     };
142
 
167
 
143
         if (oldContainer) {
168
         if (oldContainer) {
144
             oldContainer.removeClass("videoContainerFocused");
169
             oldContainer.removeClass("videoContainerFocused");
145
-            VideoLayout.enableActiveSpeaker(
146
-                    Strophe.getResourceFromJid(focusJid), false);
147
         }
170
         }
148
 
171
 
149
         // Unlock current focused.
172
         // Unlock current focused.
152
             focusedVideoSrc = null;
175
             focusedVideoSrc = null;
153
             // Enable the currently set active speaker.
176
             // Enable the currently set active speaker.
154
             if (currentActiveSpeaker) {
177
             if (currentActiveSpeaker) {
155
-                VideoLayout.enableActiveSpeaker(currentActiveSpeaker, true);
178
+                var activeSpeakerVideo = document
179
+                    .getElementById('participant_' + currentActiveSpeaker);
180
+
181
+                if (activeSpeakerVideo)
182
+                    VideoLayout.updateLargeVideo(activeSpeakerVideo.src, 1);
156
             }
183
             }
157
 
184
 
158
             return;
185
             return;
159
         }
186
         }
160
-        // Remove style for current active speaker if we're going to lock
161
-        // another video.
162
-        else if (currentActiveSpeaker) {
163
-            VideoLayout.enableActiveSpeaker(currentActiveSpeaker, false);
164
-        }
165
 
187
 
166
         // Lock new video
188
         // Lock new video
167
         focusedVideoSrc = videoSrc;
189
         focusedVideoSrc = videoSrc;
168
 
190
 
191
+        // Update focused/pinned interface.
169
         var userJid = getJidFromVideoSrc(videoSrc);
192
         var userJid = getJidFromVideoSrc(videoSrc);
170
         if (userJid)
193
         if (userJid)
171
         {
194
         {
172
             var container = getParticipantContainer(userJid);
195
             var container = getParticipantContainer(userJid);
173
             container.addClass("videoContainerFocused");
196
             container.addClass("videoContainerFocused");
174
-
175
-            var resourceJid = Strophe.getResourceFromJid(userJid);
176
-            VideoLayout.enableActiveSpeaker(resourceJid, true);
177
         }
197
         }
178
 
198
 
199
+        // Triggers a "video.selected" event. The "false" parameter indicates
200
+        // this isn't a prezi.
179
         $(document).trigger("video.selected", [false]);
201
         $(document).trigger("video.selected", [false]);
180
 
202
 
181
         VideoLayout.updateLargeVideo(videoSrc, 1);
203
         VideoLayout.updateLargeVideo(videoSrc, 1);
224
      * Shows/hides the large video.
246
      * Shows/hides the large video.
225
      */
247
      */
226
     my.setLargeVideoVisible = function(isVisible) {
248
     my.setLargeVideoVisible = function(isVisible) {
249
+        var largeVideoJid = getJidFromVideoSrc($('#largeVideo').attr('src'));
250
+        var resourceJid = Strophe.getResourceFromJid(largeVideoJid);
251
+
227
         if (isVisible) {
252
         if (isVisible) {
228
             $('#largeVideo').css({visibility: 'visible'});
253
             $('#largeVideo').css({visibility: 'visible'});
229
             $('.watermark').css({visibility: 'visible'});
254
             $('.watermark').css({visibility: 'visible'});
255
+            VideoLayout.enableActiveSpeaker(resourceJid, true);
230
         }
256
         }
231
         else {
257
         else {
232
             $('#largeVideo').css({visibility: 'hidden'});
258
             $('#largeVideo').css({visibility: 'hidden'});
233
             $('.watermark').css({visibility: 'hidden'});
259
             $('.watermark').css({visibility: 'hidden'});
260
+            VideoLayout.enableActiveSpeaker(resourceJid, false);
234
         }
261
         }
235
     };
262
     };
236
 
263
 
264
+    /**
265
+     * Indicates if the large video is currently visible.
266
+     *
267
+     * @return <tt>true</tt> if visible, <tt>false</tt> - otherwise
268
+     */
269
+    my.isLargeVideoVisible = function() {
270
+        return $('#largeVideo').is(':visible');
271
+    };
237
 
272
 
238
     /**
273
     /**
239
      * Checks if container for participant identified by given peerJid exists
274
      * Checks if container for participant identified by given peerJid exists
284
      */
319
      */
285
     my.setDisplayName = function(videoSpanId, displayName) {
320
     my.setDisplayName = function(videoSpanId, displayName) {
286
         var nameSpan = $('#' + videoSpanId + '>span.displayname');
321
         var nameSpan = $('#' + videoSpanId + '>span.displayname');
322
+        var defaultLocalDisplayName = "Me";
323
+        var defaultRemoteDisplayName = "Speaker";
287
 
324
 
288
         // If we already have a display name for this video.
325
         // If we already have a display name for this video.
289
         if (nameSpan.length > 0) {
326
         if (nameSpan.length > 0) {
291
 
328
 
292
             if (nameSpanElement.id === 'localDisplayName' &&
329
             if (nameSpanElement.id === 'localDisplayName' &&
293
                 $('#localDisplayName').text() !== displayName) {
330
                 $('#localDisplayName').text() !== displayName) {
294
-                $('#localDisplayName').text(displayName);
331
+                if (displayName)
332
+                    $('#localDisplayName').text(displayName + ' (me)');
333
+                else
334
+                    $('#localDisplayName').text(defaultLocalDisplayName);
295
             } else {
335
             } else {
296
-                $('#' + videoSpanId + '_name').text(displayName);
336
+                if (displayName)
337
+                    $('#' + videoSpanId + '_name').text(displayName);
338
+                else
339
+                    $('#' + videoSpanId + '_name').text(defaultRemoteDisplayName);
297
             }
340
             }
298
         } else {
341
         } else {
299
             var editButton = null;
342
             var editButton = null;
300
 
343
 
344
+            nameSpan = document.createElement('span');
345
+            nameSpan.className = 'displayname';
346
+            $('#' + videoSpanId)[0].appendChild(nameSpan);
347
+
301
             if (videoSpanId === 'localVideoContainer') {
348
             if (videoSpanId === 'localVideoContainer') {
302
                 editButton = createEditDisplayNameButton();
349
                 editButton = createEditDisplayNameButton();
350
+                nameSpan.innerText = defaultLocalDisplayName;
303
             }
351
             }
304
-            if (displayName.length) {
305
-                nameSpan = document.createElement('span');
306
-                nameSpan.className = 'displayname';
352
+            else {
353
+                nameSpan.innerText = defaultRemoteDisplayName;
354
+            }
355
+
356
+            if (displayName && displayName.length) {
307
                 nameSpan.innerText = displayName;
357
                 nameSpan.innerText = displayName;
308
-                $('#' + videoSpanId)[0].appendChild(nameSpan);
309
             }
358
             }
310
 
359
 
311
             if (!editButton) {
360
             if (!editButton) {
327
                 editableText.setAttribute('placeholder', 'ex. Jane Pink');
376
                 editableText.setAttribute('placeholder', 'ex. Jane Pink');
328
                 $('#' + videoSpanId)[0].appendChild(editableText);
377
                 $('#' + videoSpanId)[0].appendChild(editableText);
329
 
378
 
330
-                $('#localVideoContainer .displayname').bind("click", function (e) {
379
+                $('#localVideoContainer .displayname')
380
+                    .bind("click", function (e) {
381
+
331
                     e.preventDefault();
382
                     e.preventDefault();
332
                     $('#localDisplayName').hide();
383
                     $('#localDisplayName').hide();
333
                     $('#editDisplayName').show();
384
                     $('#editDisplayName').show();
345
                         }
396
                         }
346
 
397
 
347
                         if (!$('#localDisplayName').is(":visible")) {
398
                         if (!$('#localDisplayName').is(":visible")) {
348
-                            if (nickname) {
399
+                            if (nickname)
349
                                 $('#localDisplayName').text(nickname + " (me)");
400
                                 $('#localDisplayName').text(nickname + " (me)");
350
-                                $('#localDisplayName').show();
351
-                            }
352
-                            else {
353
-                                $('#localDisplayName').text(nickname);
354
-                            }
355
-
356
-                            $('#editDisplayName').hide();
401
+                            else
402
+                                $('#localDisplayName')
403
+                                    .text(defaultLocalDisplayName);
404
+                            $('#localDisplayName').show();
357
                         }
405
                         }
406
+
407
+                        $('#editDisplayName').hide();
358
                     };
408
                     };
359
 
409
 
360
                     $('#editDisplayName').one("focusout", function (e) {
410
                     $('#editDisplayName').one("focusout", function (e) {
378
      * @param isShow indicates if the display name should be shown or hidden
428
      * @param isShow indicates if the display name should be shown or hidden
379
      */
429
      */
380
     my.showDisplayName = function(videoSpanId, isShow) {
430
     my.showDisplayName = function(videoSpanId, isShow) {
381
-        var nameSpan = $('#' + videoSpanId + '>span.displayname').get(0);
382
-
431
+        // FIX: need to use noConflict of jquery, because apparently we're
432
+        // using another library that uses $, which conflics with jquery and
433
+        // sometimes objects are null because of that!!!!!!!!!
434
+        // http://api.jquery.com/jQuery.noConflict/
435
+        var nameSpan = jQuery('#' + videoSpanId + '>span.displayname').get(0);
383
         if (isShow) {
436
         if (isShow) {
384
             if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length) 
437
             if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length) 
385
                 nameSpan.setAttribute("style", "display:inline-block;");
438
                 nameSpan.setAttribute("style", "display:inline-block;");
540
         if (nameSpan.length > 0)
593
         if (nameSpan.length > 0)
541
             displayName = nameSpan.text();
594
             displayName = nameSpan.text();
542
 
595
 
543
-        console.log("Enable active speaker", displayName, isEnable);
596
+        console.log("UI enable active speaker",
597
+                    displayName,
598
+                    resourceJid,
599
+                    isEnable);
544
 
600
 
545
         var videoSpanId = null;
601
         var videoSpanId = null;
602
+        var videoContainerId = null;
546
         if (resourceJid
603
         if (resourceJid
547
-                === Strophe.getResourceFromJid(connection.emuc.myroomjid))
604
+                === Strophe.getResourceFromJid(connection.emuc.myroomjid)) {
548
             videoSpanId = 'localVideoWrapper';
605
             videoSpanId = 'localVideoWrapper';
549
-        else
606
+            videoContainerId = 'localVideoContainer';
607
+        }
608
+        else {
550
             videoSpanId = 'participant_' + resourceJid;
609
             videoSpanId = 'participant_' + resourceJid;
610
+            videoContainerId = videoSpanId;
611
+        }
551
 
612
 
552
-        videoSpan = document.getElementById(videoSpanId);
613
+        videoSpan = document.getElementById(videoContainerId);
553
 
614
 
554
         if (!videoSpan) {
615
         if (!videoSpan) {
555
             console.error("No video element for jid", resourceJid);
616
             console.error("No video element for jid", resourceJid);
559
         var video = $('#' + videoSpanId + '>video');
620
         var video = $('#' + videoSpanId + '>video');
560
 
621
 
561
         if (video && video.length > 0) {
622
         if (video && video.length > 0) {
562
-            var videoElement = video.get(0);
563
             if (isEnable) {
623
             if (isEnable) {
564
-                if (!videoElement.classList.contains("activespeaker"))
565
-                    videoElement.classList.add("activespeaker");
624
+                VideoLayout.showDisplayName(videoContainerId, true);
566
 
625
 
567
-                VideoLayout.showDisplayName(videoSpanId, true);
626
+                if (!videoSpan.classList.contains("activespeaker"))
627
+                    videoSpan.classList.add("activespeaker");
628
+
629
+                video.css({visibility: 'hidden'});
568
             }
630
             }
569
             else {
631
             else {
570
-                VideoLayout.showDisplayName(videoSpanId, false);
632
+                VideoLayout.showDisplayName(videoContainerId, false);
633
+
634
+                if (videoSpan.classList.contains("activespeaker"))
635
+                    videoSpan.classList.remove("activespeaker");
571
 
636
 
572
-                if (videoElement.classList.contains("activespeaker"))
573
-                    videoElement.classList.remove("activespeaker");
637
+                video.css({visibility: 'visible'});
574
             }
638
             }
575
         }
639
         }
576
     };
640
     };
733
     };
797
     };
734
 
798
 
735
     /**
799
     /**
736
-     * Returns the current active speaker.
800
+     * Returns the current active speaker resource jid.
737
      */
801
      */
738
-    my.getActiveSpeakerContainerId = function () {
739
-        return 'participant_' + currentActiveSpeaker;
802
+    my.getActiveSpeakerResourceJid = function () {
803
+        return currentActiveSpeaker;
740
     };
804
     };
741
 
805
 
742
     /**
806
     /**
862
                 === Strophe.getResourceFromJid(connection.emuc.myroomjid))
926
                 === Strophe.getResourceFromJid(connection.emuc.myroomjid))
863
             return;
927
             return;
864
 
928
 
865
-        // Disable style for previous active speaker.
866
-        if (currentActiveSpeaker
867
-                && currentActiveSpeaker !== resourceJid
868
-                && !focusedVideoSrc) {
869
-            var oldContainer  = document.getElementById(
870
-                    'participant_' + currentActiveSpeaker);
871
-
872
-            if (oldContainer) {
873
-                VideoLayout.enableActiveSpeaker(currentActiveSpeaker, false);
874
-            }
875
-        }
876
-
877
         // Obtain container for new active speaker.
929
         // Obtain container for new active speaker.
878
         var container  = document.getElementById(
930
         var container  = document.getElementById(
879
                 'participant_' + resourceJid);
931
                 'participant_' + resourceJid);
892
             if (video.length)
944
             if (video.length)
893
             {
945
             {
894
                 VideoLayout.updateLargeVideo(video[0].src);
946
                 VideoLayout.updateLargeVideo(video[0].src);
895
-                VideoLayout.enableActiveSpeaker(resourceJid, true);
896
             }
947
             }
897
         }
948
         }
898
     });
949
     });

Laddar…
Avbryt
Spara