diff --git a/openvidu-getaroom/docker/Dockerfile b/openvidu-getaroom/docker/Dockerfile index 6125e633..90a69102 100644 --- a/openvidu-getaroom/docker/Dockerfile +++ b/openvidu-getaroom/docker/Dockerfile @@ -42,7 +42,7 @@ RUN set -x \ && chmod -R go=u,go-w /home/ngrok \ && chmod go= /home/ngrok -EXPOSE 8443 +EXPOSE 4443 EXPOSE 4040 # Exec supervisord diff --git a/openvidu-getaroom/docker/ngrok.yml b/openvidu-getaroom/docker/ngrok.yml index 429a3073..68418d8f 100644 --- a/openvidu-getaroom/docker/ngrok.yml +++ b/openvidu-getaroom/docker/ngrok.yml @@ -1,5 +1,5 @@ web_addr: 0.0.0.0:4040 tunnels: app: - addr: 8443 + addr: 4443 proto: http diff --git a/openvidu-getaroom/docker/supervisord.conf b/openvidu-getaroom/docker/supervisord.conf index 79e29fad..6a30c0d0 100644 --- a/openvidu-getaroom/docker/supervisord.conf +++ b/openvidu-getaroom/docker/supervisord.conf @@ -9,7 +9,7 @@ command=/bin/bash /kms.sh redirect_stderr=true [program:openvidu-server] -command=/bin/bash -c "java -Dspring.profiles.active=ngrok -Dserver.port=8443 -Dsecurity.ignored=/** -Dspring.resources.static-locations=file:///web/ -jar /openvidu-server.jar" +command=/bin/bash -c "java -Dspring.profiles.active=ngrok -Dserver.port=4443 -Dsecurity.ignored=/** -Dspring.resources.static-locations=file:///web/ -jar /openvidu-server.jar" redirect_stderr=true [program:ngrok] diff --git a/openvidu-getaroom/web/app.js b/openvidu-getaroom/web/app.js index bf844f84..0eb0ef20 100644 --- a/openvidu-getaroom/web/app.js +++ b/openvidu-getaroom/web/app.js @@ -9,12 +9,12 @@ var numOfVideos = 0; // Keeps track of the number of videos that are being show // Check if the URL already has a room window.addEventListener('load', function () { - sessionId = window.location.hash; // For 'https://myurl/#roomId', sessionId would be '#roomId' + sessionId = window.location.hash.slice(1); // For 'https://myurl/#roomId', sessionId would be 'roomId' if (sessionId) { // The URL has a session id. Join the room right away console.log("Joining to room " + sessionId); showSessionHideJoin(); - joinRoom(sessionId); + joinRoom(); } else { // The URL has not a session id. Show welcome page showJoinHideSession(); @@ -27,23 +27,18 @@ window.addEventListener('beforeunload', function () { }); -function joinRoom(sessionId) { +function joinRoom() { if (!sessionId) { // If the user is joining to a new room - sessionId = '#' + randomString(); + sessionId = randomString(); } - // As insecure OpenVidu, the user's token can be a random string - var userId = randomString(); - // --- 1) Get an OpenVidu object and init a session with a sessionId --- + // --- 1) Get an OpenVidu object and init a session --- OV = new OpenVidu(); - - // We will join the video-call "sessionId". As there's no server, this parameter must start with the URL of - // OpenVidu Server (with secure websocket protocol: "wss://") and must include the OpenVidu secret at the end - session = OV.initSession("wss://" + location.hostname + ":8443/" + sessionId + "?secret=MY_SECRET"); + session = OV.initSession(); // --- 2) Specify the actions when events take place --- @@ -67,58 +62,60 @@ function joinRoom(sessionId) { }); - // --- 3) Connect to the session --- + // --- 3) Connect to the session with a valid user token --- - // Remember 'userId' param (usually called 'token') is irrelevant when using the insecure version of OpenVidu - session.connect(userId, function (error) { + // 'getToken' method is simulating what your server-side should do. + // 'token' parameter should be retrieved and returned by your own backend + getToken().then(token => { - // If the connection is successful, initialize a publisher and publish to the session - if (!error) { + // Connect with the token + session.connect(token) + .then(() => { - // --- 4) Get your own camera stream with the desired resolution --- + // --- 4) Get your own camera stream with the desired properties --- - publisher = OV.initPublisher('publisher', { - audio: true, // Whether you want to transmit audio or not - video: true, // Whether you want to transmit video or not - audioActive: true, // Whether you want to start the publishing with your audio unmuted or muted - videoActive: true, // Whether you want to start the publishing with your video enabled or disabled - quality: 'MEDIUM', // The quality of your video ('LOW', 'MEDIUM', 'HIGH') - screen: false // true to get your screen as video source instead of your camera + publisher = OV.initPublisher('publisher', { + audioSource: undefined, // The source of audio. If undefined default audio input + videoSource: undefined, // The source of video. If undefined default video input + publishAudio: true, // Whether you want to start the publishing with your audio unmuted or muted + publishVideo: true, // Whether you want to start the publishing with your video enabled or disabled + resolution: '640x480', // The resolution of your video + frameRate: 30, // The frame rate of your video + insertMode: 'APPEND', // How the video will be inserted in the target element 'video-container' + mirror: true // Whether to mirror your local video or not + }); + + publisher.on('videoElementCreated', function (event) { + // When your own video is added to DOM, update the page layout to fit it + numOfVideos++; + updateLayout(); + $(event.element).prop('muted', true); // Mute local video + }); + + // --- 5) Publish your stream --- + + session.publish(publisher); + }) + .catch(error => { + console.log('There was an error connecting to the session:', error.code, error.message); }); - publisher.on('videoElementCreated', function (event) { - // When your own video is added to DOM, update the page layout to fit it - numOfVideos++; - updateLayout(); - $(event.element).prop('muted', true); // Mute local video - }); + // Update the URL shown in the browser's navigation bar to show the session id + var pathname = (location.pathname.slice(-1) === "/" ? location.pathname : location.pathname + "/"); + window.history.pushState("", "", pathname + '#' + sessionId); - // --- 5) Publish your stream --- - - session.publish(publisher); - - } else { - console.log('There was an error connecting to the session:', error.code, error.message); - } + // Auxiliary methods to show the session's view + showSessionHideJoin(); + initializeSessionView(); }); - - // Update the URL shown in the browser's navigation bar to show the session id - var pathname = (location.pathname.slice(-1) === "/" ? location.pathname : location.pathname+"/"); - window.history.pushState("", "", pathname + sessionId); - - // Auxiliary methods to show the session's view - showSessionHideJoin(); - initializeSessionView(); - - return false; } function leaveRoom() { - + // --- 6) Leave the session by calling 'disconnect' method over the Session object --- session.disconnect(); - + // Back to welcome page window.location.href = window.location.origin + window.location.pathname; } @@ -154,8 +151,6 @@ function muteVideo() { } - -// Generate a random string for sessionId and userId function randomString() { return Math.random().toString(36).slice(2); } @@ -249,4 +244,69 @@ function updateLayout() { } } -/* AUXILIARY METHODS */ \ No newline at end of file + + +/** + * -------------------------- + * SERVER-SIDE RESPONSABILITY + * -------------------------- + * These methods retrieve the mandatory user token from OpenVidu Server. + * This behaviour MUST BE IN YOUR SERVER-SIDE IN PRODUCTION (by using + * the API REST, openvidu-java-client or openvidu-node-client): + * 1) POST /api/sessions + * 2) POST /api/tokens + * 3) The value returned by /api/tokens must be consumed in Session.connect() method + */ + +function getToken() { + return new Promise(async function (resolve) { + // POST /api/sessions + await apiSessions(); + // POST /api/tokens + let t = await apiTokens(); + // Return the user token + resolve(t); + }); +} + +function apiSessions() { + return new Promise((resolve, reject) => { + $.ajax({ + type: "POST", + url: "https://" + location.hostname + ":4443/api/sessions", + data: JSON.stringify({ customSessionId: sessionId }), + headers: { + "Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"), + "Content-Type": "application/json" + }, + success: (response) => { + resolve(response.id) + }, + error: (error) => { + if (error.status === 409) { + resolve(sessionId); + } else { + reject(error) + } + } + }); + }); +} + +function apiTokens() { + return new Promise((resolve, reject) => { + $.ajax({ + type: "POST", + url: "https://" + location.hostname + ":4443/api/tokens", + data: JSON.stringify({ session: sessionId }), + headers: { + "Authorization": "Basic " + btoa("OPENVIDUAPP:MY_SECRET"), + "Content-Type": "application/json" + }, + success: (response) => { + resolve(response.id) + }, + error: (error) => { reject(error) } + }); + }); +} \ No newline at end of file diff --git a/openvidu-getaroom/web/index.html b/openvidu-getaroom/web/index.html index 1dc31dc7..d97acd80 100644 --- a/openvidu-getaroom/web/index.html +++ b/openvidu-getaroom/web/index.html @@ -7,17 +7,14 @@ - - - + + + - + @@ -50,11 +47,13 @@ + + Video + + + Audio + @@ -63,10 +62,10 @@


- * ws : {
- * uri : URI to conntect to,
- * useSockJS : true (use SockJS) / false (use WebSocket) by default,
- * onconnected : callback method to invoke when connection is successful,
- * ondisconnect : callback method to invoke when the connection is lost,
- * onreconnecting : callback method to invoke when the client is reconnecting,
- * onreconnected : callback method to invoke when the client succesfully reconnects,
- * onerror : callback method to invoke when there is an error
- * },
- * rpc : {
- * requestTimeout : timeout for a request,
- * sessionStatusChanged: callback method for changes in session status,
- * mediaRenegotiation: mediaRenegotiation
- * }
- *
- */
-function JsonRpcClient(configuration) {
- var self = this;
- var wsConfig = configuration.ws;
- var notReconnectIfNumLessThan = -1;
- var pingNextNum = 0;
- var enabledPings = true;
- var pingPongStarted = false;
- var pingInterval;
- var status = DISCONNECTED;
- var onreconnecting = wsConfig.onreconnecting;
- var onreconnected = wsConfig.onreconnected;
- var onconnected = wsConfig.onconnected;
- var onerror = wsConfig.onerror;
- configuration.rpc.pull = function (params, request) {
- request.reply(null, "push");
- };
- wsConfig.onreconnecting = function () {
- Logger.debug("--------- ONRECONNECTING -----------");
- if (status === RECONNECTING) {
- Logger.error("Websocket already in RECONNECTING state when receiving a new ONRECONNECTING message. Ignoring it");
- return;
- }
- status = RECONNECTING;
- if (onreconnecting) {
- onreconnecting();
- }
- };
- wsConfig.onreconnected = function () {
- Logger.debug("--------- ONRECONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONRECONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- updateNotReconnectIfLessThan();
- usePing();
- if (onreconnected) {
- onreconnected();
- }
- };
- wsConfig.onconnected = function () {
- Logger.debug("--------- ONCONNECTED -----------");
- if (status === CONNECTED) {
- Logger.error("Websocket already in CONNECTED state when receiving a new ONCONNECTED message. Ignoring it");
- return;
- }
- status = CONNECTED;
- enabledPings = true;
- usePing();
- if (onconnected) {
- onconnected();
- }
- };
- wsConfig.onerror = function (error) {
- Logger.debug("--------- ONERROR -----------");
- status = DISCONNECTED;
- if (onerror) {
- onerror(error);
- }
- };
- var ws = new WebSocketWithReconnection(wsConfig);
- Logger.debug('Connecting websocket to URI: ' + wsConfig.uri);
- var rpcBuilderOptions = {
- request_timeout: configuration.rpc.requestTimeout,
- ping_request_timeout: configuration.rpc.heartbeatRequestTimeout
- };
- var rpc = new RpcBuilder(RpcBuilder.packers.JsonRPC, rpcBuilderOptions, ws, function (request) {
- Logger.debug('Received request: ' + JSON.stringify(request));
- try {
- var func = configuration.rpc[request.method];
- if (func === undefined) {
- Logger.error("Method " + request.method + " not registered in client");
- }
- else {
- func(request.params, request);
- }
- }
- catch (err) {
- Logger.error('Exception processing request: ' + JSON.stringify(request));
- Logger.error(err);
- }
- });
- this.send = function (method, params, callback) {
- if (method !== 'ping') {
- Logger.debug('Request: method:' + method + " params:" + JSON.stringify(params));
- }
- var requestTime = Date.now();
- rpc.encode(method, params, function (error, result) {
- if (error) {
- try {
- Logger.error("ERROR:" + error.message + " in Request: method:" +
- method + " params:" + JSON.stringify(params) + " request:" +
- error.request);
- if (error.data) {
- Logger.error("ERROR DATA:" + JSON.stringify(error.data));
- }
- }
- catch (e) { }
- error.requestTime = requestTime;
- }
- if (callback) {
- if (result != undefined && result.value !== 'pong') {
- Logger.debug('Response: ' + JSON.stringify(result));
- }
- callback(error, result);
- }
- });
- };
- function updateNotReconnectIfLessThan() {
- Logger.debug("notReconnectIfNumLessThan = " + pingNextNum + ' (old=' +
- notReconnectIfNumLessThan + ')');
- notReconnectIfNumLessThan = pingNextNum;
- }
- function sendPing() {
- if (enabledPings) {
- var params = null;
- if (pingNextNum == 0 || pingNextNum == notReconnectIfNumLessThan) {
- params = {
- interval: configuration.heartbeat || PING_INTERVAL
- };
- }
- pingNextNum++;
- self.send('ping', params, (function (pingNum) {
- return function (error, result) {
- if (error) {
- Logger.debug("Error in ping request #" + pingNum + " (" +
- error.message + ")");
- if (pingNum > notReconnectIfNumLessThan) {
- enabledPings = false;
- updateNotReconnectIfLessThan();
- Logger.debug("Server did not respond to ping message #" +
- pingNum + ". Reconnecting... ");
- ws.reconnectWs();
- }
- }
- };
- })(pingNextNum));
- }
- else {
- Logger.debug("Trying to send ping, but ping is not enabled");
- }
- }
- /*
- * If configuration.hearbeat has any value, the ping-pong will work with the interval
- * of configuration.hearbeat
- */
- function usePing() {
- if (!pingPongStarted) {
- Logger.debug("Starting ping (if configured)");
- pingPongStarted = true;
- if (configuration.heartbeat != undefined) {
- pingInterval = setInterval(sendPing, configuration.heartbeat);
- sendPing();
- }
- }
- }
- this.close = function () {
- Logger.debug("Closing jsonRpcClient explicitly by client");
- if (pingInterval != undefined) {
- Logger.debug("Clearing ping interval");
- clearInterval(pingInterval);
- }
- pingPongStarted = false;
- enabledPings = false;
- if (configuration.sendCloseMessage) {
- Logger.debug("Sending close message");
- this.send('closeSession', null, function (error, result) {
- if (error) {
- Logger.error("Error sending close message: " + JSON.stringify(error));
- }
- ws.close();
- });
- }
- else {
- ws.close();
- }
- };
- // This method is only for testing
- this.forceClose = function (millis) {
- ws.forceClose(millis);
- };
- this.reconnect = function () {
- ws.reconnectWs();
- };
-}
-module.exports = JsonRpcClient;
-
-},{"../":45,"./transports/webSocketWithReconnection":44}],43:[function(require,module,exports){
-/*
- * (C) Copyright 2014 Kurento (http://kurento.org/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-var WebSocketWithReconnection = require('./webSocketWithReconnection');
-exports.WebSocketWithReconnection = WebSocketWithReconnection;
-
-},{"./webSocketWithReconnection":44}],44:[function(require,module,exports){
-(function (global){
-/*
- * (C) Copyright 2013-2015 Kurento (http://kurento.org/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-"use strict";
-var BrowserWebSocket = global.WebSocket || global.MozWebSocket;
-var Logger = console;
-/**
- * Get either the `WebSocket` or `MozWebSocket` globals
- * in the browser or try to resolve WebSocket-compatible
- * interface exposed by `ws` for Node-like environment.
- */
-/*var WebSocket = BrowserWebSocket;
-if (!WebSocket && typeof window === 'undefined') {
- try {
- WebSocket = require('ws');
- } catch (e) { }
-}*/
-//var SockJS = require('sockjs-client');
-var MAX_RETRIES = 2000; // Forever...
-var RETRY_TIME_MS = 3000; // FIXME: Implement exponential wait times...
-var CONNECTING = 0;
-var OPEN = 1;
-var CLOSING = 2;
-var CLOSED = 3;
-/*
-config = {
- uri : wsUri,
- useSockJS : true (use SockJS) / false (use WebSocket) by default,
- onconnected : callback method to invoke when connection is successful,
- ondisconnect : callback method to invoke when the connection is lost,
- onreconnecting : callback method to invoke when the client is reconnecting,
- onreconnected : callback method to invoke when the client succesfully reconnects,
- };
-*/
-function WebSocketWithReconnection(config) {
- var closing = false;
- var registerMessageHandler;
- var wsUri = config.uri;
- var useSockJS = config.useSockJS;
- var reconnecting = false;
- var forcingDisconnection = false;
- var ws;
- if (useSockJS) {
- ws = new SockJS(wsUri);
- }
- else {
- ws = new WebSocket(wsUri);
- }
- ws.onopen = function () {
- logConnected(ws, wsUri);
- if (config.onconnected) {
- config.onconnected();
- }
- };
- ws.onerror = function (error) {
- Logger.error("Could not connect to " + wsUri + " (invoking onerror if defined)", error);
- if (config.onerror) {
- config.onerror(error);
- }
- };
- function logConnected(ws, wsUri) {
- try {
- Logger.debug("WebSocket connected to " + wsUri);
- }
- catch (e) {
- Logger.error(e);
- }
- }
- var reconnectionOnClose = function () {
- if (ws.readyState === CLOSED) {
- if (closing) {
- Logger.debug("Connection closed by user");
- }
- else {
- Logger.debug("Connection closed unexpectecly. Reconnecting...");
- reconnectToSameUri(MAX_RETRIES, 1);
- }
- }
- else {
- Logger.debug("Close callback from previous websocket. Ignoring it");
- }
- };
- ws.onclose = reconnectionOnClose;
- function reconnectToSameUri(maxRetries, numRetries) {
- Logger.debug("reconnectToSameUri (attempt #" + numRetries + ", max=" + maxRetries + ")");
- if (numRetries === 1) {
- if (reconnecting) {
- Logger.warn("Trying to reconnectToNewUri when reconnecting... Ignoring this reconnection.");
- return;
- }
- else {
- reconnecting = true;
- }
- if (config.onreconnecting) {
- config.onreconnecting();
- }
- }
- if (forcingDisconnection) {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- else {
- if (config.newWsUriOnReconnection) {
- config.newWsUriOnReconnection(function (error, newWsUri) {
- if (error) {
- Logger.debug(error);
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, newWsUri);
- }
- });
- }
- else {
- reconnectToNewUri(maxRetries, numRetries, wsUri);
- }
- }
- }
- // TODO Test retries. How to force not connection?
- function reconnectToNewUri(maxRetries, numRetries, reconnectWsUri) {
- Logger.debug("Reconnection attempt #" + numRetries);
- ws.close();
- wsUri = reconnectWsUri || wsUri;
- var newWs;
- if (useSockJS) {
- newWs = new SockJS(wsUri);
- }
- else {
- newWs = new WebSocket(wsUri);
- }
- newWs.onopen = function () {
- Logger.debug("Reconnected after " + numRetries + " attempts...");
- logConnected(newWs, wsUri);
- reconnecting = false;
- registerMessageHandler();
- if (config.onreconnected()) {
- config.onreconnected();
- }
- newWs.onclose = reconnectionOnClose;
- };
- var onErrorOrClose = function (error) {
- Logger.warn("Reconnection error: ", error);
- if (numRetries === maxRetries) {
- if (config.ondisconnect) {
- config.ondisconnect();
- }
- }
- else {
- setTimeout(function () {
- reconnectToSameUri(maxRetries, numRetries + 1);
- }, RETRY_TIME_MS);
- }
- };
- newWs.onerror = onErrorOrClose;
- ws = newWs;
- }
- this.close = function () {
- closing = true;
- ws.close();
- };
- // This method is only for testing
- this.forceClose = function (millis) {
- Logger.debug("Testing: Force WebSocket close");
- if (millis) {
- Logger.debug("Testing: Change wsUri for " + millis + " millis to simulate net failure");
- var goodWsUri = wsUri;
- wsUri = "wss://21.234.12.34.4:443/";
- forcingDisconnection = true;
- setTimeout(function () {
- Logger.debug("Testing: Recover good wsUri " + goodWsUri);
- wsUri = goodWsUri;
- forcingDisconnection = false;
- }, millis);
- }
- ws.close();
- };
- this.reconnectWs = function () {
- Logger.debug("reconnectWs");
- reconnectToSameUri(MAX_RETRIES, 1, wsUri);
- };
- this.send = function (message) {
- ws.send(message);
- };
- this.addEventListener = function (type, callback) {
- registerMessageHandler = function () {
- ws.addEventListener(type, callback);
- };
- registerMessageHandler();
- };
-}
-module.exports = WebSocketWithReconnection;
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-
-},{}],45:[function(require,module,exports){
-/*
- * (C) Copyright 2014 Kurento (http://kurento.org/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-var defineProperty_IE8 = false;
-if (Object.defineProperty) {
- try {
- Object.defineProperty({}, "x", {});
- }
- catch (e) {
- defineProperty_IE8 = true;
- }
-}
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
-if (!Function.prototype.bind) {
- Function.prototype.bind = function (oThis) {
- if (typeof this !== 'function') {
- // closest thing possible to the ECMAScript 5
- // internal IsCallable function
- throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
- }
- var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () { }, fBound = function () {
- return fToBind.apply(this instanceof fNOP && oThis
- ? this
- : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
- };
- fNOP.prototype = this.prototype;
- fBound.prototype = new fNOP();
- return fBound;
- };
-}
-var EventEmitter = require('events').EventEmitter;
-var inherits = require('inherits');
-var packers = require('./packers');
-var Mapper = require('./Mapper');
-var BASE_TIMEOUT = 5000;
-function unifyResponseMethods(responseMethods) {
- if (!responseMethods)
- return {};
- for (var key in responseMethods) {
- var value = responseMethods[key];
- if (typeof value == 'string')
- responseMethods[key] =
- {
- response: value
- };
- }
- ;
- return responseMethods;
-}
-;
-function unifyTransport(transport) {
- if (!transport)
- return;
- // Transport as a function
- if (transport instanceof Function)
- return { send: transport };
- // WebSocket & DataChannel
- if (transport.send instanceof Function)
- return transport;
- // Message API (Inter-window & WebWorker)
- if (transport.postMessage instanceof Function) {
- transport.send = transport.postMessage;
- return transport;
- }
- // Stream API
- if (transport.write instanceof Function) {
- transport.send = transport.write;
- return transport;
- }
- // Transports that only can receive messages, but not send
- if (transport.onmessage !== undefined)
- return;
- if (transport.pause instanceof Function)
- return;
- throw new SyntaxError("Transport is not a function nor a valid object");
-}
-;
-/**
- * Representation of a RPC notification
- *
- * @class
- *
- * @constructor
- *
- * @param {String} method -method of the notification
- * @param params - parameters of the notification
- */
-function RpcNotification(method, params) {
- if (defineProperty_IE8) {
- this.method = method;
- this.params = params;
- }
- else {
- Object.defineProperty(this, 'method', { value: method, enumerable: true });
- Object.defineProperty(this, 'params', { value: params, enumerable: true });
- }
-}
-;
-/**
- * @class
- *
- * @constructor
- *
- * @param {object} packer
- *
- * @param {object} [options]
- *
- * @param {object} [transport]
- *
- * @param {Function} [onRequest]
- */
-function RpcBuilder(packer, options, transport, onRequest) {
- var self = this;
- if (!packer)
- throw new SyntaxError('Packer is not defined');
- if (!packer.pack || !packer.unpack)
- throw new SyntaxError('Packer is invalid');
- var responseMethods = unifyResponseMethods(packer.responseMethods);
- if (options instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = options;
- transport = undefined;
- options = undefined;
- }
- ;
- if (options && options.send instanceof Function) {
- if (transport && !(transport instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- onRequest = transport;
- transport = options;
- options = undefined;
- }
- ;
- if (transport instanceof Function) {
- if (onRequest != undefined)
- throw new SyntaxError("There can't be parameters after onRequest");
- onRequest = transport;
- transport = undefined;
- }
- ;
- if (transport && transport.send instanceof Function)
- if (onRequest && !(onRequest instanceof Function))
- throw new SyntaxError("Only a function can be after transport");
- options = options || {};
- EventEmitter.call(this);
- if (onRequest)
- this.on('request', onRequest);
- if (defineProperty_IE8)
- this.peerID = options.peerID;
- else
- Object.defineProperty(this, 'peerID', { value: options.peerID });
- var max_retries = options.max_retries || 0;
- function transportMessage(event) {
- self.decode(event.data || event);
- }
- ;
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- // Remove listener from old transport
- if (transport) {
- // W3C transports
- if (transport.removeEventListener)
- transport.removeEventListener('message', transportMessage);
- else if (transport.removeListener)
- transport.removeListener('data', transportMessage);
- }
- ;
- // Set listener on new transport
- if (value) {
- // W3C transports
- if (value.addEventListener)
- value.addEventListener('message', transportMessage);
- else if (value.addListener)
- value.addListener('data', transportMessage);
- }
- ;
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- this.setTransport(transport);
- var request_timeout = options.request_timeout || BASE_TIMEOUT;
- var ping_request_timeout = options.ping_request_timeout || request_timeout;
- var response_timeout = options.response_timeout || BASE_TIMEOUT;
- var duplicates_timeout = options.duplicates_timeout || BASE_TIMEOUT;
- var requestID = 0;
- var requests = new Mapper();
- var responses = new Mapper();
- var processedResponses = new Mapper();
- var message2Key = {};
- /**
- * Store the response to prevent to process duplicate request later
- */
- function storeResponse(message, id, dest) {
- var response = {
- message: message,
- /** Timeout to auto-clean old responses */
- timeout: setTimeout(function () {
- responses.remove(id, dest);
- }, response_timeout)
- };
- responses.set(response, id, dest);
- }
- ;
- /**
- * Store the response to ignore duplicated messages later
- */
- function storeProcessedResponse(ack, from) {
- var timeout = setTimeout(function () {
- processedResponses.remove(ack, from);
- }, duplicates_timeout);
- processedResponses.set(timeout, ack, from);
- }
- ;
- /**
- * Representation of a RPC request
- *
- * @class
- * @extends RpcNotification
- *
- * @constructor
- *
- * @param {String} method -method of the notification
- * @param params - parameters of the notification
- * @param {Integer} id - identifier of the request
- * @param [from] - source of the notification
- */
- function RpcRequest(method, params, id, from, transport) {
- RpcNotification.call(this, method, params);
- this.getTransport = function () {
- return transport;
- };
- this.setTransport = function (value) {
- transport = unifyTransport(value);
- };
- if (!defineProperty_IE8)
- Object.defineProperty(this, 'transport', {
- get: this.getTransport.bind(this),
- set: this.setTransport.bind(this)
- });
- var response = responses.get(id, from);
- /**
- * @constant {Boolean} duplicated
- */
- if (!(transport || self.getTransport())) {
- if (defineProperty_IE8)
- this.duplicated = Boolean(response);
- else
- Object.defineProperty(this, 'duplicated', {
- value: Boolean(response)
- });
- }
- var responseMethod = responseMethods[method];
- this.pack = packer.pack.bind(packer, this, id);
- /**
- * Generate a response to this request
- *
- * @param {Error} [error]
- * @param {*} [result]
- *
- * @returns {string}
- */
- this.reply = function (error, result, transport) {
- // Fix optional parameters
- if (error instanceof Function || error && error.send instanceof Function) {
- if (result != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = error;
- result = null;
- error = undefined;
- }
- else if (result instanceof Function
- || result && result.send instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- transport = result;
- result = null;
- }
- ;
- transport = unifyTransport(transport);
- // Duplicated request, remove old response timeout
- if (response)
- clearTimeout(response.timeout);
- if (from != undefined) {
- if (error)
- error.dest = from;
- if (result)
- result.dest = from;
- }
- ;
- var message;
- // New request or overriden one, create new response with provided data
- if (error || result != undefined) {
- if (self.peerID != undefined) {
- if (error)
- error.from = self.peerID;
- else
- result.from = self.peerID;
- }
- // Protocol indicates that responses has own request methods
- if (responseMethod) {
- if (responseMethod.error == undefined && error)
- message =
- {
- error: error
- };
- else {
- var method = error
- ? responseMethod.error
- : responseMethod.response;
- message =
- {
- method: method,
- params: error || result
- };
- }
- }
- else
- message =
- {
- error: error,
- result: result
- };
- message = packer.pack(message, id);
- }
- else if (response)
- message = response.message;
- else
- message = packer.pack({ result: null }, id);
- // Store the response to prevent to process a duplicated request later
- storeResponse(message, id, from);
- // Return the stored response so it can be directly send back
- transport = transport || this.getTransport() || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- }
- ;
- inherits(RpcRequest, RpcNotification);
- function cancel(message) {
- var key = message2Key[message];
- if (!key)
- return;
- delete message2Key[message];
- var request = requests.pop(key.id, key.dest);
- if (!request)
- return;
- clearTimeout(request.timeout);
- // Start duplicated responses timeout
- storeProcessedResponse(key.id, key.dest);
- }
- ;
- /**
- * Allow to cancel a request and don't wait for a response
- *
- * If `message` is not given, cancel all the request
- */
- this.cancel = function (message) {
- if (message)
- return cancel(message);
- for (var message in message2Key)
- cancel(message);
- };
- this.close = function () {
- // Prevent to receive new messages
- var transport = this.getTransport();
- if (transport && transport.close)
- transport.close();
- // Request & processed responses
- this.cancel();
- processedResponses.forEach(clearTimeout);
- // Responses
- responses.forEach(function (response) {
- clearTimeout(response.timeout);
- });
- };
- /**
- * Generates and encode a JsonRPC 2.0 message
- *
- * @param {String} method -method of the notification
- * @param params - parameters of the notification
- * @param [dest] - destination of the notification
- * @param {object} [transport] - transport where to send the message
- * @param [callback] - function called when a response to this request is
- * received. If not defined, a notification will be send instead
- *
- * @returns {string} A raw JsonRPC 2.0 request or notification string
- */
- this.encode = function (method, params, dest, transport, callback) {
- // Fix optional parameters
- if (params instanceof Function) {
- if (dest != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = params;
- transport = undefined;
- dest = undefined;
- params = undefined;
- }
- else if (dest instanceof Function) {
- if (transport != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = dest;
- transport = undefined;
- dest = undefined;
- }
- else if (transport instanceof Function) {
- if (callback != undefined)
- throw new SyntaxError("There can't be parameters after callback");
- callback = transport;
- transport = undefined;
- }
- ;
- if (self.peerID != undefined) {
- params = params || {};
- params.from = self.peerID;
- }
- ;
- if (dest != undefined) {
- params = params || {};
- params.dest = dest;
- }
- ;
- // Encode message
- var message = {
- method: method,
- params: params
- };
- if (callback) {
- var id = requestID++;
- var retried = 0;
- message = packer.pack(message, id);
- function dispatchCallback(error, result) {
- self.cancel(message);
- callback(error, result);
- }
- ;
- var request = {
- message: message,
- callback: dispatchCallback,
- responseMethods: responseMethods[method] || {}
- };
- var encode_transport = unifyTransport(transport);
- function sendRequest(transport) {
- var rt = (method === 'ping' ? ping_request_timeout : request_timeout);
- request.timeout = setTimeout(timeout, rt * Math.pow(2, retried++));
- message2Key[message] = { id: id, dest: dest };
- requests.set(request, id, dest);
- transport = transport || encode_transport || self.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- }
- ;
- function retry(transport) {
- transport = unifyTransport(transport);
- console.warn(retried + ' retry for request message:', message);
- var timeout = processedResponses.pop(id, dest);
- clearTimeout(timeout);
- return sendRequest(transport);
- }
- ;
- function timeout() {
- if (retried < max_retries)
- return retry(transport);
- var error = new Error('Request has timed out');
- error.request = message;
- error.retry = retry;
- dispatchCallback(error);
- }
- ;
- return sendRequest(transport);
- }
- ;
- // Return the packed message
- message = packer.pack(message);
- transport = transport || this.getTransport();
- if (transport)
- return transport.send(message);
- return message;
- };
- /**
- * Decode and process a JsonRPC 2.0 message
- *
- * @param {string} message - string with the content of the message
- *
- * @returns {RpcNotification|RpcRequest|undefined} - the representation of the
- * notification or the request. If a response was processed, it will return
- * `undefined` to notify that it was processed
- *
- * @throws {TypeError} - Message is not defined
- */
- this.decode = function (message, transport) {
- if (!message)
- throw new TypeError("Message is not defined");
- try {
- message = packer.unpack(message);
- }
- catch (e) {
- // Ignore invalid messages
- return console.debug(e, message);
- }
- ;
- var id = message.id;
- var ack = message.ack;
- var method = message.method;
- var params = message.params || {};
- var from = params.from;
- var dest = params.dest;
- // Ignore messages send by us
- if (self.peerID != undefined && from == self.peerID)
- return;
- // Notification
- if (id == undefined && ack == undefined) {
- var notification = new RpcNotification(method, params);
- if (self.emit('request', notification))
- return;
- return notification;
- }
- ;
- function processRequest() {
- // If we have a transport and it's a duplicated request, reply inmediatly
- transport = unifyTransport(transport) || self.getTransport();
- if (transport) {
- var response = responses.get(id, from);
- if (response)
- return transport.send(response.message);
- }
- ;
- var idAck = (id != undefined) ? id : ack;
- var request = new RpcRequest(method, params, idAck, from, transport);
- if (self.emit('request', request))
- return;
- return request;
- }
- ;
- function processResponse(request, error, result) {
- request.callback(error, result);
- }
- ;
- function duplicatedResponse(timeout) {
- console.warn("Response already processed", message);
- // Update duplicated responses timeout
- clearTimeout(timeout);
- storeProcessedResponse(ack, from);
- }
- ;
- // Request, or response with own method
- if (method) {
- // Check if it's a response with own method
- if (dest == undefined || dest == self.peerID) {
- var request = requests.get(ack, from);
- if (request) {
- var responseMethods = request.responseMethods;
- if (method == responseMethods.error)
- return processResponse(request, params);
- if (method == responseMethods.response)
- return processResponse(request, null, params);
- return processRequest();
- }
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- }
- // Request
- return processRequest();
- }
- ;
- var error = message.error;
- var result = message.result;
- // Ignore responses not send to us
- if (error && error.dest && error.dest != self.peerID)
- return;
- if (result && result.dest && result.dest != self.peerID)
- return;
- // Response
- var request = requests.get(ack, from);
- if (!request) {
- var processed = processedResponses.get(ack, from);
- if (processed)
- return duplicatedResponse(processed);
- return console.warn("No callback was defined for this message", message);
- }
- ;
- // Process response
- processResponse(request, error, result);
- };
-}
-;
-inherits(RpcBuilder, EventEmitter);
-RpcBuilder.RpcNotification = RpcNotification;
-module.exports = RpcBuilder;
-var clients = require('./clients');
-var transports = require('./clients/transports');
-RpcBuilder.clients = clients;
-RpcBuilder.clients.transports = transports;
-RpcBuilder.packers = packers;
-
-},{"./Mapper":40,"./clients":41,"./clients/transports":43,"./packers":48,"events":1,"inherits":6}],46:[function(require,module,exports){
-/**
- * JsonRPC 2.0 packer
- */
-/**
- * Pack a JsonRPC 2.0 message
- *
- * @param {Object} message - object to be packaged. It requires to have all the
- * fields needed by the JsonRPC 2.0 message that it's going to be generated
- *
- * @return {String} - the stringified JsonRPC 2.0 message
- */
-function pack(message, id) {
- var result = {
- jsonrpc: "2.0"
- };
- // Request
- if (message.method) {
- result.method = message.method;
- if (message.params)
- result.params = message.params;
- // Request is a notification
- if (id != undefined)
- result.id = id;
- }
- else if (id != undefined) {
- if (message.error) {
- if (message.result !== undefined)
- throw new TypeError("Both result and error are defined");
- result.error = message.error;
- }
- else if (message.result !== undefined)
- result.result = message.result;
- else
- throw new TypeError("No result or error is defined");
- result.id = id;
- }
- ;
- return JSON.stringify(result);
-}
-;
-/**
- * Unpack a JsonRPC 2.0 message
- *
- * @param {String} message - string with the content of the JsonRPC 2.0 message
- *
- * @throws {TypeError} - Invalid JsonRPC version
- *
- * @return {Object} - object filled with the JsonRPC 2.0 message content
- */
-function unpack(message) {
- var result = message;
- if (typeof message === 'string' || message instanceof String) {
- result = JSON.parse(message);
- }
- // Check if it's a valid message
- var version = result.jsonrpc;
- if (version !== '2.0')
- throw new TypeError("Invalid JsonRPC version '" + version + "': " + message);
- // Response
- if (result.method == undefined) {
- if (result.id == undefined)
- throw new TypeError("Invalid message: " + message);
- var result_defined = result.result !== undefined;
- var error_defined = result.error !== undefined;
- // Check only result or error is defined, not both or none
- if (result_defined && error_defined)
- throw new TypeError("Both result and error are defined: " + message);
- if (!result_defined && !error_defined)
- throw new TypeError("No result or error is defined: " + message);
- result.ack = result.id;
- delete result.id;
- }
- // Return unpacked message
- return result;
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],47:[function(require,module,exports){
-function pack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-function unpack(message) {
- throw new TypeError("Not yet implemented");
-}
-;
-exports.pack = pack;
-exports.unpack = unpack;
-
-},{}],48:[function(require,module,exports){
-var JsonRPC = require('./JsonRPC');
-var XmlRPC = require('./XmlRPC');
-exports.JsonRPC = JsonRPC;
-exports.XmlRPC = XmlRPC;
-
-},{"./JsonRPC":46,"./XmlRPC":47}],49:[function(require,module,exports){
-/*
- * (C) Copyright 2014-2015 Kurento (http://kurento.org/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-var freeice = require('freeice');
-var inherits = require('inherits');
-var UAParser = require('ua-parser-js');
-var uuid = require('uuid');
-var hark = require('hark');
-var EventEmitter = require('events').EventEmitter;
-var recursive = require('merge').recursive.bind(undefined, true);
-var sdpTranslator = require('sdp-translator');
-var logger = window.Logger || console;
-// var gUM = navigator.mediaDevices.getUserMedia || function (constraints) {
-// return new Promise(navigator.getUserMedia(constraints, function (stream) {
-// videoStream = stream
-// start()
-// }).eror(callback));
-// }
-/*try {
- require('kurento-browser-extensions')
-} catch (error) {
- if (typeof getScreenConstraints === 'undefined') {
- logger.warn('screen sharing is not available')
-
- getScreenConstraints = function getScreenConstraints(sendSource, callback) {
- callback(new Error("This library is not enabled for screen sharing"))
- }
- }
-}*/
-var MEDIA_CONSTRAINTS = {
- audio: true,
- video: {
- width: 640,
- framerate: 15
- }
-};
-// Somehow, the UAParser constructor gets an empty window object.
-// We need to pass the user agent string in order to get information
-var ua = (window && window.navigator) ? window.navigator.userAgent : '';
-var parser = new UAParser(ua);
-var browser = parser.getBrowser();
-var usePlanB = false;
-if (browser.name === 'Chrome' || browser.name === 'Chromium') {
- logger.debug(browser.name + ": using SDP PlanB");
- usePlanB = true;
-}
-function noop(error) {
- if (error)
- logger.error(error);
-}
-function trackStop(track) {
- track.stop && track.stop();
-}
-function streamStop(stream) {
- stream.getTracks().forEach(trackStop);
-}
-/**
- * Returns a string representation of a SessionDescription object.
- */
-var dumpSDP = function (description) {
- if (typeof description === 'undefined' || description === null) {
- return '';
- }
- return 'type: ' + description.type + '\r\n' + description.sdp;
-};
-function bufferizeCandidates(pc, onerror) {
- var candidatesQueue = [];
- pc.addEventListener('signalingstatechange', function () {
- if (this.signalingState === 'stable') {
- while (candidatesQueue.length) {
- var entry = candidatesQueue.shift();
- this.addIceCandidate(entry.candidate, entry.callback, entry.callback);
- }
- }
- });
- return function (candidate, callback) {
- callback = callback || onerror;
- switch (pc.signalingState) {
- case 'closed':
- callback(new Error('PeerConnection object is closed'));
- break;
- case 'stable':
- if (pc.remoteDescription) {
- pc.addIceCandidate(candidate, callback, callback);
- }
- break;
- default:
- candidatesQueue.push({
- candidate: candidate,
- callback: callback
- });
- }
- };
-}
-/* Simulcast utilities */
-function removeFIDFromOffer(sdp) {
- var n = sdp.indexOf("a=ssrc-group:FID");
- if (n > 0) {
- return sdp.slice(0, n);
- }
- else {
- return sdp;
- }
-}
-function getSimulcastInfo(videoStream) {
- var videoTracks = videoStream.getVideoTracks();
- if (!videoTracks.length) {
- logger.warn('No video tracks available in the video stream');
- return '';
- }
- var lines = [
- 'a=x-google-flag:conference',
- 'a=ssrc-group:SIM 1 2 3',
- 'a=ssrc:1 cname:localVideo',
- 'a=ssrc:1 msid:' + videoStream.id + ' ' + videoTracks[0].id,
- 'a=ssrc:1 mslabel:' + videoStream.id,
- 'a=ssrc:1 label:' + videoTracks[0].id,
- 'a=ssrc:2 cname:localVideo',
- 'a=ssrc:2 msid:' + videoStream.id + ' ' + videoTracks[0].id,
- 'a=ssrc:2 mslabel:' + videoStream.id,
- 'a=ssrc:2 label:' + videoTracks[0].id,
- 'a=ssrc:3 cname:localVideo',
- 'a=ssrc:3 msid:' + videoStream.id + ' ' + videoTracks[0].id,
- 'a=ssrc:3 mslabel:' + videoStream.id,
- 'a=ssrc:3 label:' + videoTracks[0].id
- ];
- lines.push('');
- return lines.join('\n');
-}
-/**
- * Wrapper object of an RTCPeerConnection. This object is aimed to simplify the
- * development of WebRTC-based applications.
- *
- * @constructor module:kurentoUtils.WebRtcPeer
- *
- * @param {String} mode Mode in which the PeerConnection will be configured.
- * Valid values are: 'recv', 'send', and 'sendRecv'
- * @param localVideo Video tag for the local stream
- * @param remoteVideo Video tag for the remote stream
- * @param {MediaStream} videoStream Stream to be used as primary source
- * (typically video and audio, or only video if combined with audioStream) for
- * localVideo and to be added as stream to the RTCPeerConnection
- * @param {MediaStream} audioStream Stream to be used as second source
- * (typically for audio) for localVideo and to be added as stream to the
- * RTCPeerConnection
- */
-function WebRtcPeer(mode, options, callback) {
- if (!(this instanceof WebRtcPeer)) {
- return new WebRtcPeer(mode, options, callback);
- }
- WebRtcPeer.super_.call(this);
- if (options instanceof Function) {
- callback = options;
- options = undefined;
- }
- options = options || {};
- callback = (callback || noop).bind(this);
- var self = this;
- var localVideo = options.localVideo;
- var remoteVideo = options.remoteVideo;
- var videoStream = options.videoStream;
- var audioStream = options.audioStream;
- var mediaConstraints = options.mediaConstraints;
- var connectionConstraints = options.connectionConstraints;
- var pc = options.peerConnection;
- var sendSource = options.sendSource || 'webcam';
- var dataChannelConfig = options.dataChannelConfig;
- var useDataChannels = options.dataChannels || false;
- var dataChannel;
- var guid = uuid.v4();
- var configuration = recursive({
- iceServers: freeice()
- }, options.configuration);
- var onicecandidate = options.onicecandidate;
- if (onicecandidate)
- this.on('icecandidate', onicecandidate);
- var oncandidategatheringdone = options.oncandidategatheringdone;
- if (oncandidategatheringdone) {
- this.on('candidategatheringdone', oncandidategatheringdone);
- }
- var simulcast = options.simulcast;
- var multistream = options.multistream;
- var interop = new sdpTranslator.Interop();
- var candidatesQueueOut = [];
- var candidategatheringdone = false;
- Object.defineProperties(this, {
- 'peerConnection': {
- get: function () {
- return pc;
- }
- },
- 'id': {
- value: options.id || guid,
- writable: false
- },
- 'remoteVideo': {
- get: function () {
- return remoteVideo;
- }
- },
- 'localVideo': {
- get: function () {
- return localVideo;
- }
- },
- 'dataChannel': {
- get: function () {
- return dataChannel;
- }
- },
- /**
- * @member {(external:ImageData|undefined)} currentFrame
- */
- 'currentFrame': {
- get: function () {
- // [ToDo] Find solution when we have a remote stream but we didn't set
- // a remoteVideo tag
- if (!remoteVideo)
- return;
- if (remoteVideo.readyState < remoteVideo.HAVE_CURRENT_DATA)
- throw new Error('No video stream data available');
- var canvas = document.createElement('canvas');
- canvas.width = remoteVideo.videoWidth;
- canvas.height = remoteVideo.videoHeight;
- canvas.getContext('2d').drawImage(remoteVideo, 0, 0);
- return canvas;
- }
- }
- });
- // Init PeerConnection
- if (!pc) {
- pc = new RTCPeerConnection(configuration);
- if (useDataChannels && !dataChannel) {
- var dcId = 'WebRtcPeer-' + self.id;
- var dcOptions = undefined;
- if (dataChannelConfig) {
- dcId = dataChannelConfig.id || dcId;
- dcOptions = dataChannelConfig.options;
- }
- dataChannel = pc.createDataChannel(dcId, dcOptions);
- if (dataChannelConfig) {
- dataChannel.onopen = dataChannelConfig.onopen;
- dataChannel.onclose = dataChannelConfig.onclose;
- dataChannel.onmessage = dataChannelConfig.onmessage;
- dataChannel.onbufferedamountlow = dataChannelConfig.onbufferedamountlow;
- dataChannel.onerror = dataChannelConfig.onerror || noop;
- }
- }
- }
- pc.addEventListener('icecandidate', function (event) {
- var candidate = event.candidate;
- if (EventEmitter.listenerCount(self, 'icecandidate') ||
- EventEmitter.listenerCount(self, 'candidategatheringdone')) {
- if (candidate) {
- var cand;
- if (multistream && usePlanB) {
- cand = interop.candidateToUnifiedPlan(candidate);
- }
- else {
- cand = candidate;
- }
- self.emit('icecandidate', cand);
- candidategatheringdone = false;
- }
- else if (!candidategatheringdone) {
- self.emit('candidategatheringdone');
- candidategatheringdone = true;
- }
- }
- else if (!candidategatheringdone) {
- // Not listening to 'icecandidate' or 'candidategatheringdone' events, queue
- // the candidate until one of them is listened
- candidatesQueueOut.push(candidate);
- if (!candidate)
- candidategatheringdone = true;
- }
- });
- pc.ontrack = options.onaddstream;
- pc.onnegotiationneeded = options.onnegotiationneeded;
- this.on('newListener', function (event, listener) {
- if (event === 'icecandidate' || event === 'candidategatheringdone') {
- while (candidatesQueueOut.length) {
- var candidate = candidatesQueueOut.shift();
- if (!candidate === (event === 'candidategatheringdone')) {
- listener(candidate);
- }
- }
- }
- });
- var addIceCandidate = bufferizeCandidates(pc);
- /**
- * Callback function invoked when an ICE candidate is received. Developers are
- * expected to invoke this function in order to complete the SDP negotiation.
- *
- * @function module:kurentoUtils.WebRtcPeer.prototype.addIceCandidate
- *
- * @param iceCandidate - Literal object with the ICE candidate description
- * @param callback - Called when the ICE candidate has been added.
- */
- this.addIceCandidate = function (iceCandidate, callback) {
- var candidate;
- if (multistream && usePlanB) {
- candidate = interop.candidateToPlanB(iceCandidate);
- }
- else {
- candidate = new RTCIceCandidate(iceCandidate);
- }
- logger.debug('Remote ICE candidate received', iceCandidate);
- callback = (callback || noop).bind(this);
- addIceCandidate(candidate, callback);
- };
- this.generateOffer = function (callback) {
- callback = callback.bind(this);
- var offerAudio = true;
- var offerVideo = true;
- // Constraints must have both blocks
- if (mediaConstraints) {
- offerAudio = (typeof mediaConstraints.audio === 'boolean') ?
- mediaConstraints.audio : true;
- offerVideo = (typeof mediaConstraints.video === 'boolean') ?
- mediaConstraints.video : true;
- }
- var browserDependantConstraints = {
- offerToReceiveAudio: (mode !== 'sendonly' && offerAudio),
- offerToReceiveVideo: (mode !== 'sendonly' && offerVideo)
- };
- //FIXME: clarify possible constraints passed to createOffer()
- /*var constraints = recursive(browserDependantConstraints,
- connectionConstraints)*/
- var constraints = browserDependantConstraints;
- logger.debug('constraints: ' + JSON.stringify(constraints));
- pc.createOffer(constraints).then(function (offer) {
- logger.debug('Created SDP offer');
- offer = mangleSdpToAddSimulcast(offer);
- return pc.setLocalDescription(offer);
- }).then(function () {
- var localDescription = pc.localDescription;
- logger.debug('Local description set', localDescription.sdp);
- if (multistream && usePlanB) {
- localDescription = interop.toUnifiedPlan(localDescription);
- logger.debug('offer::origPlanB->UnifiedPlan', dumpSDP(localDescription));
- }
- callback(null, localDescription.sdp, self.processAnswer.bind(self));
- }).catch(callback);
- };
- this.getLocalSessionDescriptor = function () {
- return pc.localDescription;
- };
- this.getRemoteSessionDescriptor = function () {
- return pc.remoteDescription;
- };
- function setRemoteVideo() {
- if (remoteVideo) {
- var stream = pc.getRemoteStreams()[0];
- var url = stream ? URL.createObjectURL(stream) : '';
- remoteVideo.pause();
- remoteVideo.src = url;
- remoteVideo.load();
- logger.debug('Remote URL:', url);
- }
- }
- this.showLocalVideo = function () {
- localVideo.src = URL.createObjectURL(videoStream);
- localVideo.muted = true;
- };
- this.send = function (data) {
- if (dataChannel && dataChannel.readyState === 'open') {
- dataChannel.send(data);
- }
- else {
- logger.warn('Trying to send data over a non-existing or closed data channel');
- }
- };
- /**
- * Callback function invoked when a SDP answer is received. Developers are
- * expected to invoke this function in order to complete the SDP negotiation.
- *
- * @function module:kurentoUtils.WebRtcPeer.prototype.processAnswer
- *
- * @param sdpAnswer - Description of sdpAnswer
- * @param callback -
- * Invoked after the SDP answer is processed, or there is an error.
- */
- this.processAnswer = function (sdpAnswer, callback) {
- callback = (callback || noop).bind(this);
- var answer = new RTCSessionDescription({
- type: 'answer',
- sdp: sdpAnswer
- });
- if (multistream && usePlanB) {
- var planBAnswer = interop.toPlanB(answer);
- logger.debug('asnwer::planB', dumpSDP(planBAnswer));
- answer = planBAnswer;
- }
- logger.debug('SDP answer received, setting remote description');
- if (pc.signalingState === 'closed') {
- return callback('PeerConnection is closed');
- }
- pc.setRemoteDescription(answer, function () {
- setRemoteVideo();
- callback();
- }, callback);
- };
- /**
- * Callback function invoked when a SDP offer is received. Developers are
- * expected to invoke this function in order to complete the SDP negotiation.
- *
- * @function module:kurentoUtils.WebRtcPeer.prototype.processOffer
- *
- * @param sdpOffer - Description of sdpOffer
- * @param callback - Called when the remote description has been set
- * successfully.
- */
- this.processOffer = function (sdpOffer, callback) {
- callback = callback.bind(this);
- var offer = new RTCSessionDescription({
- type: 'offer',
- sdp: sdpOffer
- });
- if (multistream && usePlanB) {
- var planBOffer = interop.toPlanB(offer);
- logger.debug('offer::planB', dumpSDP(planBOffer));
- offer = planBOffer;
- }
- logger.debug('SDP offer received, setting remote description');
- if (pc.signalingState === 'closed') {
- return callback('PeerConnection is closed');
- }
- pc.setRemoteDescription(offer).then(function () {
- return setRemoteVideo();
- }).then(function () {
- return pc.createAnswer();
- }).then(function (answer) {
- answer = mangleSdpToAddSimulcast(answer);
- logger.debug('Created SDP answer');
- return pc.setLocalDescription(answer);
- }).then(function () {
- var localDescription = pc.localDescription;
- if (multistream && usePlanB) {
- localDescription = interop.toUnifiedPlan(localDescription);
- logger.debug('answer::origPlanB->UnifiedPlan', dumpSDP(localDescription));
- }
- logger.debug('Local description set', localDescription.sdp);
- callback(null, localDescription.sdp);
- }).catch(callback);
- };
- function mangleSdpToAddSimulcast(answer) {
- if (simulcast) {
- if (browser.name === 'Chrome' || browser.name === 'Chromium') {
- logger.debug('Adding multicast info');
- answer = new RTCSessionDescription({
- 'type': answer.type,
- 'sdp': removeFIDFromOffer(answer.sdp) + getSimulcastInfo(videoStream)
- });
- }
- else {
- logger.warn('Simulcast is only available in Chrome browser.');
- }
- }
- return answer;
- }
- /**
- * This function creates the RTCPeerConnection object taking into account the
- * properties received in the constructor. It starts the SDP negotiation
- * process: generates the SDP offer and invokes the onsdpoffer callback. This
- * callback is expected to send the SDP offer, in order to obtain an SDP
- * answer from another peer.
- */
- function start() {
- if (pc.signalingState === 'closed') {
- callback('The peer connection object is in "closed" state. This is most likely due to an invocation of the dispose method before accepting in the dialogue');
- }
- if (videoStream && localVideo) {
- self.showLocalVideo();
- }
- if (videoStream) {
- pc.addStream(videoStream);
- }
- if (audioStream) {
- pc.addStream(audioStream);
- }
- // [Hack] https://code.google.com/p/chromium/issues/detail?id=443558
- var browser = parser.getBrowser();
- if (mode === 'sendonly' &&
- (browser.name === 'Chrome' || browser.name === 'Chromium') &&
- browser.major === 39) {
- mode = 'sendrecv';
- }
- callback();
- }
- if (mode !== 'recvonly' && !videoStream && !audioStream) {
- function getMedia(constraints) {
- if (constraints === undefined) {
- constraints = MEDIA_CONSTRAINTS;
- }
- navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
- videoStream = stream;
- start();
- }).catch(callback);
- }
- if (sendSource === 'webcam') {
- getMedia(mediaConstraints);
- }
- else {
- getScreenConstraints(sendSource, function (error, constraints_) {
- if (error)
- return callback(error);
- constraints = [mediaConstraints];
- constraints.unshift(constraints_);
- getMedia(recursive.apply(undefined, constraints));
- }, guid);
- }
- }
- else {
- setTimeout(start, 0);
- }
- this.on('_dispose', function () {
- if (localVideo) {
- localVideo.pause();
- localVideo.src = '';
- localVideo.load();
- //Unmute local video in case the video tag is later used for remote video
- localVideo.muted = false;
- }
- if (remoteVideo) {
- remoteVideo.pause();
- remoteVideo.src = '';
- remoteVideo.load();
- }
- self.removeAllListeners();
- if (window.cancelChooseDesktopMedia !== undefined) {
- window.cancelChooseDesktopMedia(guid);
- }
- });
-}
-inherits(WebRtcPeer, EventEmitter);
-function createEnableDescriptor(type) {
- var method = 'get' + type + 'Tracks';
- return {
- enumerable: true,
- get: function () {
- // [ToDo] Should return undefined if not all tracks have the same value?
- if (!this.peerConnection)
- return;
- var streams = this.peerConnection.getLocalStreams();
- if (!streams.length)
- return;
- for (var i = 0, stream; stream = streams[i]; i++) {
- var tracks = stream[method]();
- for (var j = 0, track; track = tracks[j]; j++)
- if (!track.enabled)
- return false;
- }
- return true;
- },
- set: function (value) {
- function trackSetEnable(track) {
- track.enabled = value;
- }
- this.peerConnection.getLocalStreams().forEach(function (stream) {
- stream[method]().forEach(trackSetEnable);
- });
- }
- };
-}
-Object.defineProperties(WebRtcPeer.prototype, {
- 'enabled': {
- enumerable: true,
- get: function () {
- return this.audioEnabled && this.videoEnabled;
- },
- set: function (value) {
- this.audioEnabled = this.videoEnabled = value;
- }
- },
- 'audioEnabled': createEnableDescriptor('Audio'),
- 'videoEnabled': createEnableDescriptor('Video')
-});
-WebRtcPeer.prototype.getLocalStream = function (index) {
- if (this.peerConnection) {
- return this.peerConnection.getLocalStreams()[index || 0];
- }
-};
-WebRtcPeer.prototype.getRemoteStream = function (index) {
- if (this.peerConnection) {
- return this.peerConnection.getRemoteStreams()[index || 0];
- }
-};
-/**
- * @description This method frees the resources used by WebRtcPeer.
- *
- * @function module:kurentoUtils.WebRtcPeer.prototype.dispose
- */
-WebRtcPeer.prototype.dispose = function () {
- logger.debug('Disposing WebRtcPeer');
- var pc = this.peerConnection;
- var dc = this.dataChannel;
- try {
- if (dc) {
- if (dc.signalingState === 'closed')
- return;
- dc.close();
- }
- if (pc) {
- if (pc.signalingState === 'closed')
- return;
- pc.getLocalStreams().forEach(streamStop);
- // FIXME This is not yet implemented in firefox
- // if(videoStream) pc.removeStream(videoStream);
- // if(audioStream) pc.removeStream(audioStream);
- pc.close();
- }
- }
- catch (err) {
- logger.warn('Exception disposing webrtc peer ' + err);
- }
- this.emit('_dispose');
-};
-//
-// Specialized child classes
-//
-function WebRtcPeerRecvonly(options, callback) {
- if (!(this instanceof WebRtcPeerRecvonly)) {
- return new WebRtcPeerRecvonly(options, callback);
- }
- WebRtcPeerRecvonly.super_.call(this, 'recvonly', options, callback);
-}
-inherits(WebRtcPeerRecvonly, WebRtcPeer);
-function WebRtcPeerSendonly(options, callback) {
- if (!(this instanceof WebRtcPeerSendonly)) {
- return new WebRtcPeerSendonly(options, callback);
- }
- WebRtcPeerSendonly.super_.call(this, 'sendonly', options, callback);
-}
-inherits(WebRtcPeerSendonly, WebRtcPeer);
-function WebRtcPeerSendrecv(options, callback) {
- if (!(this instanceof WebRtcPeerSendrecv)) {
- return new WebRtcPeerSendrecv(options, callback);
- }
- WebRtcPeerSendrecv.super_.call(this, 'sendrecv', options, callback);
-}
-inherits(WebRtcPeerSendrecv, WebRtcPeer);
-function harkUtils(stream, options) {
- return hark(stream, options);
-}
-exports.bufferizeCandidates = bufferizeCandidates;
-exports.WebRtcPeerRecvonly = WebRtcPeerRecvonly;
-exports.WebRtcPeerSendonly = WebRtcPeerSendonly;
-exports.WebRtcPeerSendrecv = WebRtcPeerSendrecv;
-exports.hark = harkUtils;
-
-},{"events":1,"freeice":2,"hark":5,"inherits":6,"merge":7,"sdp-translator":16,"ua-parser-js":20,"uuid":21}],50:[function(require,module,exports){
-/*
- * (C) Copyright 2014 Kurento (http://kurento.org/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-/**
- * This module contains a set of reusable components that have been found useful
- * during the development of the WebRTC applications with Kurento.
- *
- * @module kurentoUtils
- *
- * @copyright 2014 Kurento (http://kurento.org/)
- * @license ALv2
- */
-var WebRtcPeer = require('./WebRtcPeer');
-exports.WebRtcPeer = WebRtcPeer;
-
-},{"./WebRtcPeer":49}],51:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenVidu_1 = require("./OpenVidu");
-//This export with --standalone option allows using OpenVidu from bowser with namespace
-//export { OpenVidu } from './OpenVidu';
-//This "hack" allows to use OpenVidu from the global space window
-if (window) {
- window["OpenVidu"] = OpenVidu_1.OpenVidu;
-}
-//Command to generate bundle.js without namespace
-//watchify Main.ts -p [ tsify ] --exclude kurento-browser-extensions --debug -o ../static/js/OpenVidu.js -v
-
-},{"./OpenVidu":52}],52:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-/*
- * (C) Copyright 2017 OpenVidu (http://openvidu.io/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-var OpenViduInternal_1 = require("../OpenViduInternal/OpenViduInternal");
-var Session_1 = require("./Session");
-var Publisher_1 = require("./Publisher");
-var OpenViduError_1 = require("../OpenViduInternal/OpenViduError");
-var LocalRecorder_1 = require("../OpenViduInternal/LocalRecorder");
-var adapter = require("webrtc-adapter");
-var screenSharingAuto = require("../ScreenSharing/Screen-Capturing-Auto.js");
-var DetectRTC = require("../KurentoUtils/DetectRTC");
-if (window) {
- window["adapter"] = adapter;
-}
-var OpenVidu = /** @class */ (function () {
- function OpenVidu() {
- this.openVidu = new OpenViduInternal_1.OpenViduInternal();
- console.info("'OpenVidu' initialized");
- }
- ;
- OpenVidu.prototype.initSession = function (param1, param2) {
- if (typeof param2 == "string") {
- return new Session_1.Session(this.openVidu.initSession(param2), this);
- }
- else {
- return new Session_1.Session(this.openVidu.initSession(param1), this);
- }
- };
- OpenVidu.prototype.initPublisher = function (parentId, cameraOptions, callback) {
- var publisher;
- if (cameraOptions != null) {
- cameraOptions.audio = cameraOptions.audio != null ? cameraOptions.audio : true;
- cameraOptions.video = cameraOptions.video != null ? cameraOptions.video : true;
- if (!cameraOptions.screen) {
- // Webcam and/or microphone is being requested
- var cameraOptionsAux = {
- sendAudio: cameraOptions.audio != null ? cameraOptions.audio : true,
- sendVideo: cameraOptions.video != null ? cameraOptions.video : true,
- activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true,
- activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true,
- dataChannel: true,
- mediaConstraints: this.openVidu.generateMediaConstraints(cameraOptions)
- };
- cameraOptions = cameraOptionsAux;
- publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(parentId, cameraOptions, true, callback), parentId, false);
- console.info("'Publisher' initialized");
- return publisher;
- }
- else {
- // Screen share is being requested
- publisher = new Publisher_1.Publisher(this.openVidu.initPublisherScreen(parentId, true, callback), parentId, true);
- if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 52) {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- cameraOptions = {
- sendAudio: cameraOptions.audio,
- sendVideo: cameraOptions.video,
- activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true,
- activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true,
- dataChannel: true,
- mediaConstraints: {
- video: screenConstraints.video,
- audio: false
- }
- };
- publisher.stream.configureScreenOptions(cameraOptions);
- console.info("'Publisher' initialized");
- publisher.stream.ee.emitEvent('can-request-screen');
- });
- return publisher;
- }
- else if (DetectRTC.browser.name === 'Chrome') {
- // Screen is being requested
- /*screenSharing.isChromeExtensionAvailable((availability) => {
- switch (availability) {
- case 'available':
- console.warn('EXTENSION AVAILABLE!!!');
- screenSharing.getScreenConstraints((error, screenConstraints) => {
- if (!error) {
- console.warn(screenConstraints);
- }
- });
- break;
- case 'unavailable':
- console.warn('EXTENSION NOT AVAILABLE!!!');
- break;
- case 'isFirefox':
- console.warn('IT IS FIREFOX!!!');
- screenSharing.getScreenConstraints((error, screenConstraints) => {
- if (!error) {
- console.warn(screenConstraints);
- }
- });
- break;
- }
- });*/
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- if (error === 'not-installed') {
- var error_1 = new OpenViduError_1.OpenViduError("SCREEN_EXTENSION_NOT_INSTALLED" /* SCREEN_EXTENSION_NOT_INSTALLED */, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk');
- console.error(error_1);
- if (callback)
- callback(error_1);
- return;
- }
- else if (error === 'permission-denied') {
- var error_2 = new OpenViduError_1.OpenViduError("SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */, 'You must allow access to one window of your desktop');
- console.error(error_2);
- if (callback)
- callback(error_2);
- return;
- }
- cameraOptions = {
- sendAudio: cameraOptions.audio != null ? cameraOptions.audio : true,
- sendVideo: cameraOptions.video != null ? cameraOptions.video : true,
- activeAudio: cameraOptions.audioActive != null ? cameraOptions.audioActive : true,
- activeVideo: cameraOptions.videoActive != null ? cameraOptions.videoActive : true,
- dataChannel: true,
- mediaConstraints: {
- video: screenConstraints.video,
- audio: false
- }
- };
- publisher.stream.configureScreenOptions(cameraOptions);
- publisher.stream.ee.emitEvent('can-request-screen');
- }, function (error) {
- console.error('getScreenId error', error);
- return;
- });
- console.info("'Publisher' initialized");
- return publisher;
- }
- else {
- console.error('Screen sharing not supported on ' + DetectRTC.browser.name);
- if (!!callback)
- callback(new OpenViduError_1.OpenViduError("SCREEN_SHARING_NOT_SUPPORTED" /* SCREEN_SHARING_NOT_SUPPORTED */, 'Screen sharing not supported on ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version));
- }
- }
- }
- else {
- cameraOptions = {
- sendAudio: true,
- sendVideo: true,
- activeAudio: true,
- activeVideo: true,
- dataChannel: true,
- mediaConstraints: {
- audio: true,
- video: { width: { ideal: 1280 } }
- }
- };
- publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(parentId, cameraOptions, true, callback), parentId, false);
- console.info("'Publisher' initialized");
- return publisher;
- }
- };
- OpenVidu.prototype.reinitPublisher = function (publisher) {
- if (publisher.stream.typeOfVideo !== 'SCREEN') {
- publisher = new Publisher_1.Publisher(this.openVidu.initPublisherTagged(publisher.stream.getParentId(), publisher.stream.outboundOptions, false), publisher.stream.getParentId(), false);
- console.info("'Publisher' initialized");
- return publisher;
- }
- else {
- publisher = new Publisher_1.Publisher(this.openVidu.initPublisherScreen(publisher.stream.getParentId(), false), publisher.stream.getParentId(), true);
- if (DetectRTC.browser.name === 'Firefox' && DetectRTC.browser.version >= 52) {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- publisher.stream.outboundOptions.mediaConstraints.video = screenConstraints.video;
- publisher.stream.configureScreenOptions(publisher.stream.outboundOptions);
- console.info("'Publisher' initialized");
- publisher.stream.ee.emitEvent('can-request-screen');
- });
- return publisher;
- }
- else if (DetectRTC.browser.name === 'Chrome') {
- screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) {
- if (error === 'not-installed') {
- var error_3 = new OpenViduError_1.OpenViduError("SCREEN_EXTENSION_NOT_INSTALLED" /* SCREEN_EXTENSION_NOT_INSTALLED */, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk');
- console.error(error_3);
- return;
- }
- else if (error === 'permission-denied') {
- var error_4 = new OpenViduError_1.OpenViduError("SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */, 'You must allow access to one window of your desktop');
- console.error(error_4);
- return;
- }
- publisher.stream.outboundOptions.mediaConstraints.video = screenConstraints.video;
- publisher.stream.configureScreenOptions(publisher.stream.outboundOptions);
- publisher.stream.ee.emitEvent('can-request-screen');
- }, function (error) {
- console.error('getScreenId error', error);
- return;
- });
- console.info("'Publisher' initialized");
- return publisher;
- }
- else {
- console.error('Screen sharing not supported on ' + DetectRTC.browser.name);
- }
- }
- };
- OpenVidu.prototype.checkSystemRequirements = function () {
- var defaultWebRTCSupport = DetectRTC.isWebRTCSupported;
- var browser = DetectRTC.browser.name;
- var version = DetectRTC.browser.version;
- if ((browser !== 'Chrome') && (browser !== 'Firefox') && (browser !== 'Opera')) {
- return 0;
- }
- else {
- return defaultWebRTCSupport ? 1 : 0;
- }
- };
- OpenVidu.prototype.getDevices = function (callback) {
- navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) {
- callback(null, deviceInfos);
- }).catch(function (error) {
- console.error("Error getting devices", error);
- callback(error, null);
- });
- };
- OpenVidu.prototype.enableProdMode = function () {
- console.log = function () { };
- console.debug = function () { };
- console.info = function () { };
- console.warn = function () { };
- };
- OpenVidu.prototype.initLocalRecorder = function (stream) {
- return new LocalRecorder_1.LocalRecorder(stream);
- };
- return OpenVidu;
-}());
-exports.OpenVidu = OpenVidu;
-
-},{"../KurentoUtils/DetectRTC":39,"../OpenViduInternal/LocalRecorder":57,"../OpenViduInternal/OpenViduError":58,"../OpenViduInternal/OpenViduInternal":59,"../ScreenSharing/Screen-Capturing-Auto.js":63,"./Publisher":53,"./Session":54,"webrtc-adapter":26}],53:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var EventEmitter = require("wolfy87-eventemitter");
-var Publisher = /** @class */ (function () {
- function Publisher(stream, parentId, isScreenRequested) {
- var _this = this;
- this.ee = new EventEmitter();
- this.accessAllowed = false;
- this.isScreenRequested = false;
- this.stream = stream;
- this.isScreenRequested = isScreenRequested;
- // Listens to the deactivation of the default behaviour upon the deletion of a Stream object
- this.ee.addListener('stream-destroyed-default', function (event) {
- var s = event.stream;
- s.addOnceEventListener('video-removed', function () {
- _this.ee.emitEvent('videoElementDestroyed');
- });
- s.removeVideo();
- });
- if (document.getElementById(parentId) != null) {
- this.element = document.getElementById(parentId);
- }
- }
- Publisher.prototype.publishAudio = function (value) {
- this.stream.getWebRtcPeer().audioEnabled = value;
- };
- Publisher.prototype.publishVideo = function (value) {
- this.stream.getWebRtcPeer().videoEnabled = value;
- };
- Publisher.prototype.destroy = function () {
- if (!!this.session)
- this.session.unpublish(this);
- this.stream.dispose();
- this.stream.removeVideo(this.element);
- return this;
- };
- Publisher.prototype.subscribeToRemote = function () {
- this.stream.subscribeToMyRemote();
- };
- Publisher.prototype.on = function (eventName, callback) {
- var _this = this;
- this.ee.addListener(eventName, function (event) {
- if (event) {
- console.info("Event '" + eventName + "' triggered by 'Publisher'", event);
- }
- else {
- console.info("Event '" + eventName + "' triggered by 'Publisher'");
- }
- callback(event);
- });
- if (eventName == 'streamCreated') {
- if (this.stream.isPublisherPublished) {
- this.ee.emitEvent('streamCreated', [{ stream: this.stream }]);
- }
- else {
- this.stream.addEventListener('stream-created-by-publisher', function () {
- _this.ee.emitEvent('streamCreated', [{ stream: _this.stream }]);
- });
- }
- }
- if (eventName == 'videoElementCreated') {
- if (this.stream.isVideoELementCreated) {
- this.ee.emitEvent('videoElementCreated', [{
- element: this.stream.getVideoElement()
- }]);
- }
- else {
- this.stream.addEventListener('video-element-created-by-stream', function (element) {
- _this.id = element.id;
- _this.ee.emitEvent('videoElementCreated', [{
- element: element.element
- }]);
- });
- }
- }
- if (eventName == 'videoPlaying') {
- var video = this.stream.getVideoElement();
- if (!this.stream.displayMyRemote() && video &&
- video.currentTime > 0 &&
- video.paused == false &&
- video.ended == false &&
- video.readyState == 4) {
- this.ee.emitEvent('videoPlaying', [{
- element: this.stream.getVideoElement()
- }]);
- }
- else {
- this.stream.addEventListener('video-is-playing', function (element) {
- _this.ee.emitEvent('videoPlaying', [{
- element: element.element
- }]);
- });
- }
- }
- if (eventName == 'remoteVideoPlaying') {
- var video = this.stream.getVideoElement();
- if (this.stream.displayMyRemote() && video &&
- video.currentTime > 0 &&
- video.paused == false &&
- video.ended == false &&
- video.readyState == 4) {
- this.ee.emitEvent('remoteVideoPlaying', [{
- element: this.stream.getVideoElement()
- }]);
- }
- else {
- this.stream.addEventListener('remote-video-is-playing', function (element) {
- _this.ee.emitEvent('remoteVideoPlaying', [{
- element: element.element
- }]);
- });
- }
- }
- if (eventName == 'accessAllowed') {
- if (this.stream.accessIsAllowed) {
- this.ee.emitEvent('accessAllowed');
- }
- else {
- this.stream.addEventListener('access-allowed-by-publisher', function () {
- _this.ee.emitEvent('accessAllowed');
- });
- }
- }
- if (eventName == 'accessDenied') {
- if (this.stream.accessIsDenied) {
- this.ee.emitEvent('accessDenied');
- }
- else {
- this.stream.addEventListener('access-denied-by-publisher', function () {
- _this.ee.emitEvent('accessDenied');
- });
- }
- }
- };
- return Publisher;
-}());
-exports.Publisher = Publisher;
-
-},{"wolfy87-eventemitter":38}],54:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenViduError_1 = require("../OpenViduInternal/OpenViduError");
-var Subscriber_1 = require("./Subscriber");
-var EventEmitter = require("wolfy87-eventemitter");
-var DetectRTC = require("../KurentoUtils/DetectRTC");
-var Session = /** @class */ (function () {
- function Session(session, openVidu) {
- var _this = this;
- this.session = session;
- this.openVidu = openVidu;
- this.ee = new EventEmitter();
- this.sessionId = session.getSessionId();
- // Listens to the deactivation of the default behaviour upon the deletion of a Stream object
- this.session.addEventListener('stream-destroyed-default', function (event) {
- event.stream.removeVideo();
- });
- // Listens to the deactivation of the default behaviour upon the disconnection of a Session
- this.session.addEventListener('session-disconnected-default', function () {
- var s;
- for (var streamId in _this.session.getRemoteStreams()) {
- _this.session.getRemoteStreams()[streamId].removeVideo();
- }
- if (_this.connection && (Object.keys(_this.connection.getStreams()).length > 0)) {
- for (var streamId in _this.connection.getStreams()) {
- _this.connection.getStreams()[streamId].removeVideo();
- }
- }
- });
- // Sets or updates the value of 'connection' property. Triggered by SessionInternal when succesful connection
- this.session.addEventListener('update-connection-object', function (event) {
- _this.connection = event.connection;
- });
- }
- Session.prototype.connect = function (param1, param2, param3) {
- // Early configuration to deactivate automatic subscription to streams
- if (param3) {
- if (this.openVidu.checkSystemRequirements()) {
- this.session.configure({
- sessionId: this.session.getSessionId(),
- participantId: param1,
- metadata: this.session.stringClientMetadata(param2),
- subscribeToStreams: false
- });
- this.session.connect(param1, param3);
- }
- else {
- param3(new OpenViduError_1.OpenViduError("BROWSER_NOT_SUPPORTED" /* BROWSER_NOT_SUPPORTED */, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu'));
- }
- }
- else {
- if (this.openVidu.checkSystemRequirements()) {
- this.session.configure({
- sessionId: this.session.getSessionId(),
- participantId: param1,
- metadata: '',
- subscribeToStreams: false
- });
- this.session.connect(param1, param2);
- }
- else {
- param2(new OpenViduError_1.OpenViduError("BROWSER_NOT_SUPPORTED" /* BROWSER_NOT_SUPPORTED */, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu'));
- }
- }
- };
- Session.prototype.disconnect = function () {
- var _this = this;
- this.openVidu.openVidu.close(false);
- this.session.emitEvent('sessionDisconnected', [{
- preventDefault: function () { _this.session.removeEvent('session-disconnected-default'); }
- }]);
- this.session.emitEvent('session-disconnected-default', [{}]);
- };
- Session.prototype.publish = function (publisher) {
- var _this = this;
- if (!publisher.stream.isPublisherPublished) {
- if (publisher.isScreenRequested) {
- if (!publisher.stream.isScreenRequestedReady) {
- publisher.stream.addOnceEventListener('screen-ready', function () {
- _this.streamPublish(publisher);
- });
- }
- else {
- this.streamPublish(publisher);
- }
- }
- else {
- this.streamPublish(publisher);
- }
- }
- else {
- publisher = this.openVidu.reinitPublisher(publisher);
- if (publisher.isScreenRequested && !publisher.stream.isScreenRequestedReady) {
- publisher.stream.addOnceEventListener('screen-ready', function () {
- _this.streamPublish(publisher);
- });
- }
- else {
- this.streamPublish(publisher);
- }
- }
- };
- Session.prototype.streamPublish = function (publisher) {
- publisher.session = this;
- this.connection.addStream(publisher.stream);
- publisher.stream.publish();
- };
- Session.prototype.unpublish = function (publisher) {
- this.session.unpublish(publisher);
- };
- Session.prototype.on = function (eventName, callback) {
- this.session.addEventListener(eventName, function (event) {
- if (event) {
- console.info("Event '" + eventName + "' triggered by 'Session'", event);
- }
- else {
- console.info("Event '" + eventName + "' triggered by 'Session'");
- }
- callback(event);
- });
- };
- Session.prototype.once = function (eventName, callback) {
- this.session.addOnceEventListener(eventName, function (event) {
- callback(event);
- });
- };
- Session.prototype.off = function (eventName, eventHandler) {
- this.session.removeListener(eventName, eventHandler);
- };
- Session.prototype.subscribe = function (param1, param2, param3) {
- // Subscription
- this.session.subscribe(param1);
- var subscriber = new Subscriber_1.Subscriber(param1, param2);
- param1.playOnlyVideo(param2, null);
- return subscriber;
- };
- Session.prototype.unsubscribe = function (subscriber) {
- this.session.unsubscribe(subscriber.stream);
- subscriber.stream.removeVideo();
- };
- Session.prototype.signal = function (signal, completionHandler) {
- var signalMessage = {};
- if (signal.to && signal.to.length > 0) {
- var connectionIds = [];
- for (var i = 0; i < signal.to.length; i++) {
- connectionIds.push(signal.to[i].connectionId);
- }
- signalMessage['to'] = connectionIds;
- }
- else {
- signalMessage['to'] = [];
- }
- signalMessage['data'] = signal.data ? signal.data : '';
- signalMessage['type'] = signal.type ? signal.type : '';
- this.openVidu.openVidu.sendMessage(JSON.stringify(signalMessage));
- };
- return Session;
-}());
-exports.Session = Session;
-
-},{"../KurentoUtils/DetectRTC":39,"../OpenViduInternal/OpenViduError":58,"./Subscriber":55,"wolfy87-eventemitter":38}],55:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var EventEmitter = require("wolfy87-eventemitter");
-var Subscriber = /** @class */ (function () {
- function Subscriber(stream, parentId) {
- var _this = this;
- this.ee = new EventEmitter();
- this.stream = stream;
- if (document.getElementById(parentId) != null) {
- this.element = document.getElementById(parentId);
- }
- // Listens to deletion of the HTML video element of the Subscriber
- this.stream.addEventListener('video-removed', function () {
- _this.ee.emitEvent('videoElementDestroyed');
- });
- }
- Subscriber.prototype.on = function (eventName, callback) {
- var _this = this;
- this.ee.addListener(eventName, function (event) {
- if (event) {
- console.info("Event '" + eventName + "' triggered by 'Subscriber'", event);
- }
- else {
- console.info("Event '" + eventName + "' triggered by 'Subscriber'");
- }
- callback(event);
- });
- if (eventName == 'videoElementCreated') {
- if (this.stream.isVideoELementCreated) {
- this.ee.emitEvent('videoElementCreated', [{
- element: this.stream.getVideoElement()
- }]);
- }
- else {
- this.stream.addOnceEventListener('video-element-created-by-stream', function (element) {
- _this.id = element.id;
- _this.ee.emitEvent('videoElementCreated', [{
- element: element
- }]);
- });
- }
- }
- if (eventName == 'videoPlaying') {
- var video = this.stream.getVideoElement();
- if (!this.stream.displayMyRemote() && video &&
- video.currentTime > 0 &&
- video.paused == false &&
- video.ended == false &&
- video.readyState == 4) {
- this.ee.emitEvent('videoPlaying', [{
- element: this.stream.getVideoElement()
- }]);
- }
- else {
- this.stream.addOnceEventListener('video-is-playing', function (element) {
- _this.ee.emitEvent('videoPlaying', [{
- element: element.element
- }]);
- });
- }
- }
- };
- return Subscriber;
-}());
-exports.Subscriber = Subscriber;
-
-},{"wolfy87-eventemitter":38}],56:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var Stream_1 = require("./Stream");
-var Connection = /** @class */ (function () {
- function Connection(openVidu, local, room, options) {
- this.openVidu = openVidu;
- this.local = local;
- this.room = room;
- this.options = options;
- this.streams = {};
- console.info("'Connection' created (" + (local ? "local" : "remote") + ")" + (local ? "" : ", with 'connectionId' [" + (options ? options.id : '') + "] "));
- if (options && !local) {
- this.connectionId = options.id;
- if (options.metadata) {
- this.data = options.metadata;
- }
- if (options.streams) {
- this.initRemoteStreams(options);
- }
- }
- }
- Connection.prototype.addStream = function (stream) {
- stream.connection = this;
- this.streams[stream.streamId] = stream;
- //this.room.getStreams()[stream.streamId] = stream;
- };
- Connection.prototype.removeStream = function (key) {
- delete this.streams[key];
- //delete this.room.getStreams()[key];
- delete this.inboundStreamsOpts;
- };
- Connection.prototype.setOptions = function (options) {
- this.options = options;
- };
- Connection.prototype.getStreams = function () {
- return this.streams;
- };
- Connection.prototype.dispose = function () {
- for (var key in this.streams) {
- this.streams[key].dispose();
- }
- };
- Connection.prototype.sendIceCandidate = function (candidate) {
- console.debug((this.local ? "Local" : "Remote"), "candidate for", this.connectionId, JSON.stringify(candidate));
- this.openVidu.sendRequest("onIceCandidate", {
- endpointName: this.connectionId,
- candidate: candidate.candidate,
- sdpMid: candidate.sdpMid,
- sdpMLineIndex: candidate.sdpMLineIndex
- }, function (error, response) {
- if (error) {
- console.error("Error sending ICE candidate: "
- + JSON.stringify(error));
- }
- });
- };
- Connection.prototype.initRemoteStreams = function (options) {
- var opts;
- for (var _i = 0, _a = options.streams; _i < _a.length; _i++) {
- opts = _a[_i];
- var streamOptions = {
- id: opts.id,
- connection: this,
- recvAudio: (opts.audioActive == null ? true : opts.audioActive),
- recvVideo: (opts.videoActive == null ? true : opts.videoActive),
- typeOfVideo: opts.typeOfVideo,
- };
- var stream = new Stream_1.Stream(this.openVidu, false, this.room, streamOptions);
- this.addStream(stream);
- this.inboundStreamsOpts = streamOptions;
- }
- console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + "] is now configured for receiving Streams with options: ", this.inboundStreamsOpts);
- };
- return Connection;
-}());
-exports.Connection = Connection;
-
-},{"./Stream":61}],57:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var LocalRecoderState;
-(function (LocalRecoderState) {
- LocalRecoderState["READY"] = "READY";
- LocalRecoderState["RECORDING"] = "RECORDING";
- LocalRecoderState["PAUSED"] = "PAUSED";
- LocalRecoderState["FINISHED"] = "FINISHED";
-})(LocalRecoderState = exports.LocalRecoderState || (exports.LocalRecoderState = {}));
-var LocalRecorder = /** @class */ (function () {
- function LocalRecorder(stream) {
- this.chunks = [];
- this.count = 0;
- this.stream = stream;
- this.connectionId = (!!this.stream.connection) ? this.stream.connection.connectionId : 'default-connection';
- this.id = this.stream.streamId + '_' + this.connectionId + '_localrecord';
- this.state = "READY" /* READY */;
- }
- LocalRecorder.prototype.record = function () {
- var _this = this;
- if (typeof MediaRecorder === 'undefined') {
- console.error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder');
- throw (Error('MediaRecorder not supported on your browser. See compatibility in https://caniuse.com/#search=MediaRecorder'));
- }
- if (this.state !== "READY" /* READY */) {
- throw (Error('\'LocalRecord.record()\' needs \'LocalRecord.state\' to be \'READY\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.clean()\' or init a new LocalRecorder before'));
- }
- console.log("Starting local recording of stream '" + this.stream.streamId + "' of connection '" + this.connectionId + "'");
- if (typeof MediaRecorder.isTypeSupported == 'function') {
- var options = void 0;
- if (MediaRecorder.isTypeSupported('video/webm;codecs=vp9')) {
- options = { mimeType: 'video/webm;codecs=vp9' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=h264')) {
- options = { mimeType: 'video/webm;codecs=h264' };
- }
- else if (MediaRecorder.isTypeSupported('video/webm;codecs=vp8')) {
- options = { mimeType: 'video/webm;codecs=vp8' };
- }
- console.log('Using mimeType ' + options.mimeType);
- this.mediaRecorder = new MediaRecorder(this.stream.getMediaStream(), options);
- }
- else {
- console.warn('isTypeSupported is not supported, using default codecs for browser');
- this.mediaRecorder = new MediaRecorder(this.stream.getMediaStream());
- }
- this.mediaRecorder.start(10);
- this.mediaRecorder.ondataavailable = function (e) {
- _this.chunks.push(e.data);
- };
- this.mediaRecorder.onerror = function (e) {
- console.error('MediaRecorder error: ', e);
- };
- this.mediaRecorder.onstart = function () {
- console.log('MediaRecorder started (state=' + _this.mediaRecorder.state + ")");
- };
- this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- };
- this.mediaRecorder.onpause = function () {
- console.log('MediaRecorder paused (state=' + _this.mediaRecorder.state + ")");
- };
- this.mediaRecorder.onresume = function () {
- console.log('MediaRecorder resumed (state=' + _this.mediaRecorder.state + ")");
- };
- this.mediaRecorder.onwarning = function (e) {
- console.log('MediaRecorder warning: ' + e);
- };
- this.state = "RECORDING" /* RECORDING */;
- };
- LocalRecorder.prototype.stop = function () {
- var _this = this;
- return new Promise(function (resolve, reject) {
- try {
- if (_this.state === "READY" /* READY */ || _this.state === "FINISHED" /* FINISHED */) {
- throw (Error('\'LocalRecord.stop()\' needs \'LocalRecord.state\' to be \'RECORDING\' or \'PAUSED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.start()\' before'));
- }
- _this.mediaRecorder.onstop = function () {
- _this.onStopDefault();
- resolve();
- };
- }
- catch (e) {
- reject(e);
- }
- try {
- _this.mediaRecorder.stop();
- }
- catch (e) {
- reject(e);
- }
- });
- };
- LocalRecorder.prototype.pause = function () {
- if (this.state !== "RECORDING" /* RECORDING */) {
- throw (Error('\'LocalRecord.pause()\' needs \'LocalRecord.state\' to be \'RECORDING\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.start()\' or \'LocalRecorder.resume()\' before'));
- }
- this.mediaRecorder.pause();
- this.state = "PAUSED" /* PAUSED */;
- };
- LocalRecorder.prototype.resume = function () {
- if (this.state !== "PAUSED" /* PAUSED */) {
- throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.pause()\' before'));
- }
- this.mediaRecorder.resume();
- this.state = "RECORDING" /* RECORDING */;
- };
- LocalRecorder.prototype.preview = function (parentElement) {
- if (this.state !== "FINISHED" /* FINISHED */) {
- throw (Error('\'LocalRecord.preview()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- this.videoPreview = document.createElement('video');
- this.videoPreview.id = this.id;
- this.videoPreview.autoplay = true;
- if (typeof parentElement === "string") {
- this.htmlParentElementId = parentElement;
- var parentElementDom = document.getElementById(parentElement);
- if (parentElementDom) {
- this.videoPreview = parentElementDom.appendChild(this.videoPreview);
- }
- }
- else {
- this.htmlParentElementId = parentElement.id;
- this.videoPreview = parentElement.appendChild(this.videoPreview);
- }
- this.videoPreview.src = this.videoPreviewSrc;
- return this.videoPreview;
- };
- LocalRecorder.prototype.clean = function () {
- var _this = this;
- var f = function () {
- delete _this.blob;
- _this.chunks = [];
- _this.count = 0;
- delete _this.mediaRecorder;
- _this.state = "READY" /* READY */;
- };
- if (this.state === "RECORDING" /* RECORDING */ || this.state === "PAUSED" /* PAUSED */) {
- this.stop().then(function () { return f(); }).catch(function () { return f(); });
- }
- else {
- f();
- }
- };
- LocalRecorder.prototype.download = function () {
- if (this.state !== "FINISHED" /* FINISHED */) {
- throw (Error('\'LocalRecord.download()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var a = document.createElement("a");
- a.style.display = 'none';
- document.body.appendChild(a);
- var url = window.URL.createObjectURL(this.blob);
- a.href = url;
- a.download = this.id + '.webm';
- a.click();
- window.URL.revokeObjectURL(url);
- document.body.removeChild(a);
- }
- };
- LocalRecorder.prototype.getBlob = function () {
- if (this.state !== "FINISHED" /* FINISHED */) {
- throw (Error('Call \'LocalRecord.stop()\' before getting Blob file'));
- }
- else {
- return this.blob;
- }
- };
- LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== "FINISHED" /* FINISHED */) {
- reject(Error('\'LocalRecord.uploadAsBinary()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_1 = new XMLHttpRequest();
- http_1.open("POST", endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_1.setRequestHeader(key, headers[key]);
- }
- }
- http_1.onreadystatechange = function () {
- if (http_1.readyState === 4) {
- if (http_1.status.toString().charAt(0) === '2') {
- // Success response from server (HTTP status standard: 2XX is success)
- resolve(http_1.responseText);
- }
- else {
- reject(Error("Upload error: " + http_1.status));
- }
- }
- };
- http_1.send(_this.blob);
- }
- });
- };
- LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) {
- var _this = this;
- return new Promise(function (resolve, reject) {
- if (_this.state !== "FINISHED" /* FINISHED */) {
- reject(Error('\'LocalRecord.uploadAsMultipartfile()\' needs \'LocalRecord.state\' to be \'FINISHED\' (current value: \'' + _this.state + '\'). Call \'LocalRecorder.stop()\' before'));
- }
- else {
- var http_2 = new XMLHttpRequest();
- http_2.open("POST", endpoint, true);
- if (typeof headers === 'object') {
- for (var _i = 0, _a = Object.keys(headers); _i < _a.length; _i++) {
- var key = _a[_i];
- http_2.setRequestHeader(key, headers[key]);
- }
- }
- var sendable = new FormData();
- sendable.append("file", _this.blob, _this.id + ".webm");
- http_2.onreadystatechange = function () {
- if (http_2.readyState === 4) {
- if (http_2.status.toString().charAt(0) === '2') {
- // Success response from server (HTTP status standard: 2XX is success)
- resolve(http_2.responseText);
- }
- else {
- reject(Error("Upload error: " + http_2.status));
- }
- }
- };
- http_2.send(sendable);
- }
- });
- };
- LocalRecorder.prototype.onStopDefault = function () {
- console.log('MediaRecorder stopped (state=' + this.mediaRecorder.state + ")");
- this.blob = new Blob(this.chunks, { type: "video/webm" });
- this.chunks = [];
- this.videoPreviewSrc = window.URL.createObjectURL(this.blob);
- this.state = "FINISHED" /* FINISHED */;
- };
- return LocalRecorder;
-}());
-exports.LocalRecorder = LocalRecorder;
-
-},{}],58:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-var OpenViduErrorName;
-(function (OpenViduErrorName) {
- OpenViduErrorName["BROWSER_NOT_SUPPORTED"] = "BROWSER_NOT_SUPPORTED";
- OpenViduErrorName["CAMERA_ACCESS_DENIED"] = "CAMERA_ACCESS_DENIED";
- OpenViduErrorName["MICROPHONE_ACCESS_DENIED"] = "MICROPHONE_ACCESS_DENIED";
- OpenViduErrorName["SCREEN_CAPTURE_DENIED"] = "SCREEN_CAPTURE_DENIED";
- OpenViduErrorName["NO_VIDEO_DEVICE"] = "NO_VIDEO_DEVICE";
- OpenViduErrorName["NO_INPUT_DEVICE"] = "NO_INPUT_DEVICE";
- OpenViduErrorName["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED";
- OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED";
- OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR";
-})(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {}));
-var OpenViduError = /** @class */ (function () {
- function OpenViduError(name, message) {
- this.name = name;
- this.message = message;
- }
- return OpenViduError;
-}());
-exports.OpenViduError = OpenViduError;
-
-},{}],59:[function(require,module,exports){
-"use strict";
-Object.defineProperty(exports, "__esModule", { value: true });
-/*
- * (C) Copyright 2017 OpenVidu (http://openvidu.io/)
- *
- * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-var SessionInternal_1 = require("./SessionInternal");
-var OpenViduError_1 = require("./OpenViduError");
-var Stream_1 = require("./Stream");
-var RpcBuilder = require("../KurentoUtils/kurento-jsonrpc");
-var OpenViduInternal = /** @class */ (function () {
- function OpenViduInternal() {
- this.recorder = false;
- }
- /* NEW METHODS */
- OpenViduInternal.prototype.initSession = function (sessionId) {
- console.info("'Session' initialized with 'sessionId' [" + sessionId + "]");
- this.session = new SessionInternal_1.SessionInternal(this, sessionId);
- return this.session;
- };
- OpenViduInternal.prototype.initPublisherTagged = function (parentId, cameraOptions, newStream, callback) {
- var _this = this;
- if (newStream) {
- if (cameraOptions == null) {
- cameraOptions = {
- sendAudio: true,
- sendVideo: true,
- activeAudio: true,
- activeVideo: true,
- dataChannel: true,
- mediaConstraints: {
- audio: true,
- video: { width: { ideal: 1280 } }
- }
- };
- }
- this.localStream = new Stream_1.Stream(this, true, this.session, cameraOptions);
- }
- this.localStream.requestCameraAccess(function (error, localStream) {
- if (error) {
- // Neither localStream or microphone device is allowed/able to capture media
- console.error(error);
- if (callback) {
- callback(error);
- }
- _this.localStream.ee.emitEvent('access-denied-by-publisher');
- }
- else {
- _this.localStream.setVideoElement(_this.cameraReady(localStream, parentId));
- if (callback) {
- callback(undefined);
- }
- }
- });
- return this.localStream;
- };
- OpenViduInternal.prototype.initPublisherScreen = function (parentId, newStream, callback) {
- var _this = this;
- if (newStream) {
- this.localStream = new Stream_1.Stream(this, true, this.session, 'screen-options');
- }
- this.localStream.addOnceEventListener('can-request-screen', function () {
- _this.localStream.requestCameraAccess(function (error, localStream) {
- if (error) {
- _this.localStream.ee.emitEvent('access-denied-by-publisher');
- var errorName = "SCREEN_CAPTURE_DENIED" /* SCREEN_CAPTURE_DENIED */;
- var errorMessage = 'You must allow access to one window of your desktop';
- var e = new OpenViduError_1.OpenViduError(errorName, errorMessage);
- console.error(e);
- if (callback) {
- callback(e);
- }
- }
- else {
- _this.localStream.setVideoElement(_this.cameraReady(localStream, parentId));
- if (_this.localStream.getSendAudio()) {
- // If the user wants to send audio with the screen capturing
- navigator.mediaDevices.getUserMedia({ audio: true, video: false })
- .then(function (userStream) {
- _this.localStream.getMediaStream().addTrack(userStream.getAudioTracks()[0]);
- // Mute audio if 'activeAudio' property is false
- if (userStream.getAudioTracks()[0] != null) {
- userStream.getAudioTracks()[0].enabled = _this.localStream.outboundOptions.activeAudio;
- }
- _this.localStream.isScreenRequestedReady = true;
- _this.localStream.ee.emitEvent('screen-ready');
- if (callback) {
- callback(undefined);
- }
- })
- .catch(function (error) {
- _this.localStream.ee.emitEvent('access-denied-by-publisher');
- console.error("Error accessing the microphone", error);
- if (callback) {
- var errorName = "MICROPHONE_ACCESS_DENIED" /* MICROPHONE_ACCESS_DENIED */;
- var errorMessage = error.toString();
- callback(new OpenViduError_1.OpenViduError(errorName, errorMessage));
- }
- });
- }
- else {
- _this.localStream.isScreenRequestedReady = true;
- _this.localStream.ee.emitEvent('screen-ready');
- if (callback) {
- callback(undefined);
- }
- }
- }
- });
- });
- return this.localStream;
- };
- OpenViduInternal.prototype.cameraReady = function (localStream, parentId) {
- this.localStream = localStream;
- var videoElement = this.localStream.playOnlyVideo(parentId, null);
- this.localStream.emitStreamReadyEvent();
- return videoElement;
- };
- OpenViduInternal.prototype.getLocalStream = function () {
- return this.localStream;
- };
- /* NEW METHODS */
- OpenViduInternal.prototype.getWsUri = function () {
- return this.wsUri;
- };
- OpenViduInternal.prototype.setWsUri = function (wsUri) {
- this.wsUri = wsUri;
- };
- OpenViduInternal.prototype.getSecret = function () {
- return this.secret;
- };
- OpenViduInternal.prototype.setSecret = function (secret) {
- this.secret = secret;
- };
- OpenViduInternal.prototype.getRecorder = function () {
- return this.recorder;
- };
- OpenViduInternal.prototype.setRecorder = function (recorder) {
- this.recorder = recorder;
- };
- OpenViduInternal.prototype.getOpenViduServerURL = function () {
- return 'https://' + this.wsUri.split("wss://")[1].split("/room")[0];
- };
- OpenViduInternal.prototype.getRoom = function () {
- return this.session;
- };
- OpenViduInternal.prototype.connect = function (callback) {
- this.callback = callback;
- this.initJsonRpcClient(this.wsUri);
- };
- OpenViduInternal.prototype.initJsonRpcClient = function (wsUri) {
- var config = {
- heartbeat: 3000,
- sendCloseMessage: false,
- ws: {
- uri: wsUri,
- useSockJS: false,
- onconnected: this.connectCallback.bind(this),
- ondisconnect: this.disconnectCallback.bind(this),
- onreconnecting: this.reconnectingCallback.bind(this),
- onreconnected: this.reconnectedCallback.bind(this)
- },
- rpc: {
- requestTimeout: 15000,
- //notifications
- participantJoined: this.onParticipantJoined.bind(this),
- participantPublished: this.onParticipantPublished.bind(this),
- participantUnpublished: this.onParticipantUnpublished.bind(this),
- participantLeft: this.onParticipantLeft.bind(this),
- participantEvicted: this.onParticipantEvicted.bind(this),
- sendMessage: this.onNewMessage.bind(this),
- iceCandidate: this.iceCandidateEvent.bind(this),
- mediaError: this.onMediaError.bind(this),
- }
- };
- this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config);
- };
- OpenViduInternal.prototype.connectCallback = function (error) {
- if (error) {
- this.callback(error);
- }
- else {
- this.callback(null);
- }
- };
- OpenViduInternal.prototype.isRoomAvailable = function () {
- if (this.session !== undefined && this.session instanceof SessionInternal_1.SessionInternal) {
- return true;
- }
- else {
- console.warn('Session instance not found');
- return false;
- }
- };
- OpenViduInternal.prototype.disconnectCallback = function () {
- console.warn('Websocket connection lost');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenViduInternal.prototype.reconnectingCallback = function () {
- console.warn('Websocket connection lost (reconnecting)');
- if (this.isRoomAvailable()) {
- this.session.onLostConnection();
- }
- else {
- alert('Connection error. Please reload page.');
- }
- };
- OpenViduInternal.prototype.reconnectedCallback = function () {
- console.warn('Websocket reconnected');
- };
- OpenViduInternal.prototype.onParticipantJoined = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onParticipantJoined(params);
- }
- };
- OpenViduInternal.prototype.onParticipantPublished = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onParticipantPublished(params);
- }
- };
- OpenViduInternal.prototype.onParticipantUnpublished = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onParticipantUnpublished(params);
- }
- };
- OpenViduInternal.prototype.onParticipantLeft = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onParticipantLeft(params);
- }
- };
- OpenViduInternal.prototype.onParticipantEvicted = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onParticipantEvicted(params);
- }
- };
- OpenViduInternal.prototype.onNewMessage = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onNewMessage(params);
- }
- };
- OpenViduInternal.prototype.iceCandidateEvent = function (params) {
- if (this.isRoomAvailable()) {
- this.session.recvIceCandidate(params);
- }
- };
- OpenViduInternal.prototype.onRoomClosed = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onRoomClosed(params);
- }
- };
- OpenViduInternal.prototype.onMediaError = function (params) {
- if (this.isRoomAvailable()) {
- this.session.onMediaError(params);
- }
- };
- OpenViduInternal.prototype.setRpcParams = function (params) {
- this.rpcParams = params;
- };
- OpenViduInternal.prototype.sendRequest = function (method, params, callback) {
- if (params && params instanceof Function) {
- callback = params;
- params = undefined;
- }
- params = params || {};
- if (this.rpcParams && this.rpcParams !== null && this.rpcParams !== undefined) {
- for (var index in this.rpcParams) {
- if (this.rpcParams.hasOwnProperty(index)) {
- params[index] = this.rpcParams[index];
- console.debug('RPC param added to request {' + index + ': ' + this.rpcParams[index] + '}');
- }
- }
- }
- console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}');
- this.jsonRpcClient.send(method, params, callback);
- };
- OpenViduInternal.prototype.close = function (forced) {
- if (this.isRoomAvailable()) {
- this.session.leave(forced, this.jsonRpcClient);
- }
- };
- ;
- OpenViduInternal.prototype.disconnectParticipant = function (stream) {
- if (this.isRoomAvailable()) {
- this.session.disconnect(stream);
- }
- };
- //CHAT
- OpenViduInternal.prototype.sendMessage = function (message) {
- this.sendRequest('sendMessage', {
- message: message
- }, function (error, response) {
- if (error) {
- console.error(error);
- }
- });
- };
- ;
- OpenViduInternal.prototype.generateMediaConstraints = function (cameraOptions) {
- var mediaConstraints = {
- audio: cameraOptions.audio,
- video: {}
- };
- if (!cameraOptions.video) {
- mediaConstraints.video = false;
- }
- else {
- var w = void 0, h = void 0;
- switch (cameraOptions.quality) {
- case 'LOW':
- w = 320;
- h = 240;
- break;
- case 'MEDIUM':
- w = 640;
- h = 480;
- break;
- case 'HIGH':
- w = 1280;
- h = 720;
- break;
- default:
- w = 640;
- h = 480;
- }
- mediaConstraints.video['width'] = { exact: w };
- mediaConstraints.video['height'] = { exact: h };
- //mediaConstraints.video['frameRate'] = { ideal: Number((