|
@@ -15,6 +15,7 @@ var ssrc2jid = {};
|
15
|
15
|
*/
|
16
|
16
|
var ssrc2videoType = {};
|
17
|
17
|
var videoSrcToSsrc = {};
|
|
18
|
+var mutedAudios = {};
|
18
|
19
|
|
19
|
20
|
var localVideoSrc = null;
|
20
|
21
|
var flipXLocalVideo = true;
|
|
@@ -35,6 +36,8 @@ var getVideoPosition;
|
35
|
36
|
|
36
|
37
|
/* window.onbeforeunload = closePageWarning; */
|
37
|
38
|
|
|
39
|
+var preMuted = false;
|
|
40
|
+
|
38
|
41
|
function init() {
|
39
|
42
|
RTC = setupRTC();
|
40
|
43
|
if (RTC === null) {
|
|
@@ -179,6 +182,10 @@ function change_local_audio(stream) {
|
179
|
182
|
RTC.attachMediaStream($('#localAudio'), stream);
|
180
|
183
|
document.getElementById('localAudio').autoplay = true;
|
181
|
184
|
document.getElementById('localAudio').volume = 0;
|
|
185
|
+ if (preMuted) {
|
|
186
|
+ toggleAudio();
|
|
187
|
+ preMuted = false;
|
|
188
|
+ }
|
182
|
189
|
}
|
183
|
190
|
|
184
|
191
|
function change_local_video(stream, flipX) {
|
|
@@ -485,8 +492,13 @@ $(document).bind('callactive.jingle', function (event, videoelem, sid) {
|
485
|
492
|
}
|
486
|
493
|
});
|
487
|
494
|
|
488
|
|
-$(document).bind('callterminated.jingle', function (event, sid, reason) {
|
489
|
|
- // FIXME
|
|
495
|
+$(document).bind('callterminated.jingle', function (event, sid, jid, reason) {
|
|
496
|
+ // Leave the room if my call has been remotely terminated.
|
|
497
|
+ if (connection.emuc.joined && focus == null && reason === 'kick') {
|
|
498
|
+ connection.emuc.doLeave();
|
|
499
|
+ openMessageDialog( "Session Terminated",
|
|
500
|
+ "Ouch! You have been kicked out of the meet!");
|
|
501
|
+ }
|
490
|
502
|
});
|
491
|
503
|
|
492
|
504
|
$(document).bind('setLocalDescription.jingle', function (event, sid) {
|
|
@@ -579,15 +591,25 @@ $(document).bind('entered.muc', function (event, jid, info, pres) {
|
579
|
591
|
});
|
580
|
592
|
|
581
|
593
|
$(document).bind('left.muc', function (event, jid) {
|
582
|
|
- console.log('left', jid);
|
|
594
|
+ console.log('left.muc', jid);
|
|
595
|
+ // Need to call this with a slight delay, otherwise the element couldn't be
|
|
596
|
+ // found for some reason.
|
|
597
|
+ window.setTimeout(function () {
|
|
598
|
+ var container = document.getElementById(
|
|
599
|
+ 'participant_' + Strophe.getResourceFromJid(jid));
|
|
600
|
+ if (container) {
|
|
601
|
+ // hide here, wait for video to close before removing
|
|
602
|
+ $(container).hide();
|
|
603
|
+ resizeThumbnails();
|
|
604
|
+ }
|
|
605
|
+ }, 10);
|
|
606
|
+
|
583
|
607
|
connection.jingle.terminateByJid(jid);
|
584
|
|
- var container = document.getElementById('participant_' + Strophe.getResourceFromJid(jid));
|
585
|
|
- if (container) {
|
586
|
|
- // hide here, wait for video to close before removing
|
587
|
|
- $(container).hide();
|
588
|
|
- resizeThumbnails();
|
589
|
|
- }
|
590
|
|
- if (focus === null && connection.emuc.myroomjid === connection.emuc.list_members[0]) {
|
|
608
|
+
|
|
609
|
+ if (focus == null
|
|
610
|
+ && jid !== connection.emuc.myroomjid
|
|
611
|
+ && connection.emuc.myroomjid === connection.emuc.list_members[0]
|
|
612
|
+ && connection.emuc.list_members.length > 1) {
|
591
|
613
|
console.log('welcome to our new focus... myself');
|
592
|
614
|
focus = new ColibriFocus(connection, config.hosts.bridge);
|
593
|
615
|
if (Object.keys(connection.emuc.members).length > 0) {
|
|
@@ -603,7 +625,8 @@ $(document).bind('left.muc', function (event, jid) {
|
603
|
625
|
focus = new ColibriFocus(connection, config.hosts.bridge);
|
604
|
626
|
}
|
605
|
627
|
if (connection.emuc.getPrezi(jid)) {
|
606
|
|
- $(document).trigger('presentationremoved.muc', [jid, connection.emuc.getPrezi(jid)]);
|
|
628
|
+ $(document).trigger('presentationremoved.muc',
|
|
629
|
+ [jid, connection.emuc.getPrezi(jid)]);
|
607
|
630
|
}
|
608
|
631
|
});
|
609
|
632
|
|
|
@@ -686,6 +709,11 @@ $(document).bind('audiomuted.muc', function (event, jid, isMuted) {
|
686
|
709
|
videoSpanId = 'participant_' + Strophe.getResourceFromJid(jid);
|
687
|
710
|
}
|
688
|
711
|
|
|
712
|
+ if (focus) {
|
|
713
|
+ mutedAudios[jid] = isMuted;
|
|
714
|
+ updateRemoteVideoMenu(jid, isMuted);
|
|
715
|
+ }
|
|
716
|
+
|
689
|
717
|
if (videoSpanId)
|
690
|
718
|
showAudioIndicator(videoSpanId, isMuted);
|
691
|
719
|
});
|
|
@@ -700,7 +728,7 @@ $(document).bind('videomuted.muc', function (event, jid, isMuted) {
|
700
|
728
|
}
|
701
|
729
|
|
702
|
730
|
if (videoSpanId)
|
703
|
|
- showAudioIndicator(videoSpanId, isMuted);
|
|
731
|
+ showVideoIndicator(videoSpanId, isMuted);
|
704
|
732
|
});
|
705
|
733
|
|
706
|
734
|
/**
|
|
@@ -821,8 +849,11 @@ function toggleVideo() {
|
821
|
849
|
* Mutes / unmutes audio for the local participant.
|
822
|
850
|
*/
|
823
|
851
|
function toggleAudio() {
|
824
|
|
- if (!(connection && connection.jingle.localAudio))
|
|
852
|
+ if (!(connection && connection.jingle.localAudio)) {
|
|
853
|
+ preMuted = true;
|
825
|
854
|
return;
|
|
855
|
+ }
|
|
856
|
+
|
826
|
857
|
var localAudio = connection.jingle.localAudio;
|
827
|
858
|
for (var idx = 0; idx < localAudio.getAudioTracks().length; idx++) {
|
828
|
859
|
var audioEnabled = localAudio.getAudioTracks()[idx].enabled;
|
|
@@ -831,6 +862,8 @@ function toggleAudio() {
|
831
|
862
|
connection.emuc.addAudioInfoToPresence(audioEnabled); //isMuted is the opposite of audioEnabled
|
832
|
863
|
connection.emuc.sendPresence();
|
833
|
864
|
}
|
|
865
|
+
|
|
866
|
+ buttonClick("#mute", "icon-microphone icon-mic-disabled");
|
834
|
867
|
}
|
835
|
868
|
|
836
|
869
|
/**
|
|
@@ -1167,6 +1200,22 @@ function buttonClick(id, classname) {
|
1167
|
1200
|
$(id).toggleClass(classname); // add the class to the clicked element
|
1168
|
1201
|
}
|
1169
|
1202
|
|
|
1203
|
+/**
|
|
1204
|
+ * Shows a message to the user.
|
|
1205
|
+ *
|
|
1206
|
+ * @param titleString the title of the message
|
|
1207
|
+ * @param messageString the text of the message
|
|
1208
|
+ */
|
|
1209
|
+function openMessageDialog(titleString, messageString) {
|
|
1210
|
+ console.log("OPEN MESSAGE DIALOG");
|
|
1211
|
+ $.prompt(messageString,
|
|
1212
|
+ {
|
|
1213
|
+ title: titleString,
|
|
1214
|
+ persistent: false
|
|
1215
|
+ }
|
|
1216
|
+ );
|
|
1217
|
+}
|
|
1218
|
+
|
1170
|
1219
|
/**
|
1171
|
1220
|
* Opens the lock room dialog.
|
1172
|
1221
|
*/
|
|
@@ -1448,7 +1497,7 @@ function ensurePeerContainerExists(peerJid) {
|
1448
|
1497
|
return;
|
1449
|
1498
|
}
|
1450
|
1499
|
|
1451
|
|
- var container = addRemoteVideoContainer(videoSpanId);
|
|
1500
|
+ var container = addRemoteVideoContainer(peerJid, videoSpanId);
|
1452
|
1501
|
|
1453
|
1502
|
var nickfield = document.createElement('span');
|
1454
|
1503
|
nickfield.className = "nick";
|
|
@@ -1457,11 +1506,15 @@ function ensurePeerContainerExists(peerJid) {
|
1457
|
1506
|
resizeThumbnails();
|
1458
|
1507
|
}
|
1459
|
1508
|
|
1460
|
|
-function addRemoteVideoContainer(id) {
|
|
1509
|
+function addRemoteVideoContainer(peerJid, spanId) {
|
1461
|
1510
|
var container = document.createElement('span');
|
1462
|
|
- container.id = id;
|
|
1511
|
+ container.id = spanId;
|
1463
|
1512
|
container.className = 'videocontainer';
|
1464
|
1513
|
var remotes = document.getElementById('remoteVideos');
|
|
1514
|
+
|
|
1515
|
+ if (focus)
|
|
1516
|
+ addRemoteVideoMenu(peerJid, container);
|
|
1517
|
+
|
1465
|
1518
|
remotes.appendChild(container);
|
1466
|
1519
|
return container;
|
1467
|
1520
|
}
|
|
@@ -1476,6 +1529,97 @@ function createFocusIndicatorElement(parentElement) {
|
1476
|
1529
|
parentElement.appendChild(focusIndicator);
|
1477
|
1530
|
}
|
1478
|
1531
|
|
|
1532
|
+function addRemoteVideoMenu(jid, parentElement) {
|
|
1533
|
+ var spanElement = document.createElement('span');
|
|
1534
|
+ spanElement.className = 'remotevideomenu';
|
|
1535
|
+
|
|
1536
|
+ parentElement.appendChild(spanElement);
|
|
1537
|
+
|
|
1538
|
+ var menuElement = document.createElement('i');
|
|
1539
|
+ menuElement.className = 'fa fa-angle-down';
|
|
1540
|
+ menuElement.title = 'Remote user controls';
|
|
1541
|
+ spanElement.appendChild(menuElement);
|
|
1542
|
+
|
|
1543
|
+// <ul class="popupmenu">
|
|
1544
|
+// <li><a href="#">Mute</a></li>
|
|
1545
|
+// <li><a href="#">Eject</a></li>
|
|
1546
|
+// </ul>
|
|
1547
|
+ var popupmenuElement = document.createElement('ul');
|
|
1548
|
+ popupmenuElement.className = 'popupmenu';
|
|
1549
|
+ popupmenuElement.id = 'remote_popupmenu_' + Strophe.getResourceFromJid(jid);
|
|
1550
|
+ spanElement.appendChild(popupmenuElement);
|
|
1551
|
+
|
|
1552
|
+ var muteMenuItem = document.createElement('li');
|
|
1553
|
+ var muteLinkItem = document.createElement('a');
|
|
1554
|
+
|
|
1555
|
+ var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
|
1556
|
+
|
|
1557
|
+ if (!mutedAudios[jid]) {
|
|
1558
|
+ muteLinkItem.innerHTML = mutedIndicator + 'Mute';
|
|
1559
|
+ muteLinkItem.className = 'mutelink';
|
|
1560
|
+ }
|
|
1561
|
+ else {
|
|
1562
|
+ muteLinkItem.innerHTML = mutedIndicator + ' Muted';
|
|
1563
|
+ muteLinkItem.className = 'mutelink disabled';
|
|
1564
|
+ }
|
|
1565
|
+
|
|
1566
|
+ muteLinkItem.onclick = function(){
|
|
1567
|
+ if ($(this).attr('disabled') != undefined) {
|
|
1568
|
+ event.preventDefault();
|
|
1569
|
+ }
|
|
1570
|
+ var isMute = !mutedAudios[jid];
|
|
1571
|
+ connection.moderate.setMute(jid, isMute);
|
|
1572
|
+ popupmenuElement.setAttribute('style', 'display:none;');
|
|
1573
|
+
|
|
1574
|
+ if (isMute) {
|
|
1575
|
+ this.innerHTML = mutedIndicator + ' Muted';
|
|
1576
|
+ this.className = 'mutelink disabled';
|
|
1577
|
+ }
|
|
1578
|
+ else {
|
|
1579
|
+ this.innerHTML = mutedIndicator + ' Mute';
|
|
1580
|
+ this.className = 'mutelink';
|
|
1581
|
+ }
|
|
1582
|
+ };
|
|
1583
|
+
|
|
1584
|
+ muteMenuItem.appendChild(muteLinkItem);
|
|
1585
|
+ popupmenuElement.appendChild(muteMenuItem);
|
|
1586
|
+
|
|
1587
|
+ var ejectIndicator = "<i class='fa fa-eject'></i>";
|
|
1588
|
+
|
|
1589
|
+ var ejectMenuItem = document.createElement('li');
|
|
1590
|
+ var ejectLinkItem = document.createElement('a');
|
|
1591
|
+ ejectLinkItem.innerHTML = ejectIndicator + ' Kick out';
|
|
1592
|
+ ejectLinkItem.onclick = function(){
|
|
1593
|
+ connection.moderate.eject(jid);
|
|
1594
|
+ popupmenuElement.setAttribute('style', 'display:none;');
|
|
1595
|
+ };
|
|
1596
|
+
|
|
1597
|
+ ejectMenuItem.appendChild(ejectLinkItem);
|
|
1598
|
+ popupmenuElement.appendChild(ejectMenuItem);
|
|
1599
|
+}
|
|
1600
|
+
|
|
1601
|
+function updateRemoteVideoMenu(jid, isMuted) {
|
|
1602
|
+ var muteMenuItem
|
|
1603
|
+ = $('#remote_popupmenu_'
|
|
1604
|
+ + Strophe.getResourceFromJid(jid)
|
|
1605
|
+ + '>li>a.mutelink');
|
|
1606
|
+
|
|
1607
|
+ var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
|
1608
|
+
|
|
1609
|
+ if (muteMenuItem.length) {
|
|
1610
|
+ var muteLink = muteMenuItem.get(0);
|
|
1611
|
+
|
|
1612
|
+ if (isMuted === 'true') {
|
|
1613
|
+ muteLink.innerHTML = mutedIndicator + ' Muted';
|
|
1614
|
+ muteLink.className = 'mutelink disabled';
|
|
1615
|
+ }
|
|
1616
|
+ else {
|
|
1617
|
+ muteLink.innerHTML = mutedIndicator + ' Mute';
|
|
1618
|
+ muteLink.className = 'mutelink';
|
|
1619
|
+ }
|
|
1620
|
+ }
|
|
1621
|
+}
|
|
1622
|
+
|
1479
|
1623
|
/**
|
1480
|
1624
|
* Toggles the application in and out of full screen mode
|
1481
|
1625
|
* (a.k.a. presentation mode in Chrome).
|