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;
|
||||
/**
|
||||
* Method used to calculate large video size.
|
||||
* @type {function()}
|
||||
* @type {function ()}
|
||||
*/
|
||||
var getVideoSize;
|
||||
/**
|
||||
* Method used to get large video position.
|
||||
* @type {function()}
|
||||
* @type {function ()}
|
||||
*/
|
||||
var getVideoPosition;
|
||||
|
||||
|
@ -40,9 +40,11 @@ function init() {
|
|||
if (RTC === null) {
|
||||
window.location.href = 'webrtcrequired.html';
|
||||
return;
|
||||
/*
|
||||
} else if (RTC.browser !== 'chrome') {
|
||||
window.location.href = 'chromeonly.html';
|
||||
return;
|
||||
*/
|
||||
}
|
||||
|
||||
connection = new Strophe.Connection(document.getElementById('boshURL').value || config.bosh || '/http-bind');
|
||||
|
@ -69,9 +71,9 @@ function init() {
|
|||
if (config.useStunTurn) {
|
||||
connection.jingle.getStunAndTurnCredentials();
|
||||
}
|
||||
obtainAudioAndVideoPermissions(function(){
|
||||
getUserMediaWithConstraints( ['audio'], audioStreamReady,
|
||||
function(error){
|
||||
obtainAudioAndVideoPermissions(function () {
|
||||
getUserMediaWithConstraints(['audio'], audioStreamReady,
|
||||
function (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.
|
||||
* 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
|
||||
if(location.protocol !== 'https:') {
|
||||
if (location.protocol !== 'https:') {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
// Get AV
|
||||
getUserMediaWithConstraints(
|
||||
['audio', 'video'],
|
||||
function(avStream) {
|
||||
function (avStream) {
|
||||
avStream.stop();
|
||||
callback();
|
||||
},
|
||||
function(error){
|
||||
function (error) {
|
||||
console.error('failed to obtain audio/video stream - stop', error);
|
||||
});
|
||||
}
|
||||
|
@ -110,8 +112,8 @@ function audioStreamReady(stream) {
|
|||
|
||||
change_local_audio(stream);
|
||||
|
||||
if(RTC.browser !== 'firefox') {
|
||||
getUserMediaWithConstraints( ['video'], videoStreamReady, videoStreamFailed, config.resolution || '360' );
|
||||
if (RTC.browser !== 'firefox') {
|
||||
getUserMediaWithConstraints(['video'], videoStreamReady, videoStreamFailed, config.resolution || '360');
|
||||
} else {
|
||||
doJoin();
|
||||
}
|
||||
|
@ -169,7 +171,7 @@ function doJoin() {
|
|||
roomjid += '/' + Strophe.getNodeFromJid(connection.jid);
|
||||
}
|
||||
} else {
|
||||
roomjid += '/' + Strophe.getNodeFromJid(connection.jid).substr(0,8);
|
||||
roomjid += '/' + Strophe.getNodeFromJid(connection.jid).substr(0, 8);
|
||||
}
|
||||
connection.emuc.doJoin(roomjid);
|
||||
}
|
||||
|
@ -186,7 +188,7 @@ function change_local_video(stream, flipX) {
|
|||
connection.jingle.localVideo = stream;
|
||||
|
||||
var localVideo = document.createElement('video');
|
||||
localVideo.id = 'localVideo_'+stream.id;
|
||||
localVideo.id = 'localVideo_' + stream.id;
|
||||
localVideo.autoplay = true;
|
||||
localVideo.volume = 0; // is it required if audio is separated ?
|
||||
localVideo.oncontextmenu = function () { return false; };
|
||||
|
@ -196,7 +198,9 @@ function change_local_video(stream, flipX) {
|
|||
|
||||
var localVideoSelector = $('#' + localVideo.id);
|
||||
// Add click handler
|
||||
localVideoSelector.click(function () { handleVideoThumbClicked(localVideo.src); } );
|
||||
localVideoSelector.click(function () {
|
||||
handleVideoThumbClicked(localVideo.src);
|
||||
});
|
||||
// Add stream ended handler
|
||||
stream.onended = function () {
|
||||
localVideoContainer.removeChild(localVideo);
|
||||
|
@ -204,7 +208,7 @@ function change_local_video(stream, flipX) {
|
|||
};
|
||||
// Flip video x axis if needed
|
||||
flipXLocalVideo = flipX;
|
||||
if(flipX) {
|
||||
if (flipX) {
|
||||
localVideoSelector.addClass("flipVideoX");
|
||||
}
|
||||
// Attach WebRTC stream
|
||||
|
@ -216,7 +220,7 @@ function change_local_video(stream, flipX) {
|
|||
|
||||
$(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
||||
function waitForRemoteVideo(selector, sid, ssrc) {
|
||||
if(selector.removed) {
|
||||
if (selector.removed) {
|
||||
console.warn("media removed before had started", selector);
|
||||
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
|
||||
// in order to get rid of too many maps
|
||||
if(ssrc) {
|
||||
if (ssrc) {
|
||||
videoSrcToSsrc[sel.attr('src')] = ssrc;
|
||||
} else {
|
||||
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');
|
||||
ssrclines = ssrclines.filter(function (line) {
|
||||
return line.indexOf('mslabel:' + data.stream.label) !== -1;
|
||||
});
|
||||
});
|
||||
if (ssrclines.length) {
|
||||
thessrc = ssrclines[0].substring(7).split(' ')[0];
|
||||
// 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();
|
||||
RTC.attachMediaStream(sel, data.stream);
|
||||
|
||||
if(isVideo) {
|
||||
if (isVideo) {
|
||||
waitForRemoteVideo(sel, sid, thessrc);
|
||||
}
|
||||
|
||||
|
@ -316,9 +320,9 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
|||
sel.removed = true;
|
||||
sel.remove();
|
||||
|
||||
var audioCount = $('#'+container.id+'>audio').length;
|
||||
var videoCount = $('#'+container.id+'>video').length;
|
||||
if(!audioCount && !videoCount) {
|
||||
var audioCount = $('#' + container.id + '>audio').length;
|
||||
var videoCount = $('#' + container.id + '>video').length;
|
||||
if (!audioCount && !videoCount) {
|
||||
console.log("Remove whole user");
|
||||
// Remove whole container
|
||||
container.remove();
|
||||
|
@ -330,14 +334,17 @@ $(document).bind('remotestreamadded.jingle', function (event, data, sid) {
|
|||
};
|
||||
|
||||
// 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
|
||||
if (isVideo
|
||||
&& data.peerjid && sess.peerjid === data.peerjid &&
|
||||
data.stream.getVideoTracks().length === 0 &&
|
||||
connection.jingle.localVideo.getVideoTracks().length > 0) {
|
||||
window.setTimeout(function() {
|
||||
if (isVideo &&
|
||||
data.peerjid && sess.peerjid === data.peerjid &&
|
||||
data.stream.getVideoTracks().length === 0 &&
|
||||
connection.jingle.localVideo.getVideoTracks().length > 0) {
|
||||
//
|
||||
window.setTimeout(function () {
|
||||
sendKeyframe(sess.peerconnection);
|
||||
}, 3000);
|
||||
}
|
||||
|
@ -361,17 +368,17 @@ function handleVideoThumbClicked(videoSrc) {
|
|||
* Checks if removed video is currently displayed and tries to display another one instead.
|
||||
* @param removedVideoSrc src stream identifier of the video.
|
||||
*/
|
||||
function checkChangeLargeVideo(removedVideoSrc){
|
||||
function checkChangeLargeVideo(removedVideoSrc) {
|
||||
if (removedVideoSrc === $('#largeVideo').attr('src')) {
|
||||
// this is currently displayed as large
|
||||
// pick the last visible video in the row
|
||||
// if nobody else is left, this picks the local video
|
||||
var pick = $('#remoteVideos>span[id!="mixedstream"]:visible:last>video').get(0);
|
||||
|
||||
if(!pick) {
|
||||
if (!pick) {
|
||||
console.info("Last visible video no longer exists");
|
||||
pick = $('#remoteVideos>span[id!="mixedstream"]>video').get(0);
|
||||
if(!pick) {
|
||||
if (!pick) {
|
||||
// Try local video
|
||||
console.info("Fallback to local video...");
|
||||
pick = $('#remoteVideos>span>span>video').get(0);
|
||||
|
@ -396,8 +403,10 @@ function sendKeyframe(pc) {
|
|||
function () {
|
||||
pc.createAnswer(
|
||||
function (modifiedAnswer) {
|
||||
pc.setLocalDescription(modifiedAnswer,
|
||||
pc.setLocalDescription(
|
||||
modifiedAnswer,
|
||||
function () {
|
||||
// noop
|
||||
},
|
||||
function (error) {
|
||||
console.log('triggerKeyframe setLocalDescription failed', error);
|
||||
|
@ -436,7 +445,7 @@ function muteVideo(pc, unmute) {
|
|||
function () {
|
||||
console.log('mute SLD ok');
|
||||
},
|
||||
function(error) {
|
||||
function (error) {
|
||||
console.log('mute SLD error');
|
||||
}
|
||||
);
|
||||
|
@ -497,11 +506,11 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) {
|
|||
newssrcs[type] = ssrc;
|
||||
|
||||
directions[type] = (
|
||||
SDPUtil.find_line(media, 'a=sendrecv')
|
||||
|| SDPUtil.find_line(media, 'a=recvonly')
|
||||
|| SDPUtil.find_line('a=sendonly')
|
||||
|| SDPUtil.find_line('a=inactive')
|
||||
|| 'a=sendrecv' ).substr(2);
|
||||
SDPUtil.find_line(media, 'a=sendrecv') ||
|
||||
SDPUtil.find_line(media, 'a=recvonly') ||
|
||||
SDPUtil.find_line('a=sendonly') ||
|
||||
SDPUtil.find_line('a=inactive') ||
|
||||
'a=sendrecv').substr(2);
|
||||
}
|
||||
});
|
||||
console.log('new ssrcs', newssrcs);
|
||||
|
@ -513,7 +522,7 @@ $(document).bind('setLocalDescription.jingle', function (event, sid) {
|
|||
i++;
|
||||
var type = mtype;
|
||||
// Change video type to screen
|
||||
if(mtype === 'video' && isUsingScreenStream) {
|
||||
if (mtype === 'video' && isUsingScreenStream) {
|
||||
type = 'screen';
|
||||
}
|
||||
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) {
|
||||
|
||||
// Remove old ssrcs coming from the jid
|
||||
Object.keys(ssrc2jid).forEach(function(ssrc){
|
||||
if(ssrc2jid[ssrc] == jid){
|
||||
delete ssrc2jid[ssrc];
|
||||
}
|
||||
if(ssrc2videoType == jid){
|
||||
delete ssrc2videoType[ssrc];
|
||||
}
|
||||
Object.keys(ssrc2jid).forEach(function (ssrc) {
|
||||
if (ssrc2jid[ssrc] == jid) {
|
||||
delete ssrc2jid[ssrc];
|
||||
}
|
||||
if (ssrc2videoType == jid) {
|
||||
delete ssrc2videoType[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
|
||||
if (type === 'video' || type === 'screen') {
|
||||
var el = $('#participant_' + Strophe.getResourceFromJid(jid) + '>video');
|
||||
switch(ssrc.getAttribute('direction')) {
|
||||
switch (ssrc.getAttribute('direction')) {
|
||||
case 'sendrecv':
|
||||
el.show();
|
||||
break;
|
||||
|
@ -650,27 +659,24 @@ $(document).bind('passwordrequired.muc', function (event, jid) {
|
|||
console.log('on password required', jid);
|
||||
|
||||
$.prompt('<h2>Password required</h2>' +
|
||||
'<input id="lockKey" type="text" placeholder="shared key" autofocus>',
|
||||
{
|
||||
persistent: true,
|
||||
buttons: { "Ok": true , "Cancel": false},
|
||||
defaultButton: 1,
|
||||
loaded: function(event) {
|
||||
document.getElementById('lockKey').focus();
|
||||
},
|
||||
submit: function(e,v,m,f){
|
||||
if(v)
|
||||
{
|
||||
var lockKey = document.getElementById('lockKey');
|
||||
'<input id="lockKey" type="text" placeholder="shared key" autofocus>', {
|
||||
persistent: true,
|
||||
buttons: { "Ok": true, "Cancel": false},
|
||||
defaultButton: 1,
|
||||
loaded: function (event) {
|
||||
document.getElementById('lockKey').focus();
|
||||
},
|
||||
submit: function (e, v, m, f) {
|
||||
if (v) {
|
||||
var lockKey = document.getElementById('lockKey');
|
||||
|
||||
if (lockKey.value !== null)
|
||||
{
|
||||
setSharedKey(lockKey.value);
|
||||
connection.emuc.doJoin(jid, lockKey.value);
|
||||
}
|
||||
}
|
||||
if (lockKey.value !== null) {
|
||||
setSharedKey(lockKey.value);
|
||||
connection.emuc.doJoin(jid, lockKey.value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(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
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function isVideoSrcDesktop(videoSrc){
|
||||
function isVideoSrcDesktop(videoSrc) {
|
||||
// FIXME: fix this mapping mess...
|
||||
// figure out if large video is desktop stream or just a camera
|
||||
var isDesktop = false;
|
||||
if(localVideoSrc === videoSrc) {
|
||||
if (localVideoSrc === videoSrc) {
|
||||
// local video
|
||||
isDesktop = isUsingScreenStream;
|
||||
} else {
|
||||
// Do we have associations...
|
||||
var videoSsrc = videoSrcToSsrc[videoSrc];
|
||||
if(videoSsrc) {
|
||||
if (videoSsrc) {
|
||||
var videoType = ssrc2videoType[videoSsrc];
|
||||
if(videoType) {
|
||||
if (videoType) {
|
||||
// Finally there...
|
||||
isDesktop = videoType === 'screen';
|
||||
} else {
|
||||
|
@ -769,12 +775,12 @@ function isVideoSrcDesktop(videoSrc){
|
|||
*/
|
||||
function setLargeVideoVisible(isVisible) {
|
||||
if (isVisible) {
|
||||
$('#largeVideo').css({visibility:'visible'});
|
||||
$('.watermark').css({visibility:'visible'});
|
||||
$('#largeVideo').css({visibility: 'visible'});
|
||||
$('.watermark').css({visibility: 'visible'});
|
||||
}
|
||||
else {
|
||||
$('#largeVideo').css({visibility:'hidden'});
|
||||
$('.watermark').css({visibility:'hidden'});
|
||||
$('#largeVideo').css({visibility: 'hidden'});
|
||||
$('.watermark').css({visibility: 'hidden'});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -789,8 +795,8 @@ function toggleVideo() {
|
|||
var sess = getConferenceHandler();
|
||||
if (sess) {
|
||||
sess.toggleVideoMute(
|
||||
function(isMuted){
|
||||
if(isMuted) {
|
||||
function (isMuted) {
|
||||
if (isMuted) {
|
||||
$('#video').removeClass("icon-camera");
|
||||
$('#video').addClass("icon-camera icon-camera-disabled");
|
||||
} else {
|
||||
|
@ -801,7 +807,7 @@ function toggleVideo() {
|
|||
);
|
||||
}
|
||||
|
||||
var sess = focus || activecall;
|
||||
sess = focus || activecall;
|
||||
if (!sess) {
|
||||
return;
|
||||
}
|
||||
|
@ -835,30 +841,30 @@ function toggleAudio() {
|
|||
* @param videoWidth the stream video width
|
||||
* @param videoHeight the stream video height
|
||||
*/
|
||||
var positionLarge = function(videoWidth, videoHeight) {
|
||||
var positionLarge = function (videoWidth, videoHeight) {
|
||||
var videoSpaceWidth = $('#videospace').width();
|
||||
var videoSpaceHeight = window.innerHeight;
|
||||
|
||||
var videoSize = getVideoSize( videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight);
|
||||
var videoSize = getVideoSize(videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight);
|
||||
|
||||
var largeVideoWidth = videoSize[0];
|
||||
var largeVideoHeight = videoSize[1];
|
||||
|
||||
var videoPosition = getVideoPosition( largeVideoWidth,
|
||||
largeVideoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight);
|
||||
var videoPosition = getVideoPosition(largeVideoWidth,
|
||||
largeVideoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight);
|
||||
|
||||
var horizontalIndent = videoPosition[0];
|
||||
var verticalIndent = videoPosition[1];
|
||||
|
||||
positionVideo( $('#largeVideo'),
|
||||
largeVideoWidth,
|
||||
largeVideoHeight,
|
||||
horizontalIndent, verticalIndent);
|
||||
positionVideo($('#largeVideo'),
|
||||
largeVideoWidth,
|
||||
largeVideoHeight,
|
||||
horizontalIndent, verticalIndent);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -868,21 +874,21 @@ var positionLarge = function(videoWidth, videoHeight) {
|
|||
* @return an array with 2 elements, the horizontal indent and the vertical
|
||||
* indent
|
||||
*/
|
||||
function getCameraVideoPosition( videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight) {
|
||||
function getCameraVideoPosition(videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight) {
|
||||
// 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.
|
||||
// Need to think it further at some point and implement it properly.
|
||||
var isFullScreen = document.fullScreen
|
||||
|| document.mozFullScreen
|
||||
|| document.webkitIsFullScreen;
|
||||
var isFullScreen = document.fullScreen ||
|
||||
document.mozFullScreen ||
|
||||
document.webkitIsFullScreen;
|
||||
if (isFullScreen)
|
||||
videoSpaceHeight = window.innerHeight;
|
||||
|
||||
var horizontalIndent = (videoSpaceWidth - videoWidth)/2;
|
||||
var verticalIndent = (videoSpaceHeight - videoHeight)/2;
|
||||
var horizontalIndent = (videoSpaceWidth - videoWidth) / 2;
|
||||
var verticalIndent = (videoSpaceHeight - videoHeight) / 2;
|
||||
|
||||
return [horizontalIndent, verticalIndent];
|
||||
}
|
||||
|
@ -894,12 +900,12 @@ function getCameraVideoPosition( videoWidth,
|
|||
* @return an array with 2 elements, the horizontal indent and the vertical
|
||||
* indent
|
||||
*/
|
||||
function getDesktopVideoPosition( videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight) {
|
||||
function getDesktopVideoPosition(videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight) {
|
||||
|
||||
var horizontalIndent = (videoSpaceWidth - videoWidth)/2;
|
||||
var horizontalIndent = (videoSpaceWidth - videoWidth) / 2;
|
||||
|
||||
var verticalIndent = 0;// Top aligned
|
||||
|
||||
|
@ -928,10 +934,10 @@ function getCameraVideoSize(videoWidth,
|
|||
|
||||
if (availableWidth / aspectRatio < videoSpaceHeight) {
|
||||
availableHeight = videoSpaceHeight;
|
||||
availableWidth = availableHeight*aspectRatio;
|
||||
availableWidth = availableHeight * aspectRatio;
|
||||
}
|
||||
|
||||
if (availableHeight*aspectRatio < videoSpaceWidth) {
|
||||
if (availableHeight * aspectRatio < videoSpaceWidth) {
|
||||
availableWidth = videoSpaceWidth;
|
||||
availableHeight = availableWidth / aspectRatio;
|
||||
}
|
||||
|
@ -945,11 +951,10 @@ function getCameraVideoSize(videoWidth,
|
|||
*
|
||||
* @return an array with 2 elements, the video width and the video height
|
||||
*/
|
||||
function getDesktopVideoSize( videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight )
|
||||
{
|
||||
function getDesktopVideoSize(videoWidth,
|
||||
videoHeight,
|
||||
videoSpaceWidth,
|
||||
videoSpaceHeight) {
|
||||
if (!videoWidth)
|
||||
videoWidth = currentVideoWidth;
|
||||
if (!videoHeight)
|
||||
|
@ -965,10 +970,10 @@ function getDesktopVideoSize( videoWidth,
|
|||
if (availableWidth / aspectRatio >= videoSpaceHeight)
|
||||
{
|
||||
availableHeight = videoSpaceHeight;
|
||||
availableWidth = availableHeight*aspectRatio;
|
||||
availableWidth = availableHeight * aspectRatio;
|
||||
}
|
||||
|
||||
if (availableHeight*aspectRatio >= videoSpaceWidth)
|
||||
if (availableHeight * aspectRatio >= videoSpaceWidth)
|
||||
{
|
||||
availableWidth = videoSpaceWidth;
|
||||
availableHeight = availableWidth / aspectRatio;
|
||||
|
@ -986,11 +991,11 @@ function getDesktopVideoSize( videoWidth,
|
|||
* @param horizontalIndent the left and right indent
|
||||
* @param verticalIndent the top and bottom indent
|
||||
*/
|
||||
function positionVideo( video,
|
||||
width,
|
||||
height,
|
||||
horizontalIndent,
|
||||
verticalIndent) {
|
||||
function positionVideo(video,
|
||||
width,
|
||||
height,
|
||||
horizontalIndent,
|
||||
verticalIndent) {
|
||||
video.width(width);
|
||||
video.height(height);
|
||||
video.css({ top: verticalIndent + 'px',
|
||||
|
@ -1014,7 +1019,7 @@ var resizeLargeVideoContainer = function () {
|
|||
resizeThumbnails();
|
||||
};
|
||||
|
||||
var calculateThumbnailSize = function() {
|
||||
var calculateThumbnailSize = function () {
|
||||
// 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
|
||||
// bottom of the large video, minus the 36px space inside the remoteVideos
|
||||
|
@ -1056,8 +1061,7 @@ $(document).ready(function () {
|
|||
// Set default desktop sharing method
|
||||
setDesktopSharing(config.desktopSharing);
|
||||
// Initialize Chrome extension inline installs
|
||||
if(config.chromeExtensionId)
|
||||
{
|
||||
if (config.chromeExtensionId) {
|
||||
initInlineInstalls();
|
||||
}
|
||||
|
||||
|
@ -1072,7 +1076,7 @@ $(document).ready(function () {
|
|||
});
|
||||
// Listen for large video size updates
|
||||
document.getElementById('largeVideo')
|
||||
.addEventListener('loadedmetadata', function(e){
|
||||
.addEventListener('loadedmetadata', function (e) {
|
||||
currentVideoWidth = this.videoWidth;
|
||||
currentVideoHeight = this.videoHeight;
|
||||
positionLarge(currentVideoWidth, currentVideoHeight);
|
||||
|
@ -1114,12 +1118,12 @@ $(window).bind('beforeunload', function () {
|
|||
|
||||
function disposeConference() {
|
||||
var handler = getConferenceHandler();
|
||||
if(handler && handler.peerconnection) {
|
||||
if (handler && handler.peerconnection) {
|
||||
// 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);
|
||||
}
|
||||
if(connection.jingle.localVideo) {
|
||||
if (connection.jingle.localVideo) {
|
||||
handler.peerconnection.removeStream(connection.jingle.localVideo);
|
||||
}
|
||||
handler.peerconnection.close();
|
||||
|
@ -1128,7 +1132,7 @@ function disposeConference() {
|
|||
activecall = null;
|
||||
}
|
||||
|
||||
function dump(elem, filename){
|
||||
function dump(elem, filename) {
|
||||
elem = elem.parentNode;
|
||||
elem.download = filename || 'meetlog.json';
|
||||
elem.href = 'data:application/json;charset=utf-8,\n';
|
||||
|
@ -1141,8 +1145,8 @@ function dump(elem, filename){
|
|||
data["jingle_" + session.sid] = {
|
||||
updateLog: session.peerconnection.updateLog,
|
||||
stats: session.peerconnection.stats,
|
||||
url: window.location.href}
|
||||
;
|
||||
url: window.location.href
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1173,56 +1177,57 @@ function openLockDialog() {
|
|||
if (focus === null) {
|
||||
if (sharedKey)
|
||||
$.prompt("This conversation is currently protected by a shared secret key.",
|
||||
{
|
||||
title: "Secrect key",
|
||||
persistent: false
|
||||
});
|
||||
{
|
||||
title: "Secrect key",
|
||||
persistent: false
|
||||
}
|
||||
);
|
||||
else
|
||||
$.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",
|
||||
persistent: false
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (sharedKey)
|
||||
{
|
||||
title: "Secrect key",
|
||||
persistent: false
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (sharedKey) {
|
||||
$.prompt("Are you sure you would like to remove your secret key?",
|
||||
{
|
||||
title: "Remove secrect key",
|
||||
persistent: false,
|
||||
buttons: { "Remove": true, "Cancel": false},
|
||||
defaultButton: 1,
|
||||
submit: function(e,v,m,f){
|
||||
if(v)
|
||||
{
|
||||
setSharedKey('');
|
||||
lockRoom(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
else
|
||||
{
|
||||
title: "Remove secrect key",
|
||||
persistent: false,
|
||||
buttons: { "Remove": true, "Cancel": false},
|
||||
defaultButton: 1,
|
||||
submit: function (e, v, m, f) {
|
||||
if (v) {
|
||||
setSharedKey('');
|
||||
lockRoom(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$.prompt('<h2>Set a secrect key to lock your room</h2>' +
|
||||
'<input id="lockKey" type="text" placeholder="your shared key" autofocus>',
|
||||
{
|
||||
persistent: false,
|
||||
buttons: { "Save": true , "Cancel": false},
|
||||
defaultButton: 1,
|
||||
loaded: function(event) {
|
||||
document.getElementById('lockKey').focus();
|
||||
},
|
||||
submit: function(e,v,m,f){
|
||||
if(v)
|
||||
{
|
||||
var lockKey = document.getElementById('lockKey');
|
||||
{
|
||||
persistent: false,
|
||||
buttons: { "Save": true, "Cancel": false},
|
||||
defaultButton: 1,
|
||||
loaded: function (event) {
|
||||
document.getElementById('lockKey').focus();
|
||||
},
|
||||
submit: function (e, v, m, f) {
|
||||
if (v) {
|
||||
var lockKey = document.getElementById('lockKey');
|
||||
|
||||
if (lockKey.value)
|
||||
{
|
||||
setSharedKey(Util.escapeHtml(lockKey.value));
|
||||
lockRoom(true);
|
||||
if (lockKey.value) {
|
||||
setSharedKey(Util.escapeHtml(lockKey.value));
|
||||
lockRoom(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1230,16 +1235,17 @@ function openLockDialog() {
|
|||
* Opens the invite link dialog.
|
||||
*/
|
||||
function openLinkDialog() {
|
||||
$.prompt('<input id="inviteLinkRef" type="text" value="'
|
||||
+ encodeURI(roomUrl) + '" onclick="this.select();" readonly>',
|
||||
{
|
||||
title: "Share this link with everyone you want to invite",
|
||||
persistent: false,
|
||||
buttons: { "Cancel": false},
|
||||
loaded: function(event) {
|
||||
document.getElementById('inviteLinkRef').select();
|
||||
}
|
||||
});
|
||||
$.prompt('<input id="inviteLinkRef" type="text" value="' +
|
||||
encodeURI(roomUrl) + '" onclick="this.select();" readonly>',
|
||||
{
|
||||
title: "Share this link with everyone you want to invite",
|
||||
persistent: false,
|
||||
buttons: { "Cancel": false},
|
||||
loaded: function (event) {
|
||||
document.getElementById('inviteLinkRef').select();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1247,40 +1253,38 @@ function openLinkDialog() {
|
|||
*/
|
||||
function openSettingsDialog() {
|
||||
$.prompt('<h2>Configure your conference</h2>' +
|
||||
'<input type="checkbox" id="initMuted"> Participants join muted<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>',
|
||||
{
|
||||
persistent: false,
|
||||
buttons: { "Save": true , "Cancel": false},
|
||||
defaultButton: 1,
|
||||
loaded: function(event) {
|
||||
document.getElementById('lockKey').focus();
|
||||
},
|
||||
submit: function(e,v,m,f){
|
||||
if(v)
|
||||
{
|
||||
if ($('#initMuted').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);
|
||||
}
|
||||
*/
|
||||
'<input type="checkbox" id="initMuted"> Participants join muted<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>',
|
||||
{
|
||||
persistent: false,
|
||||
buttons: { "Save": true, "Cancel": false},
|
||||
defaultButton: 1,
|
||||
loaded: function (event) {
|
||||
document.getElementById('lockKey').focus();
|
||||
},
|
||||
submit: function (e, v, m, f) {
|
||||
if (v) {
|
||||
if ($('#initMuted').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);
|
||||
}
|
||||
*/
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1312,10 +1316,10 @@ function updateLockButton() {
|
|||
/**
|
||||
* Hides the toolbar.
|
||||
*/
|
||||
var hideToolbar = function() {
|
||||
var hideToolbar = function () {
|
||||
|
||||
var isToolbarHover = false;
|
||||
$('#header').find('*').each(function(){
|
||||
$('#header').find('*').each(function () {
|
||||
var id = $(this).attr('id');
|
||||
if ($("#" + id + ":hover").length > 0) {
|
||||
isToolbarHover = true;
|
||||
|
@ -1418,7 +1422,7 @@ function showFocusIndicator() {
|
|||
var session = connection.jingle.sessions[Object.keys(connection.jingle.sessions)[0]];
|
||||
var focusId = 'participant_' + Strophe.getResourceFromJid(session.peerjid);
|
||||
var focusContainer = document.getElementById(focusId);
|
||||
if(!focusContainer) {
|
||||
if (!focusContainer) {
|
||||
console.error("No focus container!");
|
||||
return;
|
||||
}
|
||||
|
@ -1438,12 +1442,11 @@ function showFocusIndicator() {
|
|||
* Checks if container for participant identified by given peerJid exists in the document and creates it eventually.
|
||||
* @param peerJid peer Jid to check.
|
||||
*/
|
||||
function ensurePeerContainerExists(peerJid){
|
||||
|
||||
function ensurePeerContainerExists(peerJid) {
|
||||
var peerResource = Strophe.getResourceFromJid(peerJid);
|
||||
var videoSpanId = 'participant_' + peerResource;
|
||||
|
||||
if($('#'+videoSpanId).length > 0) {
|
||||
if ($('#' + videoSpanId).length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1482,8 +1485,7 @@ function createFocusIndicatorElement(parentElement) {
|
|||
function toggleFullScreen() {
|
||||
var fsElement = document.documentElement;
|
||||
|
||||
if (!document.mozFullScreen && !document.webkitIsFullScreen){
|
||||
|
||||
if (!document.mozFullScreen && !document.webkitIsFullScreen) {
|
||||
//Enter Full Screen
|
||||
if (fsElement.mozRequestFullScreen) {
|
||||
fsElement.mozRequestFullScreen();
|
||||
|
@ -1511,13 +1513,13 @@ function showDisplayName(videoSpanId, displayName) {
|
|||
if (nameSpan.length > 0) {
|
||||
var nameSpanElement = nameSpan.get(0);
|
||||
|
||||
if (nameSpanElement.id === 'localDisplayName'
|
||||
&& $('#localDisplayName').text() !== displayName)
|
||||
if (nameSpanElement.id === 'localDisplayName' &&
|
||||
$('#localDisplayName').text() !== displayName) {
|
||||
$('#localDisplayName').text(displayName);
|
||||
else
|
||||
} else {
|
||||
$('#' + videoSpanId + '_name').text(displayName);
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
var editButton = null;
|
||||
|
||||
if (videoSpanId === 'localVideoContainer') {
|
||||
|
@ -1532,8 +1534,7 @@ function showDisplayName(videoSpanId, displayName) {
|
|||
|
||||
if (!editButton) {
|
||||
nameSpan.id = videoSpanId + '_name';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
nameSpan.id = 'localDisplayName';
|
||||
$('#' + videoSpanId)[0].appendChild(editButton);
|
||||
|
||||
|
@ -1541,22 +1542,22 @@ function showDisplayName(videoSpanId, displayName) {
|
|||
editableText.className = 'displayname';
|
||||
editableText.id = 'editDisplayName';
|
||||
|
||||
if (displayName.length)
|
||||
editableText.value
|
||||
= displayName.substring(0, displayName.indexOf(' (me)'));
|
||||
if (displayName.length) {
|
||||
editableText.value = displayName.substring(0, displayName.indexOf(' (me)'));
|
||||
}
|
||||
|
||||
editableText.setAttribute('style', 'display:none;');
|
||||
editableText.setAttribute('placeholder', 'ex. Jane Pink');
|
||||
$('#' + videoSpanId)[0].appendChild(editableText);
|
||||
|
||||
$('#localVideoContainer .displayname').bind("click", function(e) {
|
||||
$('#localVideoContainer .displayname').bind("click", function (e) {
|
||||
e.preventDefault();
|
||||
$('#localDisplayName').hide();
|
||||
$('#editDisplayName').show();
|
||||
$('#editDisplayName').focus();
|
||||
$('#editDisplayName').select();
|
||||
|
||||
var inputDisplayNameHandler = function(name) {
|
||||
var inputDisplayNameHandler = function (name) {
|
||||
if (nickname !== name) {
|
||||
nickname = name;
|
||||
window.localStorage.displayname = nickname;
|
||||
|
@ -1661,20 +1662,21 @@ function showVideoIndicator(videoSpanId, isMuted) {
|
|||
* Resizes and repositions videos in full screen mode.
|
||||
*/
|
||||
$(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange',
|
||||
function() {
|
||||
resizeLargeVideoContainer();
|
||||
positionLarge();
|
||||
isFullScreen = document.fullScreen
|
||||
|| document.mozFullScreen
|
||||
|| document.webkitIsFullScreen;
|
||||
function () {
|
||||
resizeLargeVideoContainer();
|
||||
positionLarge();
|
||||
isFullScreen = document.fullScreen ||
|
||||
document.mozFullScreen ||
|
||||
document.webkitIsFullScreen;
|
||||
|
||||
if (isFullScreen) {
|
||||
setView("fullscreen");
|
||||
}
|
||||
else {
|
||||
setView("default");
|
||||
}
|
||||
});
|
||||
if (isFullScreen) {
|
||||
setView("fullscreen");
|
||||
}
|
||||
else {
|
||||
setView("default");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -16,7 +17,7 @@ var Chat = (function (my) {
|
|||
Chat.setChatConversationMode(true);
|
||||
}
|
||||
|
||||
$('#nickinput').keydown(function(event) {
|
||||
$('#nickinput').keydown(function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
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) {
|
||||
event.preventDefault();
|
||||
var message = Util.escapeHtml(this.value);
|
||||
|
@ -45,14 +46,14 @@ var Chat = (function (my) {
|
|||
}
|
||||
});
|
||||
|
||||
var onTextAreaResize = function() {
|
||||
var onTextAreaResize = function () {
|
||||
resizeChatConversation();
|
||||
scrollChatToBottom();
|
||||
};
|
||||
$('#usermsg').autosize({callback: onTextAreaResize});
|
||||
|
||||
$("#chatspace").bind("shown",
|
||||
function() {
|
||||
function () {
|
||||
unreadMessages = 0;
|
||||
setVisualNotification(false);
|
||||
});
|
||||
|
@ -82,9 +83,9 @@ var Chat = (function (my) {
|
|||
var escDisplayName = Util.escapeHtml(displayName);
|
||||
message = processReplacements(escMessage);
|
||||
|
||||
$('#chatconversation').append('<div class="' + divClassName + '"><b>'
|
||||
+ escDisplayName + ': </b>'
|
||||
+ message + '</div>');
|
||||
$('#chatconversation').append('<div class="' + divClassName + '"><b>' +
|
||||
escDisplayName + ': </b>' +
|
||||
message + '</div>');
|
||||
$('#chatconversation').animate(
|
||||
{ scrollTop: $('#chatconversation')[0].scrollHeight}, 1000);
|
||||
};
|
||||
|
@ -103,15 +104,15 @@ var Chat = (function (my) {
|
|||
= getVideoSize(null, null, videospaceWidth, videospaceHeight);
|
||||
var videoWidth = videoSize[0];
|
||||
var videoHeight = videoSize[1];
|
||||
var videoPosition = getVideoPosition( videoWidth,
|
||||
videoHeight,
|
||||
videospaceWidth,
|
||||
videospaceHeight);
|
||||
var videoPosition = getVideoPosition(videoWidth,
|
||||
videoHeight,
|
||||
videospaceWidth,
|
||||
videospaceHeight);
|
||||
var horizontalIndent = videoPosition[0];
|
||||
var verticalIndent = videoPosition[1];
|
||||
|
||||
if (chatspace.is(":visible")) {
|
||||
videospace.animate( {right: chatSize[0],
|
||||
videospace.animate({right: chatSize[0],
|
||||
width: videospaceWidth,
|
||||
height: videospaceHeight},
|
||||
{queue: false,
|
||||
|
@ -143,7 +144,7 @@ var Chat = (function (my) {
|
|||
height: videospaceHeight},
|
||||
{queue: false,
|
||||
duration: 500,
|
||||
complete: function() {
|
||||
complete: function () {
|
||||
scrollChatToBottom();
|
||||
chatspace.trigger('shown');
|
||||
}
|
||||
|
@ -183,9 +184,9 @@ var Chat = (function (my) {
|
|||
*/
|
||||
my.setChatConversationMode = function (isConversationMode) {
|
||||
if (isConversationMode) {
|
||||
$('#nickname').css({visibility:"hidden"});
|
||||
$('#chatconversation').css({visibility:'visible'});
|
||||
$('#usermsg').css({visibility:'visible'});
|
||||
$('#nickname').css({visibility: 'hidden'});
|
||||
$('#chatconversation').css({visibility: 'visible'});
|
||||
$('#usermsg').css({visibility: 'visible'});
|
||||
$('#usermsg').focus();
|
||||
}
|
||||
};
|
||||
|
@ -205,13 +206,13 @@ var Chat = (function (my) {
|
|||
/**
|
||||
* Returns the size of the chat.
|
||||
*/
|
||||
my.getChatSize = function() {
|
||||
my.getChatSize = function () {
|
||||
var availableHeight = window.innerHeight;
|
||||
var availableWidth = window.innerWidth;
|
||||
|
||||
var chatWidth = 200;
|
||||
if (availableWidth*0.2 < 200)
|
||||
chatWidth = availableWidth*0.2;
|
||||
if (availableWidth * 0.2 < 200)
|
||||
chatWidth = availableWidth * 0.2;
|
||||
|
||||
return [chatWidth, availableHeight];
|
||||
};
|
||||
|
@ -228,7 +229,7 @@ var Chat = (function (my) {
|
|||
$('#chatconversation').width($('#chatspace').width() - 10);
|
||||
$('#chatconversation')
|
||||
.height(window.innerHeight - 10 - parseInt(usermsgHeight));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows/hides a visual notification, indicating that a message has arrived.
|
||||
|
@ -245,15 +246,15 @@ var Chat = (function (my) {
|
|||
|
||||
var chatButtonElement
|
||||
= document.getElementById('chatButton').parentNode;
|
||||
var leftIndent = (Util.getTextWidth(chatButtonElement)
|
||||
- Util.getTextWidth(unreadMsgElement))/2;
|
||||
var topIndent = (Util.getTextHeight(chatButtonElement)
|
||||
- Util.getTextHeight(unreadMsgElement))/2 - 3;
|
||||
var leftIndent = (Util.getTextWidth(chatButtonElement) -
|
||||
Util.getTextWidth(unreadMsgElement)) / 2;
|
||||
var topIndent = (Util.getTextHeight(chatButtonElement) -
|
||||
Util.getTextHeight(unreadMsgElement)) / 2 - 3;
|
||||
|
||||
unreadMsgElement.setAttribute(
|
||||
'style',
|
||||
'top:' + topIndent
|
||||
+ '; left:' + leftIndent +';');
|
||||
'top:' + topIndent +
|
||||
'; left:' + leftIndent + ';');
|
||||
|
||||
if (!glower.hasClass('icon-chat-simple')) {
|
||||
glower.removeClass('icon-chat');
|
||||
|
@ -267,7 +268,7 @@ var Chat = (function (my) {
|
|||
}
|
||||
|
||||
if (show && !notificationInterval) {
|
||||
notificationInterval = window.setInterval(function() {
|
||||
notificationInterval = window.setInterval(function () {
|
||||
glower.toggleClass('active');
|
||||
}, 800);
|
||||
}
|
||||
|
@ -282,7 +283,7 @@ var Chat = (function (my) {
|
|||
* Scrolls chat to the bottom.
|
||||
*/
|
||||
function scrollChatToBottom() {
|
||||
setTimeout(function() {
|
||||
setTimeout(function () {
|
||||
$('#chatconversation').scrollTop(
|
||||
$('#chatconversation')[0].scrollHeight);
|
||||
}, 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).
|
||||
* @type {boolean}
|
||||
|
@ -12,7 +13,7 @@ var switchInProgress = false;
|
|||
/**
|
||||
* Method used to get screen sharing stream.
|
||||
*
|
||||
* @type {function(stream_callback, failure_callback}
|
||||
* @type {function (stream_callback, failure_callback}
|
||||
*/
|
||||
var obtainDesktopStream = null;
|
||||
|
||||
|
@ -22,149 +23,6 @@ var obtainDesktopStream = 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.
|
||||
* 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) {
|
||||
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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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 getWebStoreInstallUrl()
|
||||
{
|
||||
return "https://chrome.google.com/webstore/detail/" + config.chromeExtensionId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,20 +59,21 @@ function isUpdateRequired(minVersion, extVersion)
|
|||
var s2 = extVersion.split('.');
|
||||
|
||||
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]);
|
||||
if(i < s2.length)
|
||||
if (i < s2.length)
|
||||
n2 = parseInt(s2[i]);
|
||||
|
||||
if(isNaN(n1) || isNaN(n2))
|
||||
if (isNaN(n1) || isNaN(n2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(n1 !== n2)
|
||||
else if (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)
|
||||
return false;
|
||||
}
|
||||
catch(e)
|
||||
catch (e)
|
||||
{
|
||||
console.error("Failed to parse extension version", e);
|
||||
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) {
|
||||
// Sends 'getStream' msg to the extension. Extension id must be defined in the config.
|
||||
chrome.runtime.sendMessage(
|
||||
config.chromeExtensionId,
|
||||
{ getStream: true},
|
||||
function(response) {
|
||||
if(!response) {
|
||||
function (response) {
|
||||
if (!response) {
|
||||
failCallback(chrome.runtime.lastError);
|
||||
return;
|
||||
}
|
||||
console.log("Response from extension: "+response);
|
||||
if(response.streamId) {
|
||||
console.log("Response from extension: " + response);
|
||||
if (response.streamId) {
|
||||
getUserMediaWithConstraints(
|
||||
['desktop'],
|
||||
function(stream) {
|
||||
function (stream) {
|
||||
streamCallback(stream);
|
||||
},
|
||||
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', {
|
||||
// logs raw stanzas and makes them available for download as JSON
|
||||
connection: null,
|
||||
|
|
25
etherpad.js
25
etherpad.js
|
@ -1,3 +1,4 @@
|
|||
/* global $, config, Prezi, Util, connection, setLargeVideoVisible, dockToolbar */
|
||||
var Etherpad = (function (my) {
|
||||
var etherpadName = null;
|
||||
var etherpadIFrame = null;
|
||||
|
@ -15,8 +16,8 @@ var Etherpad = (function (my) {
|
|||
|
||||
if (!name) {
|
||||
// In case we're the focus we generate the name.
|
||||
etherpadName = Math.random().toString(36).substring(7)
|
||||
+ '_' + (new Date().getTime()).toString();
|
||||
etherpadName = Math.random().toString(36).substring(7) +
|
||||
'_' + (new Date().getTime()).toString();
|
||||
shareEtherpad();
|
||||
}
|
||||
else
|
||||
|
@ -41,27 +42,27 @@ var Etherpad = (function (my) {
|
|||
|
||||
if ($('#etherpad>iframe').css('visibility') === 'hidden') {
|
||||
largeVideo.fadeOut(300, function () {
|
||||
if (Prezi.isPresentationVisible())
|
||||
largeVideo.css({opacity:'0'});
|
||||
else {
|
||||
if (Prezi.isPresentationVisible()) {
|
||||
largeVideo.css({opacity: '0'});
|
||||
} else {
|
||||
setLargeVideoVisible(false);
|
||||
dockToolbar(true);
|
||||
}
|
||||
|
||||
$('#etherpad>iframe').fadeIn(300, function() {
|
||||
$('#etherpad>iframe').fadeIn(300, function () {
|
||||
document.body.style.background = '#eeeeee';
|
||||
$('#etherpad>iframe').css({visibility:'visible'});
|
||||
$('#etherpad').css({zIndex:2});
|
||||
$('#etherpad>iframe').css({visibility: 'visible'});
|
||||
$('#etherpad').css({zIndex: 2});
|
||||
});
|
||||
});
|
||||
}
|
||||
else if ($('#etherpad>iframe')) {
|
||||
$('#etherpad>iframe').fadeOut(300, function () {
|
||||
$('#etherpad>iframe').css({visibility:'hidden'});
|
||||
$('#etherpad').css({zIndex:0});
|
||||
$('#etherpad>iframe').css({visibility: 'hidden'});
|
||||
$('#etherpad').css({zIndex: 0});
|
||||
document.body.style.background = 'black';
|
||||
if (!isPresentation) {
|
||||
$('#largeVideo').fadeIn(300, function() {
|
||||
$('#largeVideo').fadeIn(300, function () {
|
||||
setLargeVideoVisible(true);
|
||||
dockToolbar(false);
|
||||
});
|
||||
|
@ -99,7 +100,7 @@ var Etherpad = (function (my) {
|
|||
*/
|
||||
function enableEtherpadButton() {
|
||||
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.
|
||||
*/
|
||||
|
@ -8,7 +9,7 @@ var Util = (function (my) {
|
|||
*
|
||||
* @param el the element
|
||||
*/
|
||||
my.getTextWidth = function(el) {
|
||||
my.getTextWidth = function (el) {
|
||||
return (el.clientWidth + 1);
|
||||
};
|
||||
|
||||
|
@ -17,7 +18,7 @@ var Util = (function (my) {
|
|||
*
|
||||
* @param el the element
|
||||
*/
|
||||
my.getTextHeight = function(el) {
|
||||
my.getTextHeight = function (el) {
|
||||
return (el.clientHeight + 1);
|
||||
};
|
||||
|
||||
|
@ -26,7 +27,7 @@ var Util = (function (my) {
|
|||
*
|
||||
* @param number the number to cast
|
||||
*/
|
||||
my.toInteger = function(number) {
|
||||
my.toInteger = function (number) {
|
||||
return Math.round(Number(number));
|
||||
};
|
||||
|
||||
|
@ -35,27 +36,25 @@ var Util = (function (my) {
|
|||
*
|
||||
* @param id the identifier of the audio element.
|
||||
*/
|
||||
my.playSoundNotification = function(id) {
|
||||
my.playSoundNotification = function (id) {
|
||||
document.getElementById(id).play();
|
||||
};
|
||||
|
||||
/**
|
||||
* Escapes the given text.
|
||||
*/
|
||||
my.escapeHtml = function(unsafeText) {
|
||||
my.escapeHtml = function (unsafeText) {
|
||||
return $('<div/>').text(unsafeText).html();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the available video width.
|
||||
*/
|
||||
my.getAvailableVideoWidth = function() {
|
||||
var chatspaceWidth = $('#chatspace').is(":visible")
|
||||
? $('#chatspace').width()
|
||||
: 0;
|
||||
my.getAvailableVideoWidth = function () {
|
||||
var chatspaceWidth = $('#chatspace').is(":visible") ? $('#chatspace').width() : 0;
|
||||
|
||||
return window.innerWidth - chatspaceWidth;
|
||||
};
|
||||
|
||||
return my;
|
||||
}(Util || {}));
|
||||
}(Util || {}));
|
||||
|
|
Loading…
Reference in New Issue