Преглед на файлове

Active speaker user interface improvements and fixes.

j8
yanas преди 10 години
родител
ревизия
662287bf4a
променени са 3 файла, в които са добавени 134 реда и са изтрити 84 реда
  1. 24
    24
      app.js
  2. 1
    2
      css/videolayout_default.css
  3. 109
    58
      videolayout.js

+ 24
- 24
app.js Целия файл

@@ -309,10 +309,14 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
309 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 320
     // Add hover handler
317 321
     $(container).hover(
318 322
         function() {
@@ -327,10 +331,8 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
327 331
 
328 332
             // If the video has been "pinned" by the user we want to keep the
329 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 336
                 VideoLayout.showDisplayName(container.id, false);
335 337
         }
336 338
     );
@@ -445,10 +447,8 @@ function statsUpdated(statsCollector)
445 447
         var peerStats = statsCollector.jid2stats[jid];
446 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,7 +460,7 @@ function statsUpdated(statsCollector)
460 460
  */
461 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,7 +545,9 @@ $(document).bind('callactive.jingle', function (event, videoelem, sid) {
545 545
         videoelem.show();
546 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 551
             VideoLayout.updateLargeVideo(videoelem.attr('src'), 1);
550 552
 
551 553
         VideoLayout.showFocusIndicator();
@@ -740,16 +742,14 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
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 Целия файл

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

+ 109
- 58
videolayout.js Целия файл

@@ -27,17 +27,23 @@ var VideoLayout = (function (my) {
27 27
         localVideoContainer.appendChild(localVideo);
28 28
 
29 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 32
         localVideoSelector.click(function () {
32 33
             VideoLayout.handleVideoThumbClicked(localVideo.src);
33 34
         });
35
+        $('#localVideoContainer').click(function () {
36
+            VideoLayout.handleVideoThumbClicked(localVideo.src);
37
+        });
38
+
34 39
         // Add hover handler
35 40
         $('#localVideoContainer').hover(
36 41
             function() {
37 42
                 VideoLayout.showDisplayName('localVideoContainer', true);
38 43
             },
39 44
             function() {
40
-                if (focusedVideoSrc !== localVideo.src)
45
+                if (!VideoLayout.isLargeVideoVisible()
46
+                        || localVideo.src !== $('#largeVideo').attr('src'))
41 47
                     VideoLayout.showDisplayName('localVideoContainer', false);
42 48
             }
43 49
         );
@@ -103,6 +109,8 @@ var VideoLayout = (function (my) {
103 109
             var isVisible = $('#largeVideo').is(':visible');
104 110
 
105 111
             $('#largeVideo').fadeOut(300, function () {
112
+                var oldSrc = $(this).attr('src');
113
+
106 114
                 $(this).attr('src', newSrc);
107 115
 
108 116
                 // Screen stream is already rotated
@@ -129,8 +137,25 @@ var VideoLayout = (function (my) {
129 137
                                     ? getDesktopVideoPosition
130 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 157
                     $(this).fadeIn(300);
158
+                }
134 159
             });
135 160
         }
136 161
     };
@@ -142,8 +167,6 @@ var VideoLayout = (function (my) {
142 167
 
143 168
         if (oldContainer) {
144 169
             oldContainer.removeClass("videoContainerFocused");
145
-            VideoLayout.enableActiveSpeaker(
146
-                    Strophe.getResourceFromJid(focusJid), false);
147 170
         }
148 171
 
149 172
         // Unlock current focused.
@@ -152,30 +175,29 @@ var VideoLayout = (function (my) {
152 175
             focusedVideoSrc = null;
153 176
             // Enable the currently set active speaker.
154 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 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 188
         // Lock new video
167 189
         focusedVideoSrc = videoSrc;
168 190
 
191
+        // Update focused/pinned interface.
169 192
         var userJid = getJidFromVideoSrc(videoSrc);
170 193
         if (userJid)
171 194
         {
172 195
             var container = getParticipantContainer(userJid);
173 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 201
         $(document).trigger("video.selected", [false]);
180 202
 
181 203
         VideoLayout.updateLargeVideo(videoSrc, 1);
@@ -224,16 +246,29 @@ var VideoLayout = (function (my) {
224 246
      * Shows/hides the large video.
225 247
      */
226 248
     my.setLargeVideoVisible = function(isVisible) {
249
+        var largeVideoJid = getJidFromVideoSrc($('#largeVideo').attr('src'));
250
+        var resourceJid = Strophe.getResourceFromJid(largeVideoJid);
251
+
227 252
         if (isVisible) {
228 253
             $('#largeVideo').css({visibility: 'visible'});
229 254
             $('.watermark').css({visibility: 'visible'});
255
+            VideoLayout.enableActiveSpeaker(resourceJid, true);
230 256
         }
231 257
         else {
232 258
             $('#largeVideo').css({visibility: 'hidden'});
233 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 274
      * Checks if container for participant identified by given peerJid exists
@@ -284,6 +319,8 @@ var VideoLayout = (function (my) {
284 319
      */
285 320
     my.setDisplayName = function(videoSpanId, displayName) {
286 321
         var nameSpan = $('#' + videoSpanId + '>span.displayname');
322
+        var defaultLocalDisplayName = "Me";
323
+        var defaultRemoteDisplayName = "Speaker";
287 324
 
288 325
         // If we already have a display name for this video.
289 326
         if (nameSpan.length > 0) {
@@ -291,21 +328,33 @@ var VideoLayout = (function (my) {
291 328
 
292 329
             if (nameSpanElement.id === 'localDisplayName' &&
293 330
                 $('#localDisplayName').text() !== displayName) {
294
-                $('#localDisplayName').text(displayName);
331
+                if (displayName)
332
+                    $('#localDisplayName').text(displayName + ' (me)');
333
+                else
334
+                    $('#localDisplayName').text(defaultLocalDisplayName);
295 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 341
         } else {
299 342
             var editButton = null;
300 343
 
344
+            nameSpan = document.createElement('span');
345
+            nameSpan.className = 'displayname';
346
+            $('#' + videoSpanId)[0].appendChild(nameSpan);
347
+
301 348
             if (videoSpanId === 'localVideoContainer') {
302 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 357
                 nameSpan.innerText = displayName;
308
-                $('#' + videoSpanId)[0].appendChild(nameSpan);
309 358
             }
310 359
 
311 360
             if (!editButton) {
@@ -327,7 +376,9 @@ var VideoLayout = (function (my) {
327 376
                 editableText.setAttribute('placeholder', 'ex. Jane Pink');
328 377
                 $('#' + videoSpanId)[0].appendChild(editableText);
329 378
 
330
-                $('#localVideoContainer .displayname').bind("click", function (e) {
379
+                $('#localVideoContainer .displayname')
380
+                    .bind("click", function (e) {
381
+
331 382
                     e.preventDefault();
332 383
                     $('#localDisplayName').hide();
333 384
                     $('#editDisplayName').show();
@@ -345,16 +396,15 @@ var VideoLayout = (function (my) {
345 396
                         }
346 397
 
347 398
                         if (!$('#localDisplayName').is(":visible")) {
348
-                            if (nickname) {
399
+                            if (nickname)
349 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 410
                     $('#editDisplayName').one("focusout", function (e) {
@@ -378,8 +428,11 @@ var VideoLayout = (function (my) {
378 428
      * @param isShow indicates if the display name should be shown or hidden
379 429
      */
380 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 436
         if (isShow) {
384 437
             if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length) 
385 438
                 nameSpan.setAttribute("style", "display:inline-block;");
@@ -540,16 +593,24 @@ var VideoLayout = (function (my) {
540 593
         if (nameSpan.length > 0)
541 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 601
         var videoSpanId = null;
602
+        var videoContainerId = null;
546 603
         if (resourceJid
547
-                === Strophe.getResourceFromJid(connection.emuc.myroomjid))
604
+                === Strophe.getResourceFromJid(connection.emuc.myroomjid)) {
548 605
             videoSpanId = 'localVideoWrapper';
549
-        else
606
+            videoContainerId = 'localVideoContainer';
607
+        }
608
+        else {
550 609
             videoSpanId = 'participant_' + resourceJid;
610
+            videoContainerId = videoSpanId;
611
+        }
551 612
 
552
-        videoSpan = document.getElementById(videoSpanId);
613
+        videoSpan = document.getElementById(videoContainerId);
553 614
 
554 615
         if (!videoSpan) {
555 616
             console.error("No video element for jid", resourceJid);
@@ -559,18 +620,21 @@ var VideoLayout = (function (my) {
559 620
         var video = $('#' + videoSpanId + '>video');
560 621
 
561 622
         if (video && video.length > 0) {
562
-            var videoElement = video.get(0);
563 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 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,10 +797,10 @@ var VideoLayout = (function (my) {
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,18 +926,6 @@ var VideoLayout = (function (my) {
862 926
                 === Strophe.getResourceFromJid(connection.emuc.myroomjid))
863 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 929
         // Obtain container for new active speaker.
878 930
         var container  = document.getElementById(
879 931
                 'participant_' + resourceJid);
@@ -892,7 +944,6 @@ var VideoLayout = (function (my) {
892 944
             if (video.length)
893 945
             {
894 946
                 VideoLayout.updateLargeVideo(video[0].src);
895
-                VideoLayout.enableActiveSpeaker(resourceJid, true);
896 947
             }
897 948
         }
898 949
     });

Loading…
Отказ
Запис