fix errors reported by jshint
This commit is contained in:
parent
84593b2bcb
commit
78c8f43c3d
492
app.js
492
app.js
|
@ -24,12 +24,12 @@ var currentVideoWidth = null;
|
||||||
var currentVideoHeight = null;
|
var currentVideoHeight = null;
|
||||||
/**
|
/**
|
||||||
* Method used to calculate large video size.
|
* Method used to calculate large video size.
|
||||||
* @type {function()}
|
* @type {function ()}
|
||||||
*/
|
*/
|
||||||
var getVideoSize;
|
var getVideoSize;
|
||||||
/**
|
/**
|
||||||
* Method used to get large video position.
|
* Method used to get large video position.
|
||||||
* @type {function()}
|
* @type {function ()}
|
||||||
*/
|
*/
|
||||||
var getVideoPosition;
|
var getVideoPosition;
|
||||||
|
|
||||||
|
@ -40,9 +40,11 @@ function init() {
|
||||||
if (RTC === null) {
|
if (RTC === null) {
|
||||||
window.location.href = 'webrtcrequired.html';
|
window.location.href = 'webrtcrequired.html';
|
||||||
return;
|
return;
|
||||||
|
/*
|
||||||
} else if (RTC.browser !== 'chrome') {
|
} else if (RTC.browser !== 'chrome') {
|
||||||
window.location.href = 'chromeonly.html';
|
window.location.href = 'chromeonly.html';
|
||||||
return;
|
return;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind');
|
connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind');
|
||||||
|
@ -69,9 +71,9 @@ function init() {
|
||||||
if (config.useStunTurn) {
|
if (config.useStunTurn) {
|
||||||
connection.jingle.getStunAndTurnCredentials();
|
connection.jingle.getStunAndTurnCredentials();
|
||||||
}
|
}
|
||||||
obtainAudioAndVideoPermissions(function(){
|
obtainAudioAndVideoPermissions(function () {
|
||||||
getUserMediaWithConstraints( ['audio'], audioStreamReady,
|
getUserMediaWithConstraints(['audio'], audioStreamReady,
|
||||||
function(error){
|
function (error) {
|
||||||
console.error('failed to obtain audio stream - stop', error);
|
console.error('failed to obtain audio stream - stop', error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -88,20 +90,20 @@ function init() {
|
||||||
* We first ask for audio and video combined stream in order to get permissions and not to ask twice.
|
* We first ask for audio and video combined stream in order to get permissions and not to ask twice.
|
||||||
* Then we dispose the stream and continue with separate audio, video streams(required for desktop sharing).
|
* Then we dispose the stream and continue with separate audio, video streams(required for desktop sharing).
|
||||||
*/
|
*/
|
||||||
function obtainAudioAndVideoPermissions(callback){
|
function obtainAudioAndVideoPermissions(callback) {
|
||||||
// This makes sense only on https sites otherwise we'll be asked for permissions every time
|
// This makes sense only on https sites otherwise we'll be asked for permissions every time
|
||||||
if(location.protocol !== 'https:') {
|
if (location.protocol !== 'https:') {
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Get AV
|
// Get AV
|
||||||
getUserMediaWithConstraints(
|
getUserMediaWithConstraints(
|
||||||
['audio', 'video'],
|
['audio', 'video'],
|
||||||
function(avStream) {
|
function (avStream) {
|
||||||
avStream.stop();
|
avStream.stop();
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
function(error){
|
function (error) {
|
||||||
console.error('failed to obtain audio/video stream - stop', error);
|
console.error('failed to obtain audio/video stream - stop', error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -110,8 +112,8 @@ function audioStreamReady(stream) {
|
||||||
|
|
||||||
change_local_audio(stream);
|
change_local_audio(stream);
|
||||||
|
|
||||||
if(RTC.browser !== 'firefox') {
|
if (RTC.browser !== 'firefox') {
|
||||||
getUserMediaWithConstraints( ['video'], videoStreamReady, videoStreamFailed, config.resolution || '360' );
|
getUserMediaWithConstraints(['video'], videoStreamReady, videoStreamFailed, config.resolution || '360');
|
||||||
} else {
|
} else {
|
||||||
doJoin();
|
doJoin();
|
||||||
}
|
}
|
||||||
|
@ -169,7 +171,7 @@ function doJoin() {
|
||||||
roomjid += '/' + Strophe.getNodeFromJid(connection.jid);
|
roomjid += '/' + Strophe.getNodeFromJid(connection.jid);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
roomjid += '/' + Strophe.getNodeFromJid(connection.jid).substr(0,8);
|
roomjid += '/' + Strophe.getNodeFromJid(connection.jid).substr(0, 8);
|
||||||
}
|
}
|
||||||
connection.emuc.doJoin(roomjid);
|
connection.emuc.doJoin(roomjid);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +188,7 @@ function change_local_video(stream, flipX) {
|
||||||
connection.jingle.localVideo = stream;
|
connection.jingle.localVideo = stream;
|
||||||
|
|
||||||
var localVideo = document.createElement('video');
|
var localVideo = document.createElement('video');
|
||||||
localVideo.id = 'localVideo_'+stream.id;
|
localVideo.id = 'localVideo_' + stream.id;
|
||||||
localVideo.autoplay = true;
|
localVideo.autoplay = true;
|
||||||
localVideo.volume = 0; // is it required if audio is separated ?
|
localVideo.volume = 0; // is it required if audio is separated ?
|
||||||
localVideo.oncontextmenu = function () { return false; };
|
localVideo.oncontextmenu = function () { return false; };
|
||||||
|
@ -196,7 +198,9 @@ function change_local_video(stream, flipX) {
|
||||||
|
|
||||||
var localVideoSelector = $('#' + localVideo.id);
|
var localVideoSelector = $('#' + localVideo.id);
|
||||||
// Add click handler
|
// Add click handler
|
||||||
localVideoSelector.click(function () { handleVideoThumbClicked(localVideo.src); } );
|
localVideoSelector.click(function () {
|
||||||
|
handleVideoThumbClicked(localVideo.src);
|
||||||
|
});
|
||||||
// Add stream ended handler
|
// Add stream ended handler
|
||||||
stream.onended = function () {
|
stream.onended = function () {
|
||||||
localVideoContainer.removeChild(localVideo);
|
localVideoContainer.removeChild(localVideo);
|
||||||
|
@ -204,7 +208,7 @@ function change_local_video(stream, flipX) {
|
||||||
};
|
};
|
||||||
// Flip video x axis if needed
|
// Flip video x axis if needed
|
||||||
flipXLocalVideo = flipX;
|
flipXLocalVideo = flipX;
|
||||||
if(flipX) {
|
if (flipX) {
|
||||||
localVideoSelector.addClass("flipVideoX");
|
localVideoSelector.addClass("flipVideoX");
|
||||||
}
|
}
|
||||||
// Attach WebRTC stream
|
// Attach WebRTC stream
|
||||||
|
@ -216,7 +220,7 @@ function change_local_video(stream, flipX) {
|
||||||
|
|
||||||
$(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
$(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||||
function waitForRemoteVideo(selector, sid, ssrc) {
|
function waitForRemoteVideo(selector, sid, ssrc) {
|
||||||
if(selector.removed) {
|
if (selector.removed) {
|
||||||
console.warn("media removed before had started", selector);
|
console.warn("media removed before had started", selector);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +234,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||||
|
|
||||||
// FIXME: add a class that will associate peer Jid, video.src, it's ssrc and video type
|
// FIXME: add a class that will associate peer Jid, video.src, it's ssrc and video type
|
||||||
// in order to get rid of too many maps
|
// in order to get rid of too many maps
|
||||||
if(ssrc) {
|
if (ssrc) {
|
||||||
videoSrcToSsrc[sel.attr('src')] = ssrc;
|
videoSrcToSsrc[sel.attr('src')] = ssrc;
|
||||||
} else {
|
} else {
|
||||||
console.warn("No ssrc given for video", sel);
|
console.warn("No ssrc given for video", sel);
|
||||||
|
@ -250,7 +254,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||||
var ssrclines = SDPUtil.find_lines(sess.peerconnection.remoteDescription.sdp, 'a=ssrc');
|
var ssrclines = SDPUtil.find_lines(sess.peerconnection.remoteDescription.sdp, 'a=ssrc');
|
||||||
ssrclines = ssrclines.filter(function (line) {
|
ssrclines = ssrclines.filter(function (line) {
|
||||||
return line.indexOf('mslabel:' + data.stream.label) !== -1;
|
return line.indexOf('mslabel:' + data.stream.label) !== -1;
|
||||||
});
|
});
|
||||||
if (ssrclines.length) {
|
if (ssrclines.length) {
|
||||||
thessrc = ssrclines[0].substring(7).split(' ')[0];
|
thessrc = ssrclines[0].substring(7).split(' ')[0];
|
||||||
// ok to overwrite the one from focus? might save work in colibri.js
|
// ok to overwrite the one from focus? might save work in colibri.js
|
||||||
|
@ -305,7 +309,7 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||||
sel.hide();
|
sel.hide();
|
||||||
RTC.attachMediaStream(sel, data.stream);
|
RTC.attachMediaStream(sel, data.stream);
|
||||||
|
|
||||||
if(isVideo) {
|
if (isVideo) {
|
||||||
waitForRemoteVideo(sel, sid, thessrc);
|
waitForRemoteVideo(sel, sid, thessrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,9 +320,9 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||||
sel.removed = true;
|
sel.removed = true;
|
||||||
sel.remove();
|
sel.remove();
|
||||||
|
|
||||||
var audioCount = $('#'+container.id+'>audio').length;
|
var audioCount = $('#' + container.id + '>audio').length;
|
||||||
var videoCount = $('#'+container.id+'>video').length;
|
var videoCount = $('#' + container.id + '>video').length;
|
||||||
if(!audioCount && !videoCount) {
|
if (!audioCount && !videoCount) {
|
||||||
console.log("Remove whole user");
|
console.log("Remove whole user");
|
||||||
// Remove whole container
|
// Remove whole container
|
||||||
container.remove();
|
container.remove();
|
||||||
|
@ -330,14 +334,17 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add click handler
|
// Add click handler
|
||||||
sel.click(function () { handleVideoThumbClicked(vid.src); });
|
sel.click(function () {
|
||||||
|
handleVideoThumbClicked(vid.src);
|
||||||
|
});
|
||||||
|
|
||||||
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
||||||
if (isVideo
|
if (isVideo &&
|
||||||
&& data.peerjid && sess.peerjid === data.peerjid &&
|
data.peerjid && sess.peerjid === data.peerjid &&
|
||||||
data.stream.getVideoTracks().length === 0 &&
|
data.stream.getVideoTracks().length === 0 &&
|
||||||
connection.jingle.localVideo.getVideoTracks().length > 0) {
|
connection.jingle.localVideo.getVideoTracks().length > 0) {
|
||||||
window.setTimeout(function() {
|
//
|
||||||
|
window.setTimeout(function () {
|
||||||
sendKeyframe(sess.peerconnection);
|
sendKeyframe(sess.peerconnection);
|
||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
@ -361,17 +368,17 @@ function handleVideoThumbClicked(videoSrc) {
|
||||||
* Checks if removed video is currently displayed and tries to display another one instead.
|
* Checks if removed video is currently displayed and tries to display another one instead.
|
||||||
* @param removedVideoSrc src stream identifier of the video.
|
* @param removedVideoSrc src stream identifier of the video.
|
||||||
*/
|
*/
|
||||||
function checkChangeLargeVideo(removedVideoSrc){
|
function checkChangeLargeVideo(removedVideoSrc) {
|
||||||
if (removedVideoSrc === $('#largeVideo').attr('src')) {
|
if (removedVideoSrc === $('#largeVideo').attr('src')) {
|
||||||
// this is currently displayed as large
|
// this is currently displayed as large
|
||||||
// pick the last visible video in the row
|
// pick the last visible video in the row
|
||||||
// if nobody else is left, this picks the local video
|
// if nobody else is left, this picks the local video
|
||||||
var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>video').get(0);
|
var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>video').get(0);
|
||||||
|
|
||||||
if(!pick) {
|
if (!pick) {
|
||||||
console.info("Last visible video no longer exists");
|
console.info("Last visible video no longer exists");
|
||||||
pick = $('#remoteVideos>span[id!="mixedstream"]>video').get(0);
|
pick = $('#remoteVideos>span[id!="mixedstream"]>video').get(0);
|
||||||
if(!pick) {
|
if (!pick) {
|
||||||
// Try local video
|
// Try local video
|
||||||
console.info("Fallback to local video...");
|
console.info("Fallback to local video...");
|
||||||
pick = $('#remoteVideos>span>span>video').get(0);
|
pick = $('#remoteVideos>span>span>video').get(0);
|
||||||
|
@ -396,8 +403,10 @@ function sendKeyframe(pc) {
|
||||||
function () {
|
function () {
|
||||||
pc.createAnswer(
|
pc.createAnswer(
|
||||||
function (modifiedAnswer) {
|
function (modifiedAnswer) {
|
||||||
pc.setLocalDescription(modifiedAnswer,
|
pc.setLocalDescription(
|
||||||
|
modifiedAnswer,
|
||||||
function () {
|
function () {
|
||||||
|
// noop
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
console.log('triggerKeyframe setLocalDescription failed', error);
|
console.log('triggerKeyframe setLocalDescription failed', error);
|
||||||
|
@ -436,7 +445,7 @@ function muteVideo(pc, unmute) {
|
||||||
function () {
|
function () {
|
||||||
console.log('mute SLD ok');
|
console.log('mute SLD ok');
|
||||||
},
|
},
|
||||||
function(error) {
|
function (error) {
|
||||||
console.log('mute SLD error');
|
console.log('mute SLD error');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -497,11 +506,11 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) {
|
||||||
newssrcs[type] = ssrc;
|
newssrcs[type] = ssrc;
|
||||||
|
|
||||||
directions[type] = (
|
directions[type] = (
|
||||||
SDPUtil.find_line(media, 'a=sendrecv')
|
SDPUtil.find_line(media, 'a=sendrecv') ||
|
||||||
|| SDPUtil.find_line(media, 'a=recvonly')
|
SDPUtil.find_line(media, 'a=recvonly') ||
|
||||||
|| SDPUtil.find_line('a=sendonly')
|
SDPUtil.find_line('a=sendonly') ||
|
||||||
|| SDPUtil.find_line('a=inactive')
|
SDPUtil.find_line('a=inactive') ||
|
||||||
|| 'a=sendrecv' ).substr(2);
|
'a=sendrecv').substr(2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
console.log('new ssrcs', newssrcs);
|
console.log('new ssrcs', newssrcs);
|
||||||
|
@ -513,7 +522,7 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) {
|
||||||
i++;
|
i++;
|
||||||
var type = mtype;
|
var type = mtype;
|
||||||
// Change video type to screen
|
// Change video type to screen
|
||||||
if(mtype === 'video' && isUsingScreenStream) {
|
if (mtype === 'video' && isUsingScreenStream) {
|
||||||
type = 'screen';
|
type = 'screen';
|
||||||
}
|
}
|
||||||
connection.emuc.addMediaToPresence(i, type, newssrcs[mtype], directions[mtype]);
|
connection.emuc.addMediaToPresence(i, type, newssrcs[mtype], directions[mtype]);
|
||||||
|
@ -603,13 +612,13 @@ $(document).bind('left.muc', function (event, jid) {
|
||||||
$(document).bind('presence.muc', function (event, jid, info, pres) {
|
$(document).bind('presence.muc', function (event, jid, info, pres) {
|
||||||
|
|
||||||
// Remove old ssrcs coming from the jid
|
// Remove old ssrcs coming from the jid
|
||||||
Object.keys(ssrc2jid).forEach(function(ssrc){
|
Object.keys(ssrc2jid).forEach(function (ssrc) {
|
||||||
if(ssrc2jid[ssrc] == jid){
|
if (ssrc2jid[ssrc] == jid) {
|
||||||
delete ssrc2jid[ssrc];
|
delete ssrc2jid[ssrc];
|
||||||
}
|
}
|
||||||
if(ssrc2videoType == jid){
|
if (ssrc2videoType == jid) {
|
||||||
delete ssrc2videoType[ssrc];
|
delete ssrc2videoType[ssrc];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(pres).find('>media[xmlns="http://estos.de/ns/mjs"]>source').each(function (idx, ssrc) {
|
$(pres).find('>media[xmlns="http://estos.de/ns/mjs"]>source').each(function (idx, ssrc) {
|
||||||
|
@ -623,7 +632,7 @@ $(document).bind('presence.muc', function (event, jid, info, pres) {
|
||||||
// might need to update the direction if participant just went from sendrecv to recvonly
|
// might need to update the direction if participant just went from sendrecv to recvonly
|
||||||
if (type === 'video' || type === 'screen') {
|
if (type === 'video' || type === 'screen') {
|
||||||
var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>video');
|
var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>video');
|
||||||
switch(ssrc.getAttribute('direction')) {
|
switch (ssrc.getAttribute('direction')) {
|
||||||
case 'sendrecv':
|
case 'sendrecv':
|
||||||
el.show();
|
el.show();
|
||||||
break;
|
break;
|
||||||
|
@ -650,27 +659,24 @@ $(document).bind('passwordrequired.muc', function (event, jid) {
|
||||||
console.log('on password required', jid);
|
console.log('on password required', jid);
|
||||||
|
|
||||||
$.prompt('<h2>Password required</h2>' +
|
$.prompt('<h2>Password required</h2>' +
|
||||||
'<input id="lockKey" type="text" placeholder="shared key" autofocus>',
|
'<input id="lockKey" type="text" placeholder="shared key" autofocus>', {
|
||||||
{
|
persistent: true,
|
||||||
persistent: true,
|
buttons: { "Ok": true, "Cancel": false},
|
||||||
buttons: { "Ok": true , "Cancel": false},
|
defaultButton: 1,
|
||||||
defaultButton: 1,
|
loaded: function (event) {
|
||||||
loaded: function(event) {
|
document.getElementById('lockKey').focus();
|
||||||
document.getElementById('lockKey').focus();
|
},
|
||||||
},
|
submit: function (e, v, m, f) {
|
||||||
submit: function(e,v,m,f){
|
if (v) {
|
||||||
if(v)
|
var lockKey = document.getElementById('lockKey');
|
||||||
{
|
|
||||||
var lockKey = document.getElementById('lockKey');
|
|
||||||
|
|
||||||
if (lockKey.value !== null)
|
if (lockKey.value !== null) {
|
||||||
{
|
setSharedKey(lockKey.value);
|
||||||
setSharedKey(lockKey.value);
|
connection.emuc.doJoin(jid, lockKey.value);
|
||||||
connection.emuc.doJoin(jid, lockKey.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document).bind('audiomuted.muc', function (event, jid, isMuted) {
|
$(document).bind('audiomuted.muc', function (event, jid, isMuted) {
|
||||||
|
@ -739,19 +745,19 @@ function updateLargeVideo(newSrc, vol) {
|
||||||
* @param videoSrc eg. blob:https%3A//pawel.jitsi.net/9a46e0bd-131e-4d18-9c14-a9264e8db395
|
* @param videoSrc eg. blob:https%3A//pawel.jitsi.net/9a46e0bd-131e-4d18-9c14-a9264e8db395
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function isVideoSrcDesktop(videoSrc){
|
function isVideoSrcDesktop(videoSrc) {
|
||||||
// FIXME: fix this mapping mess...
|
// FIXME: fix this mapping mess...
|
||||||
// figure out if large video is desktop stream or just a camera
|
// figure out if large video is desktop stream or just a camera
|
||||||
var isDesktop = false;
|
var isDesktop = false;
|
||||||
if(localVideoSrc === videoSrc) {
|
if (localVideoSrc === videoSrc) {
|
||||||
// local video
|
// local video
|
||||||
isDesktop = isUsingScreenStream;
|
isDesktop = isUsingScreenStream;
|
||||||
} else {
|
} else {
|
||||||
// Do we have associations...
|
// Do we have associations...
|
||||||
var videoSsrc = videoSrcToSsrc[videoSrc];
|
var videoSsrc = videoSrcToSsrc[videoSrc];
|
||||||
if(videoSsrc) {
|
if (videoSsrc) {
|
||||||
var videoType = ssrc2videoType[videoSsrc];
|
var videoType = ssrc2videoType[videoSsrc];
|
||||||
if(videoType) {
|
if (videoType) {
|
||||||
// Finally there...
|
// Finally there...
|
||||||
isDesktop = videoType === 'screen';
|
isDesktop = videoType === 'screen';
|
||||||
} else {
|
} else {
|
||||||
|
@ -769,12 +775,12 @@ function isVideoSrcDesktop(videoSrc){
|
||||||
*/
|
*/
|
||||||
function setLargeVideoVisible(isVisible) {
|
function setLargeVideoVisible(isVisible) {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
$('#largeVideo').css({visibility:'visible'});
|
$('#largeVideo').css({visibility: 'visible'});
|
||||||
$('.watermark').css({visibility:'visible'});
|
$('.watermark').css({visibility: 'visible'});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$('#largeVideo').css({visibility:'hidden'});
|
$('#largeVideo').css({visibility: 'hidden'});
|
||||||
$('.watermark').css({visibility:'hidden'});
|
$('.watermark').css({visibility: 'hidden'});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,8 +795,8 @@ function toggleVideo() {
|
||||||
var sess = getConferenceHandler();
|
var sess = getConferenceHandler();
|
||||||
if (sess) {
|
if (sess) {
|
||||||
sess.toggleVideoMute(
|
sess.toggleVideoMute(
|
||||||
function(isMuted){
|
function (isMuted) {
|
||||||
if(isMuted) {
|
if (isMuted) {
|
||||||
$('#video').removeClass("icon-camera");
|
$('#video').removeClass("icon-camera");
|
||||||
$('#video').addClass("icon-camera icon-camera-disabled");
|
$('#video').addClass("icon-camera icon-camera-disabled");
|
||||||
} else {
|
} else {
|
||||||
|
@ -801,7 +807,7 @@ function toggleVideo() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sess = focus || activecall;
|
sess = focus || activecall;
|
||||||
if (!sess) {
|
if (!sess) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -835,30 +841,30 @@ function toggleAudio() {
|
||||||
* @param videoWidth the stream video width
|
* @param videoWidth the stream video width
|
||||||
* @param videoHeight the stream video height
|
* @param videoHeight the stream video height
|
||||||
*/
|
*/
|
||||||
var positionLarge = function(videoWidth, videoHeight) {
|
var positionLarge = function (videoWidth, videoHeight) {
|
||||||
var videoSpaceWidth = $('#videospace').width();
|
var videoSpaceWidth = $('#videospace').width();
|
||||||
var videoSpaceHeight = window.innerHeight;
|
var videoSpaceHeight = window.innerHeight;
|
||||||
|
|
||||||
var videoSize = getVideoSize( videoWidth,
|
var videoSize = getVideoSize(videoWidth,
|
||||||
videoHeight,
|
videoHeight,
|
||||||
videoSpaceWidth,
|
videoSpaceWidth,
|
||||||
videoSpaceHeight);
|
videoSpaceHeight);
|
||||||
|
|
||||||
var largeVideoWidth = videoSize[0];
|
var largeVideoWidth = videoSize[0];
|
||||||
var largeVideoHeight = videoSize[1];
|
var largeVideoHeight = videoSize[1];
|
||||||
|
|
||||||
var videoPosition = getVideoPosition( largeVideoWidth,
|
var videoPosition = getVideoPosition(largeVideoWidth,
|
||||||
largeVideoHeight,
|
largeVideoHeight,
|
||||||
videoSpaceWidth,
|
videoSpaceWidth,
|
||||||
videoSpaceHeight);
|
videoSpaceHeight);
|
||||||
|
|
||||||
var horizontalIndent = videoPosition[0];
|
var horizontalIndent = videoPosition[0];
|
||||||
var verticalIndent = videoPosition[1];
|
var verticalIndent = videoPosition[1];
|
||||||
|
|
||||||
positionVideo( $('#largeVideo'),
|
positionVideo($('#largeVideo'),
|
||||||
largeVideoWidth,
|
largeVideoWidth,
|
||||||
largeVideoHeight,
|
largeVideoHeight,
|
||||||
horizontalIndent, verticalIndent);
|
horizontalIndent, verticalIndent);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -868,21 +874,21 @@ var positionLarge = function(videoWidth, videoHeight) {
|
||||||
* @return an array with 2 elements, the horizontal indent and the vertical
|
* @return an array with 2 elements, the horizontal indent and the vertical
|
||||||
* indent
|
* indent
|
||||||
*/
|
*/
|
||||||
function getCameraVideoPosition( videoWidth,
|
function getCameraVideoPosition(videoWidth,
|
||||||
videoHeight,
|
videoHeight,
|
||||||
videoSpaceWidth,
|
videoSpaceWidth,
|
||||||
videoSpaceHeight) {
|
videoSpaceHeight) {
|
||||||
// Parent height isn't completely calculated when we position the video in
|
// Parent height isn't completely calculated when we position the video in
|
||||||
// full screen mode and this is why we use the screen height in this case.
|
// full screen mode and this is why we use the screen height in this case.
|
||||||
// Need to think it further at some point and implement it properly.
|
// Need to think it further at some point and implement it properly.
|
||||||
var isFullScreen = document.fullScreen
|
var isFullScreen = document.fullScreen ||
|
||||||
|| document.mozFullScreen
|
document.mozFullScreen ||
|
||||||
|| document.webkitIsFullScreen;
|
document.webkitIsFullScreen;
|
||||||
if (isFullScreen)
|
if (isFullScreen)
|
||||||
videoSpaceHeight = window.innerHeight;
|
videoSpaceHeight = window.innerHeight;
|
||||||
|
|
||||||
var horizontalIndent = (videoSpaceWidth - videoWidth)/2;
|
var horizontalIndent = (videoSpaceWidth - videoWidth) / 2;
|
||||||
var verticalIndent = (videoSpaceHeight - videoHeight)/2;
|
var verticalIndent = (videoSpaceHeight - videoHeight) / 2;
|
||||||
|
|
||||||
return [horizontalIndent, verticalIndent];
|
return [horizontalIndent, verticalIndent];
|
||||||
}
|
}
|
||||||
|
@ -894,12 +900,12 @@ function getCameraVideoPosition( videoWidth,
|
||||||
* @return an array with 2 elements, the horizontal indent and the vertical
|
* @return an array with 2 elements, the horizontal indent and the vertical
|
||||||
* indent
|
* indent
|
||||||
*/
|
*/
|
||||||
function getDesktopVideoPosition( videoWidth,
|
function getDesktopVideoPosition(videoWidth,
|
||||||
videoHeight,
|
videoHeight,
|
||||||
videoSpaceWidth,
|
videoSpaceWidth,
|
||||||
videoSpaceHeight) {
|
videoSpaceHeight) {
|
||||||
|
|
||||||
var horizontalIndent = (videoSpaceWidth - videoWidth)/2;
|
var horizontalIndent = (videoSpaceWidth - videoWidth) / 2;
|
||||||
|
|
||||||
var verticalIndent = 0;// Top aligned
|
var verticalIndent = 0;// Top aligned
|
||||||
|
|
||||||
|
@ -928,10 +934,10 @@ function getCameraVideoSize(videoWidth,
|
||||||
|
|
||||||
if (availableWidth / aspectRatio < videoSpaceHeight) {
|
if (availableWidth / aspectRatio < videoSpaceHeight) {
|
||||||
availableHeight = videoSpaceHeight;
|
availableHeight = videoSpaceHeight;
|
||||||
availableWidth = availableHeight*aspectRatio;
|
availableWidth = availableHeight * aspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (availableHeight*aspectRatio < videoSpaceWidth) {
|
if (availableHeight * aspectRatio < videoSpaceWidth) {
|
||||||
availableWidth = videoSpaceWidth;
|
availableWidth = videoSpaceWidth;
|
||||||
availableHeight = availableWidth / aspectRatio;
|
availableHeight = availableWidth / aspectRatio;
|
||||||
}
|
}
|
||||||
|
@ -945,11 +951,10 @@ function getCameraVideoSize(videoWidth,
|
||||||
*
|
*
|
||||||
* @return an array with 2 elements, the video width and the video height
|
* @return an array with 2 elements, the video width and the video height
|
||||||
*/
|
*/
|
||||||
function getDesktopVideoSize( videoWidth,
|
function getDesktopVideoSize(videoWidth,
|
||||||
videoHeight,
|
videoHeight,
|
||||||
videoSpaceWidth,
|
videoSpaceWidth,
|
||||||
videoSpaceHeight )
|
videoSpaceHeight) {
|
||||||
{
|
|
||||||
if (!videoWidth)
|
if (!videoWidth)
|
||||||
videoWidth = currentVideoWidth;
|
videoWidth = currentVideoWidth;
|
||||||
if (!videoHeight)
|
if (!videoHeight)
|
||||||
|
@ -965,10 +970,10 @@ function getDesktopVideoSize( videoWidth,
|
||||||
if (availableWidth / aspectRatio >= videoSpaceHeight)
|
if (availableWidth / aspectRatio >= videoSpaceHeight)
|
||||||
{
|
{
|
||||||
availableHeight = videoSpaceHeight;
|
availableHeight = videoSpaceHeight;
|
||||||
availableWidth = availableHeight*aspectRatio;
|
availableWidth = availableHeight * aspectRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (availableHeight*aspectRatio >= videoSpaceWidth)
|
if (availableHeight * aspectRatio >= videoSpaceWidth)
|
||||||
{
|
{
|
||||||
availableWidth = videoSpaceWidth;
|
availableWidth = videoSpaceWidth;
|
||||||
availableHeight = availableWidth / aspectRatio;
|
availableHeight = availableWidth / aspectRatio;
|
||||||
|
@ -986,11 +991,11 @@ function getDesktopVideoSize( videoWidth,
|
||||||
* @param horizontalIndent the left and right indent
|
* @param horizontalIndent the left and right indent
|
||||||
* @param verticalIndent the top and bottom indent
|
* @param verticalIndent the top and bottom indent
|
||||||
*/
|
*/
|
||||||
function positionVideo( video,
|
function positionVideo(video,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
horizontalIndent,
|
horizontalIndent,
|
||||||
verticalIndent) {
|
verticalIndent) {
|
||||||
video.width(width);
|
video.width(width);
|
||||||
video.height(height);
|
video.height(height);
|
||||||
video.css({ top: verticalIndent + 'px',
|
video.css({ top: verticalIndent + 'px',
|
||||||
|
@ -1014,7 +1019,7 @@ var resizeLargeVideoContainer = function () {
|
||||||
resizeThumbnails();
|
resizeThumbnails();
|
||||||
};
|
};
|
||||||
|
|
||||||
var calculateThumbnailSize = function() {
|
var calculateThumbnailSize = function () {
|
||||||
// Calculate the available height, which is the inner window height minus
|
// Calculate the available height, which is the inner window height minus
|
||||||
// 39px for the header minus 2px for the delimiter lines on the top and
|
// 39px for the header minus 2px for the delimiter lines on the top and
|
||||||
// bottom of the large video, minus the 36px space inside the remoteVideos
|
// bottom of the large video, minus the 36px space inside the remoteVideos
|
||||||
|
@ -1056,8 +1061,7 @@ $(document).ready(function () {
|
||||||
// Set default desktop sharing method
|
// Set default desktop sharing method
|
||||||
setDesktopSharing(config.desktopSharing);
|
setDesktopSharing(config.desktopSharing);
|
||||||
// Initialize Chrome extension inline installs
|
// Initialize Chrome extension inline installs
|
||||||
if(config.chromeExtensionId)
|
if (config.chromeExtensionId) {
|
||||||
{
|
|
||||||
initInlineInstalls();
|
initInlineInstalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1072,7 +1076,7 @@ $(document).ready(function () {
|
||||||
});
|
});
|
||||||
// Listen for large video size updates
|
// Listen for large video size updates
|
||||||
document.getElementById('largeVideo')
|
document.getElementById('largeVideo')
|
||||||
.addEventListener('loadedmetadata', function(e){
|
.addEventListener('loadedmetadata', function (e) {
|
||||||
currentVideoWidth = this.videoWidth;
|
currentVideoWidth = this.videoWidth;
|
||||||
currentVideoHeight = this.videoHeight;
|
currentVideoHeight = this.videoHeight;
|
||||||
positionLarge(currentVideoWidth, currentVideoHeight);
|
positionLarge(currentVideoWidth, currentVideoHeight);
|
||||||
|
@ -1114,12 +1118,12 @@ $(window).bind('beforeunload', function () {
|
||||||
|
|
||||||
function disposeConference() {
|
function disposeConference() {
|
||||||
var handler = getConferenceHandler();
|
var handler = getConferenceHandler();
|
||||||
if(handler && handler.peerconnection) {
|
if (handler && handler.peerconnection) {
|
||||||
// FIXME: probably removing streams is not required and close() should be enough
|
// FIXME: probably removing streams is not required and close() should be enough
|
||||||
if(connection.jingle.localAudio) {
|
if (connection.jingle.localAudio) {
|
||||||
handler.peerconnection.removeStream(connection.jingle.localAudio);
|
handler.peerconnection.removeStream(connection.jingle.localAudio);
|
||||||
}
|
}
|
||||||
if(connection.jingle.localVideo) {
|
if (connection.jingle.localVideo) {
|
||||||
handler.peerconnection.removeStream(connection.jingle.localVideo);
|
handler.peerconnection.removeStream(connection.jingle.localVideo);
|
||||||
}
|
}
|
||||||
handler.peerconnection.close();
|
handler.peerconnection.close();
|
||||||
|
@ -1128,7 +1132,7 @@ function disposeConference() {
|
||||||
activecall = null;
|
activecall = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dump(elem, filename){
|
function dump(elem, filename) {
|
||||||
elem = elem.parentNode;
|
elem = elem.parentNode;
|
||||||
elem.download = filename || 'meetlog.json';
|
elem.download = filename || 'meetlog.json';
|
||||||
elem.href = 'data:application/json;charset=utf-8,\n';
|
elem.href = 'data:application/json;charset=utf-8,\n';
|
||||||
|
@ -1141,8 +1145,8 @@ function dump(elem, filename){
|
||||||
data["jingle_" + session.sid] = {
|
data["jingle_" + session.sid] = {
|
||||||
updateLog: session.peerconnection.updateLog,
|
updateLog: session.peerconnection.updateLog,
|
||||||
stats: session.peerconnection.stats,
|
stats: session.peerconnection.stats,
|
||||||
url: window.location.href}
|
url: window.location.href
|
||||||
;
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1173,56 +1177,57 @@ function openLockDialog() {
|
||||||
if (focus === null) {
|
if (focus === null) {
|
||||||
if (sharedKey)
|
if (sharedKey)
|
||||||
$.prompt("This conversation is currently protected by a shared secret key.",
|
$.prompt("This conversation is currently protected by a shared secret key.",
|
||||||
{
|
{
|
||||||
title: "Secrect key",
|
title: "Secrect key",
|
||||||
persistent: false
|
persistent: false
|
||||||
});
|
}
|
||||||
|
);
|
||||||
else
|
else
|
||||||
$.prompt("This conversation isn't currently protected by a secret key. Only the owner of the conference could set a shared key.",
|
$.prompt("This conversation isn't currently protected by a secret key. Only the owner of the conference could set a shared key.",
|
||||||
{
|
{
|
||||||
title: "Secrect key",
|
title: "Secrect key",
|
||||||
persistent: false
|
persistent: false
|
||||||
});
|
}
|
||||||
}
|
);
|
||||||
else {
|
} else {
|
||||||
if (sharedKey)
|
if (sharedKey) {
|
||||||
$.prompt("Are you sure you would like to remove your secret key?",
|
$.prompt("Are you sure you would like to remove your secret key?",
|
||||||
{
|
{
|
||||||
title: "Remove secrect key",
|
title: "Remove secrect key",
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: { "Remove": true, "Cancel": false},
|
buttons: { "Remove": true, "Cancel": false},
|
||||||
defaultButton: 1,
|
defaultButton: 1,
|
||||||
submit: function(e,v,m,f){
|
submit: function (e, v, m, f) {
|
||||||
if(v)
|
if (v) {
|
||||||
{
|
setSharedKey('');
|
||||||
setSharedKey('');
|
lockRoom(false);
|
||||||
lockRoom(false);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
else
|
} else {
|
||||||
$.prompt('<h2>Set a secrect key to lock your room</h2>' +
|
$.prompt('<h2>Set a secrect key to lock your room</h2>' +
|
||||||
'<input id="lockKey" type="text" placeholder="your shared key" autofocus>',
|
'<input id="lockKey" type="text" placeholder="your shared key" autofocus>',
|
||||||
{
|
{
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: { "Save": true , "Cancel": false},
|
buttons: { "Save": true, "Cancel": false},
|
||||||
defaultButton: 1,
|
defaultButton: 1,
|
||||||
loaded: function(event) {
|
loaded: function (event) {
|
||||||
document.getElementById('lockKey').focus();
|
document.getElementById('lockKey').focus();
|
||||||
},
|
},
|
||||||
submit: function(e,v,m,f){
|
submit: function (e, v, m, f) {
|
||||||
if(v)
|
if (v) {
|
||||||
{
|
var lockKey = document.getElementById('lockKey');
|
||||||
var lockKey = document.getElementById('lockKey');
|
|
||||||
|
|
||||||
if (lockKey.value)
|
if (lockKey.value) {
|
||||||
{
|
setSharedKey(Util.escapeHtml(lockKey.value));
|
||||||
setSharedKey(Util.escapeHtml(lockKey.value));
|
lockRoom(true);
|
||||||
lockRoom(true);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1230,16 +1235,17 @@ function openLockDialog() {
|
||||||
* Opens the invite link dialog.
|
* Opens the invite link dialog.
|
||||||
*/
|
*/
|
||||||
function openLinkDialog() {
|
function openLinkDialog() {
|
||||||
$.prompt('<input id="inviteLinkRef" type="text" value="'
|
$.prompt('<input id="inviteLinkRef" type="text" value="' +
|
||||||
+ encodeURI(roomUrl) + '" onclick="this.select();" readonly>',
|
encodeURI(roomUrl) + '" onclick="this.select();" readonly>',
|
||||||
{
|
{
|
||||||
title: "Share this link with everyone you want to invite",
|
title: "Share this link with everyone you want to invite",
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: { "Cancel": false},
|
buttons: { "Cancel": false},
|
||||||
loaded: function(event) {
|
loaded: function (event) {
|
||||||
document.getElementById('inviteLinkRef').select();
|
document.getElementById('inviteLinkRef').select();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1247,40 +1253,38 @@ function openLinkDialog() {
|
||||||
*/
|
*/
|
||||||
function openSettingsDialog() {
|
function openSettingsDialog() {
|
||||||
$.prompt('<h2>Configure your conference</h2>' +
|
$.prompt('<h2>Configure your conference</h2>' +
|
||||||
'<input type="checkbox" id="initMuted"> Participants join muted<br/>' +
|
'<input type="checkbox" id="initMuted"> Participants join muted<br/>' +
|
||||||
'<input type="checkbox" id="requireNicknames"> Require nicknames<br/><br/>' +
|
'<input type="checkbox" id="requireNicknames"> Require nicknames<br/><br/>' +
|
||||||
'Set a secrect key to lock your room: <input id="lockKey" type="text" placeholder="your shared key" autofocus>',
|
'Set a secrect key to lock your room: <input id="lockKey" type="text" placeholder="your shared key" autofocus>',
|
||||||
{
|
{
|
||||||
persistent: false,
|
persistent: false,
|
||||||
buttons: { "Save": true , "Cancel": false},
|
buttons: { "Save": true, "Cancel": false},
|
||||||
defaultButton: 1,
|
defaultButton: 1,
|
||||||
loaded: function(event) {
|
loaded: function (event) {
|
||||||
document.getElementById('lockKey').focus();
|
document.getElementById('lockKey').focus();
|
||||||
},
|
},
|
||||||
submit: function(e,v,m,f){
|
submit: function (e, v, m, f) {
|
||||||
if(v)
|
if (v) {
|
||||||
{
|
if ($('#initMuted').is(":checked")) {
|
||||||
if ($('#initMuted').is(":checked"))
|
// it is checked
|
||||||
{
|
|
||||||
// it is checked
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($('#requireNicknames').is(":checked"))
|
|
||||||
{
|
|
||||||
// it is checked
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
var lockKey = document.getElementById('lockKey');
|
|
||||||
|
|
||||||
if (lockKey.value)
|
|
||||||
{
|
|
||||||
setSharedKey(lockKey.value);
|
|
||||||
lockRoom(true);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($('#requireNicknames').is(":checked")) {
|
||||||
|
// it is checked
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
var lockKey = document.getElementById('lockKey');
|
||||||
|
|
||||||
|
if (lockKey.value)
|
||||||
|
{
|
||||||
|
setSharedKey(lockKey.value);
|
||||||
|
lockRoom(true);
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1312,10 +1316,10 @@ function updateLockButton() {
|
||||||
/**
|
/**
|
||||||
* Hides the toolbar.
|
* Hides the toolbar.
|
||||||
*/
|
*/
|
||||||
var hideToolbar = function() {
|
var hideToolbar = function () {
|
||||||
|
|
||||||
var isToolbarHover = false;
|
var isToolbarHover = false;
|
||||||
$('#header').find('*').each(function(){
|
$('#header').find('*').each(function () {
|
||||||
var id = $(this).attr('id');
|
var id = $(this).attr('id');
|
||||||
if ($("#" + id + ":hover").length > 0) {
|
if ($("#" + id + ":hover").length > 0) {
|
||||||
isToolbarHover = true;
|
isToolbarHover = true;
|
||||||
|
@ -1418,7 +1422,7 @@ function showFocusIndicator() {
|
||||||
var session = connection.jingle.sessions[Object.keys(connection.jingle.sessions)[0]];
|
var session = connection.jingle.sessions[Object.keys(connection.jingle.sessions)[0]];
|
||||||
var focusId = 'participant_' + Strophe.getResourceFromJid(session.peerjid);
|
var focusId = 'participant_' + Strophe.getResourceFromJid(session.peerjid);
|
||||||
var focusContainer = document.getElementById(focusId);
|
var focusContainer = document.getElementById(focusId);
|
||||||
if(!focusContainer) {
|
if (!focusContainer) {
|
||||||
console.error("No focus container!");
|
console.error("No focus container!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1438,12 +1442,11 @@ function showFocusIndicator() {
|
||||||
* Checks if container for participant identified by given peerJid exists in the document and creates it eventually.
|
* Checks if container for participant identified by given peerJid exists in the document and creates it eventually.
|
||||||
* @param peerJid peer Jid to check.
|
* @param peerJid peer Jid to check.
|
||||||
*/
|
*/
|
||||||
function ensurePeerContainerExists(peerJid){
|
function ensurePeerContainerExists(peerJid) {
|
||||||
|
|
||||||
var peerResource = Strophe.getResourceFromJid(peerJid);
|
var peerResource = Strophe.getResourceFromJid(peerJid);
|
||||||
var videoSpanId = 'participant_' + peerResource;
|
var videoSpanId = 'participant_' + peerResource;
|
||||||
|
|
||||||
if($('#'+videoSpanId).length > 0) {
|
if ($('#' + videoSpanId).length > 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1482,8 +1485,7 @@ function createFocusIndicatorElement(parentElement) {
|
||||||
function toggleFullScreen() {
|
function toggleFullScreen() {
|
||||||
var fsElement = document.documentElement;
|
var fsElement = document.documentElement;
|
||||||
|
|
||||||
if (!document.mozFullScreen && !document.webkitIsFullScreen){
|
if (!document.mozFullScreen && !document.webkitIsFullScreen) {
|
||||||
|
|
||||||
//Enter Full Screen
|
//Enter Full Screen
|
||||||
if (fsElement.mozRequestFullScreen) {
|
if (fsElement.mozRequestFullScreen) {
|
||||||
fsElement.mozRequestFullScreen();
|
fsElement.mozRequestFullScreen();
|
||||||
|
@ -1511,13 +1513,13 @@ function showDisplayName(videoSpanId, displayName) {
|
||||||
if (nameSpan.length > 0) {
|
if (nameSpan.length > 0) {
|
||||||
var nameSpanElement = nameSpan.get(0);
|
var nameSpanElement = nameSpan.get(0);
|
||||||
|
|
||||||
if (nameSpanElement.id === 'localDisplayName'
|
if (nameSpanElement.id === 'localDisplayName' &&
|
||||||
&& $('#localDisplayName').text() !== displayName)
|
$('#localDisplayName').text() !== displayName) {
|
||||||
$('#localDisplayName').text(displayName);
|
$('#localDisplayName').text(displayName);
|
||||||
else
|
} else {
|
||||||
$('#' + videoSpanId + '_name').text(displayName);
|
$('#' + videoSpanId + '_name').text(displayName);
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
var editButton = null;
|
var editButton = null;
|
||||||
|
|
||||||
if (videoSpanId === 'localVideoContainer') {
|
if (videoSpanId === 'localVideoContainer') {
|
||||||
|
@ -1532,8 +1534,7 @@ function showDisplayName(videoSpanId, displayName) {
|
||||||
|
|
||||||
if (!editButton) {
|
if (!editButton) {
|
||||||
nameSpan.id = videoSpanId + '_name';
|
nameSpan.id = videoSpanId + '_name';
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
nameSpan.id = 'localDisplayName';
|
nameSpan.id = 'localDisplayName';
|
||||||
$('#' + videoSpanId)[0].appendChild(editButton);
|
$('#' + videoSpanId)[0].appendChild(editButton);
|
||||||
|
|
||||||
|
@ -1541,22 +1542,22 @@ function showDisplayName(videoSpanId, displayName) {
|
||||||
editableText.className = 'displayname';
|
editableText.className = 'displayname';
|
||||||
editableText.id = 'editDisplayName';
|
editableText.id = 'editDisplayName';
|
||||||
|
|
||||||
if (displayName.length)
|
if (displayName.length) {
|
||||||
editableText.value
|
editableText.value = displayName.substring(0, displayName.indexOf(' (me)'));
|
||||||
= displayName.substring(0, displayName.indexOf(' (me)'));
|
}
|
||||||
|
|
||||||
editableText.setAttribute('style', 'display:none;');
|
editableText.setAttribute('style', 'display:none;');
|
||||||
editableText.setAttribute('placeholder', 'ex. Jane Pink');
|
editableText.setAttribute('placeholder', 'ex. Jane Pink');
|
||||||
$('#' + videoSpanId)[0].appendChild(editableText);
|
$('#' + videoSpanId)[0].appendChild(editableText);
|
||||||
|
|
||||||
$('#localVideoContainer .displayname').bind("click", function(e) {
|
$('#localVideoContainer .displayname').bind("click", function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$('#localDisplayName').hide();
|
$('#localDisplayName').hide();
|
||||||
$('#editDisplayName').show();
|
$('#editDisplayName').show();
|
||||||
$('#editDisplayName').focus();
|
$('#editDisplayName').focus();
|
||||||
$('#editDisplayName').select();
|
$('#editDisplayName').select();
|
||||||
|
|
||||||
var inputDisplayNameHandler = function(name) {
|
var inputDisplayNameHandler = function (name) {
|
||||||
if (nickname !== name) {
|
if (nickname !== name) {
|
||||||
nickname = name;
|
nickname = name;
|
||||||
window.localStorage.displayname = nickname;
|
window.localStorage.displayname = nickname;
|
||||||
|
@ -1661,20 +1662,21 @@ function showVideoIndicator(videoSpanId, isMuted) {
|
||||||
* Resizes and repositions videos in full screen mode.
|
* Resizes and repositions videos in full screen mode.
|
||||||
*/
|
*/
|
||||||
$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
|
$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
|
||||||
function() {
|
function () {
|
||||||
resizeLargeVideoContainer();
|
resizeLargeVideoContainer();
|
||||||
positionLarge();
|
positionLarge();
|
||||||
isFullScreen = document.fullScreen
|
isFullScreen = document.fullScreen ||
|
||||||
|| document.mozFullScreen
|
document.mozFullScreen ||
|
||||||
|| document.webkitIsFullScreen;
|
document.webkitIsFullScreen;
|
||||||
|
|
||||||
if (isFullScreen) {
|
if (isFullScreen) {
|
||||||
setView("fullscreen");
|
setView("fullscreen");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setView("default");
|
setView("default");
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the current view.
|
* Sets the current view.
|
||||||
|
|
57
chat.js
57
chat.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* global $, Util, connection, nickname:true, getVideoSize, getVideoPosition, showToolbar, processReplacements */
|
||||||
/**
|
/**
|
||||||
* Chat related user interface.
|
* Chat related user interface.
|
||||||
*/
|
*/
|
||||||
|
@ -16,7 +17,7 @@ var Chat = (function (my) {
|
||||||
Chat.setChatConversationMode(true);
|
Chat.setChatConversationMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#nickinput').keydown(function(event) {
|
$('#nickinput').keydown(function (event) {
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var val = Util.escapeHtml(this.value);
|
var val = Util.escapeHtml(this.value);
|
||||||
|
@ -35,7 +36,7 @@ var Chat = (function (my) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#usermsg').keydown(function(event) {
|
$('#usermsg').keydown(function (event) {
|
||||||
if (event.keyCode === 13) {
|
if (event.keyCode === 13) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var message = Util.escapeHtml(this.value);
|
var message = Util.escapeHtml(this.value);
|
||||||
|
@ -45,14 +46,14 @@ var Chat = (function (my) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var onTextAreaResize = function() {
|
var onTextAreaResize = function () {
|
||||||
resizeChatConversation();
|
resizeChatConversation();
|
||||||
scrollChatToBottom();
|
scrollChatToBottom();
|
||||||
};
|
};
|
||||||
$('#usermsg').autosize({callback: onTextAreaResize});
|
$('#usermsg').autosize({callback: onTextAreaResize});
|
||||||
|
|
||||||
$("#chatspace").bind("shown",
|
$("#chatspace").bind("shown",
|
||||||
function() {
|
function () {
|
||||||
unreadMessages = 0;
|
unreadMessages = 0;
|
||||||
setVisualNotification(false);
|
setVisualNotification(false);
|
||||||
});
|
});
|
||||||
|
@ -82,9 +83,9 @@ var Chat = (function (my) {
|
||||||
var escDisplayName = Util.escapeHtml(displayName);
|
var escDisplayName = Util.escapeHtml(displayName);
|
||||||
message = processReplacements(escMessage);
|
message = processReplacements(escMessage);
|
||||||
|
|
||||||
$('#chatconversation').append('<div class="' + divClassName + '"><b>'
|
$('#chatconversation').append('<div class="' + divClassName + '"><b>' +
|
||||||
+ escDisplayName + ': </b>'
|
escDisplayName + ': </b>' +
|
||||||
+ message + '</div>');
|
message + '</div>');
|
||||||
$('#chatconversation').animate(
|
$('#chatconversation').animate(
|
||||||
{ scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
|
{ scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
|
||||||
};
|
};
|
||||||
|
@ -103,15 +104,15 @@ var Chat = (function (my) {
|
||||||
= getVideoSize(null, null, videospaceWidth, videospaceHeight);
|
= getVideoSize(null, null, videospaceWidth, videospaceHeight);
|
||||||
var videoWidth = videoSize[0];
|
var videoWidth = videoSize[0];
|
||||||
var videoHeight = videoSize[1];
|
var videoHeight = videoSize[1];
|
||||||
var videoPosition = getVideoPosition( videoWidth,
|
var videoPosition = getVideoPosition(videoWidth,
|
||||||
videoHeight,
|
videoHeight,
|
||||||
videospaceWidth,
|
videospaceWidth,
|
||||||
videospaceHeight);
|
videospaceHeight);
|
||||||
var horizontalIndent = videoPosition[0];
|
var horizontalIndent = videoPosition[0];
|
||||||
var verticalIndent = videoPosition[1];
|
var verticalIndent = videoPosition[1];
|
||||||
|
|
||||||
if (chatspace.is(":visible")) {
|
if (chatspace.is(":visible")) {
|
||||||
videospace.animate( {right: chatSize[0],
|
videospace.animate({right: chatSize[0],
|
||||||
width: videospaceWidth,
|
width: videospaceWidth,
|
||||||
height: videospaceHeight},
|
height: videospaceHeight},
|
||||||
{queue: false,
|
{queue: false,
|
||||||
|
@ -143,7 +144,7 @@ var Chat = (function (my) {
|
||||||
height: videospaceHeight},
|
height: videospaceHeight},
|
||||||
{queue: false,
|
{queue: false,
|
||||||
duration: 500,
|
duration: 500,
|
||||||
complete: function() {
|
complete: function () {
|
||||||
scrollChatToBottom();
|
scrollChatToBottom();
|
||||||
chatspace.trigger('shown');
|
chatspace.trigger('shown');
|
||||||
}
|
}
|
||||||
|
@ -183,9 +184,9 @@ var Chat = (function (my) {
|
||||||
*/
|
*/
|
||||||
my.setChatConversationMode = function (isConversationMode) {
|
my.setChatConversationMode = function (isConversationMode) {
|
||||||
if (isConversationMode) {
|
if (isConversationMode) {
|
||||||
$('#nickname').css({visibility:"hidden"});
|
$('#nickname').css({visibility: 'hidden'});
|
||||||
$('#chatconversation').css({visibility:'visible'});
|
$('#chatconversation').css({visibility: 'visible'});
|
||||||
$('#usermsg').css({visibility:'visible'});
|
$('#usermsg').css({visibility: 'visible'});
|
||||||
$('#usermsg').focus();
|
$('#usermsg').focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -205,13 +206,13 @@ var Chat = (function (my) {
|
||||||
/**
|
/**
|
||||||
* Returns the size of the chat.
|
* Returns the size of the chat.
|
||||||
*/
|
*/
|
||||||
my.getChatSize = function() {
|
my.getChatSize = function () {
|
||||||
var availableHeight = window.innerHeight;
|
var availableHeight = window.innerHeight;
|
||||||
var availableWidth = window.innerWidth;
|
var availableWidth = window.innerWidth;
|
||||||
|
|
||||||
var chatWidth = 200;
|
var chatWidth = 200;
|
||||||
if (availableWidth*0.2 < 200)
|
if (availableWidth * 0.2 < 200)
|
||||||
chatWidth = availableWidth*0.2;
|
chatWidth = availableWidth * 0.2;
|
||||||
|
|
||||||
return [chatWidth, availableHeight];
|
return [chatWidth, availableHeight];
|
||||||
};
|
};
|
||||||
|
@ -228,7 +229,7 @@ var Chat = (function (my) {
|
||||||
$('#chatconversation').width($('#chatspace').width() - 10);
|
$('#chatconversation').width($('#chatspace').width() - 10);
|
||||||
$('#chatconversation')
|
$('#chatconversation')
|
||||||
.height(window.innerHeight - 10 - parseInt(usermsgHeight));
|
.height(window.innerHeight - 10 - parseInt(usermsgHeight));
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows/hides a visual notification, indicating that a message has arrived.
|
* Shows/hides a visual notification, indicating that a message has arrived.
|
||||||
|
@ -245,15 +246,15 @@ var Chat = (function (my) {
|
||||||
|
|
||||||
var chatButtonElement
|
var chatButtonElement
|
||||||
= document.getElementById('chatButton').parentNode;
|
= document.getElementById('chatButton').parentNode;
|
||||||
var leftIndent = (Util.getTextWidth(chatButtonElement)
|
var leftIndent = (Util.getTextWidth(chatButtonElement) -
|
||||||
- Util.getTextWidth(unreadMsgElement))/2;
|
Util.getTextWidth(unreadMsgElement)) / 2;
|
||||||
var topIndent = (Util.getTextHeight(chatButtonElement)
|
var topIndent = (Util.getTextHeight(chatButtonElement) -
|
||||||
- Util.getTextHeight(unreadMsgElement))/2 - 3;
|
Util.getTextHeight(unreadMsgElement)) / 2 - 3;
|
||||||
|
|
||||||
unreadMsgElement.setAttribute(
|
unreadMsgElement.setAttribute(
|
||||||
'style',
|
'style',
|
||||||
'top:' + topIndent
|
'top:' + topIndent +
|
||||||
+ '; left:' + leftIndent +';');
|
'; left:' + leftIndent + ';');
|
||||||
|
|
||||||
if (!glower.hasClass('icon-chat-simple')) {
|
if (!glower.hasClass('icon-chat-simple')) {
|
||||||
glower.removeClass('icon-chat');
|
glower.removeClass('icon-chat');
|
||||||
|
@ -267,7 +268,7 @@ var Chat = (function (my) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (show && !notificationInterval) {
|
if (show && !notificationInterval) {
|
||||||
notificationInterval = window.setInterval(function() {
|
notificationInterval = window.setInterval(function () {
|
||||||
glower.toggleClass('active');
|
glower.toggleClass('active');
|
||||||
}, 800);
|
}, 800);
|
||||||
}
|
}
|
||||||
|
@ -282,7 +283,7 @@ var Chat = (function (my) {
|
||||||
* Scrolls chat to the bottom.
|
* Scrolls chat to the bottom.
|
||||||
*/
|
*/
|
||||||
function scrollChatToBottom() {
|
function scrollChatToBottom() {
|
||||||
setTimeout(function() {
|
setTimeout(function () {
|
||||||
$('#chatconversation').scrollTop(
|
$('#chatconversation').scrollTop(
|
||||||
$('#chatconversation')[0].scrollHeight);
|
$('#chatconversation')[0].scrollHeight);
|
||||||
}, 5);
|
}, 5);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* global $, config, connection, chrome, alert, getUserMediaWithConstraints, change_local_video, getConferenceHandler */
|
||||||
/**
|
/**
|
||||||
* Indicates that desktop stream is currently in use(for toggle purpose).
|
* Indicates that desktop stream is currently in use(for toggle purpose).
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
|
@ -12,7 +13,7 @@ var switchInProgress = false;
|
||||||
/**
|
/**
|
||||||
* Method used to get screen sharing stream.
|
* Method used to get screen sharing stream.
|
||||||
*
|
*
|
||||||
* @type {function(stream_callback, failure_callback}
|
* @type {function (stream_callback, failure_callback}
|
||||||
*/
|
*/
|
||||||
var obtainDesktopStream = null;
|
var obtainDesktopStream = null;
|
||||||
|
|
||||||
|
@ -22,149 +23,6 @@ var obtainDesktopStream = null;
|
||||||
*/
|
*/
|
||||||
var _desktopSharingEnabled = null;
|
var _desktopSharingEnabled = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {boolean} <tt>true</tt> if desktop sharing feature is available and enabled.
|
|
||||||
*/
|
|
||||||
function isDesktopSharingEnabled() {
|
|
||||||
if(_desktopSharingEnabled === null){
|
|
||||||
if(obtainDesktopStream === obtainScreenFromExtension) {
|
|
||||||
// Parse chrome version
|
|
||||||
var userAgent = navigator.userAgent.toLowerCase();
|
|
||||||
// We can assume that user agent is chrome, because it's enforced when 'ext' streaming method is set
|
|
||||||
var ver = parseInt(userAgent.match(/chrome\/(\d+)\./)[1], 10);
|
|
||||||
console.log("Chrome version" + userAgent, ver);
|
|
||||||
_desktopSharingEnabled = ver >= 34;
|
|
||||||
} else {
|
|
||||||
_desktopSharingEnabled = obtainDesktopStream === obtainWebRTCScreen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _desktopSharingEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call this method to toggle desktop sharing feature.
|
|
||||||
* @param method pass "ext" to use chrome extension for desktop capture(chrome extension required),
|
|
||||||
* pass "webrtc" to use WebRTC "screen" desktop source('chrome://flags/#enable-usermedia-screen-capture'
|
|
||||||
* must be enabled), pass any other string or nothing in order to disable this feature completely.
|
|
||||||
*/
|
|
||||||
function setDesktopSharing(method) {
|
|
||||||
// Check if we are running chrome
|
|
||||||
if(!navigator.webkitGetUserMedia){
|
|
||||||
obtainDesktopStream = null;
|
|
||||||
console.info("Desktop sharing disabled");
|
|
||||||
} else if(method == "ext") {
|
|
||||||
obtainDesktopStream = obtainScreenFromExtension;
|
|
||||||
console.info("Using Chrome extension for desktop sharing");
|
|
||||||
} else if(method == "webrtc") {
|
|
||||||
obtainDesktopStream = obtainWebRTCScreen;
|
|
||||||
console.info("Using Chrome WebRTC for desktop sharing");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset enabled cache
|
|
||||||
_desktopSharingEnabled = null;
|
|
||||||
|
|
||||||
showDesktopSharingButton();
|
|
||||||
}
|
|
||||||
|
|
||||||
function showDesktopSharingButton() {
|
|
||||||
if(isDesktopSharingEnabled()) {
|
|
||||||
$('#desktopsharing').css( {display:"inline"} );
|
|
||||||
} else {
|
|
||||||
$('#desktopsharing').css( {display:"none"} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes <link rel=chrome-webstore-item /> with extension id set in config.js to support inline installs.
|
|
||||||
* Host site must be selected as main website of published extension.
|
|
||||||
*/
|
|
||||||
function initInlineInstalls()
|
|
||||||
{
|
|
||||||
$("link[rel=chrome-webstore-item]").attr("href", getWebStoreInstallUrl());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs inline install URL for Chrome desktop streaming extension.
|
|
||||||
* The 'chromeExtensionId' must be defined in config.js.
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
function getWebStoreInstallUrl()
|
|
||||||
{
|
|
||||||
return "https://chrome.google.com/webstore/detail/" + config.chromeExtensionId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Toggles screen sharing.
|
|
||||||
*/
|
|
||||||
function toggleScreenSharing() {
|
|
||||||
if (switchInProgress || !obtainDesktopStream) {
|
|
||||||
console.warn("Switch in progress or no method defined");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switchInProgress = true;
|
|
||||||
|
|
||||||
// Only the focus is able to set a shared key.
|
|
||||||
if(!isUsingScreenStream)
|
|
||||||
{
|
|
||||||
obtainDesktopStream(
|
|
||||||
function(stream) {
|
|
||||||
// We now use screen stream
|
|
||||||
isUsingScreenStream = true;
|
|
||||||
// Hook 'ended' event to restore camera when screen stream stops
|
|
||||||
stream.addEventListener('ended',
|
|
||||||
function(e) {
|
|
||||||
if(!switchInProgress && isUsingScreenStream) {
|
|
||||||
toggleScreenSharing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
newStreamCreated(stream);
|
|
||||||
},
|
|
||||||
getSwitchStreamFailed );
|
|
||||||
} else {
|
|
||||||
// Disable screen stream
|
|
||||||
getUserMediaWithConstraints(
|
|
||||||
['video'],
|
|
||||||
function(stream) {
|
|
||||||
// We are now using camera stream
|
|
||||||
isUsingScreenStream = false;
|
|
||||||
newStreamCreated(stream);
|
|
||||||
},
|
|
||||||
getSwitchStreamFailed, config.resolution || '360'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSwitchStreamFailed(error) {
|
|
||||||
console.error("Failed to obtain the stream to switch to", error);
|
|
||||||
switchInProgress = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function newStreamCreated(stream) {
|
|
||||||
|
|
||||||
var oldStream = connection.jingle.localVideo;
|
|
||||||
|
|
||||||
change_local_video(stream, !isUsingScreenStream);
|
|
||||||
|
|
||||||
var conferenceHandler = getConferenceHandler();
|
|
||||||
if(conferenceHandler) {
|
|
||||||
// FIXME: will block switchInProgress on true value in case of exception
|
|
||||||
conferenceHandler.switchStreams(stream, oldStream, streamSwitchDone);
|
|
||||||
} else {
|
|
||||||
// We are done immediately
|
|
||||||
console.error("No conference handler");
|
|
||||||
streamSwitchDone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function streamSwitchDone() {
|
|
||||||
//window.setTimeout(
|
|
||||||
// function() {
|
|
||||||
switchInProgress = false;
|
|
||||||
// }, 100
|
|
||||||
//);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method obtains desktop stream from WebRTC 'screen' source.
|
* Method obtains desktop stream from WebRTC 'screen' source.
|
||||||
* Flag 'chrome://flags/#enable-usermedia-screen-capture' must be enabled.
|
* Flag 'chrome://flags/#enable-usermedia-screen-capture' must be enabled.
|
||||||
|
@ -178,58 +36,13 @@ function obtainWebRTCScreen(streamCallback, failCallback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks Chrome extension to call chooseDesktopMedia and gets chrome 'desktop' stream for returned stream token.
|
* Constructs inline install URL for Chrome desktop streaming extension.
|
||||||
|
* The 'chromeExtensionId' must be defined in config.js.
|
||||||
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function obtainScreenFromExtension(streamCallback, failCallback) {
|
function getWebStoreInstallUrl()
|
||||||
checkExtInstalled(
|
{
|
||||||
function(isInstalled) {
|
return "https://chrome.google.com/webstore/detail/" + config.chromeExtensionId;
|
||||||
if(isInstalled) {
|
|
||||||
doGetStreamFromExtension(streamCallback, failCallback);
|
|
||||||
} else {
|
|
||||||
chrome.webstore.install(
|
|
||||||
getWebStoreInstallUrl(),
|
|
||||||
function(arg) {
|
|
||||||
console.log("Extension installed successfully", arg);
|
|
||||||
// We need to reload the page in order to get the access to chrome.runtime
|
|
||||||
window.location.reload(false);
|
|
||||||
},
|
|
||||||
function(arg) {
|
|
||||||
console.log("Failed to install the extension", arg);
|
|
||||||
failCallback(arg);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkExtInstalled(isInstalledCallback) {
|
|
||||||
if(!chrome.runtime) {
|
|
||||||
// No API, so no extension for sure
|
|
||||||
isInstalledCallback(false);
|
|
||||||
}
|
|
||||||
chrome.runtime.sendMessage(
|
|
||||||
config.chromeExtensionId,
|
|
||||||
{ getVersion: true },
|
|
||||||
function(response){
|
|
||||||
if(!response || !response.version) {
|
|
||||||
// Communication failure - assume that no endpoint exists
|
|
||||||
console.warn("Extension not installed?: "+chrome.runtime.lastError);
|
|
||||||
isInstalledCallback(false);
|
|
||||||
} else {
|
|
||||||
// Check installed extension version
|
|
||||||
var extVersion = response.version;
|
|
||||||
console.log('Extension version is: '+extVersion);
|
|
||||||
var updateRequired = isUpdateRequired(config.minChromeExtVersion, extVersion);
|
|
||||||
if(updateRequired) {
|
|
||||||
alert(
|
|
||||||
'Jitsi Desktop Streamer requires update. ' +
|
|
||||||
'Changes will take effect after next Chrome restart.' );
|
|
||||||
}
|
|
||||||
isInstalledCallback(!updateRequired);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -246,20 +59,21 @@ function isUpdateRequired(minVersion, extVersion)
|
||||||
var s2 = extVersion.split('.');
|
var s2 = extVersion.split('.');
|
||||||
|
|
||||||
var len = Math.max(s1.length, s2.length);
|
var len = Math.max(s1.length, s2.length);
|
||||||
for(var i = 0; i < len; i++)
|
for (var i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
var n1=0,n2=0;
|
var n1 = 0,
|
||||||
|
n2 = 0;
|
||||||
|
|
||||||
if(i < s1.length)
|
if (i < s1.length)
|
||||||
n1 = parseInt(s1[i]);
|
n1 = parseInt(s1[i]);
|
||||||
if(i < s2.length)
|
if (i < s2.length)
|
||||||
n2 = parseInt(s2[i]);
|
n2 = parseInt(s2[i]);
|
||||||
|
|
||||||
if(isNaN(n1) || isNaN(n2))
|
if (isNaN(n1) || isNaN(n2))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if(n1 !== n2)
|
else if (n1 !== n2)
|
||||||
{
|
{
|
||||||
return n1 > n2;
|
return n1 > n2;
|
||||||
}
|
}
|
||||||
|
@ -269,28 +83,58 @@ function isUpdateRequired(minVersion, extVersion)
|
||||||
// their components (even if one of them is longer, has more components)
|
// their components (even if one of them is longer, has more components)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch(e)
|
catch (e)
|
||||||
{
|
{
|
||||||
console.error("Failed to parse extension version", e);
|
console.error("Failed to parse extension version", e);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function checkExtInstalled(isInstalledCallback) {
|
||||||
|
if (!chrome.runtime) {
|
||||||
|
// No API, so no extension for sure
|
||||||
|
isInstalledCallback(false);
|
||||||
|
}
|
||||||
|
chrome.runtime.sendMessage(
|
||||||
|
config.chromeExtensionId,
|
||||||
|
{ getVersion: true },
|
||||||
|
function (response) {
|
||||||
|
if (!response || !response.version) {
|
||||||
|
// Communication failure - assume that no endpoint exists
|
||||||
|
console.warn("Extension not installed?: " + chrome.runtime.lastError);
|
||||||
|
isInstalledCallback(false);
|
||||||
|
} else {
|
||||||
|
// Check installed extension version
|
||||||
|
var extVersion = response.version;
|
||||||
|
console.log('Extension version is: ' + extVersion);
|
||||||
|
var updateRequired = isUpdateRequired(config.minChromeExtVersion, extVersion);
|
||||||
|
if (updateRequired) {
|
||||||
|
alert(
|
||||||
|
'Jitsi Desktop Streamer requires update. ' +
|
||||||
|
'Changes will take effect after next Chrome restart.');
|
||||||
|
}
|
||||||
|
isInstalledCallback(!updateRequired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function doGetStreamFromExtension(streamCallback, failCallback) {
|
function doGetStreamFromExtension(streamCallback, failCallback) {
|
||||||
// Sends 'getStream' msg to the extension. Extension id must be defined in the config.
|
// Sends 'getStream' msg to the extension. Extension id must be defined in the config.
|
||||||
chrome.runtime.sendMessage(
|
chrome.runtime.sendMessage(
|
||||||
config.chromeExtensionId,
|
config.chromeExtensionId,
|
||||||
{ getStream: true},
|
{ getStream: true},
|
||||||
function(response) {
|
function (response) {
|
||||||
if(!response) {
|
if (!response) {
|
||||||
failCallback(chrome.runtime.lastError);
|
failCallback(chrome.runtime.lastError);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log("Response from extension: "+response);
|
console.log("Response from extension: " + response);
|
||||||
if(response.streamId) {
|
if (response.streamId) {
|
||||||
getUserMediaWithConstraints(
|
getUserMediaWithConstraints(
|
||||||
['desktop'],
|
['desktop'],
|
||||||
function(stream) {
|
function (stream) {
|
||||||
streamCallback(stream);
|
streamCallback(stream);
|
||||||
},
|
},
|
||||||
failCallback,
|
failCallback,
|
||||||
|
@ -302,3 +146,162 @@ function doGetStreamFromExtension(streamCallback, failCallback) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Asks Chrome extension to call chooseDesktopMedia and gets chrome 'desktop' stream for returned stream token.
|
||||||
|
*/
|
||||||
|
function obtainScreenFromExtension(streamCallback, failCallback) {
|
||||||
|
checkExtInstalled(
|
||||||
|
function (isInstalled) {
|
||||||
|
if (isInstalled) {
|
||||||
|
doGetStreamFromExtension(streamCallback, failCallback);
|
||||||
|
} else {
|
||||||
|
chrome.webstore.install(
|
||||||
|
getWebStoreInstallUrl(),
|
||||||
|
function (arg) {
|
||||||
|
console.log("Extension installed successfully", arg);
|
||||||
|
// We need to reload the page in order to get the access to chrome.runtime
|
||||||
|
window.location.reload(false);
|
||||||
|
},
|
||||||
|
function (arg) {
|
||||||
|
console.log("Failed to install the extension", arg);
|
||||||
|
failCallback(arg);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean} <tt>true</tt> if desktop sharing feature is available and enabled.
|
||||||
|
*/
|
||||||
|
function isDesktopSharingEnabled() {
|
||||||
|
if (_desktopSharingEnabled === null) {
|
||||||
|
if (obtainDesktopStream === obtainScreenFromExtension) {
|
||||||
|
// Parse chrome version
|
||||||
|
var userAgent = navigator.userAgent.toLowerCase();
|
||||||
|
// We can assume that user agent is chrome, because it's enforced when 'ext' streaming method is set
|
||||||
|
var ver = parseInt(userAgent.match(/chrome\/(\d+)\./)[1], 10);
|
||||||
|
console.log("Chrome version" + userAgent, ver);
|
||||||
|
_desktopSharingEnabled = ver >= 34;
|
||||||
|
} else {
|
||||||
|
_desktopSharingEnabled = obtainDesktopStream === obtainWebRTCScreen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _desktopSharingEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDesktopSharingButton() {
|
||||||
|
if (isDesktopSharingEnabled()) {
|
||||||
|
$('#desktopsharing').css({display: "inline"});
|
||||||
|
} else {
|
||||||
|
$('#desktopsharing').css({display: "none"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this method to toggle desktop sharing feature.
|
||||||
|
* @param method pass "ext" to use chrome extension for desktop capture(chrome extension required),
|
||||||
|
* pass "webrtc" to use WebRTC "screen" desktop source('chrome://flags/#enable-usermedia-screen-capture'
|
||||||
|
* must be enabled), pass any other string or nothing in order to disable this feature completely.
|
||||||
|
*/
|
||||||
|
function setDesktopSharing(method) {
|
||||||
|
// Check if we are running chrome
|
||||||
|
if (!navigator.webkitGetUserMedia) {
|
||||||
|
obtainDesktopStream = null;
|
||||||
|
console.info("Desktop sharing disabled");
|
||||||
|
} else if (method == "ext") {
|
||||||
|
obtainDesktopStream = obtainScreenFromExtension;
|
||||||
|
console.info("Using Chrome extension for desktop sharing");
|
||||||
|
} else if (method == "webrtc") {
|
||||||
|
obtainDesktopStream = obtainWebRTCScreen;
|
||||||
|
console.info("Using Chrome WebRTC for desktop sharing");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset enabled cache
|
||||||
|
_desktopSharingEnabled = null;
|
||||||
|
|
||||||
|
showDesktopSharingButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes <link rel=chrome-webstore-item /> with extension id set in config.js to support inline installs.
|
||||||
|
* Host site must be selected as main website of published extension.
|
||||||
|
*/
|
||||||
|
function initInlineInstalls()
|
||||||
|
{
|
||||||
|
$("link[rel=chrome-webstore-item]").attr("href", getWebStoreInstallUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSwitchStreamFailed(error) {
|
||||||
|
console.error("Failed to obtain the stream to switch to", error);
|
||||||
|
switchInProgress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function streamSwitchDone() {
|
||||||
|
//window.setTimeout(
|
||||||
|
// function () {
|
||||||
|
switchInProgress = false;
|
||||||
|
// }, 100
|
||||||
|
//);
|
||||||
|
}
|
||||||
|
|
||||||
|
function newStreamCreated(stream) {
|
||||||
|
|
||||||
|
var oldStream = connection.jingle.localVideo;
|
||||||
|
|
||||||
|
change_local_video(stream, !isUsingScreenStream);
|
||||||
|
|
||||||
|
var conferenceHandler = getConferenceHandler();
|
||||||
|
if (conferenceHandler) {
|
||||||
|
// FIXME: will block switchInProgress on true value in case of exception
|
||||||
|
conferenceHandler.switchStreams(stream, oldStream, streamSwitchDone);
|
||||||
|
} else {
|
||||||
|
// We are done immediately
|
||||||
|
console.error("No conference handler");
|
||||||
|
streamSwitchDone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggles screen sharing.
|
||||||
|
*/
|
||||||
|
function toggleScreenSharing() {
|
||||||
|
if (switchInProgress || !obtainDesktopStream) {
|
||||||
|
console.warn("Switch in progress or no method defined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
switchInProgress = true;
|
||||||
|
|
||||||
|
// Only the focus is able to set a shared key.
|
||||||
|
if (!isUsingScreenStream)
|
||||||
|
{
|
||||||
|
obtainDesktopStream(
|
||||||
|
function (stream) {
|
||||||
|
// We now use screen stream
|
||||||
|
isUsingScreenStream = true;
|
||||||
|
// Hook 'ended' event to restore camera when screen stream stops
|
||||||
|
stream.addEventListener('ended',
|
||||||
|
function (e) {
|
||||||
|
if (!switchInProgress && isUsingScreenStream) {
|
||||||
|
toggleScreenSharing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
newStreamCreated(stream);
|
||||||
|
},
|
||||||
|
getSwitchStreamFailed);
|
||||||
|
} else {
|
||||||
|
// Disable screen stream
|
||||||
|
getUserMediaWithConstraints(
|
||||||
|
['video'],
|
||||||
|
function (stream) {
|
||||||
|
// We are now using camera stream
|
||||||
|
isUsingScreenStream = false;
|
||||||
|
newStreamCreated(stream);
|
||||||
|
},
|
||||||
|
getSwitchStreamFailed, config.resolution || '360'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* global Strophe */
|
||||||
Strophe.addConnectionPlugin('logger', {
|
Strophe.addConnectionPlugin('logger', {
|
||||||
// logs raw stanzas and makes them available for download as JSON
|
// logs raw stanzas and makes them available for download as JSON
|
||||||
connection: null,
|
connection: null,
|
||||||
|
|
25
etherpad.js
25
etherpad.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* global $, config, Prezi, Util, connection, setLargeVideoVisible, dockToolbar */
|
||||||
var Etherpad = (function (my) {
|
var Etherpad = (function (my) {
|
||||||
var etherpadName = null;
|
var etherpadName = null;
|
||||||
var etherpadIFrame = null;
|
var etherpadIFrame = null;
|
||||||
|
@ -15,8 +16,8 @@ var Etherpad = (function (my) {
|
||||||
|
|
||||||
if (!name) {
|
if (!name) {
|
||||||
// In case we're the focus we generate the name.
|
// In case we're the focus we generate the name.
|
||||||
etherpadName = Math.random().toString(36).substring(7)
|
etherpadName = Math.random().toString(36).substring(7) +
|
||||||
+ '_' + (new Date().getTime()).toString();
|
'_' + (new Date().getTime()).toString();
|
||||||
shareEtherpad();
|
shareEtherpad();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -41,27 +42,27 @@ var Etherpad = (function (my) {
|
||||||
|
|
||||||
if ($('#etherpad>iframe').css('visibility') === 'hidden') {
|
if ($('#etherpad>iframe').css('visibility') === 'hidden') {
|
||||||
largeVideo.fadeOut(300, function () {
|
largeVideo.fadeOut(300, function () {
|
||||||
if (Prezi.isPresentationVisible())
|
if (Prezi.isPresentationVisible()) {
|
||||||
largeVideo.css({opacity:'0'});
|
largeVideo.css({opacity: '0'});
|
||||||
else {
|
} else {
|
||||||
setLargeVideoVisible(false);
|
setLargeVideoVisible(false);
|
||||||
dockToolbar(true);
|
dockToolbar(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#etherpad>iframe').fadeIn(300, function() {
|
$('#etherpad>iframe').fadeIn(300, function () {
|
||||||
document.body.style.background = '#eeeeee';
|
document.body.style.background = '#eeeeee';
|
||||||
$('#etherpad>iframe').css({visibility:'visible'});
|
$('#etherpad>iframe').css({visibility: 'visible'});
|
||||||
$('#etherpad').css({zIndex:2});
|
$('#etherpad').css({zIndex: 2});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if ($('#etherpad>iframe')) {
|
else if ($('#etherpad>iframe')) {
|
||||||
$('#etherpad>iframe').fadeOut(300, function () {
|
$('#etherpad>iframe').fadeOut(300, function () {
|
||||||
$('#etherpad>iframe').css({visibility:'hidden'});
|
$('#etherpad>iframe').css({visibility: 'hidden'});
|
||||||
$('#etherpad').css({zIndex:0});
|
$('#etherpad').css({zIndex: 0});
|
||||||
document.body.style.background = 'black';
|
document.body.style.background = 'black';
|
||||||
if (!isPresentation) {
|
if (!isPresentation) {
|
||||||
$('#largeVideo').fadeIn(300, function() {
|
$('#largeVideo').fadeIn(300, function () {
|
||||||
setLargeVideoVisible(true);
|
setLargeVideoVisible(true);
|
||||||
dockToolbar(false);
|
dockToolbar(false);
|
||||||
});
|
});
|
||||||
|
@ -99,7 +100,7 @@ var Etherpad = (function (my) {
|
||||||
*/
|
*/
|
||||||
function enableEtherpadButton() {
|
function enableEtherpadButton() {
|
||||||
if (!$('#etherpadButton').is(":visible"))
|
if (!$('#etherpadButton').is(":visible"))
|
||||||
$('#etherpadButton').css({display:'inline-block'});
|
$('#etherpadButton').css({display: 'inline-block'});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
19
util.js
19
util.js
|
@ -1,3 +1,4 @@
|
||||||
|
/* global $ */
|
||||||
/**
|
/**
|
||||||
* Utility functions.
|
* Utility functions.
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +9,7 @@ var Util = (function (my) {
|
||||||
*
|
*
|
||||||
* @param el the element
|
* @param el the element
|
||||||
*/
|
*/
|
||||||
my.getTextWidth = function(el) {
|
my.getTextWidth = function (el) {
|
||||||
return (el.clientWidth + 1);
|
return (el.clientWidth + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,7 +18,7 @@ var Util = (function (my) {
|
||||||
*
|
*
|
||||||
* @param el the element
|
* @param el the element
|
||||||
*/
|
*/
|
||||||
my.getTextHeight = function(el) {
|
my.getTextHeight = function (el) {
|
||||||
return (el.clientHeight + 1);
|
return (el.clientHeight + 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ var Util = (function (my) {
|
||||||
*
|
*
|
||||||
* @param number the number to cast
|
* @param number the number to cast
|
||||||
*/
|
*/
|
||||||
my.toInteger = function(number) {
|
my.toInteger = function (number) {
|
||||||
return Math.round(Number(number));
|
return Math.round(Number(number));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -35,27 +36,25 @@ var Util = (function (my) {
|
||||||
*
|
*
|
||||||
* @param id the identifier of the audio element.
|
* @param id the identifier of the audio element.
|
||||||
*/
|
*/
|
||||||
my.playSoundNotification = function(id) {
|
my.playSoundNotification = function (id) {
|
||||||
document.getElementById(id).play();
|
document.getElementById(id).play();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escapes the given text.
|
* Escapes the given text.
|
||||||
*/
|
*/
|
||||||
my.escapeHtml = function(unsafeText) {
|
my.escapeHtml = function (unsafeText) {
|
||||||
return $('<div/>').text(unsafeText).html();
|
return $('<div/>').text(unsafeText).html();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the available video width.
|
* Returns the available video width.
|
||||||
*/
|
*/
|
||||||
my.getAvailableVideoWidth = function() {
|
my.getAvailableVideoWidth = function () {
|
||||||
var chatspaceWidth = $('#chatspace').is(":visible")
|
var chatspaceWidth = $('#chatspace').is(":visible") ? $('#chatspace').width() : 0;
|
||||||
? $('#chatspace').width()
|
|
||||||
: 0;
|
|
||||||
|
|
||||||
return window.innerWidth - chatspaceWidth;
|
return window.innerWidth - chatspaceWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
return my;
|
return my;
|
||||||
}(Util || {}));
|
}(Util || {}));
|
||||||
|
|
Loading…
Reference in New Issue