Updated Flash clients deskshare libs

This commit is contained in:
perroned 2016-01-13 12:03:52 -08:00
parent 4571b0532c
commit 279f40a4c2
9 changed files with 4928 additions and 4507 deletions

View File

@ -1,4 +1,5 @@
// Last time updated at Sep 23, 2014, 08:32:23
// Last time updated at January 07, 2016
// By Daniel Perrone (perroned)
// Latest file can be found here: https://cdn.webrtc-experiment.com/Screen-Capturing.js
@ -95,7 +96,7 @@ function getChromeExtensionStatus(extensionid, callback) {
if (arguments.length != 2) {
callback = extensionid;
extensionid = 'mlcengpcgchagkemmgjgafbcblmgmbkc'; // default extension-id
extensionid = 'ajhifddimkapgcifgcodmmfdlknahffk'; // Muaz Khan's Screen Capturing
}
var image = document.createElement('img');
@ -105,7 +106,7 @@ function getChromeExtensionStatus(extensionid, callback) {
window.postMessage('are-you-there', '*');
setTimeout(function() {
if (chromeMediaSource == 'screen') {
callback(extensionid == extensionid ? 'installed-enabled' : 'installed-disabled');
callback('installed-enabled');
} else callback('installed-enabled');
}, 2000);
};
@ -137,7 +138,8 @@ function getScreenConstraints(callback) {
// this statement verifies chrome extension availability
// if installed and available then it will invoke extension API
// otherwise it will fallback to command-line based screen capturing API
if (chromeMediaSource == 'desktop' && !sourceId) {
sourceId = null;
if (chromeMediaSource == 'desktop') {
getSourceId(function() {
screen_constraints.mandatory.chromeMediaSourceId = sourceId;
callback(sourceId == 'PermissionDeniedError' ? sourceId : null, screen_constraints);
@ -152,4 +154,4 @@ function getScreenConstraints(callback) {
// now invoking native getUserMedia API
callback(null, screen_constraints);
}
}

0
bigbluebutton-client/resources/prod/lib/getScreenId.js Normal file → Executable file
View File

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,716 @@
/*
* Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
* Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is jquery.jsonrpclient.js modified for Verto HTML5/Javascript Telephony Signaling and Control Protocol Stack for FreeSWITCH
*
* The Initial Developer of the Original Code is
* Textalk AB http://textalk.se/
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* jquery.jsonrpclient.js - JSON RPC client code
*
*/
/**
* This plugin requires jquery.json.js to be available, or at least the methods $.toJSON and
* $.parseJSON.
*
* The plan is to make use of websockets if they are available, but work just as well with only
* http if not.
*
* Usage example:
*
* var foo = new $.JsonRpcClient({ ajaxUrl: '/backend/jsonrpc' });
* foo.call(
* 'bar', [ 'A parameter', 'B parameter' ],
* function(result) { alert('Foo bar answered: ' + result.my_answer); },
* function(error) { console.log('There was an error', error); }
* );
*
* More examples are available in README.md
*/
(function($) {
/**
* @fn new
* @memberof $.JsonRpcClient
*
* @param options An object stating the backends:
* ajaxUrl A url (relative or absolute) to a http(s) backend.
* socketUrl A url (relative of absolute) to a ws(s) backend.
* onmessage A socket message handler for other messages (non-responses).
* getSocket A function returning a WebSocket or null.
* It must take an onmessage_cb and bind it to the onmessage event
* (or chain it before/after some other onmessage handler).
* Or, it could return null if no socket is available.
* The returned instance must have readyState <= 1, and if less than 1,
* react to onopen binding.
*/
$.JsonRpcClient = function(options) {
var self = this;
this.options = $.extend({
ajaxUrl : null,
socketUrl : null, ///< The ws-url for default getSocket.
onmessage : null, ///< Other onmessage-handler.
login : null, /// auth login
passwd : null, /// auth passwd
sessid : null,
loginParams : null,
userVariables : null,
getSocket : function(onmessage_cb) { return self._getSocket(onmessage_cb); }
}, options);
self.ws_cnt = 0;
// Declare an instance version of the onmessage callback to wrap 'this'.
this.wsOnMessage = function(event) { self._wsOnMessage(event); };
};
/// Holding the WebSocket on default getsocket.
$.JsonRpcClient.prototype._ws_socket = null;
/// Object <id>: { success_cb: cb, error_cb: cb }
$.JsonRpcClient.prototype._ws_callbacks = {};
/// The next JSON-RPC request id.
$.JsonRpcClient.prototype._current_id = 1;
$.JsonRpcClient.prototype.speedTest = function (bytes, cb) {
var socket = this.options.getSocket(this.wsOnMessage);
if (socket !== null) {
this.speedCB = cb;
this.speedBytes = bytes;
socket.send("#SPU " + bytes);
var loops = bytes / 1024;
var rem = bytes % 1024;
var i;
var data = new Array(1024).join(".");
for (i = 0; i < loops; i++) {
socket.send("#SPB " + data);
}
if (rem) {
socket.send("#SPB " + data);
}
socket.send("#SPE");
}
};
/**
* @fn call
* @memberof $.JsonRpcClient
*
* @param method The method to run on JSON-RPC server.
* @param params The params; an array or object.
* @param success_cb A callback for successful request.
* @param error_cb A callback for error.
*/
$.JsonRpcClient.prototype.call = function(method, params, success_cb, error_cb) {
// Construct the JSON-RPC 2.0 request.
if (!params) {
params = {};
}
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
var request = {
jsonrpc : '2.0',
method : method,
params : params,
id : this._current_id++ // Increase the id counter to match request/response
};
if (!success_cb) {
success_cb = function(e){console.log("Success: ", e);};
}
if (!error_cb) {
error_cb = function(e){console.log("Error: ", e);};
}
// Try making a WebSocket call.
var socket = this.options.getSocket(this.wsOnMessage);
if (socket !== null) {
this._wsCall(socket, request, success_cb, error_cb);
return;
}
// No WebSocket, and no HTTP backend? This won't work.
if (this.options.ajaxUrl === null) {
throw "$.JsonRpcClient.call used with no websocket and no http endpoint.";
}
$.ajax({
type : 'POST',
url : this.options.ajaxUrl,
data : $.toJSON(request),
dataType : 'json',
cache : false,
success : function(data) {
if ('error' in data) error_cb(data.error, this);
success_cb(data.result, this);
},
// JSON-RPC Server could return non-200 on error
error : function(jqXHR, textStatus, errorThrown) {
try {
var response = $.parseJSON(jqXHR.responseText);
if ('console' in window) console.log(response);
error_cb(response.error, this);
} catch (err) {
// Perhaps the responseText wasn't really a jsonrpc-error.
error_cb({ error: jqXHR.responseText }, this);
}
}
});
};
/**
* Notify sends a command to the server that won't need a response. In http, there is probably
* an empty response - that will be dropped, but in ws there should be no response at all.
*
* This is very similar to call, but has no id and no handling of callbacks.
*
* @fn notify
* @memberof $.JsonRpcClient
*
* @param method The method to run on JSON-RPC server.
* @param params The params; an array or object.
*/
$.JsonRpcClient.prototype.notify = function(method, params) {
// Construct the JSON-RPC 2.0 request.
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
var request = {
jsonrpc: '2.0',
method: method,
params: params
};
// Try making a WebSocket call.
var socket = this.options.getSocket(this.wsOnMessage);
if (socket !== null) {
this._wsCall(socket, request);
return;
}
// No WebSocket, and no HTTP backend? This won't work.
if (this.options.ajaxUrl === null) {
throw "$.JsonRpcClient.notify used with no websocket and no http endpoint.";
}
$.ajax({
type : 'POST',
url : this.options.ajaxUrl,
data : $.toJSON(request),
dataType : 'json',
cache : false
});
};
/**
* Make a batch-call by using a callback.
*
* The callback will get an object "batch" as only argument. On batch, you can call the methods
* "call" and "notify" just as if it was a normal $.JsonRpcClient object, and all calls will be
* sent as a batch call then the callback is done.
*
* @fn batch
* @memberof $.JsonRpcClient
*
* @param callback The main function which will get a batch handler to run call and notify on.
* @param all_done_cb A callback function to call after all results have been handled.
* @param error_cb A callback function to call if there is an error from the server.
* Note, that batch calls should always get an overall success, and the
* only error
*/
$.JsonRpcClient.prototype.batch = function(callback, all_done_cb, error_cb) {
var batch = new $.JsonRpcClient._batchObject(this, all_done_cb, error_cb);
callback(batch);
batch._execute();
};
/**
* The default getSocket handler.
*
* @param onmessage_cb The callback to be bound to onmessage events on the socket.
*
* @fn _getSocket
* @memberof $.JsonRpcClient
*/
$.JsonRpcClient.prototype.socketReady = function() {
if (this._ws_socket === null || this._ws_socket.readyState > 1) {
return false;
}
return true;
};
$.JsonRpcClient.prototype.closeSocket = function() {
var self = this;
if (self.socketReady()) {
self._ws_socket.onclose = function (w) {console.log("Closing Socket");};
self._ws_socket.close();
}
};
$.JsonRpcClient.prototype.loginData = function(params) {
var self = this;
self.options.login = params.login;
self.options.passwd = params.passwd;
self.options.loginParams = params.loginParams;
self.options.userVariables = params.userVariables;
};
$.JsonRpcClient.prototype.connectSocket = function(onmessage_cb) {
var self = this;
if (self.to) {
clearTimeout(self.to);
}
if (!self.socketReady()) {
self.authing = false;
if (self._ws_socket) {
delete self._ws_socket;
}
// No socket, or dying socket, let's get a new one.
self._ws_socket = new WebSocket(self.options.socketUrl);
if (self._ws_socket) {
// Set up onmessage handler.
self._ws_socket.onmessage = onmessage_cb;
self._ws_socket.onclose = function (w) {
if (!self.ws_sleep) {
self.ws_sleep = 1000;
}
if (self.options.onWSClose) {
self.options.onWSClose(self);
}
console.error("Websocket Lost " + self.ws_cnt + " sleep: " + self.ws_sleep + "msec");
self.to = setTimeout(function() {
console.log("Attempting Reconnection....");
self.connectSocket(onmessage_cb);
}, self.ws_sleep);
self.ws_cnt++;
if (self.ws_sleep < 3000 && (self.ws_cnt % 10) === 0) {
self.ws_sleep += 1000;
}
};
// Set up sending of message for when the socket is open.
self._ws_socket.onopen = function() {
if (self.to) {
clearTimeout(self.to);
}
self.ws_sleep = 1000;
self.ws_cnt = 0;
if (self.options.onWSConnect) {
self.options.onWSConnect(self);
}
var req;
// Send the requests.
while ((req = $.JsonRpcClient.q.pop())) {
self._ws_socket.send(req);
}
};
}
}
return self._ws_socket ? true : false;
};
$.JsonRpcClient.prototype._getSocket = function(onmessage_cb) {
// If there is no ws url set, we don't have a socket.
// Likewise, if there is no window.WebSocket.
if (this.options.socketUrl === null || !("WebSocket" in window)) return null;
this.connectSocket(onmessage_cb);
return this._ws_socket;
};
/**
* Queue to save messages delivered when websocket is not ready
*/
$.JsonRpcClient.q = [];
/**
* Internal handler to dispatch a JRON-RPC request through a websocket.
*
* @fn _wsCall
* @memberof $.JsonRpcClient
*/
$.JsonRpcClient.prototype._wsCall = function(socket, request, success_cb, error_cb) {
var request_json = $.toJSON(request);
if (socket.readyState < 1) {
// The websocket is not open yet; we have to set sending of the message in onopen.
self = this; // In closure below, this is set to the WebSocket. Use self instead.
$.JsonRpcClient.q.push(request_json);
} else {
// We have a socket and it should be ready to send on.
socket.send(request_json);
}
// Setup callbacks. If there is an id, this is a call and not a notify.
if ('id' in request && typeof success_cb !== 'undefined') {
this._ws_callbacks[request.id] = { request: request_json, request_obj: request, success_cb: success_cb, error_cb: error_cb };
}
};
/**
* Internal handler for the websocket messages. It determines if the message is a JSON-RPC
* response, and if so, tries to couple it with a given callback. Otherwise, it falls back to
* given external onmessage-handler, if any.
*
* @param event The websocket onmessage-event.
*/
$.JsonRpcClient.prototype._wsOnMessage = function(event) {
// Check if this could be a JSON RPC message.
var response;
// Special sub proto
if (event.data[0] == "#" && event.data[1] == "S" && event.data[2] == "P") {
if (event.data[3] == "U") {
this.up_dur = parseInt(event.data.substring(4));
} else if (this.speedCB && event.data[3] == "D") {
this.down_dur = parseInt(event.data.substring(4));
var up_kps = (((this.speedBytes * 8) / (this.up_dur / 1000)) / 1024).toFixed(0);
var down_kps = (((this.speedBytes * 8) / (this.down_dur / 1000)) / 1024).toFixed(0);
console.info("Speed Test: Up: " + up_kps + " Down: " + down_kps);
this.speedCB(event, { upDur: this.up_dur, downDur: this.down_dur, upKPS: up_kps, downKPS: down_kps });
this.speedCB = null;
}
return;
}
try {
response = $.parseJSON(event.data);
/// @todo Make using the jsonrcp 2.0 check optional, to use this on JSON-RPC 1 backends.
if (typeof response === 'object' &&
'jsonrpc' in response &&
response.jsonrpc === '2.0') {
/// @todo Handle bad response (without id).
// If this is an object with result, it is a response.
if ('result' in response && this._ws_callbacks[response.id]) {
// Get the success callback.
var success_cb = this._ws_callbacks[response.id].success_cb;
/*
// set the sessid if present
if ('sessid' in response.result && !this.options.sessid || (this.options.sessid != response.result.sessid)) {
this.options.sessid = response.result.sessid;
if (this.options.sessid) {
console.log("setting session UUID to: " + this.options.sessid);
}
}
*/
// Delete the callback from the storage.
delete this._ws_callbacks[response.id];
// Run callback with result as parameter.
success_cb(response.result, this);
return;
} else if ('error' in response && this._ws_callbacks[response.id]) {
// If this is an object with error, it is an error response.
// Get the error callback.
var error_cb = this._ws_callbacks[response.id].error_cb;
var orig_req = this._ws_callbacks[response.id].request;
// if this is an auth request, send the credentials and resend the failed request
if (!self.authing && response.error.code == -32000 && self.options.login && self.options.passwd) {
self.authing = true;
this.call("login", { login: self.options.login, passwd: self.options.passwd, loginParams: self.options.loginParams,
userVariables: self.options.userVariables},
this._ws_callbacks[response.id].request_obj.method == "login" ?
function(e) {
self.authing = false;
console.log("logged in");
delete self._ws_callbacks[response.id];
if (self.options.onWSLogin) {
self.options.onWSLogin(true, self);
}
}
:
function(e) {
self.authing = false;
console.log("logged in, resending request id: " + response.id);
var socket = self.options.getSocket(self.wsOnMessage);
if (socket !== null) {
socket.send(orig_req);
}
if (self.options.onWSLogin) {
self.options.onWSLogin(true, self);
}
},
function(e) {
console.log("error logging in, request id:", response.id);
delete self._ws_callbacks[response.id];
error_cb(response.error, this);
if (self.options.onWSLogin) {
self.options.onWSLogin(false, self);
}
});
return;
}
// Delete the callback from the storage.
delete this._ws_callbacks[response.id];
// Run callback with the error object as parameter.
error_cb(response.error, this);
return;
}
}
} catch (err) {
// Probably an error while parsing a non json-string as json. All real JSON-RPC cases are
// handled above, and the fallback method is called below.
console.log("ERROR: "+ err);
return;
}
// This is not a JSON-RPC response. Call the fallback message handler, if given.
if (typeof this.options.onmessage === 'function') {
event.eventData = response;
if (!event.eventData) {
event.eventData = {};
}
var reply = this.options.onmessage(event);
if (reply && typeof reply === "object" && event.eventData.id) {
var msg = {
jsonrpc: "2.0",
id: event.eventData.id,
result: reply
};
var socket = self.options.getSocket(self.wsOnMessage);
if (socket !== null) {
socket.send($.toJSON(msg));
}
}
}
};
/************************************************************************************************
* Batch object with methods
************************************************************************************************/
/**
* Handling object for batch calls.
*/
$.JsonRpcClient._batchObject = function(jsonrpcclient, all_done_cb, error_cb) {
// Array of objects to hold the call and notify requests. Each objects will have the request
// object, and unless it is a notify, success_cb and error_cb.
this._requests = [];
this.jsonrpcclient = jsonrpcclient;
this.all_done_cb = all_done_cb;
this.error_cb = typeof error_cb === 'function' ? error_cb : function() {};
};
/**
* @sa $.JsonRpcClient.prototype.call
*/
$.JsonRpcClient._batchObject.prototype.call = function(method, params, success_cb, error_cb) {
if (!params) {
params = {};
}
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
if (!success_cb) {
success_cb = function(e){console.log("Success: ", e);};
}
if (!error_cb) {
error_cb = function(e){console.log("Error: ", e);};
}
this._requests.push({
request : {
jsonrpc : '2.0',
method : method,
params : params,
id : this.jsonrpcclient._current_id++ // Use the client's id series.
},
success_cb : success_cb,
error_cb : error_cb
});
};
/**
* @sa $.JsonRpcClient.prototype.notify
*/
$.JsonRpcClient._batchObject.prototype.notify = function(method, params) {
if (this.options.sessid) {
params.sessid = this.options.sessid;
}
this._requests.push({
request : {
jsonrpc : '2.0',
method : method,
params : params
}
});
};
/**
* Executes the batched up calls.
*/
$.JsonRpcClient._batchObject.prototype._execute = function() {
var self = this;
if (this._requests.length === 0) return; // All done :P
// Collect all request data and sort handlers by request id.
var batch_request = [];
var handlers = {};
var i = 0;
var call;
var success_cb;
var error_cb;
// If we have a WebSocket, just send the requests individually like normal calls.
var socket = self.jsonrpcclient.options.getSocket(self.jsonrpcclient.wsOnMessage);
if (socket !== null) {
for (i = 0; i < this._requests.length; i++) {
call = this._requests[i];
success_cb = ('success_cb' in call) ? call.success_cb : undefined;
error_cb = ('error_cb' in call) ? call.error_cb : undefined;
self.jsonrpcclient._wsCall(socket, call.request, success_cb, error_cb);
}
if (typeof all_done_cb === 'function') all_done_cb(result);
return;
}
for (i = 0; i < this._requests.length; i++) {
call = this._requests[i];
batch_request.push(call.request);
// If the request has an id, it should handle returns (otherwise it's a notify).
if ('id' in call.request) {
handlers[call.request.id] = {
success_cb : call.success_cb,
error_cb : call.error_cb
};
}
}
success_cb = function(data) { self._batchCb(data, handlers, self.all_done_cb); };
// No WebSocket, and no HTTP backend? This won't work.
if (self.jsonrpcclient.options.ajaxUrl === null) {
throw "$.JsonRpcClient.batch used with no websocket and no http endpoint.";
}
// Send request
$.ajax({
url : self.jsonrpcclient.options.ajaxUrl,
data : $.toJSON(batch_request),
dataType : 'json',
cache : false,
type : 'POST',
// Batch-requests should always return 200
error : function(jqXHR, textStatus, errorThrown) {
self.error_cb(jqXHR, textStatus, errorThrown);
},
success : success_cb
});
};
/**
* Internal helper to match the result array from a batch call to their respective callbacks.
*
* @fn _batchCb
* @memberof $.JsonRpcClient
*/
$.JsonRpcClient._batchObject.prototype._batchCb = function(result, handlers, all_done_cb) {
for (var i = 0; i < result.length; i++) {
var response = result[i];
// Handle error
if ('error' in response) {
if (response.id === null || !(response.id in handlers)) {
// An error on a notify? Just log it to the console.
if ('console' in window) console.log(response);
} else {
handlers[response.id].error_cb(response.error, this);
}
} else {
// Here we should always have a correct id and no error.
if (!(response.id in handlers) && 'console' in window) {
console.log(response);
} else {
handlers[response.id].success_cb(response.result, this);
}
}
}
if (typeof all_done_cb === 'function') all_done_cb(result);
};
})(jQuery);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,14 @@
var callback = function(message){console.log(message);}; // holds the user's callback for a global scope
callbacks = {};
var callICEConnected = false;
var callPurposefullyEnded = false; // used to determine whether the user ended the call or the call was ended from somewhere else outside
var callTimeout = null; // function that will run if there is no call established
var toDisplayDisconnectCallback = true; // if a call is dropped only display the error the first time
var wasCallSuccessful = false; // when the websocket connection is closed this determines whether a call was ever successfully established
webcamStream = "webcamStream";
window[webcamStream] = null;
verto = null;
videoTag = null;
// save a copy of the hangup function registered for the verto object
var oldHangup = $.verto.prototype.hangup;
@ -32,7 +37,8 @@ $.verto.prototype.hangup = function(callID, userCallback) {
}
// main entry point to making a verto call
function callIntoConference(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback) {
callIntoConference_verto = function(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, videoTag, options, vertoServerCredentials) {
window.videoTag = videoTag;
// stores the user's callback in the global scope
if (userCallback) {
callback = userCallback;
@ -55,36 +61,43 @@ function callIntoConference(voiceBridge, conferenceUsername, conferenceIdNumber,
}
// runs when the websocket is successfully created
callbacks.onWSLogin = function(v, success) {
display("");
cur_call = null;
ringing = false;
console.log("Inside onWSLogin");
if (success) {
online(true);
console.log("starting call");
toDisplayDisconnectCallback = true; // yes, display an error if the socket closes
wasCallSuccessful = true; // yes, a call was successfully established through the websocket
webrtc_call(voiceBridge, conferenceUsername, conferenceIdNumber, callback);
if (!window.location.hash) {
goto_page("main");
}
webrtc_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, callback, options);
} else {
callback({'status':'failed', 'errorcode': '10XX'}); // eror logging verto into freeswitch
goto_page("main");
goto_dialog("login-error");
}
}
// set up verto
$.verto.init({}, init);
// $.verto.init({}, init(videoTag));
init(videoTag, vertoServerCredentials);
} else {
console.log("already logged into verto, going straight to making a call");
webrtc_call(voiceBridge, conferenceUsername, conferenceIdNumber, callback);
webrtc_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, callback, options);
}
}
function configStuns(callbacks, callback) {
checkSupport = function(callback) {
if(!isWebRTCAvailable_verto()) {
callback({'status': 'failed', 'errorcode': 1003}); // Browser version not supported
}
if (!navigator.getUserMedia) {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
}
if (!navigator.getUserMedia){
callback({'status': 'failed', 'errorcode': '10XX'}); // getUserMedia not supported in this browser
}
}
configStuns = function(callbacks, callback, videoTag, vertoServerCredentials) {
console.log("Fetching STUN/TURN server info for Verto initialization");
var stunsConfig = {};
$.ajax({
@ -93,6 +106,11 @@ function configStuns(callbacks, callback) {
}).done(function(data) {
console.log("ajax request done");
console.log(data);
if(data['response'] && data.response.returncode == "FAILED") {
console.error(data.response.message);
callback({'status':'failed', 'errorcode': data.response.message});
return;
}
stunsConfig['stunServers'] = ( data['stunServers'] ? data['stunServers'].map(function(data) {
return {'url': data['url']};
}) : [] );
@ -105,7 +123,7 @@ function configStuns(callbacks, callback) {
}) : [] );
stunsConfig = stunsConfig['stunServers'].concat(stunsConfig['turnServers']);
console.log("success got stun data, making verto");
makeVerto(callbacks, stunsConfig);
makeVerto(callbacks, stunsConfig, videoTag, vertoServerCredentials);
}).fail(function(data, textStatus, errorThrown) {
// BBBLog.error("Could not fetch stun/turn servers", {error: textStatus, user: callerIdName, voiceBridge: conferenceVoiceBridge});
callback({'status':'failed', 'errorcode': 1009});
@ -113,18 +131,41 @@ function configStuns(callbacks, callback) {
});
}
function docall(extension, conferenceUsername, conferenceIdNumber, callbacks) {
docall_verto = function(extension, conferenceUsername, conferenceIdNumber, callbacks, options) {
console.log(extension + ", " + conferenceUsername + ", " + conferenceIdNumber);
$('#ext').trigger('change');
if (cur_call) { // only allow for one call
console.log("Quitting: Call already in progress");
return;
}
check_vid_res();
outgoingBandwidth = "5120";
incomingBandwidth = "5120";
// determine the resolution the user chose for webcam video
my_check_vid_res();
outgoingBandwidth = "default";
incomingBandwidth = "default";
var useVideo = useCamera = useMic = false;
// debugger;
if(options.watchOnly) {
window.watchOnly = true;
window.listenOnly = false;
window.joinAudio = false;
useVideo = true;
useCamera = false;
useMic = false;
} else if(options.listenOnly) {
window.listenOnly = true;
window.watchOnly = false;
window.joinAudio = false;
useVideo = false;
useCamera = false;
useMic = false;
} else if(options.joinAudio) {
window.joinAudio = true;
window.watchOnly = false;
window.listenOnly = false;
useVideo = false;
useCamera = false;
useMic = true;
}
cur_call = verto.newCall({
destination_number: extension,
@ -132,12 +173,12 @@ function docall(extension, conferenceUsername, conferenceIdNumber, callbacks) {
caller_id_number: conferenceIdNumber,
outgoingBandwidth: outgoingBandwidth,
incomingBandwidth: incomingBandwidth,
useVideo: true,
useStereo: true,
useCamera: true,
useMic: true,
useVideo: useVideo,
useCamera: useCamera,
useMic: useMic,
dedEnc: false,
mirrorInput: false,
mirrorInput: false
});
if (callbacks != null) { // add user supplied callbacks to the current call
@ -151,31 +192,26 @@ function isLoggedIntoVerto() {
}
// overwrite and substitute my own init function
init = function() {
//$("#webcam").show();
init = function(videoTag, vertoServerCredentials) {
videoTag = window.videoTag;
cur_call = null;
share_call = null;
$(".sharediv").show();
$("#camdiv").show();
//$("#use_vid").prop("checked", "true"); //use video by default
incomingBandwidth = "default";
vqual = "qvga";
online(false);
configStuns(callbacks, callback);
configStuns(callbacks, callback, videoTag, vertoServerCredentials);
}
// checks whether Google Chrome or Firefox have the WebRTCPeerConnection object
function isWebRTCAvailable() {
function isWebRTCAvailable_verto() {
return (typeof window.webkitRTCPeerConnection !== 'undefined' || typeof window.mozRTCPeerConnection !== 'undefined');
}
// exit point for conference
function leaveWebRTCVoiceConference() {
function leaveWebRTCVoiceConference_verto() {
console.log("Leaving the voice conference");
webrtc_hangup();
webrtc_hangup_verto();
}
function make_call(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, server, recall) {
function make_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, server, recall, options) {
if (userCallback) {
callback = userCallback;
}
@ -196,7 +232,6 @@ function make_call(voiceBridge, conferenceUsername, conferenceIdNumber, userCall
var myRTCCallbacks = {
onError: function(vertoErrorObject, errorMessage) {
console.error("custom callback: onError");
console.log("current verto");
console.error(vertoErrorObject);
console.error("ERROR:");
console.error(errorMessage);
@ -239,7 +274,7 @@ function make_call(voiceBridge, conferenceUsername, conferenceIdNumber, userCall
console.log("Verto is logged into FreeSWITCH, socket is available, making call");
callICEConnected = false;
docall(voiceBridge, conferenceUsername, conferenceIdNumber, myRTCCallbacks);
docall_verto(voiceBridge, conferenceUsername, conferenceIdNumber, myRTCCallbacks, options);
if(recall === false) {
console.log('call connecting');
@ -254,14 +289,23 @@ function make_call(voiceBridge, conferenceUsername, conferenceIdNumber, userCall
}
}
function makeVerto(callbacks, stunsConfig) {
var vertoPort = "8082";
//var hostName = window.location.hostname; //TODO
var hostName = "IP"; //TODO
//var socketUrl = "ws://" + hostName + ":5066"; //TODO
var socketUrl = "wss://" + hostName + ":" + vertoPort; //TODO
var login = "1008"; //TODO
var password = "PASSWORD"; //TODO
function makeVerto(callbacks, stunsConfig, videoTag, vertoServerCredentials) {
// var vertoPort = "8082";
// //var hostName = window.location.hostname; //TODO
// var hostName = "IP"; //TODO
// //var socketUrl = "ws://" + hostName + ":5066"; //TODO
// var socketUrl = "wss://" + hostName + ":" + vertoPort; //TODO
// var login = "1008"; //TODO
// var password = "PASSWORD"; //TODO
// var minWidth = "640";
// var minHeight = "480";
// var maxWidth = "1920";
// var maxHeight = "1080";
var vertoPort = vertoServerCredentials.vertoPort;
var hostName = vertoServerCredentials.hostName;
var socketUrl = "wss://" + hostName + ":" + vertoPort;
var login = vertoServerCredentials.login;
var password = vertoServerCredentials.password;
var minWidth = "640";
var minHeight = "480";
var maxWidth = "1920";
@ -269,26 +313,41 @@ function makeVerto(callbacks, stunsConfig) {
console.log("stuns info is");
console.log(stunsConfig);
check_vid_res();
// create verto object and log in
// debugger;
verto = new $.verto({
login: login,
passwd: password,
socketUrl: socketUrl,
tag: "webcam",
tag: videoTag,
ringFile: "sounds/bell_ring2.wav",
loginParams: {foo: true, bar: "yes"},
videoParams: {
"minWidth": minWidth,
"minHeight": minHeight,
"maxWidth": maxWidth,
"maxHeight": maxHeight,
},
useVideo: false,
useCamera: false,
iceServers: stunsConfig, // use user supplied stun configuration
// iceServers: true, // use stun, use default verto configuration
}, callbacks);
refresh_devices();
}
// sets verto to begin using the resolution that the user selected
my_check_vid_res = function() {
var selectedVideoConstraints = getChosenWebcamResolution();
my_real_size(selectedVideoConstraints);
if (verto) {
verto.videoParams({
"minWidth": selectedVideoConstraints.constraints.minWidth,
"minHeight": selectedVideoConstraints.constraints.minHeight,
"maxWidth": selectedVideoConstraints.constraints.maxWidth,
"maxHeight": selectedVideoConstraints.constraints.maxHeight,
"minFrameRate": selectedVideoConstraints.constraints.minFrameRate,
"vertoBestFrameRate": selectedVideoConstraints.constraints.vertoBestFrameRate
});
}
}
my_real_size = function(selectedVideoConstraints) {
$("#" + window.videoTag).height("100%");
$("#" + window.videoTag).width("100%");
}
var RTCPeerConnectionCallbacks = {
@ -306,8 +365,11 @@ var RTCPeerConnectionCallbacks = {
//clearTimeout(callTimeout);
}
};
this.RTCPeerConnectionCallbacks = RTCPeerConnectionCallbacks;
function webrtc_call(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback) {
window.verto_afterStreamPublish = function() {}
function webrtc_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, userCallback, options) {
if (userCallback) {
callback = userCallback;
}
@ -321,103 +383,17 @@ function webrtc_call(voiceBridge, conferenceUsername, conferenceIdNumber, userCa
var server = window.document.location.hostname;
console.log("user " + conferenceUsername + " calling to " + voiceBridge);
if (isLoggedIntoVerto()) {
make_call(voiceBridge, conferenceUsername, conferenceIdNumber, callback, "", false);
make_call_verto(voiceBridge, conferenceUsername, conferenceIdNumber, callback, "", false, options);
}
}
function webrtc_hangup(userCallback) {
function webrtc_hangup_verto(userCallback) {
if (userCallback) {
callback = userCallback;
}
callPurposefullyEnded = true;
console.log("Hanging up current session");
verto.hangup(false, callback);
}
function doWebcamPreview() {
//TODO
// var hdConstraints = {
// video: {
// mandatory: {
// minWidth: 1280,
// minHeight: 720
// }
// }
// };
// var vgaConstraints = {
// video: {
// mandatory: {
// maxWidth: 640,
// maxHeight: 360
// }
// }
// };
//TODO
var vgaConstraints = {
"audio": false,
"video": {
"mandatory": {
"minWidth": 320,
"maxWidth": 320,
"minHeight": 240,
"maxHeight": 240,
"minFrameRate": 30
},
"optional": []
}
};
var hdConstraints = {
"audio": false,
"video": {
"mandatory": {
"minWidth": 1280,
"maxWidth": 1280,
"minHeight": 720,
"maxHeight": 720,
"minFrameRate": 30
},
"optional": []
}
};
var maxConstraints = {
"audio": false,
"video": {
"mandatory": {
"maxWidth": screen.width > 1920 ? screen.width : 1920,
"maxHeight": screen.height > 1080 ? screen.height : 1080,
"minWidth": screen.width > 1920 ? screen.width : 1920,
"maxWidth": screen.height > 1080 ? screen.height : 1080,
"minFrameRate": 30
},
"optional": []
}
};
//var screen_constraints = vgaConstraints;
// var screen_constraints = hdConstraints;
// console.log("screen constraints", screen_constraints)
// navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// navigator.getUserMedia(screen_constraints, function(stream) {
// var video = document.querySelector('video');
// video.src = URL.createObjectURL(stream);
// video.play();
// }, function(error) {
// return console.error(JSON.stringify(error, null, '\t'));
// });
}
function checkSupport(callback) {
if(!isWebRTCAvailable()) {
callback({'status': 'failed', 'errorcode': 1003}); // Browser version not supported
}
if (!navigator.getUserMedia) {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
}
if (!navigator.getUserMedia){
callback({'status': 'failed', 'errorcode': '10XX'}); // getUserMedia not supported in this browser
if(verto) {
verto.hangup(false, callback);
}
}

View File

@ -1,39 +1,39 @@
function screenStart(state, callback) {
if (state) {
if(!isLoggedIntoVerto()) { // start the verto log in procedure
// runs when the websocket is successfully created
callbacks.onWSLogin = function(v, success) {
doshare(state);
callback({'status':'success', 'message': 'screenshare started'});
console.log("logged in. starting screenshare");
}
// set up verto
$.verto.init({}, init);
} else {
console.log("already logged into verto, going straight to making a call");
doshare(state);
callback({'status':'success', 'message': 'screenshare started'});
var deskshareStream = "deskshareStream";
window[deskshareStream] = null;
this.share_call = null;
function endScreenshare(loggingCallback, onSuccess) {
if (share_call) {
share_call.hangup();
share_call = null;
onSuccess();
}
loggingCallback({'status':'success', 'message': 'screenshare ended'});
}
function startScreenshare(loggingCallback, videoTag, vertoServerCredentials, extensionId, onSuccess, onFail) {
if(!isLoggedIntoVerto()) { // start the verto log in procedure
// runs when the websocket is successfully created
callbacks.onWSLogin = function(v, success) {
startScreenshare2(loggingCallback, videoTag, extensionId, onSuccess, onFail);
loggingCallback({'status':'success', 'message': 'screenshare started'});
console.log("logged in. starting screenshare");
}
// set up verto
init(window.videoTag, vertoServerCredentials);
} else {
doshare(state);
callback({'status':'success', 'message': 'screenshare ended'});
console.log("already logged into verto, going straight to making a call");
startScreenshare2(loggingCallback, videoTag, extensionId, onSuccess, onFail);
loggingCallback({'status':'success', 'message': 'screenshare started'});
}
}
function doshare(on) {
if (!on) {
if (share_call) {
share_call.hangup();
}
return;
}
function startScreenshare2(loggingCallback, videoTag, extensionId, onSuccess, onFail) {
if (share_call) {
return;
}
outgoingBandwidth = incomingBandwidth = "5120";
// outgoingBandwidth = incomingBandwidth = "default";
outgoingBandwidth = incomingBandwidth = "default";
var sharedev = "screen";
if (sharedev !== "screen") {
@ -56,65 +56,112 @@ function doshare(on) {
return;
}
getChromeExtensionStatus( function(status) {
sourceId = null;
console.log("status", status);
getScreenConstraints(function(error, screen_constraints) {
if(error) {
return console.error(error);
}
var callbacks = {
onError: function(vertoErrorObject, errorMessage) {
console.error("custom callback: onError");
//
onFail();
},
onICEComplete: function(self, candidate) { // ICE candidate negotiation is complete
console.log("custom callback: onICEComplete");
//
onSuccess();
}
};
console.log('screen_constraints', screen_constraints);
if (!!navigator.mozGetUserMedia) {
var selectedDeskshareResolution = getChosenDeskshareResolution(); // this is the video profile the user chose
my_real_size(selectedDeskshareResolution);
var screen_constraints = {
"mozMediaSource": 'window',
"mediaSource": 'window',
"width": 0,
"height": 0,
frameRate : {min: 15, max: 30}
};
BBB.getMyUserInfo(function (retData){
share_call = verto.newCall({
destination_number: retData.voiceBridge + "-screen",
caller_id_name: retData.myUsername + " (Screen)",
caller_id_number: retData.myUserID + " (screen)",
outgoingBandwidth: outgoingBandwidth,
incomingBandwidth: incomingBandwidth,
videoParams: screen_constraints.mandatory,
useVideo: true,
screenShare: true,
dedEnc: true,
mirrorInput: true
});
window.listenOnly = false;
window.watchOnly = false;
window.joinAudio = true;
BBB.getMyUserInfo(function (retData){
share_call = verto.newCall({
destination_number: retData.voiceBridge + "-screen",
caller_id_name: retData.myUsername + " (Screen)",
caller_id_number: retData.myUserID + " (screen)",
outgoingBandwidth: outgoingBandwidth,
incomingBandwidth: incomingBandwidth,
videoParams: screen_constraints,
useVideo: true,
screenShare: true,
dedEnc: false,
mirrorInput: false,
tag: "webcam"
});
});
});
}
function doDesksharePreview() {
getChromeExtensionStatus(function(status) {
// sourceId = null; //TODO
getScreenConstraints(function(error, screen_constraints) {
if(error) {
return console.error(error);
}
share_call.rtc.options.callbacks = $.extend(share_call.rtc.options.callbacks, callbacks);
} else {
getChromeExtensionStatus(extensionId, function(status) {
getScreenConstraints(function(error, screen_constraints) {
if(error) {
return console.error(error);
}
console.log('screen_constraints', screen_constraints);
console.log("status", status);
console.log('screen_constraints', screen_constraints);
navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
navigator.getUserMedia({ video: screen_constraints }, function(stream) {
var video = document.querySelector('video');
video.src = URL.createObjectURL(stream);
video.play();
}, function(error) {
return console.error(JSON.stringify(error, null, '\t'));
var selectedDeskshareResolution = getChosenDeskshareResolution(); // this is the video profile the user chose
my_real_size(selectedDeskshareResolution);
var selectedDeskshareConstraints = getDeskshareConstraintsFromResolution(selectedDeskshareResolution, screen_constraints); // convert to a valid constraints object
console.log(selectedDeskshareConstraints);
window.listenOnly = false;
window.watchOnly = false;
window.joinAudio = true;
BBB.getMyUserInfo(function (retData){
share_call = verto.newCall({
destination_number: retData.voiceBridge + "-screen",
caller_id_name: retData.myUsername + " (Screen)",
caller_id_number: retData.myUserID + " (screen)",
outgoingBandwidth: outgoingBandwidth,
incomingBandwidth: incomingBandwidth,
videoParams: selectedDeskshareConstraints.video.mandatory,
useVideo: true,
screenShare: true,
dedEnc: true,
mirrorInput: true,
tag: videoTag,
});
});
share_call.rtc.options.callbacks = $.extend(share_call.rtc.options.callbacks, callbacks);
});
})
});
});
}
}
function vertoScreenStart() {
console.log("vertoScreenStart");
// screenStart(true, function () {
// });
screenStart(true, function(){});
// return the webcam resolution that the user has selected
this.getChosenDeskshareResolution = function() {
var videoConstraints = getAllPresetVideoResolutions(); // retrieve all resolutions
var selectedVideo = videoConstraints[$("#deskshareResolutions").find(":selected").val()];
return selectedVideo;
}
function vertoScreenStop() {
console.log("vertoScreenStop");
screenStart(false, function () {
});
// receives a video resolution profile, and converts it into a constraints format for getUserMedia
this.getDeskshareConstraintsFromResolution = function(resolution, constraints) {
return {
"audio": false,
"video": {
"mandatory": {
"maxWidth": resolution.constraints.maxWidth,
"maxHeight": resolution.constraints.maxHeight,
"chromeMediaSource": constraints.mandatory.chromeMediaSource,
"chromeMediaSourceId": constraints.mandatory.chromeMediaSourceId,
"minFrameRate": resolution.constraints.minFrameRate
},
"optional": []
}
};
}

File diff suppressed because it is too large Load Diff