Adds mute and kick functoinality avaialable for the focus of the conference.
This commit is contained in:
parent
ca1fc93b2d
commit
56424df0a0
176
app.js
176
app.js
|
@ -15,6 +15,7 @@ var ssrc2jid = {};
|
||||||
*/
|
*/
|
||||||
var ssrc2videoType = {};
|
var ssrc2videoType = {};
|
||||||
var videoSrcToSsrc = {};
|
var videoSrcToSsrc = {};
|
||||||
|
var mutedAudios = {};
|
||||||
|
|
||||||
var localVideoSrc = null;
|
var localVideoSrc = null;
|
||||||
var flipXLocalVideo = true;
|
var flipXLocalVideo = true;
|
||||||
|
@ -35,6 +36,8 @@ var getVideoPosition;
|
||||||
|
|
||||||
/* window.onbeforeunload = closePageWarning; */
|
/* window.onbeforeunload = closePageWarning; */
|
||||||
|
|
||||||
|
var preMuted = false;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
RTC = setupRTC();
|
RTC = setupRTC();
|
||||||
if (RTC === null) {
|
if (RTC === null) {
|
||||||
|
@ -179,6 +182,10 @@ function change_local_audio(stream) {
|
||||||
RTC.attachMediaStream($('#localAudio'), stream);
|
RTC.attachMediaStream($('#localAudio'), stream);
|
||||||
document.getElementById('localAudio').autoplay = true;
|
document.getElementById('localAudio').autoplay = true;
|
||||||
document.getElementById('localAudio').volume = 0;
|
document.getElementById('localAudio').volume = 0;
|
||||||
|
if (preMuted) {
|
||||||
|
toggleAudio();
|
||||||
|
preMuted = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function change_local_video(stream, flipX) {
|
function change_local_video(stream, flipX) {
|
||||||
|
@ -485,8 +492,13 @@ $(document).bind('callactive.jingle', function (event, videoelem, sid) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).bind('callterminated.jingle', function (event, sid, reason) {
|
$(document).bind('callterminated.jingle', function (event, sid, jid, reason) {
|
||||||
// FIXME
|
// Leave the room if my call has been remotely terminated.
|
||||||
|
if (connection.emuc.joined && focus == null && reason === 'kick') {
|
||||||
|
connection.emuc.doLeave();
|
||||||
|
openMessageDialog( "Session Terminated",
|
||||||
|
"Ouch! You have been kicked out of the meet!");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).bind('setLocalDescription.jingle', function (event, sid) {
|
$(document).bind('setLocalDescription.jingle', function (event, sid) {
|
||||||
|
@ -579,15 +591,25 @@ $(document).bind('entered.muc', function (event, jid, info, pres) {
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).bind('left.muc', function (event, jid) {
|
$(document).bind('left.muc', function (event, jid) {
|
||||||
console.log('left', jid);
|
console.log('left.muc', jid);
|
||||||
|
// Need to call this with a slight delay, otherwise the element couldn't be
|
||||||
|
// found for some reason.
|
||||||
|
window.setTimeout(function () {
|
||||||
|
var container = document.getElementById(
|
||||||
|
'participant_' + Strophe.getResourceFromJid(jid));
|
||||||
|
if (container) {
|
||||||
|
// hide here, wait for video to close before removing
|
||||||
|
$(container).hide();
|
||||||
|
resizeThumbnails();
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
|
||||||
connection.jingle.terminateByJid(jid);
|
connection.jingle.terminateByJid(jid);
|
||||||
var container = document.getElementById('participant_' + Strophe.getResourceFromJid(jid));
|
|
||||||
if (container) {
|
if (focus == null
|
||||||
// hide here, wait for video to close before removing
|
&& jid !== connection.emuc.myroomjid
|
||||||
$(container).hide();
|
&& connection.emuc.myroomjid === connection.emuc.list_members[0]
|
||||||
resizeThumbnails();
|
&& connection.emuc.list_members.length > 1) {
|
||||||
}
|
|
||||||
if (focus === null && connection.emuc.myroomjid === connection.emuc.list_members[0]) {
|
|
||||||
console.log('welcome to our new focus... myself');
|
console.log('welcome to our new focus... myself');
|
||||||
focus = new ColibriFocus(connection, config.hosts.bridge);
|
focus = new ColibriFocus(connection, config.hosts.bridge);
|
||||||
if (Object.keys(connection.emuc.members).length > 0) {
|
if (Object.keys(connection.emuc.members).length > 0) {
|
||||||
|
@ -603,7 +625,8 @@ $(document).bind('left.muc', function (event, jid) {
|
||||||
focus = new ColibriFocus(connection, config.hosts.bridge);
|
focus = new ColibriFocus(connection, config.hosts.bridge);
|
||||||
}
|
}
|
||||||
if (connection.emuc.getPrezi(jid)) {
|
if (connection.emuc.getPrezi(jid)) {
|
||||||
$(document).trigger('presentationremoved.muc', [jid, connection.emuc.getPrezi(jid)]);
|
$(document).trigger('presentationremoved.muc',
|
||||||
|
[jid, connection.emuc.getPrezi(jid)]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -686,6 +709,11 @@ $(document).bind('audiomuted.muc', function (event, jid, isMuted) {
|
||||||
videoSpanId = 'participant_' + Strophe.getResourceFromJid(jid);
|
videoSpanId = 'participant_' + Strophe.getResourceFromJid(jid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (focus) {
|
||||||
|
mutedAudios[jid] = isMuted;
|
||||||
|
updateRemoteVideoMenu(jid, isMuted);
|
||||||
|
}
|
||||||
|
|
||||||
if (videoSpanId)
|
if (videoSpanId)
|
||||||
showAudioIndicator(videoSpanId, isMuted);
|
showAudioIndicator(videoSpanId, isMuted);
|
||||||
});
|
});
|
||||||
|
@ -700,7 +728,7 @@ $(document).bind('videomuted.muc', function (event, jid, isMuted) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoSpanId)
|
if (videoSpanId)
|
||||||
showAudioIndicator(videoSpanId, isMuted);
|
showVideoIndicator(videoSpanId, isMuted);
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -821,8 +849,11 @@ function toggleVideo() {
|
||||||
* Mutes / unmutes audio for the local participant.
|
* Mutes / unmutes audio for the local participant.
|
||||||
*/
|
*/
|
||||||
function toggleAudio() {
|
function toggleAudio() {
|
||||||
if (!(connection && connection.jingle.localAudio))
|
if (!(connection && connection.jingle.localAudio)) {
|
||||||
|
preMuted = true;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var localAudio = connection.jingle.localAudio;
|
var localAudio = connection.jingle.localAudio;
|
||||||
for (var idx = 0; idx < localAudio.getAudioTracks().length; idx++) {
|
for (var idx = 0; idx < localAudio.getAudioTracks().length; idx++) {
|
||||||
var audioEnabled = localAudio.getAudioTracks()[idx].enabled;
|
var audioEnabled = localAudio.getAudioTracks()[idx].enabled;
|
||||||
|
@ -831,6 +862,8 @@ function toggleAudio() {
|
||||||
connection.emuc.addAudioInfoToPresence(audioEnabled); //isMuted is the opposite of audioEnabled
|
connection.emuc.addAudioInfoToPresence(audioEnabled); //isMuted is the opposite of audioEnabled
|
||||||
connection.emuc.sendPresence();
|
connection.emuc.sendPresence();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buttonClick("#mute", "icon-microphone icon-mic-disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1167,6 +1200,22 @@ function buttonClick(id, classname) {
|
||||||
$(id).toggleClass(classname); // add the class to the clicked element
|
$(id).toggleClass(classname); // add the class to the clicked element
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a message to the user.
|
||||||
|
*
|
||||||
|
* @param titleString the title of the message
|
||||||
|
* @param messageString the text of the message
|
||||||
|
*/
|
||||||
|
function openMessageDialog(titleString, messageString) {
|
||||||
|
console.log("OPEN MESSAGE DIALOG");
|
||||||
|
$.prompt(messageString,
|
||||||
|
{
|
||||||
|
title: titleString,
|
||||||
|
persistent: false
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the lock room dialog.
|
* Opens the lock room dialog.
|
||||||
*/
|
*/
|
||||||
|
@ -1448,7 +1497,7 @@ function ensurePeerContainerExists(peerJid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var container = addRemoteVideoContainer(videoSpanId);
|
var container = addRemoteVideoContainer(peerJid, videoSpanId);
|
||||||
|
|
||||||
var nickfield = document.createElement('span');
|
var nickfield = document.createElement('span');
|
||||||
nickfield.className = "nick";
|
nickfield.className = "nick";
|
||||||
|
@ -1457,11 +1506,15 @@ function ensurePeerContainerExists(peerJid) {
|
||||||
resizeThumbnails();
|
resizeThumbnails();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addRemoteVideoContainer(id) {
|
function addRemoteVideoContainer(peerJid, spanId) {
|
||||||
var container = document.createElement('span');
|
var container = document.createElement('span');
|
||||||
container.id = id;
|
container.id = spanId;
|
||||||
container.className = 'videocontainer';
|
container.className = 'videocontainer';
|
||||||
var remotes = document.getElementById('remoteVideos');
|
var remotes = document.getElementById('remoteVideos');
|
||||||
|
|
||||||
|
if (focus)
|
||||||
|
addRemoteVideoMenu(peerJid, container);
|
||||||
|
|
||||||
remotes.appendChild(container);
|
remotes.appendChild(container);
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
@ -1476,6 +1529,97 @@ function createFocusIndicatorElement(parentElement) {
|
||||||
parentElement.appendChild(focusIndicator);
|
parentElement.appendChild(focusIndicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addRemoteVideoMenu(jid, parentElement) {
|
||||||
|
var spanElement = document.createElement('span');
|
||||||
|
spanElement.className = 'remotevideomenu';
|
||||||
|
|
||||||
|
parentElement.appendChild(spanElement);
|
||||||
|
|
||||||
|
var menuElement = document.createElement('i');
|
||||||
|
menuElement.className = 'fa fa-angle-down';
|
||||||
|
menuElement.title = 'Remote user controls';
|
||||||
|
spanElement.appendChild(menuElement);
|
||||||
|
|
||||||
|
// <ul class="popupmenu">
|
||||||
|
// <li><a href="#">Mute</a></li>
|
||||||
|
// <li><a href="#">Eject</a></li>
|
||||||
|
// </ul>
|
||||||
|
var popupmenuElement = document.createElement('ul');
|
||||||
|
popupmenuElement.className = 'popupmenu';
|
||||||
|
popupmenuElement.id = 'remote_popupmenu_' + Strophe.getResourceFromJid(jid);
|
||||||
|
spanElement.appendChild(popupmenuElement);
|
||||||
|
|
||||||
|
var muteMenuItem = document.createElement('li');
|
||||||
|
var muteLinkItem = document.createElement('a');
|
||||||
|
|
||||||
|
var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
||||||
|
|
||||||
|
if (!mutedAudios[jid]) {
|
||||||
|
muteLinkItem.innerHTML = mutedIndicator + 'Mute';
|
||||||
|
muteLinkItem.className = 'mutelink';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
muteLinkItem.innerHTML = mutedIndicator + ' Muted';
|
||||||
|
muteLinkItem.className = 'mutelink disabled';
|
||||||
|
}
|
||||||
|
|
||||||
|
muteLinkItem.onclick = function(){
|
||||||
|
if ($(this).attr('disabled') != undefined) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
var isMute = !mutedAudios[jid];
|
||||||
|
connection.moderate.setMute(jid, isMute);
|
||||||
|
popupmenuElement.setAttribute('style', 'display:none;');
|
||||||
|
|
||||||
|
if (isMute) {
|
||||||
|
this.innerHTML = mutedIndicator + ' Muted';
|
||||||
|
this.className = 'mutelink disabled';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.innerHTML = mutedIndicator + ' Mute';
|
||||||
|
this.className = 'mutelink';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
muteMenuItem.appendChild(muteLinkItem);
|
||||||
|
popupmenuElement.appendChild(muteMenuItem);
|
||||||
|
|
||||||
|
var ejectIndicator = "<i class='fa fa-eject'></i>";
|
||||||
|
|
||||||
|
var ejectMenuItem = document.createElement('li');
|
||||||
|
var ejectLinkItem = document.createElement('a');
|
||||||
|
ejectLinkItem.innerHTML = ejectIndicator + ' Kick out';
|
||||||
|
ejectLinkItem.onclick = function(){
|
||||||
|
connection.moderate.eject(jid);
|
||||||
|
popupmenuElement.setAttribute('style', 'display:none;');
|
||||||
|
};
|
||||||
|
|
||||||
|
ejectMenuItem.appendChild(ejectLinkItem);
|
||||||
|
popupmenuElement.appendChild(ejectMenuItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateRemoteVideoMenu(jid, isMuted) {
|
||||||
|
var muteMenuItem
|
||||||
|
= $('#remote_popupmenu_'
|
||||||
|
+ Strophe.getResourceFromJid(jid)
|
||||||
|
+ '>li>a.mutelink');
|
||||||
|
|
||||||
|
var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
||||||
|
|
||||||
|
if (muteMenuItem.length) {
|
||||||
|
var muteLink = muteMenuItem.get(0);
|
||||||
|
|
||||||
|
if (isMuted === 'true') {
|
||||||
|
muteLink.innerHTML = mutedIndicator + ' Muted';
|
||||||
|
muteLink.className = 'mutelink disabled';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
muteLink.innerHTML = mutedIndicator + ' Mute';
|
||||||
|
muteLink.className = 'mutelink';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggles the application in and out of full screen mode
|
* Toggles the application in and out of full screen mode
|
||||||
* (a.k.a. presentation mode in Chrome).
|
* (a.k.a. presentation mode in Chrome).
|
||||||
|
|
|
@ -205,7 +205,6 @@ button {
|
||||||
}
|
}
|
||||||
|
|
||||||
button, input, select, textarea {
|
button, input, select, textarea {
|
||||||
font-size: 100%;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
vertical-align: baseline;
|
vertical-align: baseline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*Initialize*/
|
||||||
|
ul.popupmenu {
|
||||||
|
display:none;
|
||||||
|
position: absolute;
|
||||||
|
padding:0;
|
||||||
|
margin: 0;
|
||||||
|
bottom: 20px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
right: 10px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100px;
|
||||||
|
background-color: rgba(0,0,0,1);
|
||||||
|
-webkit-box-shadow: 0 0 2px #000000, 0 0 10px #000000;
|
||||||
|
border-radius:8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.popupmenu:after {
|
||||||
|
content: url('../images/popupPointer.png');
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -9px;
|
||||||
|
left: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.popupmenu li {
|
||||||
|
list-style-type: none;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.popupmenu li:hover {
|
||||||
|
background-color: rgba(82, 82, 82, .7);
|
||||||
|
border-radius:2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Link Appearance*/
|
||||||
|
ul.popupmenu li a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #fff;
|
||||||
|
padding: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 9pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul.popupmenu li a i {
|
||||||
|
width: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.remotevideomenu:hover ul.popupmenu {
|
||||||
|
display:block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.disabled {
|
||||||
|
color: gray !important;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
|
@ -16,9 +16,8 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
width:auto;
|
width:auto;
|
||||||
overflow: hidden;
|
|
||||||
border:1px solid transparent;
|
border:1px solid transparent;
|
||||||
z-index: 2;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.videocontainer {
|
.videocontainer {
|
||||||
|
@ -41,8 +40,8 @@
|
||||||
content:"";
|
content:"";
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
cursor: hand;
|
cursor: hand;
|
||||||
transform:scale(1.08, 1.08);
|
/* transform:scale(1.08, 1.08);
|
||||||
-webkit-transform:scale(1.08, 1.08);
|
-webkit-transform:scale(1.08, 1.08); */
|
||||||
transition-duration: 0.5s;
|
transition-duration: 0.5s;
|
||||||
-webkit-transition-duration: 0.5s;
|
-webkit-transition-duration: 0.5s;
|
||||||
-webkit-animation-name: greyPulse;
|
-webkit-animation-name: greyPulse;
|
||||||
|
@ -107,7 +106,8 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#remoteVideos .videocontainer>span.focusindicator {
|
#remoteVideos .videocontainer>span.focusindicator,
|
||||||
|
#remoteVideos .videocontainer>span.remotevideomenu {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -31,6 +31,7 @@
|
||||||
<script src="prezi.js?v=2"></script><!-- prezi plugin -->
|
<script src="prezi.js?v=2"></script><!-- prezi plugin -->
|
||||||
<script src="smileys.js?v=1"></script><!-- smiley images -->
|
<script src="smileys.js?v=1"></script><!-- smiley images -->
|
||||||
<script src="replacement.js?v=5"></script><!-- link and smiley replacement -->
|
<script src="replacement.js?v=5"></script><!-- link and smiley replacement -->
|
||||||
|
<script src="moderatemuc.js?v=1"></script><!-- moderator plugin -->
|
||||||
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
|
<script src="analytics.js?v=1"></script><!-- google analytics plugin -->
|
||||||
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="css/font.css"/>
|
<link rel="stylesheet" href="css/font.css"/>
|
||||||
|
@ -38,6 +39,7 @@
|
||||||
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=4" id="videolayout_default"/>
|
<link rel="stylesheet" type="text/css" media="screen" href="css/videolayout_default.css?v=4" id="videolayout_default"/>
|
||||||
<link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
|
<link rel="stylesheet" href="css/jquery-impromptu.css?v=4">
|
||||||
<link rel="stylesheet" href="css/modaldialog.css?v=3">
|
<link rel="stylesheet" href="css/modaldialog.css?v=3">
|
||||||
|
<link rel="stylesheet" href="css/popup_menu.css?v=1">
|
||||||
<!--
|
<!--
|
||||||
Link used for inline installation of chrome desktop streaming extension,
|
Link used for inline installation of chrome desktop streaming extension,
|
||||||
is updated automatically from the code with the value defined in config.js -->
|
is updated automatically from the code with the value defined in config.js -->
|
||||||
|
@ -49,7 +51,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<span id="toolbar">
|
<span id="toolbar">
|
||||||
<a class="button" onclick='buttonClick("#mute", "icon-microphone icon-mic-disabled");toggleAudio();'>
|
<a class="button" onclick='toggleAudio();'>
|
||||||
<i id="mute" title="Mute / unmute" class="icon-microphone"></i></a>
|
<i id="mute" title="Mute / unmute" class="icon-microphone"></i></a>
|
||||||
<div class="header_button_separator"></div>
|
<div class="header_button_separator"></div>
|
||||||
<a class="button" onclick='buttonClick("#video", "icon-camera icon-camera-disabled");toggleVideo();'>
|
<a class="button" onclick='buttonClick("#video", "icon-camera icon-camera-disabled");toggleVideo();'>
|
||||||
|
|
|
@ -848,3 +848,46 @@ ColibriFocus.prototype.terminate = function (session, reason) {
|
||||||
delete this.remotessrc[session.peerjid];
|
delete this.remotessrc[session.peerjid];
|
||||||
this.modifySources();
|
this.modifySources();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ColibriFocus.prototype.sendTerminate = function (session, reason, text) {
|
||||||
|
var term = $iq({to: session.peerjid, type: 'set'})
|
||||||
|
.c('jingle',
|
||||||
|
{xmlns: 'urn:xmpp:jingle:1',
|
||||||
|
action: 'session-terminate',
|
||||||
|
initiator: session.me,
|
||||||
|
sid: session.sid})
|
||||||
|
.c('reason')
|
||||||
|
.c(reason || 'success');
|
||||||
|
|
||||||
|
if (text) {
|
||||||
|
term.up().c('text').t(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.connection.sendIQ(term,
|
||||||
|
function () {
|
||||||
|
if (!session)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (session.peerconnection) {
|
||||||
|
session.peerconnection.close();
|
||||||
|
session.peerconnection = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.terminate();
|
||||||
|
var ack = {};
|
||||||
|
ack.source = 'terminate';
|
||||||
|
$(document).trigger('ack.jingle', [session.sid, ack]);
|
||||||
|
},
|
||||||
|
function (stanza) {
|
||||||
|
var error = ($(stanza).find('error').length) ? {
|
||||||
|
code: $(stanza).find('error').attr('code'),
|
||||||
|
reason: $(stanza).find('error :first')[0].tagName,
|
||||||
|
}:{};
|
||||||
|
$(document).trigger('ack.jingle', [self.sid, error]);
|
||||||
|
},
|
||||||
|
10000);
|
||||||
|
if (this.statsinterval !== null) {
|
||||||
|
window.clearInterval(this.statsinterval);
|
||||||
|
this.statsinterval = null;
|
||||||
|
}
|
||||||
|
};
|
|
@ -90,5 +90,5 @@ ColibriSession.prototype.sendAnswer = function (sdp, provisional) {
|
||||||
};
|
};
|
||||||
|
|
||||||
ColibriSession.prototype.sendTerminate = function (reason, text) {
|
ColibriSession.prototype.sendTerminate = function (reason, text) {
|
||||||
console.log('ColibriSession.sendTerminate');
|
this.colibri.sendTerminate(this, reason, text);
|
||||||
};
|
};
|
||||||
|
|
|
@ -112,17 +112,27 @@ Strophe.addConnectionPlugin('jingle', {
|
||||||
$(document).trigger('callaccepted.jingle', [sess.sid]);
|
$(document).trigger('callaccepted.jingle', [sess.sid]);
|
||||||
break;
|
break;
|
||||||
case 'session-terminate':
|
case 'session-terminate':
|
||||||
console.log('terminating...');
|
// If this is not the focus sending the terminate, we have
|
||||||
|
// nothing more to do here.
|
||||||
|
if (Object.keys(this.sessions).length < 1
|
||||||
|
|| !(this.sessions[Object.keys(this.sessions)[0]]
|
||||||
|
instanceof JingleSession))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
console.log('terminating...', sess.sid);
|
||||||
sess.terminate();
|
sess.terminate();
|
||||||
this.terminate(sess.sid);
|
this.terminate(sess.sid);
|
||||||
if ($(iq).find('>jingle>reason').length) {
|
if ($(iq).find('>jingle>reason').length) {
|
||||||
$(document).trigger('callterminated.jingle', [
|
$(document).trigger('callterminated.jingle', [
|
||||||
sess.sid,
|
sess.sid,
|
||||||
|
sess.peerjid,
|
||||||
$(iq).find('>jingle>reason>:first')[0].tagName,
|
$(iq).find('>jingle>reason>:first')[0].tagName,
|
||||||
$(iq).find('>jingle>reason>text').text()
|
$(iq).find('>jingle>reason>text').text()
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$(document).trigger('callterminated.jingle', [sess.sid]);
|
$(document).trigger('callterminated.jingle',
|
||||||
|
[sess.sid, sess.peerjid]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'transport-info':
|
case 'transport-info':
|
||||||
|
@ -192,6 +202,7 @@ Strophe.addConnectionPlugin('jingle', {
|
||||||
delete this.sessions[sid];
|
delete this.sessions[sid];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// Used to terminate a session when an unavailable presence is received.
|
||||||
terminateByJid: function (jid) {
|
terminateByJid: function (jid) {
|
||||||
if (this.jid2session.hasOwnProperty(jid)) {
|
if (this.jid2session.hasOwnProperty(jid)) {
|
||||||
var sess = this.jid2session[jid];
|
var sess = this.jid2session[jid];
|
||||||
|
@ -200,7 +211,22 @@ Strophe.addConnectionPlugin('jingle', {
|
||||||
console.log('peer went away silently', jid);
|
console.log('peer went away silently', jid);
|
||||||
delete this.sessions[sess.sid];
|
delete this.sessions[sess.sid];
|
||||||
delete this.jid2session[jid];
|
delete this.jid2session[jid];
|
||||||
$(document).trigger('callterminated.jingle', [sess.sid, 'gone']);
|
$(document).trigger('callterminated.jingle',
|
||||||
|
[sess.sid, jid], 'gone');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
terminateRemoteByJid: function (jid, reason) {
|
||||||
|
if (this.jid2session.hasOwnProperty(jid)) {
|
||||||
|
var sess = this.jid2session[jid];
|
||||||
|
if (sess) {
|
||||||
|
sess.sendTerminate(reason || (!sess.active()) ? 'kick' : null);
|
||||||
|
sess.terminate();
|
||||||
|
console.log('terminate peer with jid', sess.sid, jid);
|
||||||
|
delete this.sessions[sess.sid];
|
||||||
|
delete this.jid2session[jid];
|
||||||
|
$(document).trigger('callterminated.jingle',
|
||||||
|
[sess.sid, jid, 'kicked']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/**
|
||||||
|
* Moderate connection plugin.
|
||||||
|
*/
|
||||||
|
Strophe.addConnectionPlugin('moderate', {
|
||||||
|
connection: null,
|
||||||
|
roomjid: null,
|
||||||
|
myroomjid: null,
|
||||||
|
members: {},
|
||||||
|
list_members: [], // so we can elect a new focus
|
||||||
|
presMap: {},
|
||||||
|
preziMap: {},
|
||||||
|
joined: false,
|
||||||
|
isOwner: false,
|
||||||
|
init: function (conn) {
|
||||||
|
this.connection = conn;
|
||||||
|
|
||||||
|
this.connection.addHandler( this.onMute.bind(this),
|
||||||
|
'http://jitsi.org/jitmeet/audio',
|
||||||
|
'iq',
|
||||||
|
'set',
|
||||||
|
null,
|
||||||
|
null);
|
||||||
|
},
|
||||||
|
setMute: function(jid, mute) {
|
||||||
|
var iq = $iq({to: jid, type: 'set'})
|
||||||
|
.c('mute', {xmlns: 'http://jitsi.org/jitmeet/audio'})
|
||||||
|
.t(mute.toString())
|
||||||
|
.up();
|
||||||
|
|
||||||
|
this.connection.sendIQ(
|
||||||
|
iq,
|
||||||
|
function (result) {
|
||||||
|
console.log('set mute', result);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
console.log('set mute error', error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onMute: function(iq) {
|
||||||
|
var mute = $(iq).find('mute');
|
||||||
|
if (mute.length) {
|
||||||
|
toggleAudio();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
eject: function(jid) {
|
||||||
|
connection.jingle.terminateRemoteByJid(jid, 'kick');
|
||||||
|
connection.emuc.kick(jid);
|
||||||
|
}
|
||||||
|
});
|
41
muc.js
41
muc.js
|
@ -36,6 +36,12 @@ Strophe.addConnectionPlugin('emuc', {
|
||||||
}
|
}
|
||||||
this.sendPresence();
|
this.sendPresence();
|
||||||
},
|
},
|
||||||
|
doLeave: function() {
|
||||||
|
console.log("DO LEAVE", this.myroomjid);
|
||||||
|
var pres = $pres({to: this.myroomjid, type: 'unavailable' });
|
||||||
|
this.presMap.length = 0;
|
||||||
|
this.connection.send(pres);
|
||||||
|
},
|
||||||
onPresence: function (pres) {
|
onPresence: function (pres) {
|
||||||
var from = pres.getAttribute('from');
|
var from = pres.getAttribute('from');
|
||||||
var type = pres.getAttribute('type');
|
var type = pres.getAttribute('type');
|
||||||
|
@ -125,9 +131,22 @@ Strophe.addConnectionPlugin('emuc', {
|
||||||
},
|
},
|
||||||
onPresenceUnavailable: function (pres) {
|
onPresenceUnavailable: function (pres) {
|
||||||
var from = pres.getAttribute('from');
|
var from = pres.getAttribute('from');
|
||||||
delete this.members[from];
|
// Status code 110 indicates that this notification is "self-presence".
|
||||||
this.list_members.splice(this.list_members.indexOf(from), 1);
|
if (!$(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="110"]').length) {
|
||||||
$(document).trigger('left.muc', [from]);
|
delete this.members[from];
|
||||||
|
this.list_members.splice(this.list_members.indexOf(from), 1);
|
||||||
|
$(document).trigger('left.muc', [from]);
|
||||||
|
}
|
||||||
|
// If the status code is 110 this means we're leaving and we would like
|
||||||
|
// to remove everyone else from our view, so we trigger the event.
|
||||||
|
else if (this.list_members.length > 1) {
|
||||||
|
for (var i = 0; i < this.list_members.length; i++) {
|
||||||
|
var member = this.list_members[i];
|
||||||
|
delete this.members[i];
|
||||||
|
this.list_members.splice(i, 1);
|
||||||
|
$(document).trigger('left.muc', member);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
onPresenceError: function (pres) {
|
onPresenceError: function (pres) {
|
||||||
|
@ -188,6 +207,21 @@ Strophe.addConnectionPlugin('emuc', {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
kick: function (jid) {
|
||||||
|
var kickIQ = $iq({to: this.roomjid, type: 'set'})
|
||||||
|
.c('query', {xmlns: 'http://jabber.org/protocol/muc#admin'})
|
||||||
|
.c('item', {nick: Strophe.getResourceFromJid(jid), role: 'none'})
|
||||||
|
.c('reason').t('You have been kicked.').up().up().up();
|
||||||
|
|
||||||
|
this.connection.sendIQ(
|
||||||
|
kickIQ,
|
||||||
|
function (result) {
|
||||||
|
console.log('Kick participant with jid: ' + jid, result);
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
console.log('Kick participant error: ', error);
|
||||||
|
});
|
||||||
|
},
|
||||||
sendPresence: function () {
|
sendPresence: function () {
|
||||||
var pres = $pres({to: this.presMap['to'] });
|
var pres = $pres({to: this.presMap['to'] });
|
||||||
pres.c('x', {xmlns: this.presMap['xns']});
|
pres.c('x', {xmlns: this.presMap['xns']});
|
||||||
|
@ -210,7 +244,6 @@ Strophe.addConnectionPlugin('emuc', {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.presMap['videons']) {
|
if (this.presMap['videons']) {
|
||||||
console.log("SEND VIDEO MUTED", this.presMap['videomuted']);
|
|
||||||
pres.c('videomuted', {xmlns: this.presMap['videons']})
|
pres.c('videomuted', {xmlns: this.presMap['videons']})
|
||||||
.t(this.presMap['videomuted']).up();
|
.t(this.presMap['videomuted']).up();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue