|
|
@ -1,12 +1,14 @@ |
|
|
|
/* |
|
|
|
/* |
|
|
|
This file is part of the VROOM project |
|
|
|
This file is part of the VROOM project |
|
|
|
released under the MIT licence |
|
|
|
released under the MIT licence |
|
|
|
Copyright 2014 Firewall Services |
|
|
|
Copyright 2014-2015 Daniel Berteaud <daniel@firewall-services.com> |
|
|
|
Daniel Berteaud <daniel@firewall-services.com> |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
// Default notifications
|
|
|
|
// Default notifications
|
|
|
|
$.notify.defaults( { globalPosition: 'bottom left' } ); |
|
|
|
$.notify.defaults({ |
|
|
|
|
|
|
|
globalPosition: 'bottom left' |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Enable tooltip on required elements
|
|
|
|
// Enable tooltip on required elements
|
|
|
|
$('.help').tooltip({ |
|
|
|
$('.help').tooltip({ |
|
|
|
container: 'body', |
|
|
|
container: 'body', |
|
|
@ -19,6 +21,7 @@ $('.popup').popover({ |
|
|
|
$('.modal').on('show.bs.modal', function(){ |
|
|
|
$('.modal').on('show.bs.modal', function(){ |
|
|
|
$('.help').tooltip('hide'); |
|
|
|
$('.help').tooltip('hide'); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Enable bootstrap-swicth
|
|
|
|
// Enable bootstrap-swicth
|
|
|
|
$('.bs-switch').bootstrapSwitch(); |
|
|
|
$('.bs-switch').bootstrapSwitch(); |
|
|
|
|
|
|
|
|
|
|
@ -29,9 +32,12 @@ var locale = {}, |
|
|
|
// When pagination is done, how many item per page
|
|
|
|
// When pagination is done, how many item per page
|
|
|
|
var itemPerPage = 20; |
|
|
|
var itemPerPage = 20; |
|
|
|
|
|
|
|
|
|
|
|
// Will store the global webrtc object
|
|
|
|
// Some global vars, like
|
|
|
|
|
|
|
|
// the SimpleWebRTC object
|
|
|
|
var webrtc = undefined; |
|
|
|
var webrtc = undefined; |
|
|
|
|
|
|
|
// The current room configuration
|
|
|
|
var roomInfo = {}; |
|
|
|
var roomInfo = {}; |
|
|
|
|
|
|
|
// The current peers (we init the list with only ourself)
|
|
|
|
var peers = { |
|
|
|
var peers = { |
|
|
|
local: { |
|
|
|
local: { |
|
|
|
screenShared: false, |
|
|
|
screenShared: false, |
|
|
@ -44,7 +50,6 @@ var peers = { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Mark current page link as active
|
|
|
|
// Mark current page link as active
|
|
|
|
$('#lnk_' + page).addClass('active'); |
|
|
|
$('#lnk_' + page).addClass('active'); |
|
|
|
|
|
|
|
|
|
|
@ -70,6 +75,11 @@ $.ajaxSetup({ |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Define a few functions
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
// Localize a string, or just print it if localization doesn't exist
|
|
|
|
// Localize a string, or just print it if localization doesn't exist
|
|
|
|
function localize(string){ |
|
|
|
function localize(string){ |
|
|
|
if (locale[string]){ |
|
|
|
if (locale[string]){ |
|
|
@ -92,7 +102,7 @@ function showApiError(data){ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Handle lang switch
|
|
|
|
// Handle lang switch drop down menu
|
|
|
|
$('#switch_lang').change(function(){ |
|
|
|
$('#switch_lang').change(function(){ |
|
|
|
$.ajax({ |
|
|
|
$.ajax({ |
|
|
|
data: { |
|
|
|
data: { |
|
|
@ -112,9 +122,6 @@ $('#switch_lang').change(function(){ |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Define a few functions
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Escape a string to be used as a jQuerry selector
|
|
|
|
// Escape a string to be used as a jQuerry selector
|
|
|
|
// Taken from http://totaldev.com/content/escaping-characters-get-valid-jquery-id
|
|
|
|
// Taken from http://totaldev.com/content/escaping-characters-get-valid-jquery-id
|
|
|
@ -130,7 +137,7 @@ function stringEscape(string){ |
|
|
|
return string; |
|
|
|
return string; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Select a color (randomly) from this list, used for text chat
|
|
|
|
// Select a color (randomly) from this list, used for text chat, and the name under the preview
|
|
|
|
function chooseColor(){ |
|
|
|
function chooseColor(){ |
|
|
|
// Shamelessly taken from http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
|
|
|
|
// Shamelessly taken from http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
|
|
|
|
var colors = [ |
|
|
|
var colors = [ |
|
|
@ -191,15 +198,15 @@ function getTime(){ |
|
|
|
var hours = d.getHours().toString(), |
|
|
|
var hours = d.getHours().toString(), |
|
|
|
minutes = d.getMinutes().toString(), |
|
|
|
minutes = d.getMinutes().toString(), |
|
|
|
seconds = d.getSeconds().toString(); |
|
|
|
seconds = d.getSeconds().toString(); |
|
|
|
hours = (hours.length < 2) ? '0' + hours:hours; |
|
|
|
hours = (hours.length < 2) ? '0' + hours : hours; |
|
|
|
minutes = (minutes.length < 2) ? '0' + minutes:minutes; |
|
|
|
minutes = (minutes.length < 2) ? '0' + minutes : minutes; |
|
|
|
seconds = (seconds.length < 2) ? '0' + seconds:seconds; |
|
|
|
seconds = (seconds.length < 2) ? '0' + seconds : seconds; |
|
|
|
return hours + ':' + minutes + ':' + seconds; |
|
|
|
return hours + ':' + minutes + ':' + seconds; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Convert dates from UTC to local TZ
|
|
|
|
// Convert dates from UTC to local TZ
|
|
|
|
function utc2Local(date) { |
|
|
|
function utc2Local(date) { |
|
|
|
var newDate = new Date(date.getTime()+date.getTimezoneOffset()*60*1000); |
|
|
|
var newDate = new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000); |
|
|
|
var offset = date.getTimezoneOffset() / 60; |
|
|
|
var offset = date.getTimezoneOffset() / 60; |
|
|
|
var hours = date.getHours(); |
|
|
|
var hours = date.getHours(); |
|
|
|
newDate.setHours(hours - offset); |
|
|
|
newDate.setHours(hours - offset); |
|
|
@ -220,7 +227,7 @@ function maxHeight(){ |
|
|
|
return $(window).height()-$('#toolbar').height()-25; |
|
|
|
return $(window).height()-$('#toolbar').height()-25; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Create a new input field
|
|
|
|
// Create a new email input field
|
|
|
|
function addEmailInputField(form, val){ |
|
|
|
function addEmailInputField(form, val){ |
|
|
|
var parentEl = $('#' + form), |
|
|
|
var parentEl = $('#' + form), |
|
|
|
currentEntry = parentEl.find('.email-entry:last'), |
|
|
|
currentEntry = parentEl.find('.email-entry:last'), |
|
|
@ -229,6 +236,7 @@ function addEmailInputField(form, val){ |
|
|
|
newEntry.removeClass('has-error'); |
|
|
|
newEntry.removeClass('has-error'); |
|
|
|
adjustAddRemoveEmailButtons(form); |
|
|
|
adjustAddRemoveEmailButtons(form); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Adjust add and remove buttons foir email notifications
|
|
|
|
// Adjust add and remove buttons foir email notifications
|
|
|
|
function adjustAddRemoveEmailButtons(form){ |
|
|
|
function adjustAddRemoveEmailButtons(form){ |
|
|
|
$('#' + form).find('.email-entry:not(:last) .btn-add-email') |
|
|
|
$('#' + form).find('.email-entry:not(:last) .btn-add-email') |
|
|
@ -240,11 +248,12 @@ function adjustAddRemoveEmailButtons(form){ |
|
|
|
.addClass('btn-primary').addClass('btn-add-email') |
|
|
|
.addClass('btn-primary').addClass('btn-add-email') |
|
|
|
.html('<span class="glyphicon glyphicon-plus"></span>'); |
|
|
|
.html('<span class="glyphicon glyphicon-plus"></span>'); |
|
|
|
} |
|
|
|
} |
|
|
|
// Add emails input fields
|
|
|
|
// Add emails input field
|
|
|
|
$(document).on('click','button.btn-add-email',function(e){ |
|
|
|
$(document).on('click','button.btn-add-email',function(e){ |
|
|
|
e.preventDefault(); |
|
|
|
e.preventDefault(); |
|
|
|
addEmailInputField($(this).parents('.email-list:first').attr('id'), ''); |
|
|
|
addEmailInputField($(this).parents('.email-list:first').attr('id'), ''); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
// Remove email input field
|
|
|
|
$(document).on('click','button.btn-remove-email',function(e){ |
|
|
|
$(document).on('click','button.btn-remove-email',function(e){ |
|
|
|
e.preventDefault(); |
|
|
|
e.preventDefault(); |
|
|
|
el = $(this).parents('.email-entry:first'); |
|
|
|
el = $(this).parents('.email-entry:first'); |
|
|
@ -324,7 +333,7 @@ $('#configureRoomForm').submit(function(e){ |
|
|
|
$(input).parent().addClass('has-error'); |
|
|
|
$(input).parent().addClass('has-error'); |
|
|
|
//$(input).parent().notify(localize('ERROR_MAIL_INVALID'), 'error');
|
|
|
|
//$(input).parent().notify(localize('ERROR_MAIL_INVALID'), 'error');
|
|
|
|
validEmail = false; |
|
|
|
validEmail = false; |
|
|
|
// Break the each loop
|
|
|
|
// Break the each loop and return an error now, we can't submit as is
|
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
else{ |
|
|
|
else{ |
|
|
@ -368,6 +377,8 @@ $('#configureRoomForm').submit(function(e){ |
|
|
|
showApiError(data); |
|
|
|
showApiError(data); |
|
|
|
}, |
|
|
|
}, |
|
|
|
success: function(data){ |
|
|
|
success: function(data){ |
|
|
|
|
|
|
|
// On success, reset the input fields, collapse the password inputs
|
|
|
|
|
|
|
|
// and close the configuration modal
|
|
|
|
$('#ownerPass,#ownerPassConfirm,#joinPass,#joinPassConfirm').val(''); |
|
|
|
$('#ownerPass,#ownerPassConfirm,#joinPass,#joinPassConfirm').val(''); |
|
|
|
$('#configureModal').modal('hide'); |
|
|
|
$('#configureModal').modal('hide'); |
|
|
|
$('#joinPassFields,#ownerPassFields').hide(); |
|
|
|
$('#joinPassFields,#ownerPassFields').hide(); |
|
|
@ -393,9 +404,10 @@ function getRoomInfo(cb){ |
|
|
|
}, |
|
|
|
}, |
|
|
|
success: function(data){ |
|
|
|
success: function(data){ |
|
|
|
roomInfo = data; |
|
|
|
roomInfo = data; |
|
|
|
// Reset the list of email displayed, so first remove evry input field but the last one
|
|
|
|
// Reset the list of email displayed, so first remove every input field but the last one
|
|
|
|
// We keep it so we can clone it again
|
|
|
|
// We keep it so we can clone it again
|
|
|
|
$('.email-list').find('.email-entry:not(:last)').remove(); |
|
|
|
$('.email-list').find('.email-entry:not(:last)').remove(); |
|
|
|
|
|
|
|
// Now add one input per email
|
|
|
|
$.each(data.notif, function(index, obj){ |
|
|
|
$.each(data.notif, function(index, obj){ |
|
|
|
addEmailInputField('email-list-notification', obj.email); |
|
|
|
addEmailInputField('email-list-notification', obj.email); |
|
|
|
}); |
|
|
|
}); |
|
|
@ -412,6 +424,7 @@ function getRoomInfo(cb){ |
|
|
|
$('#askForNameSet').bootstrapSwitch('state', data.ask_for_name); |
|
|
|
$('#askForNameSet').bootstrapSwitch('state', data.ask_for_name); |
|
|
|
$('#joinPassSet').bootstrapSwitch('state', data.join_auth); |
|
|
|
$('#joinPassSet').bootstrapSwitch('state', data.join_auth); |
|
|
|
$('#ownerPassSet').bootstrapSwitch('state', data.owner_auth); |
|
|
|
$('#ownerPassSet').bootstrapSwitch('state', data.owner_auth); |
|
|
|
|
|
|
|
// exec the callback if defined
|
|
|
|
if (typeof cb === 'function'){ |
|
|
|
if (typeof cb === 'function'){ |
|
|
|
cb(); |
|
|
|
cb(); |
|
|
|
} |
|
|
|
} |
|
|
@ -475,7 +488,7 @@ function initIndex(){ |
|
|
|
$('#roomName').val(''); |
|
|
|
$('#roomName').val(''); |
|
|
|
$('#conflictModal').modal('hide'); |
|
|
|
$('#conflictModal').modal('hide'); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
// Check for invalid room name as user is typing
|
|
|
|
$('#roomName').on('input', function(){ |
|
|
|
$('#roomName').on('input', function(){ |
|
|
|
if (!$('#roomName').val().match(/^[\w\-]{0,49}$/)){ |
|
|
|
if (!$('#roomName').val().match(/^[\w\-]{0,49}$/)){ |
|
|
|
$('#roomName').parent().addClass('has-error'); |
|
|
|
$('#roomName').parent().addClass('has-error'); |
|
|
@ -509,6 +522,7 @@ function initDoc(){ |
|
|
|
offset: $('#headerNav').outerHeight(true) + 40 |
|
|
|
offset: $('#headerNav').outerHeight(true) + 40 |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Small delay so the affix can start when everything is loaded
|
|
|
|
setTimeout(function() { |
|
|
|
setTimeout(function() { |
|
|
|
var $sideBar = $('#toc'); |
|
|
|
var $sideBar = $('#toc'); |
|
|
|
$sideBar.affix({ |
|
|
|
$sideBar.affix({ |
|
|
@ -713,6 +727,7 @@ function initAdminRooms(){ |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Started when entering a room
|
|
|
|
function initJoin(room){ |
|
|
|
function initJoin(room){ |
|
|
|
// Auth input if access is protected
|
|
|
|
// Auth input if access is protected
|
|
|
|
$('#authBeforeJoinPass').on('input', function() { |
|
|
|
$('#authBeforeJoinPass').on('input', function() { |
|
|
@ -794,6 +809,8 @@ function initJoin(room){ |
|
|
|
$('.connecting-err-reason').text(data.msg); |
|
|
|
$('.connecting-err-reason').text(data.msg); |
|
|
|
$('#auth-before-join').slideDown(); |
|
|
|
$('#auth-before-join').slideDown(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 403 is when the room is locked, and there's no owner pass
|
|
|
|
|
|
|
|
// So there's nothing to do, the access will be denied
|
|
|
|
else if (data.status === 403){ |
|
|
|
else if (data.status === 403){ |
|
|
|
data = data.responseJSON; |
|
|
|
data = data.responseJSON; |
|
|
|
$('.connecting-err-reason').text(data.msg); |
|
|
|
$('.connecting-err-reason').text(data.msg); |
|
|
@ -806,6 +823,7 @@ function initJoin(room){ |
|
|
|
}, |
|
|
|
}, |
|
|
|
success: function(data){ |
|
|
|
success: function(data){ |
|
|
|
$('.connecting-err-reason').hide(); |
|
|
|
$('.connecting-err-reason').hide(); |
|
|
|
|
|
|
|
// Once auth is passed, we get the room configuration
|
|
|
|
$.ajax({ |
|
|
|
$.ajax({ |
|
|
|
data: { |
|
|
|
data: { |
|
|
|
req: JSON.stringify({ |
|
|
|
req: JSON.stringify({ |
|
|
@ -820,6 +838,8 @@ function initJoin(room){ |
|
|
|
}, |
|
|
|
}, |
|
|
|
success: function(data){ |
|
|
|
success: function(data){ |
|
|
|
roomInfo = data; |
|
|
|
roomInfo = data; |
|
|
|
|
|
|
|
// If our name is asked before joining the room, display the corresponding modal
|
|
|
|
|
|
|
|
// Else, just continue (with webrtc initialization
|
|
|
|
if (roomInfo.ask_for_name){ |
|
|
|
if (roomInfo.ask_for_name){ |
|
|
|
$('#display-name-pre').slideDown(); |
|
|
|
$('#display-name-pre').slideDown(); |
|
|
|
} |
|
|
|
} |
|
|
@ -831,10 +851,14 @@ function initJoin(room){ |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Always start by trying with an empty password.
|
|
|
|
|
|
|
|
// Only if one is required the modal will appear
|
|
|
|
try_auth('', false); |
|
|
|
try_auth('', false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This just create the webrtc object, and then continue
|
|
|
|
function init_webrtc(room){ |
|
|
|
function init_webrtc(room){ |
|
|
|
|
|
|
|
// First get SimpleWebRTC config from the server
|
|
|
|
$.ajax({ |
|
|
|
$.ajax({ |
|
|
|
data: { |
|
|
|
data: { |
|
|
|
req: JSON.stringify({ |
|
|
|
req: JSON.stringify({ |
|
|
@ -854,7 +878,6 @@ function init_webrtc(room){ |
|
|
|
data.config.localVideoEl = 'webRTCVideoLocal'; |
|
|
|
data.config.localVideoEl = 'webRTCVideoLocal'; |
|
|
|
webrtc = new SimpleWebRTC(data.config); |
|
|
|
webrtc = new SimpleWebRTC(data.config); |
|
|
|
// Handle the readyToCall event: join the room
|
|
|
|
// Handle the readyToCall event: join the room
|
|
|
|
// Or prompt for a name first
|
|
|
|
|
|
|
|
webrtc.once('readyToCall', function () { |
|
|
|
webrtc.once('readyToCall', function () { |
|
|
|
peers.local.id = webrtc.connection.connection.socket.sessionid; |
|
|
|
peers.local.id = webrtc.connection.connection.socket.sessionid; |
|
|
|
webrtc.joinRoom(roomName); |
|
|
|
webrtc.joinRoom(roomName); |
|
|
@ -866,7 +889,7 @@ function init_webrtc(room){ |
|
|
|
$('#no-webrtc-msg').slideDown(); |
|
|
|
$('#no-webrtc-msg').slideDown(); |
|
|
|
} |
|
|
|
} |
|
|
|
else{ |
|
|
|
else{ |
|
|
|
// Hide screen sharing btn if not supported, disable it on mobile
|
|
|
|
// Hide screen sharing btn if not supported, or when connecting from a mobile
|
|
|
|
if (!webrtc.capabilities.supportScreenSharing || !$.browser.desktop){ |
|
|
|
if (!webrtc.capabilities.supportScreenSharing || !$.browser.desktop){ |
|
|
|
$('.btn-share-screen').remove(); |
|
|
|
$('.btn-share-screen').remove(); |
|
|
|
} |
|
|
|
} |
|
|
@ -876,7 +899,7 @@ function init_webrtc(room){ |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// This is the main function called when you join a room
|
|
|
|
// This is the main function called when you join a room (after auth and all the basic stuff ready)
|
|
|
|
function initVroom(room) { |
|
|
|
function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
var mainVid = false, |
|
|
|
var mainVid = false, |
|
|
@ -915,8 +938,11 @@ function initVroom(room) { |
|
|
|
showApiError(data); |
|
|
|
showApiError(data); |
|
|
|
}, |
|
|
|
}, |
|
|
|
success: function(data){ |
|
|
|
success: function(data){ |
|
|
|
|
|
|
|
// If its our own role, check if it chagned
|
|
|
|
if (id === peers.local.id){ |
|
|
|
if (id === peers.local.id){ |
|
|
|
if (data.role != peers.local.role){ |
|
|
|
if (data.role != peers.local.role){ |
|
|
|
|
|
|
|
// In which case, we refresh room config
|
|
|
|
|
|
|
|
// and tell all other peers we've changed
|
|
|
|
getRoomInfo(); |
|
|
|
getRoomInfo(); |
|
|
|
webrtc.sendToAll('role_change', {}); |
|
|
|
webrtc.sendToAll('role_change', {}); |
|
|
|
} |
|
|
|
} |
|
|
@ -935,8 +961,8 @@ function initVroom(room) { |
|
|
|
else if (peers[id]){ |
|
|
|
else if (peers[id]){ |
|
|
|
peers[id].role = data.role; |
|
|
|
peers[id].role = data.role; |
|
|
|
if (data.role == 'owner'){ |
|
|
|
if (data.role == 'owner'){ |
|
|
|
// If this peer is a owner, we add the mark on its preview
|
|
|
|
// If this peer is an owner, we add the mark on its preview
|
|
|
|
$('#overlay_' + id).append($('<div></div>').attr('id', 'owner_' + id).addClass('owner hidden-xs')); |
|
|
|
$('#overlay_' + id).append($('<div>').attr('id', 'owner_' + id).addClass('owner hidden-xs')); |
|
|
|
// And we disable owner's action for him
|
|
|
|
// And we disable owner's action for him
|
|
|
|
$('#ownerActions_' + id).remove(); |
|
|
|
$('#ownerActions_' + id).remove(); |
|
|
|
} |
|
|
|
} |
|
|
@ -976,7 +1002,7 @@ function initVroom(room) { |
|
|
|
el.removeClass('selected'); |
|
|
|
el.removeClass('selected'); |
|
|
|
} |
|
|
|
} |
|
|
|
else{ |
|
|
|
else{ |
|
|
|
// Clone this new preview into the main div
|
|
|
|
// Clone the clicked preview and put it in the main div
|
|
|
|
$('#mainVideo').html(el.clone().dblclick(function() { |
|
|
|
$('#mainVideo').html(el.clone().dblclick(function() { |
|
|
|
fullScreen(this); |
|
|
|
fullScreen(this); |
|
|
|
}) |
|
|
|
}) |
|
|
@ -990,7 +1016,7 @@ function initVroom(room) { |
|
|
|
$('.selected').removeClass('selected'); |
|
|
|
$('.selected').removeClass('selected'); |
|
|
|
el.addClass('selected'); |
|
|
|
el.addClass('selected'); |
|
|
|
mainVid = el.attr('id'); |
|
|
|
mainVid = el.attr('id'); |
|
|
|
// Cut the volume the corresponding preview
|
|
|
|
// Cut the volume of the corresponding preview
|
|
|
|
$('#webRTCVideo video').each(function(){ |
|
|
|
$('#webRTCVideo video').each(function(){ |
|
|
|
if ($(this).get(0).paused){ |
|
|
|
if ($(this).get(0).paused){ |
|
|
|
$(this).get(0).play(); |
|
|
|
$(this).get(0).play(); |
|
|
@ -1015,17 +1041,17 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Handle a new video (either another peer, or a screen
|
|
|
|
// Handle a new video (either another peer, or a screen
|
|
|
|
// including our own local screen
|
|
|
|
// including our own local screen)
|
|
|
|
function addVideo(video,peer){ |
|
|
|
function addVideo(video, peer){ |
|
|
|
playSound('join.mp3'); |
|
|
|
playSound('join.mp3'); |
|
|
|
// The div continer of this new video
|
|
|
|
// The div container of this new video
|
|
|
|
// will contain the video preview plus all other info like displayName, overlay and volume bar
|
|
|
|
// will contain the video preview plus all other info like displayName, overlay and volume bar
|
|
|
|
var div = $('<div></div>').addClass('col-xs-3 col-sm-12 col-lg-6 previewContainer').append(video).appendTo('#webRTCVideo'); |
|
|
|
var div = $('<div>').addClass('col-xs-3 col-sm-12 col-lg-6 previewContainer').append(video).appendTo('#webRTCVideo'); |
|
|
|
var id; |
|
|
|
var id; |
|
|
|
// Peer isn't defined ? it's our own local screen
|
|
|
|
// Peer isn't defined ? it's our own local screen
|
|
|
|
if (!peer){ |
|
|
|
if (!peer){ |
|
|
|
id = 'local'; |
|
|
|
id = 'local'; |
|
|
|
$('<div></div>').addClass('displayName').attr('id', 'name_local_screen').appendTo(div); |
|
|
|
$('<div>').addClass('displayName').attr('id', 'name_local_screen').appendTo(div); |
|
|
|
updateDisplayName(id); |
|
|
|
updateDisplayName(id); |
|
|
|
$(video).addClass('latencyUnknown'); |
|
|
|
$(video).addClass('latencyUnknown'); |
|
|
|
} |
|
|
|
} |
|
|
@ -1033,7 +1059,7 @@ function initVroom(room) { |
|
|
|
else if (video.id.match(/screen/)){ |
|
|
|
else if (video.id.match(/screen/)){ |
|
|
|
id = peer.id + '_screen'; |
|
|
|
id = peer.id + '_screen'; |
|
|
|
var peer_id = video.id.replace('_screen_incoming', ''); |
|
|
|
var peer_id = video.id.replace('_screen_incoming', ''); |
|
|
|
$('<div></div>').addClass('displayName').attr('id', 'name_' + peer_id + '_screen').appendTo(div); |
|
|
|
$('<div>').addClass('displayName').attr('id', 'name_' + peer_id + '_screen').appendTo(div); |
|
|
|
updateDisplayName(peer_id); |
|
|
|
updateDisplayName(peer_id); |
|
|
|
} |
|
|
|
} |
|
|
|
// It's the webcam of a peer
|
|
|
|
// It's the webcam of a peer
|
|
|
@ -1042,31 +1068,31 @@ function initVroom(room) { |
|
|
|
id = peer.id; |
|
|
|
id = peer.id; |
|
|
|
// Create 4 divs which will contains the volume bar, the displayName, the muted/paused and
|
|
|
|
// Create 4 divs which will contains the volume bar, the displayName, the muted/paused and
|
|
|
|
// the owner actions (overlay)
|
|
|
|
// the owner actions (overlay)
|
|
|
|
$('<div></div>').addClass('volumeBar').attr('id', 'volume_' + id).appendTo(div); |
|
|
|
$('<div>').addClass('volumeBar').attr('id', 'volume_' + id).appendTo(div); |
|
|
|
$('<div></div>').addClass('displayName').attr('id', 'name_' + id).appendTo(div); |
|
|
|
$('<div>').addClass('displayName').attr('id', 'name_' + id).appendTo(div); |
|
|
|
$('<div></div>').attr('id', 'overlay_' + id).addClass('hidden-xs').appendTo(div); |
|
|
|
$('<div>').attr('id', 'overlay_' + id).addClass('hidden-xs').appendTo(div); |
|
|
|
// Will contains per peer action menu (mute/pause/kick), but will only be displayed
|
|
|
|
// Will contain per peer action menu (mute/pause/kick), but will only be displayed
|
|
|
|
// on owners screen
|
|
|
|
// on owner's screen
|
|
|
|
$('<div></div>').addClass('ownerActions hidden-xs').attr('id', 'ownerActions_' + id).appendTo(div) |
|
|
|
$('<div>').addClass('ownerActions hidden-xs').attr('id', 'ownerActions_' + id).appendTo(div) |
|
|
|
.append($('<div></div>',{ |
|
|
|
.append($('<div>',{ |
|
|
|
class: 'btn-group' |
|
|
|
class: 'btn-group' |
|
|
|
}) |
|
|
|
}) |
|
|
|
.append($('<button></button>', { |
|
|
|
.append($('<button>', { |
|
|
|
class: 'actionMute btn btn-default btn-sm', |
|
|
|
class: 'actionMute btn btn-default btn-sm', |
|
|
|
id: 'actionMute_' + id, |
|
|
|
id: 'actionMute_' + id, |
|
|
|
click: function() { mutePeer(id) }, |
|
|
|
click: function() { mutePeer(id) }, |
|
|
|
}).prop('title', localize('.MUTE_PEER'))) |
|
|
|
}).prop('title', localize('MUTE_PEER'))) |
|
|
|
.append($('<button></button>', { |
|
|
|
.append($('<button>', { |
|
|
|
class: 'actionPause btn btn-default btn-sm', |
|
|
|
class: 'actionPause btn btn-default btn-sm', |
|
|
|
id: 'actionPause_' + id, |
|
|
|
id: 'actionPause_' + id, |
|
|
|
click: function() { pausePeer(id) }, |
|
|
|
click: function() { pausePeer(id) }, |
|
|
|
}).prop('title', localize('SUSPEND_PEER'))) |
|
|
|
}).prop('title', localize('SUSPEND_PEER'))) |
|
|
|
.append($('<button></button>', { |
|
|
|
.append($('<button>', { |
|
|
|
class: 'actionPromote btn btn-default btn-sm', |
|
|
|
class: 'actionPromote btn btn-default btn-sm', |
|
|
|
id: 'actionPromote_' + id, |
|
|
|
id: 'actionPromote_' + id, |
|
|
|
click: function() { promotePeer(id) }, |
|
|
|
click: function() { promotePeer(id) }, |
|
|
|
}).prop('title', localize('PROMOTE_PEER'))) |
|
|
|
}).prop('title', localize('PROMOTE_PEER'))) |
|
|
|
.append($('<button></button>', { |
|
|
|
.append($('<button>', { |
|
|
|
class: 'actionKick btn btn-default btn-sm', |
|
|
|
class: 'actionKick btn btn-default btn-sm', |
|
|
|
id: 'actionKick_' + id, |
|
|
|
id: 'actionKick_' + id, |
|
|
|
click: function() { kickPeer(id) }, |
|
|
|
click: function() { kickPeer(id) }, |
|
|
@ -1159,7 +1185,7 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Feedback for latency with this peer
|
|
|
|
// Graphical indicator for the latency between you and a peer
|
|
|
|
function updatePeerLatency(id,time){ |
|
|
|
function updatePeerLatency(id,time){ |
|
|
|
if (!peers[id]){ |
|
|
|
if (!peers[id]){ |
|
|
|
return; |
|
|
|
return; |
|
|
@ -1178,7 +1204,7 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Add a new message to the chat history
|
|
|
|
// Add a new message to the chat history
|
|
|
|
function newChatMessage(from,message,time,color){ |
|
|
|
function newChatMessage(from, message, time, color){ |
|
|
|
var cl = (from === 'local') ? 'chatMsgSelf':'chatMsgOthers'; |
|
|
|
var cl = (from === 'local') ? 'chatMsgSelf':'chatMsgOthers'; |
|
|
|
// We need to check time format as it can be sent from another
|
|
|
|
// We need to check time format as it can be sent from another
|
|
|
|
// peer if we asked for its history. If it's not define or doesn't look
|
|
|
|
// peer if we asked for its history. If it's not define or doesn't look
|
|
|
@ -1198,9 +1224,11 @@ function initVroom(room) { |
|
|
|
var displayName = from; |
|
|
|
var displayName = from; |
|
|
|
} |
|
|
|
} |
|
|
|
// Create the new msg
|
|
|
|
// Create the new msg
|
|
|
|
var newmsg = $('<div class="chatMsg ' + cl + '"><b>' + time + ' ' + stringEscape(displayName) + '</b><p>' + linkify(stringEscape(message)) + '</p></div>').css('background-color', color); |
|
|
|
var newmsg = $('<div>').addClass('chatMsg ' + cl) |
|
|
|
|
|
|
|
.append($('<b>' + time + ' ' + stringEscape(displayName) + '</b><p>' + linkify(stringEscape(message)) + '</p>')) |
|
|
|
|
|
|
|
.css('background-color', color); |
|
|
|
// Add it in the history
|
|
|
|
// Add it in the history
|
|
|
|
$('<div class="row chatMsgContainer"></div>').append(newmsg).appendTo('#chatHistory'); |
|
|
|
$('<div>').addClass('row chatMsgContainer').append(newmsg).appendTo('#chatHistory'); |
|
|
|
// Move the scroller down
|
|
|
|
// Move the scroller down
|
|
|
|
$('#chatHistory').scrollTop($('#chatHistory').prop('scrollHeight')); |
|
|
|
$('#chatHistory').scrollTop($('#chatHistory').prop('scrollHeight')); |
|
|
|
// Record this message in the history object
|
|
|
|
// Record this message in the history object
|
|
|
@ -1215,7 +1243,7 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Mute a peer
|
|
|
|
// Mute a peer
|
|
|
|
function mutePeer(id,globalAction){ |
|
|
|
function mutePeer(id, globalAction){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
if (!globalAction || |
|
|
|
if (!globalAction || |
|
|
|
(!peers[id].micMuted && globalAction == 'mute') || |
|
|
|
(!peers[id].micMuted && globalAction == 'mute') || |
|
|
@ -1235,8 +1263,9 @@ function initVroom(room) { |
|
|
|
$.notify(localize('CANT_MUTE_OWNER'), 'error'); |
|
|
|
$.notify(localize('CANT_MUTE_OWNER'), 'error'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Pause a peer
|
|
|
|
|
|
|
|
function pausePeer(id,globalAction){ |
|
|
|
// Pause a peer's webcam
|
|
|
|
|
|
|
|
function pausePeer(id, globalAction){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
if (!globalAction || |
|
|
|
if (!globalAction || |
|
|
|
(!peers[id].videoPaused && globalAction == 'pause') || |
|
|
|
(!peers[id].videoPaused && globalAction == 'pause') || |
|
|
@ -1254,6 +1283,7 @@ function initVroom(room) { |
|
|
|
$.notify(localize('CANT_SUSPEND_OWNER'), 'error'); |
|
|
|
$.notify(localize('CANT_SUSPEND_OWNER'), 'error'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Promote a peer (he will be owner)
|
|
|
|
// Promote a peer (he will be owner)
|
|
|
|
function promotePeer(id){ |
|
|
|
function promotePeer(id){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
@ -1281,7 +1311,8 @@ function initVroom(room) { |
|
|
|
$.notify(localize('CANT_PROMOTE_OWNER'), 'error'); |
|
|
|
$.notify(localize('CANT_PROMOTE_OWNER'), 'error'); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Kick a peer
|
|
|
|
|
|
|
|
|
|
|
|
// Kick a peer our of the room
|
|
|
|
function kickPeer(id){ |
|
|
|
function kickPeer(id){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
if (peers[id] && peers[id].role != 'owner'){ |
|
|
|
webrtc.sendToAll('owner_kick', {peer: id}); |
|
|
|
webrtc.sendToAll('owner_kick', {peer: id}); |
|
|
@ -1300,22 +1331,25 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Mute our mic
|
|
|
|
// Mute our own mic
|
|
|
|
function muteMic(){ |
|
|
|
function muteMic(){ |
|
|
|
webrtc.mute(); |
|
|
|
webrtc.mute(); |
|
|
|
peers.local.micMuted = true; |
|
|
|
peers.local.micMuted = true; |
|
|
|
showVolume($('#localVolume'), -45); |
|
|
|
showVolume($('#localVolume'), -45); |
|
|
|
} |
|
|
|
} |
|
|
|
// Unmute
|
|
|
|
|
|
|
|
|
|
|
|
// Unmute our own mic
|
|
|
|
function unmuteMic(){ |
|
|
|
function unmuteMic(){ |
|
|
|
webrtc.unmute(); |
|
|
|
webrtc.unmute(); |
|
|
|
peers.local.micMuted = false; |
|
|
|
peers.local.micMuted = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Suspend or webcam
|
|
|
|
// Suspend or webcam
|
|
|
|
function suspendCam(){ |
|
|
|
function suspendCam(){ |
|
|
|
webrtc.pauseVideo(); |
|
|
|
webrtc.pauseVideo(); |
|
|
|
peers.local.videoPaused = true; |
|
|
|
peers.local.videoPaused = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Resume webcam
|
|
|
|
// Resume webcam
|
|
|
|
function resumeCam(){ |
|
|
|
function resumeCam(){ |
|
|
|
webrtc.resumeVideo(); |
|
|
|
webrtc.resumeVideo(); |
|
|
@ -1352,7 +1386,7 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
// An owner is muting/unmuting someone
|
|
|
|
// An owner is muting/unmuting someone
|
|
|
|
webrtc.on('owner_toggle_mute', function(data){ |
|
|
|
webrtc.on('owner_toggle_mute', function(data){ |
|
|
|
// Ignore this if the remote peer isn't the owner of the room
|
|
|
|
// Ignore this if the remote peer isn't an owner of the room
|
|
|
|
// or if the peer receiving it is our local screen sharing
|
|
|
|
// or if the peer receiving it is our local screen sharing
|
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
return; |
|
|
|
return; |
|
|
@ -1373,8 +1407,10 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
// It's another peer of the room
|
|
|
|
// It's another peer of the room
|
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
var who = (peers[data.id].hasName) ? peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
var who = (peers[data.id].hasName) ? |
|
|
|
var target = (peers[data.payload.peer].hasName) ? peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
|
|
|
|
var target = (peers[data.payload.peer].hasName) ? |
|
|
|
|
|
|
|
peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
if (peers[data.payload.peer].micMuted){ |
|
|
|
if (peers[data.payload.peer].micMuted){ |
|
|
|
$.notify(sprintf(localize('s_IS_UNMUTING_s'), who, target), 'info'); |
|
|
|
$.notify(sprintf(localize('s_IS_UNMUTING_s'), who, target), 'info'); |
|
|
|
} |
|
|
|
} |
|
|
@ -1383,6 +1419,7 @@ function initVroom(room) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// An owner is pausing/resuming a webcam.
|
|
|
|
// An owner is pausing/resuming a webcam.
|
|
|
|
// More or less the same dance than mute/unmute. Both fonctions should be merged
|
|
|
|
// More or less the same dance than mute/unmute. Both fonctions should be merged
|
|
|
|
webrtc.on('owner_toggle_pause', function(data){ |
|
|
|
webrtc.on('owner_toggle_pause', function(data){ |
|
|
@ -1402,8 +1439,10 @@ function initVroom(room) { |
|
|
|
$('.btn-suspend-cam').toggleClass('btn-danger').button('toggle'); |
|
|
|
$('.btn-suspend-cam').toggleClass('btn-danger').button('toggle'); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
var who = (peers[data.id].hasName) ? peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
var who = (peers[data.id].hasName) ? |
|
|
|
var target = (peers[data.payload.peer].hasName) ? peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
|
|
|
|
var target = (peers[data.payload.peer].hasName) ? |
|
|
|
|
|
|
|
peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
if (peers[data.payload.peer].videoPaused){ |
|
|
|
if (peers[data.payload.peer].videoPaused){ |
|
|
|
$.notify(sprintf(localize('s_IS_RESUMING_s'), who, target), 'info'); |
|
|
|
$.notify(sprintf(localize('s_IS_RESUMING_s'), who, target), 'info'); |
|
|
|
} |
|
|
|
} |
|
|
@ -1423,7 +1462,7 @@ function initVroom(room) { |
|
|
|
// This peer indicates he has no webcam
|
|
|
|
// This peer indicates he has no webcam
|
|
|
|
webrtc.on('media_info', function(data){ |
|
|
|
webrtc.on('media_info', function(data){ |
|
|
|
if (!data.payload.video){ |
|
|
|
if (!data.payload.video){ |
|
|
|
$('#overlay_' + data.id).append('<div id="noWebcam_' + data.id + '" class="noWebcam"></div>'); |
|
|
|
$('#overlay_' + data.id).append($('<div>').attr('id', 'noWebcam_' + data.id).addClass('noWebcam')); |
|
|
|
$('#actionPause_' + data.id).addClass('disabled'); |
|
|
|
$('#actionPause_' + data.id).addClass('disabled'); |
|
|
|
peers[data.id].hasVideo = false; |
|
|
|
peers[data.id].hasVideo = false; |
|
|
|
} |
|
|
|
} |
|
|
@ -1432,34 +1471,39 @@ function initVroom(room) { |
|
|
|
// An owner has just promoted a participant of the room to the owner role
|
|
|
|
// An owner has just promoted a participant of the room to the owner role
|
|
|
|
webrtc.on('owner_promoted', function(data){ |
|
|
|
webrtc.on('owner_promoted', function(data){ |
|
|
|
// Ignore if the emitter is not an owner, or is a screen
|
|
|
|
// Ignore if the emitter is not an owner, or is a screen
|
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
if (peers[data.id].role !== 'owner' || data.roomType === 'screen'){ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
// Are we the one being promoted ?
|
|
|
|
// Are we the one being promoted ?
|
|
|
|
if (data.payload.peer && data.payload.peer == peers.local.id && peers.local.role != 'owner'){ |
|
|
|
if (data.payload.peer && data.payload.peer === peers.local.id && peers.local.role !== 'owner'){ |
|
|
|
var who = (peers[data.id].hasName) ? peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
var who = (peers[data.id].hasName) ? |
|
|
|
|
|
|
|
peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
getPeerRole(peers.local.id); |
|
|
|
getPeerRole(peers.local.id); |
|
|
|
$.notify(sprintf(localize('s_IS_PROMOTING_YOU'), who), 'success'); |
|
|
|
$.notify(sprintf(localize('s_IS_PROMOTING_YOU'), who), 'success'); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer]){ |
|
|
|
var who = (peers[data.id].hasName) ? peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
var who = (peers[data.id].hasName) ? |
|
|
|
var target = (peers[data.payload.peer].hasName) ? peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
|
|
|
|
var target = (peers[data.payload.peer].hasName) ? |
|
|
|
|
|
|
|
peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
$.notify(sprintf(localize('s_IS_PROMOTING_s'), who, target), 'info'); |
|
|
|
$.notify(sprintf(localize('s_IS_PROMOTING_s'), who, target), 'info'); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// An owner is kicking someone out of the room
|
|
|
|
// An owner is kicking someone out of the room
|
|
|
|
webrtc.on('owner_kick', function(data){ |
|
|
|
webrtc.on('owner_kick', function(data){ |
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
if (peers[data.id].role !== 'owner' || data.roomType === 'screen'){ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
if (data.payload.peer && data.payload.peer == peers.local.id && peers.local.role != 'owner'){ |
|
|
|
if (data.payload.peer && data.payload.peer === peers.local.id && peers.local.role !== 'owner'){ |
|
|
|
hangupCall; |
|
|
|
hangupCall; |
|
|
|
window.location.assign(rootUrl + 'kicked/' + roomName); |
|
|
|
window.location.assign(rootUrl + 'kicked/' + roomName); |
|
|
|
} |
|
|
|
} |
|
|
|
else if (data.payload.peer != peers.local.id && peers[data.payload.peer] && peers[data.payload.peer].role != 'owner'){ |
|
|
|
else if (data.payload.peer !== peers.local.id && peers[data.payload.peer] && peers[data.payload.peer].role !== 'owner'){ |
|
|
|
var who = (peers[data.id].hasName) ? peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
var who = (peers[data.id].hasName) ? |
|
|
|
var target = (peers[data.payload.peer].hasName) ? peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
peers[data.id].displayName : localize('A_ROOM_ADMIN'); |
|
|
|
|
|
|
|
var target = (peers[data.payload.peer].hasName) ? |
|
|
|
|
|
|
|
peers[data.payload.peer].displayName : localize('A_PARTICIPANT'); |
|
|
|
$.notify(sprintf(localize('s_IS_KICKING_s'), who, target), 'info'); |
|
|
|
$.notify(sprintf(localize('s_IS_KICKING_s'), who, target), 'info'); |
|
|
|
// Wait a bit for the peer to leave, but end connection if it's still here
|
|
|
|
// Wait a bit for the peer to leave, but end connection if it's still here
|
|
|
|
// after 2 seconds
|
|
|
|
// after 2 seconds
|
|
|
@ -1470,6 +1514,7 @@ function initVroom(room) { |
|
|
|
}, 2000); |
|
|
|
}, 2000); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// An owner is terminating the call, obey and leave the room now
|
|
|
|
// An owner is terminating the call, obey and leave the room now
|
|
|
|
webrtc.on('terminate_room', function(data){ |
|
|
|
webrtc.on('terminate_room', function(data){ |
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
|
if (peers[data.id].role != 'owner' || data.roomType == 'screen'){ |
|
|
@ -1495,19 +1540,20 @@ function initVroom(room) { |
|
|
|
// Handle dataChannel messages (incoming)
|
|
|
|
// Handle dataChannel messages (incoming)
|
|
|
|
webrtc.on('channelMessage', function (peer, label, data){ |
|
|
|
webrtc.on('channelMessage', function (peer, label, data){ |
|
|
|
// Handle volume changes from remote peers
|
|
|
|
// Handle volume changes from remote peers
|
|
|
|
if (data.type == 'volume'){ |
|
|
|
if (data.type === 'volume'){ |
|
|
|
showVolume($('#volume_' + peer.id), data.volume); |
|
|
|
showVolume($('#volume_' + peer.id), data.volume); |
|
|
|
} |
|
|
|
} |
|
|
|
// We only want to act on data received from the vroom channel
|
|
|
|
// We only want to act on data received from the vroom channel
|
|
|
|
if (label !== 'vroom'){ |
|
|
|
if (label !== 'vroom'){ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
// Ping from the peer, lets just respond
|
|
|
|
// Ping from the peer, lets just respond with a pong
|
|
|
|
else if (data.type == 'ping'){ |
|
|
|
// used to measure latency
|
|
|
|
|
|
|
|
else if (data.type === 'ping'){ |
|
|
|
peers[peer.id].obj.sendDirectly('vroom', 'pong', data.payload); |
|
|
|
peers[peer.id].obj.sendDirectly('vroom', 'pong', data.payload); |
|
|
|
} |
|
|
|
} |
|
|
|
// Pong from the peer, lets compute reponse time
|
|
|
|
// Pong from the peer, lets compute reponse time
|
|
|
|
else if (data.type == 'pong'){ |
|
|
|
else if (data.type === 'pong'){ |
|
|
|
var diff = +new Date - parseInt(data.payload); |
|
|
|
var diff = +new Date - parseInt(data.payload); |
|
|
|
peers[peer.id].lastPong = +new Date; |
|
|
|
peers[peer.id].lastPong = +new Date; |
|
|
|
updatePeerLatency(peer.id,diff); |
|
|
|
updatePeerLatency(peer.id,diff); |
|
|
@ -1519,7 +1565,6 @@ function initVroom(room) { |
|
|
|
if (name.length > 50){ |
|
|
|
if (name.length > 50){ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
peer.logger.log('Received displayName ' + stringEscape(name) + ' from peer ' + peer.id); |
|
|
|
|
|
|
|
// Set display name under the video
|
|
|
|
// Set display name under the video
|
|
|
|
peers[peer.id].displayName = name; |
|
|
|
peers[peer.id].displayName = name; |
|
|
|
if (name !== ''){ |
|
|
|
if (name !== ''){ |
|
|
@ -1590,7 +1635,7 @@ function initVroom(room) { |
|
|
|
else{ |
|
|
|
else{ |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
$('#overlay_' + data.id).append('<div id="' + div + '" class="' + cl + '"></div>'); |
|
|
|
$('#overlay_' + data.id).append($('<div>').attr('id', div).addClass(cl)); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Handle unmute/resume
|
|
|
|
// Handle unmute/resume
|
|
|
@ -1620,7 +1665,7 @@ function initVroom(room) { |
|
|
|
getPeerRole(data.id); |
|
|
|
getPeerRole(data.id); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
//Notification from the server
|
|
|
|
// Notification from the server
|
|
|
|
webrtc.connection.connection.on('notification', function(data) { |
|
|
|
webrtc.connection.connection.on('notification', function(data) { |
|
|
|
if (!data.payload.class || !data.payload.class.match(/^(success)|(info)|(warning)|(error)$/)){ |
|
|
|
if (!data.payload.class || !data.payload.class.match(/^(success)|(info)|(warning)|(error)$/)){ |
|
|
|
data.payload.class = 'info'; |
|
|
|
data.payload.class = 'info'; |
|
|
@ -1678,8 +1723,8 @@ function initVroom(room) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Handle new video stream added: someone joined the room
|
|
|
|
// Handle new video stream added: someone joined the room
|
|
|
|
webrtc.on('videoAdded', function(video,peer){ |
|
|
|
webrtc.on('videoAdded', function(video, peer){ |
|
|
|
addVideo(video,peer); |
|
|
|
addVideo(video, peer); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// We share our screen
|
|
|
|
// We share our screen
|
|
|
@ -1693,7 +1738,7 @@ function initVroom(room) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Handle video stream removed: someone leaved the room
|
|
|
|
// Handle video stream removed: someone leaved the room
|
|
|
|
webrtc.on('videoRemoved', function(video,peer){ |
|
|
|
webrtc.on('videoRemoved', function(video, peer){ |
|
|
|
playSound('leave.mp3'); |
|
|
|
playSound('leave.mp3'); |
|
|
|
var id = (peer) ? peer.id : 'local'; |
|
|
|
var id = (peer) ? peer.id : 'local'; |
|
|
|
// Is the screen sharing of a peer being removed ?
|
|
|
|
// Is the screen sharing of a peer being removed ?
|
|
|
@ -1704,12 +1749,12 @@ function initVroom(room) { |
|
|
|
else if (peer && peers[peer.id] && id != 'local'){ |
|
|
|
else if (peer && peers[peer.id] && id != 'local'){ |
|
|
|
delete peers[peer.id]; |
|
|
|
delete peers[peer.id]; |
|
|
|
} |
|
|
|
} |
|
|
|
$("#peer_" + id).hide(300); |
|
|
|
$('#peer_' + id).hide(300); |
|
|
|
// Remove the div, but wait for the fade out to complete
|
|
|
|
// Remove the div, but wait for the fade out to complete
|
|
|
|
setTimeout(function(){ |
|
|
|
setTimeout(function(){ |
|
|
|
$("#peer_" + id).remove(); |
|
|
|
$('#peer_' + id).remove(); |
|
|
|
}, 300); |
|
|
|
}, 300); |
|
|
|
if (mainVid == id + '_video_incoming' || mainVid == id + '_incoming' || mainVid == id + 'Screen'){ |
|
|
|
if (mainVid === id + '_video_incoming' || mainVid === id + '_incoming' || mainVid === id + 'Screen'){ |
|
|
|
$('#mainVideo').hide(500); |
|
|
|
$('#mainVideo').hide(500); |
|
|
|
setTimeout(function(){ |
|
|
|
setTimeout(function(){ |
|
|
|
if ($.browser.mozilla && $('#mainVideo video').length > 0){ |
|
|
|
if ($.browser.mozilla && $('#mainVideo video').length > 0){ |
|
|
@ -1737,7 +1782,8 @@ function initVroom(room) { |
|
|
|
p2pFailure(peer); |
|
|
|
p2pFailure(peer); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Detect connection lost
|
|
|
|
// Detect connection lost and display an error msg
|
|
|
|
|
|
|
|
// TODO: we should try to reconnect
|
|
|
|
webrtc.connection.connection.socket.on('disconnect', function(){ |
|
|
|
webrtc.connection.connection.socket.on('disconnect', function(){ |
|
|
|
setTimeout(function(){ |
|
|
|
setTimeout(function(){ |
|
|
|
$('#disconnected').modal('show'); |
|
|
|
$('#disconnected').modal('show'); |
|
|
@ -1812,7 +1858,7 @@ function initVroom(room) { |
|
|
|
peers.local.hasName = true; |
|
|
|
peers.local.hasName = true; |
|
|
|
} |
|
|
|
} |
|
|
|
// And disable it again if you remove your display name
|
|
|
|
// And disable it again if you remove your display name
|
|
|
|
else if (name == ''){ |
|
|
|
else if (name === ''){ |
|
|
|
$('#chatBox').attr('disabled', true).attr('placeholder', localize('SET_YOUR_NAME_TO_CHAT')); |
|
|
|
$('#chatBox').attr('disabled', true).attr('placeholder', localize('SET_YOUR_NAME_TO_CHAT')); |
|
|
|
peers.local.hasName = false; |
|
|
|
peers.local.hasName = false; |
|
|
|
} |
|
|
|
} |
|
|
@ -1833,7 +1879,7 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
// ScreenSharing
|
|
|
|
// ScreenSharing
|
|
|
|
$('.btn-share-screen').click(function() { |
|
|
|
$('.btn-share-screen').click(function() { |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'unshare':'share'; |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'unshare' : 'share'; |
|
|
|
function cantShare(err){ |
|
|
|
function cantShare(err){ |
|
|
|
$.notify(err, 'error'); |
|
|
|
$.notify(err, 'error'); |
|
|
|
return; |
|
|
|
return; |
|
|
@ -1851,6 +1897,7 @@ function initVroom(room) { |
|
|
|
$('#chromeExtMessage').modal('show'); |
|
|
|
$('#chromeExtMessage').modal('show'); |
|
|
|
} |
|
|
|
} |
|
|
|
else{ |
|
|
|
else{ |
|
|
|
|
|
|
|
// TODO: update this message as screen sharing now works on FF too
|
|
|
|
cantShare(localize('SCREEN_SHARING_ONLY_FOR_CHROME')); |
|
|
|
cantShare(localize('SCREEN_SHARING_ONLY_FOR_CHROME')); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -1889,7 +1936,7 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
// Handle microphone mute/unmute
|
|
|
|
// Handle microphone mute/unmute
|
|
|
|
$('.btn-mute-mic').click(function() { |
|
|
|
$('.btn-mute-mic').click(function() { |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'unmute':'mute'; |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'unmute' : 'mute'; |
|
|
|
if (action === 'mute'){ |
|
|
|
if (action === 'mute'){ |
|
|
|
muteMic(); |
|
|
|
muteMic(); |
|
|
|
$.notify(localize('MIC_MUTED'), 'info'); |
|
|
|
$.notify(localize('MIC_MUTED'), 'info'); |
|
|
@ -1908,7 +1955,7 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
// Suspend the webcam
|
|
|
|
// Suspend the webcam
|
|
|
|
$('.btn-suspend-cam').click(function() { |
|
|
|
$('.btn-suspend-cam').click(function() { |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'resume':'pause'; |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'resume' : 'pause'; |
|
|
|
if (action === 'pause'){ |
|
|
|
if (action === 'pause'){ |
|
|
|
suspendCam(); |
|
|
|
suspendCam(); |
|
|
|
$.notify(localize('CAM_SUSPENDED'), 'info'); |
|
|
|
$.notify(localize('CAM_SUSPENDED'), 'info'); |
|
|
@ -1922,7 +1969,7 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
// Handle auth to become room owner
|
|
|
|
// Handle auth to become room owner
|
|
|
|
$('#authPass').on('input', function() { |
|
|
|
$('#authPass').on('input', function() { |
|
|
|
if ($('#authPass').val() == ''){ |
|
|
|
if ($('#authPass').val() === ''){ |
|
|
|
$('#authPassButton').addClass('disabled'); |
|
|
|
$('#authPassButton').addClass('disabled'); |
|
|
|
} |
|
|
|
} |
|
|
|
else{ |
|
|
|
else{ |
|
|
@ -1960,7 +2007,7 @@ function initVroom(room) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// The configuration formed has been submited successfuly
|
|
|
|
// The configuration form has been submited successfuly
|
|
|
|
// Lets announce it to the other peers
|
|
|
|
// Lets announce it to the other peers
|
|
|
|
$('#configureRoomForm').on('room_conf_updated', function(){ |
|
|
|
$('#configureRoomForm').on('room_conf_updated', function(){ |
|
|
|
webrtc.sendToAll('room_conf_updated'); |
|
|
|
webrtc.sendToAll('room_conf_updated'); |
|
|
@ -1969,7 +2016,7 @@ function initVroom(room) { |
|
|
|
// Choose another color. Useful if two peers have the same
|
|
|
|
// Choose another color. Useful if two peers have the same
|
|
|
|
$('#changeColorButton').click(function(){ |
|
|
|
$('#changeColorButton').click(function(){ |
|
|
|
peers.local.color = chooseColor(); |
|
|
|
peers.local.color = chooseColor(); |
|
|
|
// Reload etherpadiFrame if required
|
|
|
|
// Reload etherpad iframe if required to sync the new color
|
|
|
|
if (etherpad.enabled){ |
|
|
|
if (etherpad.enabled){ |
|
|
|
loadEtherpadIframe(); |
|
|
|
loadEtherpadIframe(); |
|
|
|
} |
|
|
|
} |
|
|
@ -1977,6 +2024,7 @@ function initVroom(room) { |
|
|
|
updateDisplayName('local'); |
|
|
|
updateDisplayName('local'); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Download chat history in a file
|
|
|
|
$('#saveChat').click(function(){ |
|
|
|
$('#saveChat').click(function(){ |
|
|
|
var d = new Date; |
|
|
|
var d = new Date; |
|
|
|
downloadContent('VROOM Tchat (' + room + ') ' + d.toLocaleString() + '.html', $('#chatHistory').html()); |
|
|
|
downloadContent('VROOM Tchat (' + room + ') ' + d.toLocaleString() + '.html', $('#chatHistory').html()); |
|
|
@ -1993,7 +2041,8 @@ function initVroom(room) { |
|
|
|
$('.btn-moh').toggleClass('btn-danger').button('toggle'); |
|
|
|
$('.btn-moh').toggleClass('btn-danger').button('toggle'); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Handle hangup/close window
|
|
|
|
// Handle the logout button: display a confirmation dialog
|
|
|
|
|
|
|
|
// and suspend mic and webcam
|
|
|
|
$('.btn-logout').click(function(){ |
|
|
|
$('.btn-logout').click(function(){ |
|
|
|
$('#quitModal').modal('show'); |
|
|
|
$('#quitModal').modal('show'); |
|
|
|
if (!peers.local.micMuted){ |
|
|
|
if (!peers.local.micMuted){ |
|
|
@ -2022,7 +2071,7 @@ function initVroom(room) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
window.onunload = window.onbeforeunload = hangupCall; |
|
|
|
window.onunload = window.onbeforeunload = hangupCall; |
|
|
|
|
|
|
|
|
|
|
|
// Go fullscreen on double click
|
|
|
|
// Go fullscreen on double click of our own preview
|
|
|
|
$('#webRTCVideoLocal').dblclick(function(){ |
|
|
|
$('#webRTCVideoLocal').dblclick(function(){ |
|
|
|
fullScreen(this); |
|
|
|
fullScreen(this); |
|
|
|
}); |
|
|
|
}); |
|
|
@ -2031,7 +2080,7 @@ function initVroom(room) { |
|
|
|
handlePreviewClick($(this), 'self'); |
|
|
|
handlePreviewClick($(this), 'self'); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// On click, remove the red label on the button
|
|
|
|
// On click on the chat button, remove the red label
|
|
|
|
// and reset the unread msg counter
|
|
|
|
// and reset the unread msg counter
|
|
|
|
$('#chatDropdown').click(function (){ |
|
|
|
$('#chatDropdown').click(function (){ |
|
|
|
$('#chatDropdown').removeClass('btn-danger'); |
|
|
|
$('#chatDropdown').removeClass('btn-danger'); |
|
|
@ -2040,7 +2089,7 @@ function initVroom(room) { |
|
|
|
// The input is a textarea, trigger a submit
|
|
|
|
// The input is a textarea, trigger a submit
|
|
|
|
// when the user hit enter, unless shift is pressed
|
|
|
|
// when the user hit enter, unless shift is pressed
|
|
|
|
$('#chatForm').keypress(function(e) { |
|
|
|
$('#chatForm').keypress(function(e) { |
|
|
|
if (e.which == 13 && !e.shiftKey){ |
|
|
|
if (e.which === 13 && !e.shiftKey){ |
|
|
|
// Do not add \n
|
|
|
|
// Do not add \n
|
|
|
|
e.preventDefault(); |
|
|
|
e.preventDefault(); |
|
|
|
$(this).trigger('submit'); |
|
|
|
$(this).trigger('submit'); |
|
|
@ -2078,6 +2127,7 @@ function initVroom(room) { |
|
|
|
// In any case, adapt height of the buttons
|
|
|
|
// In any case, adapt height of the buttons
|
|
|
|
$('#saveChat,#sendChat').css('height', $(this).css('height')); |
|
|
|
$('#saveChat,#sendChat').css('height', $(this).css('height')); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// Chat: send to other peers
|
|
|
|
// Chat: send to other peers
|
|
|
|
$('#chatForm').submit(function (e){ |
|
|
|
$('#chatForm').submit(function (e){ |
|
|
|
e.preventDefault(); |
|
|
|
e.preventDefault(); |
|
|
@ -2094,10 +2144,10 @@ function initVroom(room) { |
|
|
|
|
|
|
|
|
|
|
|
if (etherpad.enabled){ |
|
|
|
if (etherpad.enabled){ |
|
|
|
$('.btn-etherpad').click(function(){ |
|
|
|
$('.btn-etherpad').click(function(){ |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'hide':'show'; |
|
|
|
var action = ($(this).hasClass('btn-danger')) ? 'hide' : 'show'; |
|
|
|
if (action === 'show'){ |
|
|
|
if (action === 'show'){ |
|
|
|
// If not already loaded, load etherpad in the iFrame
|
|
|
|
// If not already loaded, load etherpad in the iFrame
|
|
|
|
if ($('#etherpadContainer').html() == ''){ |
|
|
|
if ($('#etherpadContainer').html() === ''){ |
|
|
|
loadEtherpadIframe(); |
|
|
|
loadEtherpadIframe(); |
|
|
|
} |
|
|
|
} |
|
|
|
$('#etherpadContainer').slideDown('200'); |
|
|
|
$('#etherpadContainer').slideDown('200'); |
|
|
@ -2109,8 +2159,8 @@ function initVroom(room) { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Ping all the peers every 5 sec to measure latency
|
|
|
|
// Ping every peer each 5 sec to measure latency
|
|
|
|
// Do this through dataChannel
|
|
|
|
// Do this through dataChannel to get a real idea of the latency
|
|
|
|
setInterval(function(){ |
|
|
|
setInterval(function(){ |
|
|
|
$.each(peers, function(id){ |
|
|
|
$.each(peers, function(id){ |
|
|
|
// No response from last ping ? mark latency as poor
|
|
|
|
// No response from last ping ? mark latency as poor
|
|
|
|