fix errors reported by jshint

This commit is contained in:
Philipp Hancke 2014-04-13 14:30:47 +02:00
parent 84593b2bcb
commit 78c8f43c3d
6 changed files with 509 additions and 502 deletions

492
app.js
View File

@ -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
View File

@ -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);

View File

@ -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'
);
}
}

View File

@ -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,

View File

@ -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
View File

@ -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 || {}));