|
@@ -3,6 +3,7 @@ var RTCBrowserType = require("../../RTC/RTCBrowserType");
|
3
|
3
|
var UIUtil = require("../util/UIUtil");
|
4
|
4
|
var UIEvents = require("../../../service/UI/UIEvents");
|
5
|
5
|
var xmpp = require("../../xmpp/xmpp");
|
|
6
|
+var ToolbarToggler = require("../toolbars/ToolbarToggler");
|
6
|
7
|
|
7
|
8
|
// FIXME: With Temasys we have to re-select everytime
|
8
|
9
|
//var video = $('#largeVideo');
|
|
@@ -12,9 +13,45 @@ var currentVideoHeight = null;
|
12
|
13
|
// By default we use camera
|
13
|
14
|
var getVideoSize = getCameraVideoSize;
|
14
|
15
|
var getVideoPosition = getCameraVideoPosition;
|
|
16
|
+/**
|
|
17
|
+ * The small video instance that is displayed in the large video
|
|
18
|
+ * @type {SmallVideo}
|
|
19
|
+ */
|
15
|
20
|
var currentSmallVideo = null;
|
|
21
|
+/**
|
|
22
|
+ * Indicates whether the large video is enabled.
|
|
23
|
+ * @type {boolean}
|
|
24
|
+ */
|
|
25
|
+var isEnabled = true;
|
|
26
|
+/**
|
|
27
|
+ * Current large video state.
|
|
28
|
+ * Possible values - video, prezi or etherpad.
|
|
29
|
+ * @type {string}
|
|
30
|
+ */
|
|
31
|
+var state = "video";
|
16
|
32
|
|
17
|
|
-
|
|
33
|
+/**
|
|
34
|
+ * Returns the html element associated with the passed state of large video
|
|
35
|
+ * @param state the state.
|
|
36
|
+ * @returns {JQuery|*|jQuery|HTMLElement} the container.
|
|
37
|
+ */
|
|
38
|
+function getContainerByState(state)
|
|
39
|
+{
|
|
40
|
+ var selector = null;
|
|
41
|
+ switch (state)
|
|
42
|
+ {
|
|
43
|
+ case "video":
|
|
44
|
+ selector = "#largeVideo";
|
|
45
|
+ break;
|
|
46
|
+ case "etherpad":
|
|
47
|
+ selector = "#etherpad>iframe";
|
|
48
|
+ break;
|
|
49
|
+ case "prezi":
|
|
50
|
+ selector = "#presentation>iframe";
|
|
51
|
+ break;
|
|
52
|
+ }
|
|
53
|
+ return (selector !== null)? $(selector) : null;
|
|
54
|
+}
|
18
|
55
|
|
19
|
56
|
/**
|
20
|
57
|
* Sets the size and position of the given video element.
|
|
@@ -204,6 +241,10 @@ function updateActiveSpeakerAvatarSrc() {
|
204
|
241
|
}
|
205
|
242
|
}
|
206
|
243
|
|
|
244
|
+/**
|
|
245
|
+ * Change the video source of the large video.
|
|
246
|
+ * @param isVisible
|
|
247
|
+ */
|
207
|
248
|
function changeVideo(isVisible) {
|
208
|
249
|
|
209
|
250
|
if (!currentSmallVideo) {
|
|
@@ -248,11 +289,66 @@ function changeVideo(isVisible) {
|
248
|
289
|
}
|
249
|
290
|
}
|
250
|
291
|
|
|
292
|
+/**
|
|
293
|
+ * Creates the html elements for the large video.
|
|
294
|
+ */
|
|
295
|
+function createLargeVideoHTML()
|
|
296
|
+{
|
|
297
|
+ var html = '<div id="largeVideoContainer" class="videocontainer">';
|
|
298
|
+ html += '<div id="presentation"></div>' +
|
|
299
|
+ '<div id="etherpad"></div>' +
|
|
300
|
+ '<a target="_new"><div class="watermark leftwatermark"></div></a>' +
|
|
301
|
+ '<a target="_new"><div class="watermark rightwatermark"></div></a>' +
|
|
302
|
+ '<a class="poweredby" href="http://jitsi.org" target="_new" >' +
|
|
303
|
+ '<span data-i18n="poweredby"></span> jitsi.org' +
|
|
304
|
+ '</a>'+
|
|
305
|
+ '<div id="activeSpeaker">' +
|
|
306
|
+ '<img id="activeSpeakerAvatar" src=""/>' +
|
|
307
|
+ '<canvas id="activeSpeakerAudioLevel"></canvas>' +
|
|
308
|
+ '</div>' +
|
|
309
|
+ '<video id="largeVideo" autoplay oncontextmenu="return false;"></video>';
|
|
310
|
+ html += '</div>';
|
|
311
|
+ $(html).prependTo("#videospace");
|
|
312
|
+
|
|
313
|
+ if (interfaceConfig.SHOW_JITSI_WATERMARK) {
|
|
314
|
+ var leftWatermarkDiv
|
|
315
|
+ = $("#largeVideoContainer div[class='watermark leftwatermark']");
|
|
316
|
+
|
|
317
|
+ leftWatermarkDiv.css({display: 'block'});
|
|
318
|
+ leftWatermarkDiv.parent().get(0).href
|
|
319
|
+ = interfaceConfig.JITSI_WATERMARK_LINK;
|
|
320
|
+ }
|
|
321
|
+
|
|
322
|
+ if (interfaceConfig.SHOW_BRAND_WATERMARK) {
|
|
323
|
+ var rightWatermarkDiv
|
|
324
|
+ = $("#largeVideoContainer div[class='watermark rightwatermark']");
|
|
325
|
+
|
|
326
|
+ rightWatermarkDiv.css({display: 'block'});
|
|
327
|
+ rightWatermarkDiv.parent().get(0).href
|
|
328
|
+ = interfaceConfig.BRAND_WATERMARK_LINK;
|
|
329
|
+ rightWatermarkDiv.get(0).style.backgroundImage
|
|
330
|
+ = "url(images/rightwatermark.png)";
|
|
331
|
+ }
|
|
332
|
+
|
|
333
|
+ if (interfaceConfig.SHOW_POWERED_BY) {
|
|
334
|
+ $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'});
|
|
335
|
+ }
|
|
336
|
+
|
|
337
|
+ if (!RTCBrowserType.isIExplorer()) {
|
|
338
|
+ $('#largeVideo').volume = 0;
|
|
339
|
+ }
|
|
340
|
+}
|
|
341
|
+
|
251
|
342
|
var LargeVideo = {
|
252
|
343
|
|
253
|
344
|
init: function (VideoLayout, emitter) {
|
|
345
|
+ if(!isEnabled)
|
|
346
|
+ return;
|
|
347
|
+ createLargeVideoHTML();
|
|
348
|
+
|
254
|
349
|
this.VideoLayout = VideoLayout;
|
255
|
350
|
this.eventEmitter = emitter;
|
|
351
|
+ this.eventEmitter.emit(UIEvents.LARGEVIDEO_INIT);
|
256
|
352
|
var self = this;
|
257
|
353
|
// Listen for large video size updates
|
258
|
354
|
var largeVideo = $('#largeVideo')[0];
|
|
@@ -285,6 +381,8 @@ var LargeVideo = {
|
285
|
381
|
* Updates the large video with the given new video source.
|
286
|
382
|
*/
|
287
|
383
|
updateLargeVideo: function (resourceJid, forceUpdate) {
|
|
384
|
+ if(!isEnabled)
|
|
385
|
+ return;
|
288
|
386
|
var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid);
|
289
|
387
|
console.log('hover in ' + resourceJid + ', video: ', newSmallVideo);
|
290
|
388
|
|
|
@@ -324,6 +422,8 @@ var LargeVideo = {
|
324
|
422
|
* Shows/hides the large video.
|
325
|
423
|
*/
|
326
|
424
|
setLargeVideoVisible: function(isVisible) {
|
|
425
|
+ if(!isEnabled)
|
|
426
|
+ return;
|
327
|
427
|
if (isVisible) {
|
328
|
428
|
$('#largeVideo').css({visibility: 'visible'});
|
329
|
429
|
$('.watermark').css({visibility: 'visible'});
|
|
@@ -339,6 +439,8 @@ var LargeVideo = {
|
339
|
439
|
}
|
340
|
440
|
},
|
341
|
441
|
onVideoTypeChanged: function (jid) {
|
|
442
|
+ if(!isEnabled)
|
|
443
|
+ return;
|
342
|
444
|
var resourceJid = Strophe.getResourceFromJid(jid);
|
343
|
445
|
if (LargeVideo.isCurrentlyOnLarge(resourceJid))
|
344
|
446
|
{
|
|
@@ -360,6 +462,8 @@ var LargeVideo = {
|
360
|
462
|
*/
|
361
|
463
|
position: function (videoWidth, videoHeight,
|
362
|
464
|
videoSpaceWidth, videoSpaceHeight, animate) {
|
|
465
|
+ if(!isEnabled)
|
|
466
|
+ return;
|
363
|
467
|
if(!videoSpaceWidth)
|
364
|
468
|
videoSpaceWidth = $('#videospace').width();
|
365
|
469
|
if(!videoSpaceHeight)
|
|
@@ -386,13 +490,9 @@ var LargeVideo = {
|
386
|
490
|
largeVideoHeight,
|
387
|
491
|
horizontalIndent, verticalIndent, animate);
|
388
|
492
|
},
|
389
|
|
-
|
390
|
|
- isLargeVideoOnTop: function () {
|
391
|
|
- var Etherpad = require("../etherpad/Etherpad");
|
392
|
|
- var Prezi = require("../prezi/Prezi");
|
393
|
|
- return !Prezi.isPresentationVisible() && !Etherpad.isVisible();
|
394
|
|
- },
|
395
|
493
|
resize: function (animate, isVisible, completeFunction) {
|
|
494
|
+ if(!isEnabled)
|
|
495
|
+ return;
|
396
|
496
|
var availableHeight = window.innerHeight;
|
397
|
497
|
var availableWidth = UIUtil.getAvailableVideoWidth(isVisible);
|
398
|
498
|
|
|
@@ -437,6 +537,8 @@ var LargeVideo = {
|
437
|
537
|
|
438
|
538
|
},
|
439
|
539
|
resizeVideoAreaAnimated: function (isVisible, completeFunction) {
|
|
540
|
+ if(!isEnabled)
|
|
541
|
+ return;
|
440
|
542
|
var size = this.resize(true, isVisible, completeFunction);
|
441
|
543
|
this.position(null, null, size[0], size[1], true);
|
442
|
544
|
},
|
|
@@ -444,22 +546,152 @@ var LargeVideo = {
|
444
|
546
|
return currentSmallVideo ? currentSmallVideo.getResourceJid() : null;
|
445
|
547
|
},
|
446
|
548
|
updateAvatar: function (resourceJid) {
|
|
549
|
+ if(!isEnabled)
|
|
550
|
+ return;
|
447
|
551
|
if (resourceJid === this.getResourceJid()) {
|
448
|
552
|
updateActiveSpeakerAvatarSrc();
|
449
|
553
|
}
|
450
|
554
|
},
|
451
|
555
|
showAvatar: function (resourceJid, show) {
|
|
556
|
+ if(!isEnabled)
|
|
557
|
+ return;
|
452
|
558
|
if(this.getResourceJid() === resourceJid
|
453
|
|
- && LargeVideo.isLargeVideoOnTop())
|
|
559
|
+ && state === "video")
|
454
|
560
|
{
|
455
|
561
|
$("#largeVideo").css("visibility", show ? "hidden" : "visible");
|
456
|
562
|
$('#activeSpeaker').css("visibility", show ? "visible" : "hidden");
|
457
|
563
|
return true;
|
458
|
564
|
}
|
459
|
565
|
return false;
|
|
566
|
+ },
|
|
567
|
+ /**
|
|
568
|
+ * Disables the large video
|
|
569
|
+ */
|
|
570
|
+ disable: function () {
|
|
571
|
+ isEnabled = false;
|
|
572
|
+ },
|
|
573
|
+ /**
|
|
574
|
+ * Enables the large video
|
|
575
|
+ */
|
|
576
|
+ enable: function () {
|
|
577
|
+ isEnabled = true;
|
|
578
|
+ },
|
|
579
|
+ /**
|
|
580
|
+ * Returns true if the video is enabled.
|
|
581
|
+ */
|
|
582
|
+ isEnabled: function () {
|
|
583
|
+ return isEnabled;
|
|
584
|
+ },
|
|
585
|
+ /**
|
|
586
|
+ * Creates the iframe used by the etherpad
|
|
587
|
+ * @param src the value for src attribute
|
|
588
|
+ * @param onloadHandler handler executed when the iframe loads it content
|
|
589
|
+ * @returns {HTMLElement} the iframe
|
|
590
|
+ */
|
|
591
|
+ createEtherpadIframe: function (src, onloadHandler) {
|
|
592
|
+ if(!isEnabled)
|
|
593
|
+ return;
|
|
594
|
+
|
|
595
|
+ var etherpadIFrame = document.createElement('iframe');
|
|
596
|
+ etherpadIFrame.src = src;
|
|
597
|
+ etherpadIFrame.frameBorder = 0;
|
|
598
|
+ etherpadIFrame.scrolling = "no";
|
|
599
|
+ etherpadIFrame.width = $('#largeVideoContainer').width() || 640;
|
|
600
|
+ etherpadIFrame.height = $('#largeVideoContainer').height() || 480;
|
|
601
|
+ etherpadIFrame.setAttribute('style', 'visibility: hidden;');
|
|
602
|
+
|
|
603
|
+ document.getElementById('etherpad').appendChild(etherpadIFrame);
|
|
604
|
+
|
|
605
|
+ etherpadIFrame.onload = onloadHandler;
|
|
606
|
+
|
|
607
|
+ return etherpadIFrame;
|
|
608
|
+ },
|
|
609
|
+ /**
|
|
610
|
+ * Changes the state of the large video.
|
|
611
|
+ * Possible values - video, prezi, etherpad.
|
|
612
|
+ * @param newState - the new state
|
|
613
|
+ */
|
|
614
|
+ setState: function (newState) {
|
|
615
|
+ if(state === newState)
|
|
616
|
+ return;
|
|
617
|
+ var currentContainer = getContainerByState(state);
|
|
618
|
+ if(!currentContainer)
|
|
619
|
+ return;
|
|
620
|
+
|
|
621
|
+ var self = this;
|
|
622
|
+ var oldState = state;
|
|
623
|
+
|
|
624
|
+ switch (newState)
|
|
625
|
+ {
|
|
626
|
+ case "etherpad":
|
|
627
|
+ $('#activeSpeaker').css('visibility', 'hidden');
|
|
628
|
+ currentContainer.fadeOut(300, function () {
|
|
629
|
+ if (oldState === "prezi") {
|
|
630
|
+ currentContainer.css({opacity: '0'});
|
|
631
|
+ $('#reloadPresentation').css({display: 'none'});
|
|
632
|
+ }
|
|
633
|
+ else {
|
|
634
|
+ self.setLargeVideoVisible(false);
|
|
635
|
+ }
|
|
636
|
+ });
|
|
637
|
+
|
|
638
|
+ $('#etherpad>iframe').fadeIn(300, function () {
|
|
639
|
+ document.body.style.background = '#eeeeee';
|
|
640
|
+ $('#etherpad>iframe').css({visibility: 'visible'});
|
|
641
|
+ $('#etherpad').css({zIndex: 2});
|
|
642
|
+ });
|
|
643
|
+ break;
|
|
644
|
+ case "prezi":
|
|
645
|
+ var prezi = $('#presentation>iframe');
|
|
646
|
+ currentContainer.fadeOut(300, function() {
|
|
647
|
+ document.body.style.background = 'black';
|
|
648
|
+ });
|
|
649
|
+ prezi.fadeIn(300, function() {
|
|
650
|
+ prezi.css({opacity:'1'});
|
|
651
|
+ ToolbarToggler.dockToolbar(true);//fix that
|
|
652
|
+ self.setLargeVideoVisible(false);
|
|
653
|
+ $('#etherpad>iframe').css({visibility: 'hidden'});
|
|
654
|
+ $('#etherpad').css({zIndex: 0});
|
|
655
|
+ });
|
|
656
|
+ $('#activeSpeaker').css('visibility', 'hidden');
|
|
657
|
+ break;
|
|
658
|
+
|
|
659
|
+ case "video":
|
|
660
|
+ currentContainer.fadeOut(300, function () {
|
|
661
|
+ $('#presentation>iframe').css({opacity:'0'});
|
|
662
|
+ $('#reloadPresentation').css({display:'none'});
|
|
663
|
+ $('#etherpad>iframe').css({visibility: 'hidden'});
|
|
664
|
+ $('#etherpad').css({zIndex: 0});
|
|
665
|
+ document.body.style.background = 'black';
|
|
666
|
+ ToolbarToggler.dockToolbar(false);//fix that
|
|
667
|
+ });
|
|
668
|
+ $('#largeVideo').fadeIn(300, function () {
|
|
669
|
+ self.setLargeVideoVisible(true);
|
|
670
|
+ });
|
|
671
|
+ break;
|
|
672
|
+ }
|
|
673
|
+
|
|
674
|
+ state = newState;
|
|
675
|
+
|
|
676
|
+ },
|
|
677
|
+ /**
|
|
678
|
+ * Returns the current state of the large video.
|
|
679
|
+ * @returns {string} the current state - video, prezi or etherpad.
|
|
680
|
+ */
|
|
681
|
+ getState: function () {
|
|
682
|
+ return state;
|
|
683
|
+ },
|
|
684
|
+ /**
|
|
685
|
+ * Sets hover handlers for the large video container div.
|
|
686
|
+ * @param inHandler
|
|
687
|
+ * @param outHandler
|
|
688
|
+ */
|
|
689
|
+ setHover: function(inHandler, outHandler)
|
|
690
|
+ {
|
|
691
|
+ $('#largeVideoContainer').hover(inHandler, outHandler);
|
460
|
692
|
}
|
461
|
693
|
|
462
|
|
-}
|
|
694
|
+};
|
463
|
695
|
|
464
|
696
|
|
465
|
697
|
module.exports = LargeVideo;
|