webpackJsonp(["main"],{ /***/ "../../../../../openvidu-browser2/lib/OpenVidu/Connection.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var __1 = __webpack_require__("../../../../../openvidu-browser2/lib/index.js"); /** * Represents each one of the user's connection to the session (the local one and other user's connections). * Therefore each [[Session]] and [[Stream]] object has an attribute of type Connection */ var Connection = /** @class */ (function () { /** * @hidden */ function Connection(session, opts) { this.session = session; var msg = "'Connection' created "; if (!!opts) { msg += "(remote) with 'connectionId' [" + opts.id + ']'; } else { msg += '(local)'; } console.info(msg); this.options = opts; if (!!opts) { // Connection is remote this.connectionId = opts.id; if (opts.metadata) { this.data = opts.metadata; } if (opts.streams) { this.initRemoteStreams(opts.streams); } } this.creationTime = new Date().getTime(); } /* Hidden methods */ /** * @hidden */ Connection.prototype.sendIceCandidate = function (candidate) { console.debug((!!this.stream.outboundStreamOpts ? 'Local' : 'Remote'), 'candidate for', this.connectionId, JSON.stringify(candidate)); this.session.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)); } }); }; /** * @hidden */ Connection.prototype.initRemoteStreams = function (options) { var _this = this; // This is ready for supporting multiple streams per Connection object. Right now the loop will always run just once // this.stream should also be replaced by a collection of streams to support multiple streams per Connection options.forEach(function (opts) { var streamOptions = { id: opts.id, connection: _this, frameRate: opts.frameRate, recvAudio: opts.audioActive, recvVideo: opts.videoActive, typeOfVideo: opts.typeOfVideo }; var stream = new __1.Stream(_this.session, streamOptions); _this.addStream(stream); }); console.info("Remote 'Connection' with 'connectionId' [" + this.connectionId + '] is now configured for receiving Streams with options: ', this.stream.inboundStreamOpts); }; /** * @hidden */ Connection.prototype.addStream = function (stream) { stream.connection = this; this.stream = stream; }; /** * @hidden */ Connection.prototype.removeStream = function (streamId) { delete this.stream; }; /** * @hidden */ Connection.prototype.dispose = function () { if (!!this.stream) { this.stream.dispose(); delete this.stream; } }; return Connection; }()); exports.Connection = Connection; //# sourceMappingURL=Connection.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenVidu/LocalRecorder.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018-2018 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. * */ exports.__esModule = true; var LocalRecorderState_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/LocalRecorderState.js"); /** * Easy recording of [[Stream]] objects straightaway from the browser */ var LocalRecorder = /** @class */ (function () { /** * @hidden */ 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 = LocalRecorderState_1.LocalRecoderState.READY; } /** * Starts the recording of the Stream. [[state]] property must be `READY`. After method succeeds is set to `RECORDING` */ 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 !== LocalRecorderState_1.LocalRecoderState.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 = LocalRecorderState_1.LocalRecoderState.RECORDING; }; /** * Ends the recording of the Stream. [[state]] property must be `RECORDING` or `PAUSED`. After method succeeds is set to `FINISHED` * @returns Resolved _Error_ object is null if the method succeeds */ LocalRecorder.prototype.stop = function () { var _this = this; return new Promise(function (resolve, reject) { try { if (_this.state === LocalRecorderState_1.LocalRecoderState.READY || _this.state === LocalRecorderState_1.LocalRecoderState.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); } }); }; /** * Pauses the recording of the Stream. [[state]] property must be `RECORDING`. After method succeeds is set to `PAUSED` */ LocalRecorder.prototype.pause = function () { if (this.state !== LocalRecorderState_1.LocalRecoderState.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 = LocalRecorderState_1.LocalRecoderState.PAUSED; }; /** * Resumes the recording of the Stream. [[state]] property must be `PAUSED`. After method succeeds is set to `RECORDING` */ LocalRecorder.prototype.resume = function () { if (this.state !== LocalRecorderState_1.LocalRecoderState.PAUSED) { throw (Error('\'LocalRecord.resume()\' needs \'LocalRecord.state\' to be \'PAUSED\' (current value: \'' + this.state + '\'). Call \'LocalRecorder.pause()\' before')); } this.mediaRecorder.resume(); this.state = LocalRecorderState_1.LocalRecoderState.RECORDING; }; /** * Previews the recording, appending a new HTMLVideoElement to element with id `parentId`. [[state]] property must be `FINISHED` */ LocalRecorder.prototype.preview = function (parentElement) { if (this.state !== LocalRecorderState_1.LocalRecoderState.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; }; /** * Gracefully stops and cleans the current recording (WARNING: it is completely dismissed). Sets [[state]] to `READY` so the recording can start again */ LocalRecorder.prototype.clean = function () { var _this = this; var f = function () { delete _this.blob; _this.chunks = []; _this.count = 0; delete _this.mediaRecorder; _this.state = LocalRecorderState_1.LocalRecoderState.READY; }; if (this.state === LocalRecorderState_1.LocalRecoderState.RECORDING || this.state === LocalRecorderState_1.LocalRecoderState.PAUSED) { this.stop().then(function () { return f(); })["catch"](function () { return f(); }); } else { f(); } }; /** * Downloads the recorded video through the browser. [[state]] must be `FINISHED` */ LocalRecorder.prototype.download = function () { if (this.state !== LocalRecorderState_1.LocalRecoderState.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); } }; /** * Gets the raw Blob file. Methods preview, download, uploadAsBinary and uploadAsMultipartfile use this same file to perform their specific actions. [[state]] property must be `FINISHED` */ LocalRecorder.prototype.getBlob = function () { if (this.state !== LocalRecorderState_1.LocalRecoderState.FINISHED) { throw (Error('Call \'LocalRecord.stop()\' before getting Blob file')); } else { return this.blob; } }; /** * Uploads the recorded video as a binary file performing an HTTP/POST operation to URL `endpoint`. Optional HTTP headers can be passed as second parameter. For example: * ``` * var headers = { * "Cookie": "$Version=1; Skin=new;", * "Authorization":"Basic QWxhZGpbjpuIHNlctZQ==" * } * ``` * LocalRecorder.state must be `FINISHED` */ LocalRecorder.prototype.uploadAsBinary = function (endpoint, headers) { var _this = this; return new Promise(function (resolve, reject) { if (_this.state !== LocalRecorderState_1.LocalRecoderState.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); } }); }; /** * Uploads the recorded video as a multipart file performing an HTTP/POST operation to URL `endpoint`. Optional HTTP headers can be passed as second parameter. For example: * ``` * var headers = { * "Cookie": "$Version=1; Skin=new;", * "Authorization":"Basic QWxhZGpbjpuIHNlctZQ==" * } * ``` * LocalRecorder.state must be `FINISHED` */ LocalRecorder.prototype.uploadAsMultipartfile = function (endpoint, headers) { var _this = this; return new Promise(function (resolve, reject) { if (_this.state !== LocalRecorderState_1.LocalRecoderState.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 = LocalRecorderState_1.LocalRecoderState.FINISHED; }; return LocalRecorder; }()); exports.LocalRecorder = LocalRecorder; //# sourceMappingURL=LocalRecorder.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenVidu/OpenVidu.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var __1 = __webpack_require__("../../../../../openvidu-browser2/lib/index.js"); var OpenViduError_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/OpenViduError.js"); var VideoInsertMode_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/VideoInsertMode.js"); var DetectRTC = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/DetectRTC/DetectRTC.js"); var RpcBuilder = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/index.js"); var screenSharingAuto = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/ScreenSharing/Screen-Capturing-Auto.js"); var SECRET_PARAM = '?secret='; var RECORDER_PARAM = '&recorder='; /** * Entrypoint of OpenVidu Browser library. * Use it to initialize objects of type [[Session]], [[Publisher]] and [[LocalRecorder]] */ var OpenVidu = /** @class */ (function () { function OpenVidu() { this.recorder = false; console.info("'OpenVidu' initialized"); } /** * Returns a session with id `sessionId` * @param sessionId Session unique ID generated in openvidu-server * @param callback */ OpenVidu.prototype.initSession = function (sessionId) { this.session = new __1.Session(sessionId, this); return this.session; }; /** * Returns a new publisher * @param parentId id of HTML element in which the video element of the Publisher will be appended. If null or undefined no default video will be created for this Publisher * @param completionHandler `error` parameter is null if `initPublisher` succeeds, and is defined if it fails. * `completionHandler` function is called before the Publisher dispatches an `accessAllowed` or an `accessDenied` event */ OpenVidu.prototype.initPublisher = function (targetElement, properties, completionHandler) { if (!!properties) { properties = { audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, frameRate: (typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined, insertMode: (typeof properties.insertMode !== 'undefined') ? properties.insertMode : VideoInsertMode_1.VideoInsertMode.APPEND, mirror: (typeof properties.mirror !== 'undefined') ? properties.mirror : true, publishAudio: (typeof properties.publishAudio !== 'undefined') ? properties.publishAudio : true, publishVideo: (typeof properties.publishVideo !== 'undefined') ? properties.publishVideo : true, resolution: (typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480', videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined }; } else { properties = { insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, mirror: true, publishAudio: true, publishVideo: true, resolution: '640x480' }; } var publisher = new __1.Publisher(targetElement, properties, this); publisher.initialize() .then(function () { if (!!completionHandler) { completionHandler(undefined); } })["catch"](function (error) { if (!!completionHandler) { completionHandler(error); } }); return publisher; }; /** * Returns a new local recorder for recording streams straightaway from the browser * @param stream Stream to record */ OpenVidu.prototype.initLocalRecorder = function (stream) { return new __1.LocalRecorder(stream); }; /** * Check if the browser supports WebRTC * @returns 1 if the browser supports WebRTC, 0 otherwise */ 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') && (browser !== 'Safari')) { return 0; } else { return defaultWebRTCSupport ? 1 : 0; } }; /** * Collects information about the media input devices available on the system. You can pass property `deviceId` of a [[Device]] object as value of `audioSource` or `videoSource` properties in [[initPublisher]] method */ OpenVidu.prototype.getDevices = function () { return new Promise(function (resolve, reject) { navigator.mediaDevices.enumerateDevices().then(function (deviceInfos) { var devices = []; deviceInfos.forEach(function (deviceInfo) { if (deviceInfo.kind === 'audioinput' || deviceInfo.kind === 'videoinput') { devices.push({ kind: deviceInfo.kind, deviceId: deviceInfo.deviceId, label: deviceInfo.label }); } }); resolve(devices); })["catch"](function (error) { console.error('Error getting devices', error); reject(error); }); }); }; /** * Get a MediaStream object that you can customize before calling [[initPublisher]] (pass _MediaStreamTrack_ properties of the _MediaStream_ value returned by the Promise as `audioSource` or `videoSource` properties in [[initPublisher]]) */ OpenVidu.prototype.getUserMedia = function (options) { var _this = this; return new Promise(function (resolve, reject) { _this.generateMediaConstraints(options) .then(function (constraints) { navigator.mediaDevices.getUserMedia(constraints) .then(function (mediaStream) { resolve(mediaStream); })["catch"](function (error) { var errorName; var errorMessage = error.toString(); if (!(options.videoSource === 'screen')) { errorName = (options.videoSource === false || options.videoSource === null) ? OpenViduError_1.OpenViduErrorName.MICROPHONE_ACCESS_DENIED : OpenViduError_1.OpenViduErrorName.CAMERA_ACCESS_DENIED; } else { errorName = OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED; } reject(new OpenViduError_1.OpenViduError(errorName, errorMessage)); }); })["catch"](function (error) { reject(error); }); }); }; /* tslint:disable:no-empty */ /** * Disable all logging except error level */ OpenVidu.prototype.enableProdMode = function () { console.log = function () { }; console.debug = function () { }; console.info = function () { }; console.warn = function () { }; }; /* tslint:enable:no-empty */ /* Private methods */ OpenVidu.prototype.disconnectCallback = function () { console.warn('Websocket connection lost'); if (this.isRoomAvailable()) { this.session.onLostConnection(); } else { alert('Connection error. Please reload page.'); } }; OpenVidu.prototype.reconnectingCallback = function () { console.warn('Websocket connection lost (reconnecting)'); if (this.isRoomAvailable()) { this.session.onLostConnection(); } else { alert('Connection error. Please reload page.'); } }; OpenVidu.prototype.reconnectedCallback = function () { console.warn('Websocket reconnected'); }; OpenVidu.prototype.isRoomAvailable = function () { if (this.session !== undefined && this.session instanceof __1.Session) { return true; } else { console.warn('Session instance not found'); return false; } }; OpenVidu.prototype.getSecretFromUrl = function (url) { var secret = ''; if (url.indexOf(SECRET_PARAM) !== -1) { var endOfSecret = url.lastIndexOf(RECORDER_PARAM); if (endOfSecret !== -1) { secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, endOfSecret); } else { secret = url.substring(url.lastIndexOf(SECRET_PARAM) + SECRET_PARAM.length, url.length); } } return secret; }; OpenVidu.prototype.getRecorderFromUrl = function (url) { var recorder = ''; if (url.indexOf(RECORDER_PARAM) !== -1) { recorder = url.substring(url.lastIndexOf(RECORDER_PARAM) + RECORDER_PARAM.length, url.length); } return Boolean(recorder).valueOf(); }; OpenVidu.prototype.getFinalWsUrl = function (url) { url = this.getUrlWithoutSecret(url).substring(0, url.lastIndexOf('/')) + '/room'; if (url.indexOf('.ngrok.io') !== -1) { // OpenVidu server URL referes to a ngrok IP: secure wss protocol and delete port of URL url = url.replace('ws://', 'wss://'); var regex = /\.ngrok\.io:\d+/; url = url.replace(regex, '.ngrok.io'); } else if ((url.indexOf('localhost') !== -1) || (url.indexOf('127.0.0.1') !== -1)) { // OpenVidu server URL referes to localhost IP } return url; }; /* Hidden methods */ /** * @hidden */ OpenVidu.prototype.getUrlWithoutSecret = function (url) { if (!url) { console.error('sessionId is not defined'); } if (url.indexOf(SECRET_PARAM) !== -1) { url = url.substring(0, url.lastIndexOf(SECRET_PARAM)); } return url; }; /** * @hidden */ OpenVidu.prototype.generateMediaConstraints = function (publisherProperties) { return new Promise(function (resolve, reject) { var audio, video; if (publisherProperties.audioSource === null || publisherProperties.audioSource === false) { audio = false; } else if (publisherProperties.audioSource === undefined) { audio = true; } else { audio = publisherProperties.audioSource; } if (publisherProperties.videoSource === null || publisherProperties.videoSource === false) { video = false; } else { video = { height: { ideal: 480 }, width: { ideal: 640 } }; } var mediaConstraints = { audio: audio, video: video }; if (typeof mediaConstraints.audio === 'string') { mediaConstraints.audio = { deviceId: { exact: mediaConstraints.audio } }; } if (mediaConstraints.video) { if (!!publisherProperties.resolution) { var widthAndHeight = publisherProperties.resolution.toLowerCase().split('x'); var width = Number(widthAndHeight[0]); var height = Number(widthAndHeight[1]); mediaConstraints.video.width.ideal = width; mediaConstraints.video.height.ideal = height; } if (!!publisherProperties.frameRate) { mediaConstraints.video.frameRate = { ideal: publisherProperties.frameRate }; } if (!!publisherProperties.videoSource && typeof publisherProperties.videoSource === 'string') { if (publisherProperties.videoSource === 'screen') { screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { if (!!error) { if (error === 'not-installed') { var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); console.error(error_1); reject(error_1); } else if (error === 'permission-denied') { var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); console.error(error_2); reject(error_2); } } else { mediaConstraints.video = screenConstraints.video; resolve(mediaConstraints); } }); } else { // tslint:disable-next-line:no-string-literal mediaConstraints.video['deviceId'] = { exact: publisherProperties.videoSource }; resolve(mediaConstraints); } } else { resolve(mediaConstraints); } } else { resolve(mediaConstraints); } }); }; /** * @hidden */ OpenVidu.prototype.startWs = function (onConnectSucces) { var config = { heartbeat: 40000, sendCloseMessage: false, ws: { uri: this.wsUri, useSockJS: false, onconnected: onConnectSucces, ondisconnect: this.disconnectCallback.bind(this), onreconnecting: this.reconnectingCallback.bind(this), onreconnected: this.reconnectedCallback.bind(this) }, rpc: { requestTimeout: 15000, participantJoined: this.session.onParticipantJoined.bind(this.session), participantPublished: this.session.onParticipantPublished.bind(this.session), participantUnpublished: this.session.onParticipantUnpublished.bind(this.session), participantLeft: this.session.onParticipantLeft.bind(this.session), participantEvicted: this.session.onParticipantEvicted.bind(this.session), sendMessage: this.session.onNewMessage.bind(this.session), iceCandidate: this.session.recvIceCandidate.bind(this.session), mediaError: this.session.onMediaError.bind(this.session) } }; this.jsonRpcClient = new RpcBuilder.clients.JsonRpcClient(config); }; /** * @hidden */ OpenVidu.prototype.processOpenViduUrl = function (url) { var secret = this.getSecretFromUrl(url); var recorder = this.getRecorderFromUrl(url); if (!!secret) { this.secret = secret; } if (!!recorder) { this.recorder = recorder; } this.wsUri = this.getFinalWsUrl(url); }; /** * @hidden */ OpenVidu.prototype.sendRequest = function (method, params, callback) { if (params && params instanceof Function) { callback = params; params = {}; } console.debug('Sending request: {method:"' + method + '", params: ' + JSON.stringify(params) + '}'); this.jsonRpcClient.send(method, params, callback); }; /** * @hidden */ OpenVidu.prototype.close = function (forced) { if (this.isRoomAvailable()) { this.session.leave(forced, this.jsonRpcClient); } }; /** * @hidden */ OpenVidu.prototype.getWsUri = function () { return this.wsUri; }; /** * @hidden */ OpenVidu.prototype.getSecret = function () { return this.secret; }; /** * @hidden */ OpenVidu.prototype.getRecorder = function () { return this.recorder; }; return OpenVidu; }()); exports.OpenVidu = OpenVidu; //# sourceMappingURL=OpenVidu.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenVidu/Publisher.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var __1 = __webpack_require__("../../../../../openvidu-browser2/lib/index.js"); var OpenViduError_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/OpenViduError.js"); var EventEmitter = __webpack_require__("../../../../../openvidu-browser2/node_modules/wolfy87-eventemitter/EventEmitter.js"); /** * Packs local media streams. Participants can publish it to a session. Initialized with [[OpenVidu.initPublisher]] method */ var Publisher = /** @class */ (function () { /** * @hidden */ function Publisher(targetElement, properties, openvidu) { var _this = this; this.openvidu = openvidu; this.accessAllowed = false; this.ee = new EventEmitter(); this.properties = properties; this.stream = new __1.Stream(this.session, { publisherProperties: properties, mediaConstraints: {} }); // Default behaviour upon the disposal of a Stream: // destroy video element and dispatch 'videoElementDestroyed' ('event.preventDefault()' removes this listener) this.ee.on('stream-destroyed-default', function (event) { var s = event.stream; s.once('video-removed', function () { _this.ee.emitEvent('videoElementDestroyed'); }); s.removeVideo(); }); if (typeof targetElement === 'string') { var e = document.getElementById(targetElement); if (!!e) { this.element = e; } } else if (targetElement instanceof HTMLElement) { this.element = targetElement; } if (!this.element) { console.warn("The provided 'targetElement' for the Publisher couldn't be resolved to any HTML element: " + targetElement); } } Publisher.prototype.publishAudio = function (value) { this.stream.getWebRtcPeer().audioEnabled = value; console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its audio stream'); }; Publisher.prototype.publishVideo = function (value) { this.stream.getWebRtcPeer().videoEnabled = value; console.info("'Publisher' has " + (value ? 'published' : 'unpublished') + ' its video stream'); }; Publisher.prototype.on = function (type, handler) { var _this = this; this.ee.on(type, function (event) { if (event) { console.info("Event '" + type + "' triggered by 'Publisher'", event); } else { console.info("Event '" + type + "' triggered by 'Publisher'"); } handler(event); }); if (type === 'streamCreated') { if (!!this.stream && this.stream.isPublisherPublished) { this.ee.emitEvent('streamCreated', [{ stream: this.stream }]); } else { this.stream.on('stream-created-by-publisher', function () { _this.ee.emitEvent('streamCreated', [{ stream: _this.stream }]); }); } } if (type === 'videoElementCreated') { if (!!this.stream && this.stream.isVideoELementCreated) { this.ee.emitEvent('videoElementCreated', [{ element: this.stream.getVideoElement() }]); } else { this.stream.on('video-element-created-by-stream', function (element) { _this.id = element.id; _this.ee.emitEvent('videoElementCreated', [{ element: element.element }]); }); } } if (type === '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.on('video-is-playing', function (element) { _this.ee.emitEvent('videoPlaying', [{ element: element.element }]); }); } } if (type === '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.on('remote-video-is-playing', function (element) { _this.ee.emitEvent('remoteVideoPlaying', [{ element: element.element }]); }); } } if (type === 'accessAllowed') { if (this.stream.accessIsAllowed) { this.ee.emitEvent('accessAllowed'); } } if (type === 'accessDenied') { if (this.stream.accessIsDenied) { this.ee.emitEvent('accessDenied'); } } }; Publisher.prototype.once = function (type, handler) { this.ee.once(type, function (event) { if (event) { console.info("Event '" + type + "' triggered by 'Publisher'", event); } else { console.info("Event '" + type + "' triggered by 'Publisher'"); } handler(event); }); }; Publisher.prototype.off = function (type, eventHandler) { this.ee.off(type, eventHandler); }; /* Private methods */ Publisher.prototype.userMediaHasVideo = function (callback) { var _this = this; return new Promise(function (resolve, reject) { // If the user is going to publish its screen there's a video source if (_this.properties.videoSource === 'screen') { resolve(true); } else { _this.openvidu.getDevices() .then(function (devices) { resolve(!!(devices.filter(function (device) { return device.kind === 'videoinput'; })[0])); })["catch"](function (error) { reject(error); }); } }); }; Publisher.prototype.userMediaHasAudio = function (callback) { var _this = this; return new Promise(function (resolve, reject) { _this.openvidu.getDevices() .then(function (devices) { resolve(!!(devices.filter(function (device) { return device.kind === 'audioinput'; })[0])); })["catch"](function (error) { reject(error); }); }); }; /* Hidden methods */ /** * @hidden */ Publisher.prototype.initialize = function () { var _this = this; return new Promise(function (resolve, reject) { var errorCallback = function (openViduError) { _this.stream.accessIsDenied = true; _this.stream.accessIsAllowed = false; _this.ee.emitEvent('accessDenied'); reject(openViduError); }; var successCallback = function (mediaStream) { _this.stream.accessIsAllowed = true; _this.stream.accessIsDenied = false; _this.ee.emitEvent('accessAllowed'); // Apply PublisherProperties.publishAudio and PublisherProperties.publishVideo if (!!mediaStream.getAudioTracks()[0]) { mediaStream.getAudioTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishAudio; } if (!!mediaStream.getVideoTracks()[0]) { mediaStream.getVideoTracks()[0].enabled = !!_this.stream.outboundStreamOpts.publisherProperties.publishVideo; } _this.stream.setMediaStream(mediaStream); _this.stream.insertVideo(_this.element, _this.properties.insertMode); resolve(); }; _this.openvidu.generateMediaConstraints(_this.properties) .then(function (constraints) { var outboundStreamOptions = { mediaConstraints: constraints, publisherProperties: _this.properties }; _this.stream.setOutboundStreamOptions(outboundStreamOptions); // Ask independently for audio stream and video stream. If the user asks for both of them and one is blocked, the method still // success only with the allowed input. This is not the desierd behaviour: if any of them is blocked, access should be denied var constraintsAux = {}; if (_this.stream.isSendVideo()) { constraintsAux.audio = false; constraintsAux.video = constraints.video; navigator.mediaDevices.getUserMedia(constraintsAux) .then(function (videoOnlyStream) { if (_this.stream.isSendAudio()) { constraintsAux.audio = (constraints.audio === undefined) ? true : constraints.audio; constraintsAux.video = false; navigator.mediaDevices.getUserMedia(constraintsAux) .then(function (audioOnlyStream) { videoOnlyStream.addTrack(audioOnlyStream.getAudioTracks()[0]); successCallback(videoOnlyStream); })["catch"](function (error) { videoOnlyStream.getVideoTracks().forEach(function (track) { track.stop(); }); var errorName; var errorMessage; switch (error.name.toLowerCase()) { case 'notfounderror': errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; errorMessage = error.toString(); break; case 'notallowederror': errorName = OpenViduError_1.OpenViduErrorName.MICROPHONE_ACCESS_DENIED; errorMessage = error.toString(); break; case 'overconstrainederror': if (error.constraint.toLowerCase() === 'deviceid') { errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; } else { errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; } } errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); }); } else { successCallback(videoOnlyStream); } })["catch"](function (error) { var errorName; var errorMessage; switch (error.name.toLowerCase()) { case 'notfounderror': errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; errorMessage = error.toString(); break; case 'notallowederror': errorName = _this.stream.isSendScreen() ? OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED : OpenViduError_1.OpenViduErrorName.CAMERA_ACCESS_DENIED; errorMessage = error.toString(); break; case 'overconstrainederror': if (error.constraint.toLowerCase() === 'deviceid') { errorName = OpenViduError_1.OpenViduErrorName.INPUT_VIDEO_DEVICE_NOT_FOUND; errorMessage = "Video input device with deviceId '" + constraints.video.deviceId.exact + "' not found"; } else { errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; errorMessage = "Video input device doesn't support the value passed for constraint '" + error.constraint + "'"; } } errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); }); } else if (_this.stream.isSendAudio()) { constraintsAux.audio = (constraints.audio === undefined) ? true : constraints.audio; constraintsAux.video = false; navigator.mediaDevices.getUserMedia(constraints) .then(function (audioOnlyStream) { successCallback(audioOnlyStream); })["catch"](function (error) { var errorName; var errorMessage; switch (error.name.toLowerCase()) { case 'notfounderror': errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; errorMessage = error.toString(); break; case 'notallowederror': errorName = OpenViduError_1.OpenViduErrorName.MICROPHONE_ACCESS_DENIED; errorMessage = error.toString(); break; case 'overconstrainederror': if (error.constraint.toLowerCase() === 'deviceid') { errorName = OpenViduError_1.OpenViduErrorName.INPUT_AUDIO_DEVICE_NOT_FOUND; errorMessage = "Audio input device with deviceId '" + constraints.audio.deviceId.exact + "' not found"; } else { errorName = OpenViduError_1.OpenViduErrorName.PUBLISHER_PROPERTIES_ERROR; errorMessage = "Audio input device doesn't support the value passed for constraint '" + error.constraint + "'"; } } errorCallback(new OpenViduError_1.OpenViduError(errorName, errorMessage)); }); } else { reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.NO_INPUT_SOURCE_SET, "Properties 'audioSource' and 'videoSource' cannot be set to false or null at the same time when calling 'OpenVidu.initPublisher'")); } })["catch"](function (error) { errorCallback(error); }); }); }; /** * @hidden */ Publisher.prototype.updateSession = function (session) { this.session = session; this.stream.session = session; }; /** * @hidden */ Publisher.prototype.subscribeToRemote = function () { this.stream.subscribeToMyRemote(); }; /** * @hidden */ Publisher.prototype.emitEvent = function (type, eventArray) { this.ee.emitEvent(type, eventArray); }; return Publisher; }()); exports.Publisher = Publisher; //# sourceMappingURL=Publisher.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenVidu/Session.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var __1 = __webpack_require__("../../../../../openvidu-browser2/lib/index.js"); var OpenViduError_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/OpenViduError.js"); var VideoInsertMode_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/VideoInsertMode.js"); var DetectRTC = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/DetectRTC/DetectRTC.js"); var EventEmitter = __webpack_require__("../../../../../openvidu-browser2/node_modules/wolfy87-eventemitter/EventEmitter.js"); /** * Represents a video call. It can also be seen as a room where multiple users can connect. * Participants who publish their videos to a session will be seen by the rest of users connected to that specific session. */ var Session = /** @class */ (function () { /** * @hidden */ function Session(sessionId, openvidu) { var _this = this; this.ee = new EventEmitter(); this.remoteConnections = {}; // This map is only used to avoid race condition between 'joinRoom' response and 'onParticipantPublished' notification this.remoteStreamsCreated = {}; this.openvidu = openvidu; this.sessionId = this.openvidu.getUrlWithoutSecret(sessionId); this.openvidu.processOpenViduUrl(sessionId); // Default behaviour upon the disposal of a Stream: // destroy video element // 'event.preventDefault()' removes this listener this.ee.on('stream-destroyed-default', function (event) { event.stream.removeVideo(); }); // Default behaviour upon disconnection: // remove every video element of the Session (subscribers and publisher) // 'event.preventDefault()' removes this listener this.ee.on('session-disconnected-default', function () { for (var connectionId in _this.remoteConnections) { _this.remoteConnections[connectionId].stream.removeVideo(); } if (_this.connection && _this.connection.stream) { _this.connection.stream.removeVideo(); } }); } /** * Connects to the session using `token` and executes `callback` in the end (`error` parameter null if success). Only after this method succeeds [[Session.connection]] * object will be available and properly defined. * * `metadata` parameter allows you to pass extra data to share * with other users when they receive `streamCreated` event. The structure of `metadata` string is up to you (maybe some standarized format as JSON or XML is a good idea), the only restriction is a maximum length of 10000 chars. * * This data is not considered secure, as it is generated in the client side. To pass securized data, add it as a parameter in the * token generation operation (through the API REST, openvidu-java-client or openvidu-node-client). */ Session.prototype.connect = function (token, param2, param3) { if (param3) { if (this.openvidu.checkSystemRequirements()) { // Early configuration to deactivate automatic subscription to streams this.options = { sessionId: this.sessionId, participantId: token, metadata: this.stringClientMetadata(param2), updateSpeakerInterval: 1500, thresholdSpeaker: -50 }; this.connectAux(token, param3); } else { param3(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu')); } } else { if (this.openvidu.checkSystemRequirements()) { // Early configuration to deactivate automatic subscription to streams this.options = { sessionId: this.sessionId, participantId: token, metadata: '', updateSpeakerInterval: 1500, thresholdSpeaker: -50 }; this.connectAux(token, param2); } else { param2(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.BROWSER_NOT_SUPPORTED, 'Browser ' + DetectRTC.browser.name + ' ' + DetectRTC.browser.version + ' is not supported in OpenVidu')); } } }; /** * Leaves the session, destroying all streams and deleting the user as a participant. * * The Session object of the local participant will dispatch a `sessionDisconnected` event. * Call `event.preventDefault()` to avoid automatic deletion of every HTML video element of the session (of every publisher and subscriber). * * The Session object of every other participant connected to the session will dispatch a `streamDestroyed` event * if the disconnected participant was publishing and a `connectionDestroyed` event in any case. */ Session.prototype.disconnect = function () { var _this = this; this.openvidu.close(false); this.ee.emitEvent('sessionDisconnected', [{ preventDefault: function () { _this.ee.removeEvent('session-disconnected-default'); } }]); this.ee.emitEvent('session-disconnected-default', [{}]); }; /** * Subscribes to a `stream`, adding a new HTML video element to DOM with `subscriberProperties` settings. This method is usually called in the callback of `streamCreated` event. * @param stream Stream object to subscribe to * @param targetElement HTML element where to insert the video element of the Subscriber. Can be the `id` property of any element, an HTMLElement object or null if you don't want OpenVidu to insert any videos * @param completionHandler `error` parameter is null if `initPublisher` succeeds, and is defined if it fails. * `completionHandler` function is called before the Publisher dispatches an `accessAllowed` or an `accessDenied` event */ Session.prototype.subscribe = function (stream, targetElement, param3, param4) { var properties = {}; if (!!param3 && typeof param3 !== 'function') { properties = { insertMode: (typeof param3.insertMode !== 'undefined') ? param3.insertMode : VideoInsertMode_1.VideoInsertMode.APPEND, subscribeToAudio: (typeof param3.subscribeToAudio !== 'undefined') ? param3.subscribeToAudio : true, subscribeToVideo: (typeof param3.subscribeToVideo !== 'undefined') ? param3.subscribeToVideo : true }; } else { properties = { insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, subscribeToAudio: true, subscribeToVideo: true }; } stream.subscribe(); var subscriber = new __1.Subscriber(stream, targetElement, properties); stream.insertVideo(subscriber.element, properties.insertMode); return subscriber; }; /** * Unsubscribes from `subscriber`, automatically removing its HTML video element. */ Session.prototype.unsubscribe = function (subscriber) { var connectionId = subscriber.stream.connection.connectionId; console.info('Unsubscribing from ' + connectionId); this.openvidu.sendRequest('unsubscribeFromVideo', { sender: subscriber.stream.connection.connectionId }, function (error, response) { if (error) { console.error('Error unsubscribing from ' + connectionId, error); } else { console.info('Unsubscribed correctly from ' + connectionId); } subscriber.stream.dispose(); }); subscriber.stream.removeVideo(); }; /** * Publishes the participant's audio-video stream contained in `publisher` object to the session. Every other participant connected to the session will dispatch a `streamCreated` event so they can subscribe to it. */ Session.prototype.publish = function (publisher) { var _this = this; publisher.session = this; publisher.stream.session = this; if (!publisher.stream.isPublisherPublished) { // 'Session.unpublish(Publisher)' has NOT been called this.connection.addStream(publisher.stream); publisher.stream.publish(); } else { // 'Session.unpublish(Publisher)' has been called. Must initialize again Publisher publisher.initialize() .then(function () { _this.connection.addStream(publisher.stream); publisher.stream.publish(); })["catch"](function (error) { console.error(error); }); } }; /** * Unpublishes the participant's audio-video stream contained in `publisher` object. * * The Publisher object of the local participant will dispatch a `streamDestroyed` event. Call `event.preventDefault()` to avoid automatic deletion of the HTML video element of the publisher. * * The Session object of every other participant connected to the session will also dispatch a `streamDestroyed` event. * Call `event.preventDefault()` to avoid automatic deletion of the HTML video element of the respective subscriber. */ Session.prototype.unpublish = function (publisher) { var _this = this; var stream = publisher.stream; if (!stream.connection) { console.error('The associated Connection object of this Publisher is null', stream); return; } else if (stream.connection !== this.connection) { console.error('The associated Connection object of this Publisher is not your local Connection.' + "Only moderators can force unpublish on remote Streams via 'forceUnpublish' method", stream); return; } else { stream.dispose(); console.info('Unpublishing local media (' + stream.connection.connectionId + ')'); this.openvidu.sendRequest('unpublishVideo', function (error, response) { if (error) { console.error(error); } else { console.info('Media unpublished correctly'); } }); stream.isReadyToPublish = false; delete stream.connection.stream; publisher.emitEvent('streamDestroyed', [{ stream: publisher.stream, preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } }]); publisher.emitEvent('stream-destroyed-default', [{ stream: publisher.stream }]); } }; /** * Sends one signal. `signal` object has the following optional properties: * ```json * {data:string, to:Connection[], type:string} * ``` * All users subscribed to that signal (`session.on('signal:type', ...)` or `session.on('signal', ...)` for all signals) and whose Connection objects are in `to` array will receive it */ /* tslint:disable:no-string-literal */ Session.prototype.signal = function (signal, completionHandler) { var signalMessage = {}; if (signal.to && signal.to.length > 0) { var connectionIds_1 = []; signal.to.forEach(function (connection) { connectionIds_1.push(connection.connectionId); }); signalMessage['to'] = connectionIds_1; } else { signalMessage['to'] = []; } signalMessage['data'] = signal.data ? signal.data : ''; signalMessage['type'] = signal.type ? signal.type : ''; this.openvidu.sendRequest('sendMessage', { message: JSON.stringify(signalMessage) }, function (error, response) { if (!!completionHandler) { completionHandler(!!error ? new Error(error.message) : null); } }); }; /* tslint:enable:no-string-literal */ Session.prototype.on = function (type, handler) { this.ee.on(type, function (event) { if (event) { console.info("Event '" + type + "' triggered by 'Session'", event); } else { console.info("Event '" + type + "' triggered by 'Session'"); } handler(event); }); }; Session.prototype.once = function (type, handler) { this.ee.once(type, function (event) { if (event) { console.info("Event '" + type + "' triggered by 'Session'", event); } else { console.info("Event '" + type + "' triggered by 'Session'"); } handler(event); }); }; Session.prototype.off = function (type, eventHandler) { this.ee.off(type, eventHandler); }; /* Private methods */ Session.prototype.connectAux = function (token, callback) { var _this = this; this.openvidu.startWs(function (error) { if (!!error) { callback(error); } else { var joinParams = { token: (!!token) ? token : '', session: _this.sessionId, metadata: _this.options.metadata, secret: _this.openvidu.getSecret(), recorder: _this.openvidu.getRecorder() }; _this.openvidu.sendRequest('joinRoom', joinParams, function (error, response) { // Initialize local Connection object with values returned by openvidu-server _this.connection = new __1.Connection(_this); _this.connection.connectionId = response.id; _this.connection.data = response.metadata; // Initialize remote Connections with value returned by openvidu-server var events = { connections: new Array(), streams: new Array() }; var existingParticipants = response.value; existingParticipants.forEach(function (participant) { var connection = new __1.Connection(_this, participant); _this.remoteConnections[connection.connectionId] = connection; events.connections.push(connection); if (!!connection.stream) { _this.remoteStreamsCreated[connection.stream.streamId] = true; events.streams.push(connection.stream); } }); // Own connection created event _this.ee.emitEvent('connectionCreated', [{ connection: _this.connection }]); // One 'connectionCreated' event for each existing connection in the session events.connections.forEach(function (connection) { _this.ee.emitEvent('connectionCreated', [{ connection: connection }]); }); // One 'streamCreated' event for each active stream in the session events.streams.forEach(function (stream) { _this.ee.emitEvent('streamCreated', [{ stream: stream }]); }); callback(undefined); }); } }); }; Session.prototype.stringClientMetadata = function (metadata) { if (!(typeof metadata === 'string')) { return JSON.stringify(metadata); } else { return metadata; } }; Session.prototype.getConnection = function (connectionId, errorMessage) { var _this = this; return new Promise(function (resolve, reject) { var connection = _this.remoteConnections[connectionId]; if (!!connection) { // Resolve remote connection resolve(connection); } else { if (_this.connection.connectionId === connectionId) { // Resolve local connection resolve(_this.connection); } else { // Connection not found. Reject with OpenViduError reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); } } }); }; Session.prototype.getRemoteConnection = function (connectionId, errorMessage) { var _this = this; return new Promise(function (resolve, reject) { var connection = _this.remoteConnections[connectionId]; if (!!connection) { // Resolve remote connection resolve(connection); } else { // Remote connection not found. Reject with OpenViduError reject(new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.GENERIC_ERROR, errorMessage)); } }); }; /* Hidden methods */ /** * @hidden */ Session.prototype.onParticipantJoined = function (response) { var _this = this; // Connection shouldn't exist this.getConnection(response.id, '') .then(function (connection) { console.warn('Connection ' + response.id + ' already exists in connections list'); })["catch"](function (openViduError) { var connection = new __1.Connection(_this, response); _this.remoteConnections[response.id] = connection; _this.ee.emitEvent('connectionCreated', [{ connection: connection }]); }); }; /** * @hidden */ Session.prototype.onParticipantLeft = function (msg) { var _this = this; this.getRemoteConnection(msg.name, 'Remote connection ' + msg.name + " unknown when 'onParticipantLeft'. " + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) .then(function (connection) { if (!!connection.stream) { var stream = connection.stream; _this.ee.emitEvent('streamDestroyed', [{ stream: stream, preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } }]); _this.ee.emitEvent('stream-destroyed-default', [{ stream: stream }]); delete _this.remoteStreamsCreated[stream.streamId]; } connection.dispose(); delete _this.remoteConnections[connection.connectionId]; _this.ee.emitEvent('connectionDestroyed', [{ connection: connection }]); })["catch"](function (openViduError) { console.error(openViduError); }); }; /** * @hidden */ Session.prototype.onParticipantPublished = function (response) { var _this = this; var afterConnectionFound = function (connection) { _this.remoteConnections[connection.connectionId] = connection; if (!_this.remoteStreamsCreated[connection.stream.streamId]) { // Avoid race condition between stream.subscribe() in "onParticipantPublished" and in "joinRoom" rpc callback // This condition is false if openvidu-server sends "participantPublished" event to a subscriber participant that has // already subscribed to certain stream in the callback of "joinRoom" method _this.ee.emitEvent('streamCreated', [{ stream: connection.stream }]); } _this.remoteStreamsCreated[connection.stream.streamId] = true; }; // Get the existing Connection created on 'onParticipantJoined' for // existing participants or create a new one for new participants var connection; this.getRemoteConnection(response.id, "Remote connection '" + response.id + "' unknown when 'onParticipantPublished'. " + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) .then(function (con) { // Update existing Connection connection = con; response.metadata = con.data; connection.options = response; connection.initRemoteStreams(response.streams); afterConnectionFound(connection); })["catch"](function (openViduError) { // Create new Connection connection = new __1.Connection(_this, response); afterConnectionFound(connection); }); }; /** * @hidden */ Session.prototype.onParticipantUnpublished = function (msg) { var _this = this; this.getRemoteConnection(msg.name, "Remote connection '" + msg.name + "' unknown when 'onParticipantUnpublished'. " + 'Existing remote connections: ' + JSON.stringify(Object.keys(this.remoteConnections))) .then(function (connection) { _this.ee.emitEvent('streamDestroyed', [{ stream: connection.stream, preventDefault: function () { _this.ee.removeEvent('stream-destroyed-default'); } }]); _this.ee.emitEvent('stream-destroyed-default', [{ stream: connection.stream }]); // Deleting the remote stream var streamId = connection.stream.streamId; connection.stream.dispose(); delete _this.remoteStreamsCreated[streamId]; connection.removeStream(streamId); })["catch"](function (openViduError) { console.error(openViduError); }); }; /** * @hidden */ Session.prototype.onParticipantEvicted = function (msg) { this.ee.emitEvent('participant-evicted', [{ localParticipant: this.connection }]); }; /** * @hidden */ Session.prototype.onNewMessage = function (msg) { var _this = this; console.info('New signal: ' + JSON.stringify(msg)); this.getConnection(msg.from, "Connection '" + msg.from + "' unknow when 'onNewMessage'. Existing remote connections: " + JSON.stringify(Object.keys(this.remoteConnections)) + '. Existing local connection: ' + this.connection.connectionId) .then(function (connection) { _this.ee.emitEvent('signal', [{ data: msg.data, from: connection, type: msg.type }]); _this.ee.emitEvent('signal:' + msg.type, [{ data: msg.data, from: connection, type: msg.type }]); })["catch"](function (openViduError) { console.error(openViduError); }); }; /** * @hidden */ Session.prototype.recvIceCandidate = function (msg) { var candidate = { candidate: msg.candidate, sdpMid: msg.sdpMid, sdpMLineIndex: msg.sdpMLineIndex }; this.getConnection(msg.endpointName, 'Connection not found for endpoint ' + msg.endpointName + '. Ice candidate will be ignored: ' + candidate) .then(function (connection) { var stream = connection.stream; stream.getWebRtcPeer().addIceCandidate(candidate, function (error) { if (error) { console.error('Error adding candidate for ' + stream.streamId + ' stream of endpoint ' + msg.endpointName + ': ' + error); } }); })["catch"](function (openViduError) { console.error(openViduError); }); }; /** * @hidden */ Session.prototype.onSessionClosed = function (msg) { console.info('Session closed: ' + JSON.stringify(msg)); var s = msg.room; if (s !== undefined) { this.ee.emitEvent('session-closed', [{ session: s }]); } else { console.warn('Session undefined on session closed', msg); } }; /** * @hidden */ Session.prototype.onLostConnection = function () { var _this = this; if (!this.connection) { console.warn('Not connected to session: if you are not debugging, this is probably a certificate error'); var url = 'https://' + this.openvidu.getWsUri().split('wss://')[1].split('/room')[0]; if (window.confirm('If you are not debugging, this is probably a certificate error at \"' + url + '\"\n\nClick OK to navigate and accept it')) { location.assign(url + '/accept-certificate'); } return; } console.warn('Lost connection in Session ' + this.sessionId); if (!!this.sessionId) { this.ee.emitEvent('sessionDisconnected', [{ preventDefault: function () { _this.ee.removeEvent('session-disconnected-default'); } }]); } else { console.warn('Session undefined when lost connection'); } }; /** * @hidden */ Session.prototype.onMediaError = function (params) { console.error('Media error: ' + JSON.stringify(params)); var err = params.error; if (err) { this.ee.emitEvent('error-media', [{ error: err }]); } else { console.warn('Received undefined media error. Params:', params); } }; /** * @hidden */ Session.prototype.emitEvent = function (type, eventArray) { this.ee.emitEvent(type, eventArray); }; /** * @hidden */ Session.prototype.leave = function (forced, jsonRpcClient) { forced = !!forced; console.info('Leaving Session (forced=' + forced + ')'); if (!!this.connection && !forced) { this.openvidu.sendRequest('leaveRoom', function (error, response) { if (error) { console.error(error); } jsonRpcClient.close(); }); } else { jsonRpcClient.close(); } // Dispose and delete all remote Connections for (var connectionId in this.remoteConnections) { this.remoteConnections[connectionId].dispose(); delete this.remoteConnections[connectionId]; } // Dispose local Connection this.connection.dispose(); }; return Session; }()); exports.Session = Session; //# sourceMappingURL=Session.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenVidu/Stream.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var WebRtcStats_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/WebRtcStats/WebRtcStats.js"); var EventEmitter = __webpack_require__("../../../../../openvidu-browser2/node_modules/wolfy87-eventemitter/EventEmitter.js"); var kurentoUtils = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-utils-js/index.js"); var VideoInsertMode_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/VideoInsertMode.js"); /** * Represents each one of the videos send and receive by a user in a session. * Therefore each [[Publisher]] and [[Subscriber]] has an attribute of type Stream */ var Stream = /** @class */ (function () { /** * @hidden */ function Stream(session, options) { var _this = this; this.ee = new EventEmitter(); this.isSubscribeToRemote = false; /** * @hidden */ this.isReadyToPublish = false; /** * @hidden */ this.isPublisherPublished = false; /** * @hidden */ this.isVideoELementCreated = false; /** * @hidden */ this.accessIsAllowed = false; /** * @hidden */ this.accessIsDenied = false; this.session = session; if (options.hasOwnProperty('id')) { // InboundStreamOptions: stream belongs to a Subscriber this.inboundStreamOpts = options; this.streamId = this.inboundStreamOpts.id; this.typeOfVideo = this.inboundStreamOpts.typeOfVideo; this.hasAudio = this.inboundStreamOpts.recvAudio; this.hasVideo = this.inboundStreamOpts.recvVideo; this.frameRate = (this.inboundStreamOpts.frameRate === -1) ? undefined : this.inboundStreamOpts.frameRate; } else { // OutboundStreamOptions: stream belongs to a Publisher this.outboundStreamOpts = options; if (this.isSendVideo()) { if (this.isSendScreen()) { this.streamId = 'SCREEN'; this.typeOfVideo = 'SCREEN'; } else { this.streamId = 'CAMERA'; this.typeOfVideo = 'CAMERA'; } this.frameRate = this.outboundStreamOpts.publisherProperties.frameRate; } else { this.streamId = 'MICRO'; this.typeOfVideo = ''; } this.hasAudio = this.isSendAudio(); this.hasVideo = this.isSendVideo(); } this.on('mediastream-updated', function () { if (_this.video) _this.video.srcObject = _this.mediaStream; console.debug('Video srcObject [' + _this.mediaStream + '] updated in stream [' + _this.streamId + ']'); }); } /** * @hidden */ Stream.prototype.getMediaStream = function () { return this.mediaStream; }; /** * @hidden */ Stream.prototype.setMediaStream = function (mediaStream) { this.mediaStream = mediaStream; this.ee.emitEvent('mediastream-updated'); }; /** * @hidden */ Stream.prototype.getWebRtcPeer = function () { return this.webRtcPeer; }; /** * @hidden */ Stream.prototype.getRTCPeerConnection = function () { return this.webRtcPeer.peerConnection; }; /** * @hidden */ Stream.prototype.getVideoElement = function () { return this.video; }; /** * @hidden */ Stream.prototype.subscribeToMyRemote = function () { this.isSubscribeToRemote = true; }; /** * @hidden */ Stream.prototype.setOutboundStreamOptions = function (outboundStreamOpts) { this.outboundStreamOpts = outboundStreamOpts; }; /** * @hidden */ Stream.prototype.subscribe = function () { this.initWebRtcPeer(this.startVideoCallback); }; /** * @hidden */ Stream.prototype.publish = function () { var _this = this; // FIXME: Throw error when stream is not local if (this.isReadyToPublish) { this.initWebRtcPeer(this.publishVideoCallback); } else { this.ee.once('stream-ready', function (streamEvent) { _this.publish(); }); } }; /** * @hidden */ Stream.prototype.dispose = function () { if (this.webRtcPeer) { this.webRtcPeer.dispose(); } else { if (this.mediaStream) { this.mediaStream.getAudioTracks().forEach(function (track) { track.stop(); }); this.mediaStream.getVideoTracks().forEach(function (track) { track.stop(); }); } } if (this.speechEvent) { this.speechEvent.stop(); } this.stopWebRtcStats(); console.info((!!this.outboundStreamOpts ? 'Local ' : 'Remote ') + "'Stream' with id [" + this.streamId + "]' has been succesfully disposed"); }; /** * @hidden */ Stream.prototype.displayMyRemote = function () { return this.isSubscribeToRemote; }; /** * @hidden */ Stream.prototype.on = function (eventName, listener) { this.ee.on(eventName, listener); }; /** * @hidden */ Stream.prototype.once = function (eventName, listener) { this.ee.once(eventName, listener); }; /** * @hidden */ Stream.prototype.insertVideo = function (targetElement, insertMode) { var _this = this; if (!!targetElement) { this.video = document.createElement('video'); this.video.id = (this.isLocal() ? 'local-' : 'remote-') + 'video-' + this.streamId; this.video.autoplay = true; this.video.controls = false; this.video.srcObject = this.mediaStream; if (this.isLocal() && !this.displayMyRemote()) { this.video.muted = true; this.video.oncanplay = function () { console.info("Local 'Stream' with id [" + _this.streamId + '] video is now playing'); _this.ee.emitEvent('video-is-playing', [{ element: _this.video }]); }; } else { this.video.title = this.streamId; } this.targetElement = targetElement; this.parentId = targetElement.id; insertMode = !!insertMode ? insertMode : VideoInsertMode_1.VideoInsertMode.APPEND; this.insertElementWithMode(this.video, insertMode); this.ee.emitEvent('video-element-created-by-stream', [{ element: this.video }]); this.isVideoELementCreated = true; } this.isReadyToPublish = true; this.ee.emitEvent('stream-ready'); return this.video; }; /** * @hidden */ Stream.prototype.removeVideo = function () { if (this.video) { if (document.getElementById(this.parentId)) { document.getElementById(this.parentId).removeChild(this.video); this.ee.emitEvent('video-removed'); } delete this.video; } }; /** * @hidden */ Stream.prototype.isSendAudio = function () { return (!!this.outboundStreamOpts && this.outboundStreamOpts.publisherProperties.audioSource !== null && this.outboundStreamOpts.publisherProperties.audioSource !== false); }; /** * @hidden */ Stream.prototype.isSendVideo = function () { return (!!this.outboundStreamOpts && this.outboundStreamOpts.publisherProperties.videoSource !== null && this.outboundStreamOpts.publisherProperties.videoSource !== false); }; /** * @hidden */ Stream.prototype.isSendScreen = function () { return (!!this.outboundStreamOpts && this.outboundStreamOpts.publisherProperties.videoSource === 'screen'); }; Stream.prototype.initWebRtcPeer = function (sdpOfferCallback) { var _this = this; if (this.isLocal()) { var userMediaConstraints = { audio: this.isSendAudio(), video: this.isSendVideo() }; var options = { videoStream: this.mediaStream, mediaConstraints: userMediaConstraints, onicecandidate: this.connection.sendIceCandidate.bind(this.connection) }; if (this.displayMyRemote()) { this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendrecv(options, function (error) { if (error) { return console.error(error); } _this.webRtcPeer.generateOffer(sdpOfferCallback.bind(_this)); }); } else { this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerSendonly(options, function (error) { if (error) { return console.error(error); } _this.webRtcPeer.generateOffer(sdpOfferCallback.bind(_this)); }); } this.isPublisherPublished = true; this.ee.emitEvent('stream-created-by-publisher'); } else { var offerConstraints = { audio: this.inboundStreamOpts.recvAudio, video: this.inboundStreamOpts.recvVideo }; console.debug("'Session.subscribe(Stream)' called. Constraints of generate SDP offer", offerConstraints); var options = { onicecandidate: this.connection.sendIceCandidate.bind(this.connection), mediaConstraints: offerConstraints }; this.webRtcPeer = kurentoUtils.WebRtcPeer.WebRtcPeerRecvonly(options, function (error) { if (error) { return console.error(error); } _this.webRtcPeer.generateOffer(sdpOfferCallback.bind(_this)); }); } console.debug('Waiting for SDP offer to be generated (' + (this.isLocal() ? 'local' : 'remote') + " 'Stream': " + this.streamId + ')'); }; Stream.prototype.publishVideoCallback = function (error, sdpOfferParam, wp) { var _this = this; if (error) { return console.error('(publish) SDP offer error: ' + JSON.stringify(error)); } console.debug('Sending SDP offer to publish as ' + this.streamId, sdpOfferParam); this.session.openvidu.sendRequest('publishVideo', { sdpOffer: sdpOfferParam, doLoopback: this.displayMyRemote() || false, audioActive: this.isSendAudio(), videoActive: this.isSendVideo(), typeOfVideo: ((this.isSendVideo()) ? (this.isSendScreen() ? 'SCREEN' : 'CAMERA') : ''), frameRate: !!this.frameRate ? this.frameRate : -1 }, function (error, response) { if (error) { console.error('Error on publishVideo: ' + JSON.stringify(error)); } else { _this.processSdpAnswer(response.sdpAnswer); console.info("'Publisher' succesfully published to session"); } }); }; Stream.prototype.startVideoCallback = function (error, sdpOfferParam, wp) { var _this = this; if (error) { return console.error('(subscribe) SDP offer error: ' + JSON.stringify(error)); } console.debug('Sending SDP offer to subscribe to ' + this.streamId, sdpOfferParam); this.session.openvidu.sendRequest('receiveVideoFrom', { sender: this.streamId, sdpOffer: sdpOfferParam }, function (error, response) { if (error) { console.error('Error on recvVideoFrom: ' + JSON.stringify(error)); } else { _this.processSdpAnswer(response.sdpAnswer); } }); }; Stream.prototype.processSdpAnswer = function (sdpAnswer) { var _this = this; var answer = new RTCSessionDescription({ type: 'answer', sdp: sdpAnswer }); console.debug(this.streamId + ': set peer connection with recvd SDP answer', sdpAnswer); var streamId = this.streamId; var peerConnection = this.webRtcPeer.peerConnection; peerConnection.setRemoteDescription(answer, function () { // Avoids to subscribe to your own stream remotely // except when showMyRemote is true if (!_this.isLocal() || _this.displayMyRemote()) { _this.mediaStream = peerConnection.getRemoteStreams()[0]; console.debug('Peer remote stream', _this.mediaStream); if (!!_this.mediaStream) { _this.ee.emitEvent('mediastream-updated'); if (!!_this.mediaStream.getAudioTracks()[0]) { _this.speechEvent = kurentoUtils.WebRtcPeer.hark(_this.mediaStream, { threshold: _this.session.options.thresholdSpeaker }); _this.speechEvent.on('speaking', function () { _this.session.emitEvent('publisherStartSpeaking', [{ connection: _this.connection, streamId: _this.streamId }]); }); _this.speechEvent.on('stopped_speaking', function () { _this.session.emitEvent('publisherStopSpeaking', [{ connection: _this.connection, streamId: _this.streamId }]); }); } } if (!!_this.video) { // let thumbnailId = this.video.thumb; _this.video.oncanplay = function () { if (_this.isLocal() && _this.displayMyRemote()) { console.info("Your own remote 'Stream' with id [" + _this.streamId + '] video is now playing'); _this.ee.emitEvent('remote-video-is-playing', [{ element: _this.video }]); } else if (!_this.isLocal() && !_this.displayMyRemote()) { console.info("Remote 'Stream' with id [" + _this.streamId + '] video is now playing'); _this.ee.emitEvent('video-is-playing', [{ element: _this.video }]); } // show(thumbnailId); // this.hideSpinner(this.streamId); }; } _this.session.emitEvent('stream-subscribed', [{ stream: _this }]); } _this.initWebRtcStats(); }, function (error) { console.error(_this.streamId + ': Error setting SDP to the peer connection: ' + JSON.stringify(error)); }); }; Stream.prototype.initWebRtcStats = function () { this.webRtcStats = new WebRtcStats_1.WebRtcStats(this); this.webRtcStats.initWebRtcStats(); }; Stream.prototype.stopWebRtcStats = function () { if (!!this.webRtcStats && this.webRtcStats.isEnabled()) { this.webRtcStats.stopWebRtcStats(); } }; Stream.prototype.isLocal = function () { // inbound options undefined and outbound options defined return (!this.inboundStreamOpts && !!this.outboundStreamOpts); }; Stream.prototype.insertElementWithMode = function (element, insertMode) { if (!!this.targetElement) { switch (insertMode) { case VideoInsertMode_1.VideoInsertMode.AFTER: this.targetElement.parentNode.insertBefore(element, this.targetElement.nextSibling); break; case VideoInsertMode_1.VideoInsertMode.APPEND: this.targetElement.appendChild(element); break; case VideoInsertMode_1.VideoInsertMode.BEFORE: this.targetElement.parentNode.insertBefore(element, this.targetElement); break; case VideoInsertMode_1.VideoInsertMode.PREPEND: this.targetElement.insertBefore(element, this.targetElement.childNodes[0]); break; case VideoInsertMode_1.VideoInsertMode.REPLACE: this.targetElement.parentNode.replaceChild(element, this.targetElement); break; default: this.insertElementWithMode(element, VideoInsertMode_1.VideoInsertMode.APPEND); } } }; return Stream; }()); exports.Stream = Stream; //# sourceMappingURL=Stream.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenVidu/Subscriber.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var EventEmitter = __webpack_require__("../../../../../openvidu-browser2/node_modules/wolfy87-eventemitter/EventEmitter.js"); /** * Packs remote media streams. Participants automatically receive them when others publish their streams. Initialized with [[Session.subscribe]] method */ var Subscriber = /** @class */ (function () { /** * @hidden */ function Subscriber(stream, targetElement, properties) { var _this = this; this.ee = new EventEmitter(); this.stream = stream; this.properties = properties; if (typeof targetElement === 'string') { var e = document.getElementById(targetElement); if (!!e) { this.element = e; } } else if (targetElement instanceof HTMLElement) { this.element = targetElement; } // Listens to deletion of the HTML video element of the Subscriber's stream this.stream.on('video-removed', function () { _this.ee.emitEvent('videoElementDestroyed'); }); } Subscriber.prototype.subscribeToAudio = function (value) { this.stream.getWebRtcPeer().audioEnabled = value; console.info("'Subscriber' has " + (value ? 'subscribed' : 'unsubscribed') + ' to its audio stream'); return this; }; Subscriber.prototype.subscribeToVideo = function (value) { this.stream.getWebRtcPeer().videoEnabled = value; console.info("'Subscriber' has " + (value ? 'subscribed' : 'unsubscribed') + ' to its video stream'); return this; }; Subscriber.prototype.on = function (type, handler) { var _this = this; this.ee.on(type, function (event) { if (event) { console.info("Event '" + type + "' triggered by 'Subscriber'", event); } else { console.info("Event '" + type + "' triggered by 'Subscriber'"); } handler(event); }); if (type === 'videoElementCreated') { if (this.stream.isVideoELementCreated) { this.ee.emitEvent('videoElementCreated', [{ element: this.stream.getVideoElement() }]); } else { this.stream.once('video-element-created-by-stream', function (element) { _this.id = element.id; _this.ee.emitEvent('videoElementCreated', [{ element: element }]); }); } } if (type === '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.once('video-is-playing', function (element) { _this.ee.emitEvent('videoPlaying', [{ element: element.element }]); }); } } }; Subscriber.prototype.once = function (type, handler) { this.ee.once(type, function (event) { if (event) { console.info("Event '" + type + "' triggered once by 'Subscriber'", event); } else { console.info("Event '" + type + "' triggered once by 'Subscriber'"); } handler(event); }); }; Subscriber.prototype.off = function (type, eventHandler) { this.ee.off(type, eventHandler); }; return Subscriber; }()); exports.Subscriber = Subscriber; //# sourceMappingURL=Subscriber.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/DetectRTC/DetectRTC.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(process, global) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__; (function () { var browserFakeUserAgent = 'Fake/5.0 (FakeOS) AppleWebKit/123 (KHTML, like Gecko) Fake/12.3.4567.89 Fake/123.45'; var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node && !process.browser; if (isNodejs) { var version = process.versions.node.toString().replace('v', ''); browserFakeUserAgent = 'Nodejs/' + version + ' (NodeOS) AppleWebKit/' + version + ' (KHTML, like Gecko) Nodejs/' + version + ' Nodejs/' + version; } (function (that) { if (typeof window !== 'undefined') { return; } if (typeof window === 'undefined' && typeof global !== 'undefined') { global.navigator = { userAgent: browserFakeUserAgent, getUserMedia: function () { } }; that.window = global; } else if (typeof window === 'undefined') { } if (typeof location === 'undefined') { that.location = { protocol: 'file:', href: '', hash: '' }; } if (typeof screen === 'undefined') { that.screen = { width: 0, height: 0 }; } })(typeof global !== 'undefined' ? global : window); var navigator = window.navigator; if (typeof navigator !== 'undefined') { if (typeof navigator.webkitGetUserMedia !== 'undefined') { navigator.getUserMedia = navigator.webkitGetUserMedia; } if (typeof navigator.mozGetUserMedia !== 'undefined') { navigator.getUserMedia = navigator.mozGetUserMedia; } } else { navigator = { getUserMedia: function () { }, userAgent: browserFakeUserAgent }; } var isMobileDevice = !!(/Android|webOS|iPhone|iPad|iPod|BB10|BlackBerry|IEMobile|Opera Mini|Mobile|mobile/i.test(navigator.userAgent || '')); var isEdge = navigator.userAgent.indexOf('Edge') !== -1 && (!!navigator.msSaveOrOpenBlob || !!navigator.msSaveBlob); var isOpera = !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0; var isFirefox = typeof window.InstallTrigger !== 'undefined'; var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); var isChrome = !!window.chrome && !isOpera; var isIE = typeof document !== 'undefined' && !!document.documentMode && !isEdge; function getBrowserInfo() { var nVer = navigator.appVersion; var nAgt = navigator.userAgent; var browserName = navigator.appName; var fullVersion = '' + parseFloat(navigator.appVersion); var majorVersion = parseInt(navigator.appVersion, 10); var nameOffset, verOffset, ix; if (isOpera) { browserName = 'Opera'; try { fullVersion = navigator.userAgent.split('OPR/')[1].split(' ')[0]; majorVersion = fullVersion.split('.')[0]; } catch (e) { fullVersion = '0.0.0.0'; majorVersion = 0; } } else if (isIE) { verOffset = nAgt.indexOf('rv:'); if (verOffset > 0) { fullVersion = nAgt.substring(verOffset + 3); } else { verOffset = nAgt.indexOf('MSIE'); fullVersion = nAgt.substring(verOffset + 5); } browserName = 'IE'; } else if (isChrome) { verOffset = nAgt.indexOf('Chrome'); browserName = 'Chrome'; fullVersion = nAgt.substring(verOffset + 7); } else if (isSafari) { verOffset = nAgt.indexOf('Safari'); browserName = 'Safari'; fullVersion = nAgt.substring(verOffset + 7); if ((verOffset = nAgt.indexOf('Version')) !== -1) { fullVersion = nAgt.substring(verOffset + 8); } if (navigator.userAgent.indexOf('Version/') !== -1) { fullVersion = navigator.userAgent.split('Version/')[1].split(' ')[0]; } } else if (isFirefox) { verOffset = nAgt.indexOf('Firefox'); browserName = 'Firefox'; fullVersion = nAgt.substring(verOffset + 8); } else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) { browserName = nAgt.substring(nameOffset, verOffset); fullVersion = nAgt.substring(verOffset + 1); if (browserName.toLowerCase() === browserName.toUpperCase()) { browserName = navigator.appName; } } if (isEdge) { browserName = 'Edge'; fullVersion = navigator.userAgent.split('Edge/')[1]; } if ((ix = fullVersion.search(/[; \)]/)) !== -1) { fullVersion = fullVersion.substring(0, ix); } majorVersion = parseInt('' + fullVersion, 10); if (isNaN(majorVersion)) { fullVersion = '' + parseFloat(navigator.appVersion); majorVersion = parseInt(navigator.appVersion, 10); } return { fullVersion: fullVersion, version: majorVersion, name: browserName, isPrivateBrowsing: false }; } function retry(isDone, next) { var currentTrial = 0, maxRetry = 50, interval = 10, isTimeout = false; var id = window.setInterval(function () { if (isDone()) { window.clearInterval(id); next(isTimeout); } if (currentTrial++ > maxRetry) { window.clearInterval(id); isTimeout = true; next(isTimeout); } }, 10); } function isIE10OrLater(userAgent) { var ua = userAgent.toLowerCase(); if (ua.indexOf('msie') === 0 && ua.indexOf('trident') === 0) { return false; } var match = /(?:msie|rv:)\s?([\d\.]+)/.exec(ua); if (match && parseInt(match[1], 10) >= 10) { return true; } return false; } function detectPrivateMode(callback) { var isPrivate; try { if (window.webkitRequestFileSystem) { window.webkitRequestFileSystem(window.TEMPORARY, 1, function () { isPrivate = false; }, function (e) { isPrivate = true; }); } else if (window.indexedDB && /Firefox/.test(window.navigator.userAgent)) { var db; try { db = window.indexedDB.open('test'); db.onerror = function () { return true; }; } catch (e) { isPrivate = true; } if (typeof isPrivate === 'undefined') { retry(function isDone() { return db.readyState === 'done' ? true : false; }, function next(isTimeout) { if (!isTimeout) { isPrivate = db.result ? false : true; } }); } } else if (isIE10OrLater(window.navigator.userAgent)) { isPrivate = false; try { if (!window.indexedDB) { isPrivate = true; } } catch (e) { isPrivate = true; } } else if (window.localStorage && /Safari/.test(window.navigator.userAgent)) { try { window.localStorage.setItem('test', 1); } catch (e) { isPrivate = true; } if (typeof isPrivate === 'undefined') { isPrivate = false; window.localStorage.removeItem('test'); } } } catch (e) { isPrivate = false; } retry(function isDone() { return typeof isPrivate !== 'undefined' ? true : false; }, function next(isTimeout) { callback(isPrivate); }); } var isMobile = { Android: function () { return navigator.userAgent.match(/Android/i); }, BlackBerry: function () { return navigator.userAgent.match(/BlackBerry|BB10/i); }, iOS: function () { return navigator.userAgent.match(/iPhone|iPad|iPod/i); }, Opera: function () { return navigator.userAgent.match(/Opera Mini/i); }, Windows: function () { return navigator.userAgent.match(/IEMobile/i); }, any: function () { return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); }, getOsName: function () { var osName = 'Unknown OS'; if (isMobile.Android()) { osName = 'Android'; } if (isMobile.BlackBerry()) { osName = 'BlackBerry'; } if (isMobile.iOS()) { osName = 'iOS'; } if (isMobile.Opera()) { osName = 'Opera Mini'; } if (isMobile.Windows()) { osName = 'Windows'; } return osName; } }; function detectDesktopOS() { var unknown = '-'; var nVer = navigator.appVersion; var nAgt = navigator.userAgent; var os = unknown; var clientStrings = [{ s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, { s: 'Windows Vista', r: /Windows NT 6.0/ }, { s: 'Windows Server 2003', r: /Windows NT 5.2/ }, { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, { s: 'Windows 2000', r: /(Windows NT 5.0|Windows 2000)/ }, { s: 'Windows ME', r: /(Win 9x 4.90|Windows ME)/ }, { s: 'Windows 98', r: /(Windows 98|Win98)/ }, { s: 'Windows 95', r: /(Windows 95|Win95|Windows_95)/ }, { s: 'Windows NT 4.0', r: /(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/ }, { s: 'Windows CE', r: /Windows CE/ }, { s: 'Windows 3.11', r: /Win16/ }, { s: 'Android', r: /Android/ }, { s: 'Open BSD', r: /OpenBSD/ }, { s: 'Sun OS', r: /SunOS/ }, { s: 'Linux', r: /(Linux|X11)/ }, { s: 'iOS', r: /(iPhone|iPad|iPod)/ }, { s: 'Mac OS X', r: /Mac OS X/ }, { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, { s: 'QNX', r: /QNX/ }, { s: 'UNIX', r: /UNIX/ }, { s: 'BeOS', r: /BeOS/ }, { s: 'OS/2', r: /OS\/2/ }, { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ }]; for (var i = 0, cs; cs = clientStrings[i]; i++) { if (cs.r.test(nAgt)) { os = cs.s; break; } } var osVersion = unknown; if (/Windows/.test(os)) { if (/Windows (.*)/.test(os)) { osVersion = /Windows (.*)/.exec(os)[1]; } os = 'Windows'; } switch (os) { case 'Mac OS X': if (/Mac OS X (10[\.\_\d]+)/.test(nAgt)) { osVersion = /Mac OS X (10[\.\_\d]+)/.exec(nAgt)[1]; } break; case 'Android': if (/Android ([\.\_\d]+)/.test(nAgt)) { osVersion = /Android ([\.\_\d]+)/.exec(nAgt)[1]; } break; case 'iOS': if (/OS (\d+)_(\d+)_?(\d+)?/.test(nAgt)) { osVersion = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); osVersion = osVersion[1] + '.' + osVersion[2] + '.' + (osVersion[3] | 0); } break; } return { osName: os, osVersion: osVersion }; } var osName = 'Unknown OS'; var osVersion = 'Unknown OS Version'; function getAndroidVersion(ua) { ua = (ua || navigator.userAgent).toLowerCase(); var match = ua.match(/android\s([0-9\.]*)/); return match ? match[1] : false; } var osInfo = detectDesktopOS(); if (osInfo && osInfo.osName && osInfo.osName != '-') { osName = osInfo.osName; osVersion = osInfo.osVersion; } else if (isMobile.any()) { osName = isMobile.getOsName(); if (osName == 'Android') { osVersion = getAndroidVersion(); } } var isNodejs = typeof process === 'object' && typeof process.versions === 'object' && process.versions.node; if (osName === 'Unknown OS' && isNodejs) { osName = 'Nodejs'; osVersion = process.versions.node.toString().replace('v', ''); } var isCanvasSupportsStreamCapturing = false; var isVideoSupportsStreamCapturing = false; ['captureStream', 'mozCaptureStream', 'webkitCaptureStream'].forEach(function (item) { if (typeof document === 'undefined' || typeof document.createElement !== 'function') { return; } if (!isCanvasSupportsStreamCapturing && item in document.createElement('canvas')) { isCanvasSupportsStreamCapturing = true; } if (!isVideoSupportsStreamCapturing && item in document.createElement('video')) { isVideoSupportsStreamCapturing = true; } }); function DetectLocalIPAddress(callback, stream) { if (!DetectRTC.isWebRTCSupported) { return; } getIPs(function (ip) { if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)) { callback('Local: ' + ip); } else { callback('Public: ' + ip); } }, stream); } function getIPs(callback, stream) { if (typeof document === 'undefined' || typeof document.getElementById !== 'function') { return; } var ipDuplicates = {}; var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; if (!RTCPeerConnection) { var iframe = document.getElementById('iframe'); if (!iframe) { return; } var win = iframe.contentWindow; RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection; } if (!RTCPeerConnection) { return; } var peerConfig = null; if (DetectRTC.browser === 'Chrome' && DetectRTC.browser.version < 58) { peerConfig = { optional: [{ RtpDataChannels: true }] }; } var servers = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] }; var pc = new RTCPeerConnection(servers, peerConfig); if (stream) { if (pc.addStream) { pc.addStream(stream); } else if (pc.addTrack && stream.getTracks()[0]) { pc.addTrack(stream.getTracks()[0], stream); } } function handleCandidate(candidate) { var ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3})/; var match = ipRegex.exec(candidate); if (!match) { return; } var ipAddress = match[1]; if (ipDuplicates[ipAddress] === undefined) { callback(ipAddress); } ipDuplicates[ipAddress] = true; } pc.onicecandidate = function (ice) { if (ice.candidate) { handleCandidate(ice.candidate.candidate); } }; if (!stream) { try { pc.createDataChannel('sctp', {}); } catch (e) { } } if (DetectRTC.isPromisesSupported) { pc.createOffer().then(function (result) { pc.setLocalDescription(result).then(afterCreateOffer); }); } else { pc.createOffer(function (result) { pc.setLocalDescription(result, afterCreateOffer, function () { }); }, function () { }); } function afterCreateOffer() { var lines = pc.localDescription.sdp.split('\n'); lines.forEach(function (line) { if (line.indexOf('a=candidate:') === 0) { handleCandidate(line); } }); } } var MediaDevices = []; var audioInputDevices = []; var audioOutputDevices = []; var videoInputDevices = []; if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { navigator.enumerateDevices = function (callback) { var enumerateDevices = navigator.mediaDevices.enumerateDevices(); if (enumerateDevices && enumerateDevices.then) { navigator.mediaDevices.enumerateDevices().then(callback).catch(function () { callback([]); }); } else { callback([]); } }; } var canEnumerate = false; if (typeof MediaStreamTrack !== 'undefined' && 'getSources' in MediaStreamTrack) { canEnumerate = true; } else if (navigator.mediaDevices && !!navigator.mediaDevices.enumerateDevices) { canEnumerate = true; } var hasMicrophone = false; var hasSpeakers = false; var hasWebcam = false; var isWebsiteHasMicrophonePermissions = false; var isWebsiteHasWebcamPermissions = false; function checkDeviceSupport(callback) { if (!canEnumerate) { if (callback) { callback(); } return; } if (!navigator.enumerateDevices && window.MediaStreamTrack && window.MediaStreamTrack.getSources) { navigator.enumerateDevices = window.MediaStreamTrack.getSources.bind(window.MediaStreamTrack); } if (!navigator.enumerateDevices && navigator.enumerateDevices) { navigator.enumerateDevices = navigator.enumerateDevices.bind(navigator); } if (!navigator.enumerateDevices) { if (callback) { callback(); } return; } MediaDevices = []; audioInputDevices = []; audioOutputDevices = []; videoInputDevices = []; hasMicrophone = false; hasSpeakers = false; hasWebcam = false; isWebsiteHasMicrophonePermissions = false; isWebsiteHasWebcamPermissions = false; var alreadyUsedDevices = {}; navigator.enumerateDevices(function (devices) { devices.forEach(function (_device) { var device = {}; for (var d in _device) { try { if (typeof _device[d] !== 'function') { device[d] = _device[d]; } } catch (e) { } } if (alreadyUsedDevices[device.deviceId + device.label + device.kind]) { return; } if (device.kind === 'audio') { device.kind = 'audioinput'; } if (device.kind === 'video') { device.kind = 'videoinput'; } if (!device.deviceId) { device.deviceId = device.id; } if (!device.id) { device.id = device.deviceId; } if (!device.label) { device.isCustomLabel = true; if (device.kind === 'videoinput') { device.label = 'Camera ' + (videoInputDevices.length + 1); } else if (device.kind === 'audioinput') { device.label = 'Microphone ' + (audioInputDevices.length + 1); } else if (device.kind === 'audiooutput') { device.label = 'Speaker ' + (audioOutputDevices.length + 1); } else { device.label = 'Please invoke getUserMedia once.'; } if (typeof DetectRTC !== 'undefined' && DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { device.label = 'HTTPs is required to get label of this ' + device.kind + ' device.'; } } } else { if (device.kind === 'videoinput' && !isWebsiteHasWebcamPermissions) { isWebsiteHasWebcamPermissions = true; } if (device.kind === 'audioinput' && !isWebsiteHasMicrophonePermissions) { isWebsiteHasMicrophonePermissions = true; } } if (device.kind === 'audioinput') { hasMicrophone = true; if (audioInputDevices.indexOf(device) === -1) { audioInputDevices.push(device); } } if (device.kind === 'audiooutput') { hasSpeakers = true; if (audioOutputDevices.indexOf(device) === -1) { audioOutputDevices.push(device); } } if (device.kind === 'videoinput') { hasWebcam = true; if (videoInputDevices.indexOf(device) === -1) { videoInputDevices.push(device); } } MediaDevices.push(device); alreadyUsedDevices[device.deviceId + device.label + device.kind] = device; }); if (typeof DetectRTC !== 'undefined') { DetectRTC.MediaDevices = MediaDevices; DetectRTC.hasMicrophone = hasMicrophone; DetectRTC.hasSpeakers = hasSpeakers; DetectRTC.hasWebcam = hasWebcam; DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; DetectRTC.audioInputDevices = audioInputDevices; DetectRTC.audioOutputDevices = audioOutputDevices; DetectRTC.videoInputDevices = videoInputDevices; } if (callback) { callback(); } }); } var DetectRTC = window.DetectRTC || {}; DetectRTC.browser = getBrowserInfo(); detectPrivateMode(function (isPrivateBrowsing) { DetectRTC.browser.isPrivateBrowsing = !!isPrivateBrowsing; }); DetectRTC.browser['is' + DetectRTC.browser.name] = true; DetectRTC.osName = osName; DetectRTC.osVersion = osVersion; var isNodeWebkit = typeof process === 'object' && typeof process.versions === 'object' && process.versions['node-webkit']; var isWebRTCSupported = false; ['RTCPeerConnection', 'webkitRTCPeerConnection', 'mozRTCPeerConnection', 'RTCIceGatherer'].forEach(function (item) { if (isWebRTCSupported) { return; } if (item in window) { isWebRTCSupported = true; } }); DetectRTC.isWebRTCSupported = isWebRTCSupported; DetectRTC.isORTCSupported = typeof RTCIceGatherer !== 'undefined'; var webAudio = { isSupported: false, isCreateMediaStreamSourceSupported: false }; ['AudioContext', 'webkitAudioContext', 'mozAudioContext', 'msAudioContext'].forEach(function (item) { if (webAudio.isSupported) { return; } if (item in window) { webAudio.isSupported = true; if (window[item] && 'createMediaStreamSource' in window[item].prototype) { webAudio.isCreateMediaStreamSourceSupported = true; } } }); DetectRTC.isAudioContextSupported = webAudio.isSupported; DetectRTC.isCreateMediaStreamSourceSupported = webAudio.isCreateMediaStreamSourceSupported; var isRtpDataChannelsSupported = false; if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 31) { isRtpDataChannelsSupported = true; } DetectRTC.isRtpDataChannelsSupported = isRtpDataChannelsSupported; var isSCTPSupportd = false; if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 28) { isSCTPSupportd = true; } else if (DetectRTC.browser.isChrome && DetectRTC.browser.version > 25) { isSCTPSupportd = true; } else if (DetectRTC.browser.isOpera && DetectRTC.browser.version >= 11) { isSCTPSupportd = true; } DetectRTC.isSctpDataChannelsSupported = isSCTPSupportd; DetectRTC.isMobileDevice = isMobileDevice; var isGetUserMediaSupported = false; if (navigator.getUserMedia) { isGetUserMediaSupported = true; } else if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { isGetUserMediaSupported = true; } if (DetectRTC.browser.isChrome && DetectRTC.browser.version >= 46 && !/^(https:|chrome-extension:)$/g.test(location.protocol || '')) { if (typeof document !== 'undefined' && typeof document.domain === 'string' && document.domain.search && document.domain.search(/localhost|127.0./g) === -1) { isGetUserMediaSupported = 'Requires HTTPs'; } } if (DetectRTC.osName === 'Nodejs') { isGetUserMediaSupported = false; } DetectRTC.isGetUserMediaSupported = isGetUserMediaSupported; var displayResolution = ''; if (screen.width) { var width = (screen.width) ? screen.width : ''; var height = (screen.height) ? screen.height : ''; displayResolution += '' + width + ' x ' + height; } DetectRTC.displayResolution = displayResolution; function getAspectRatio(w, h) { function gcd(a, b) { return (b == 0) ? a : gcd(b, a % b); } var r = gcd(w, h); return (w / r) / (h / r); } DetectRTC.displayAspectRatio = getAspectRatio(screen.width, screen.height).toFixed(2); DetectRTC.isCanvasSupportsStreamCapturing = isCanvasSupportsStreamCapturing; DetectRTC.isVideoSupportsStreamCapturing = isVideoSupportsStreamCapturing; if (DetectRTC.browser.name == 'Chrome' && DetectRTC.browser.version >= 53) { if (!DetectRTC.isCanvasSupportsStreamCapturing) { DetectRTC.isCanvasSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; } if (!DetectRTC.isVideoSupportsStreamCapturing) { DetectRTC.isVideoSupportsStreamCapturing = 'Requires chrome flag: enable-experimental-web-platform-features'; } } DetectRTC.DetectLocalIPAddress = DetectLocalIPAddress; DetectRTC.isWebSocketsSupported = 'WebSocket' in window && 2 === window.WebSocket.CLOSING; DetectRTC.isWebSocketsBlocked = !DetectRTC.isWebSocketsSupported; if (DetectRTC.osName === 'Nodejs') { DetectRTC.isWebSocketsSupported = true; DetectRTC.isWebSocketsBlocked = false; } DetectRTC.checkWebSocketsSupport = function (callback) { callback = callback || function () { }; try { var starttime; var websocket = new WebSocket('wss://echo.websocket.org:443/'); websocket.onopen = function () { DetectRTC.isWebSocketsBlocked = false; starttime = (new Date).getTime(); websocket.send('ping'); }; websocket.onmessage = function () { DetectRTC.WebsocketLatency = (new Date).getTime() - starttime + 'ms'; callback(); websocket.close(); websocket = null; }; websocket.onerror = function () { DetectRTC.isWebSocketsBlocked = true; callback(); }; } catch (e) { DetectRTC.isWebSocketsBlocked = true; callback(); } }; DetectRTC.load = function (callback) { callback = callback || function () { }; checkDeviceSupport(callback); }; if (typeof checkDeviceSupport === 'function') { } if (typeof MediaDevices !== 'undefined') { DetectRTC.MediaDevices = MediaDevices; } else { DetectRTC.MediaDevices = []; } DetectRTC.hasMicrophone = hasMicrophone; DetectRTC.hasSpeakers = hasSpeakers; DetectRTC.hasWebcam = hasWebcam; DetectRTC.isWebsiteHasWebcamPermissions = isWebsiteHasWebcamPermissions; DetectRTC.isWebsiteHasMicrophonePermissions = isWebsiteHasMicrophonePermissions; DetectRTC.audioInputDevices = audioInputDevices; DetectRTC.audioOutputDevices = audioOutputDevices; DetectRTC.videoInputDevices = videoInputDevices; var isSetSinkIdSupported = false; if (typeof document !== 'undefined' && typeof document.createElement === 'function' && 'setSinkId' in document.createElement('video')) { isSetSinkIdSupported = true; } DetectRTC.isSetSinkIdSupported = isSetSinkIdSupported; var isRTPSenderReplaceTracksSupported = false; if (DetectRTC.browser.isFirefox && typeof mozRTCPeerConnection !== 'undefined') { if ('getSenders' in mozRTCPeerConnection.prototype) { isRTPSenderReplaceTracksSupported = true; } } else if (DetectRTC.browser.isChrome && typeof webkitRTCPeerConnection !== 'undefined') { if ('getSenders' in webkitRTCPeerConnection.prototype) { isRTPSenderReplaceTracksSupported = true; } } DetectRTC.isRTPSenderReplaceTracksSupported = isRTPSenderReplaceTracksSupported; var isRemoteStreamProcessingSupported = false; if (DetectRTC.browser.isFirefox && DetectRTC.browser.version > 38) { isRemoteStreamProcessingSupported = true; } DetectRTC.isRemoteStreamProcessingSupported = isRemoteStreamProcessingSupported; var isApplyConstraintsSupported = false; if (typeof MediaStreamTrack !== 'undefined' && 'applyConstraints' in MediaStreamTrack.prototype) { isApplyConstraintsSupported = true; } DetectRTC.isApplyConstraintsSupported = isApplyConstraintsSupported; var isMultiMonitorScreenCapturingSupported = false; if (DetectRTC.browser.isFirefox && DetectRTC.browser.version >= 43) { isMultiMonitorScreenCapturingSupported = true; } DetectRTC.isMultiMonitorScreenCapturingSupported = isMultiMonitorScreenCapturingSupported; DetectRTC.isPromisesSupported = !!('Promise' in window); if (typeof DetectRTC === 'undefined') { window.DetectRTC = {}; } var MediaStream = window.MediaStream; if (typeof MediaStream === 'undefined' && typeof webkitMediaStream !== 'undefined') { MediaStream = webkitMediaStream; } if (typeof MediaStream !== 'undefined') { DetectRTC.MediaStream = Object.keys(MediaStream.prototype); } else DetectRTC.MediaStream = false; if (typeof MediaStreamTrack !== 'undefined') { DetectRTC.MediaStreamTrack = Object.keys(MediaStreamTrack.prototype); } else DetectRTC.MediaStreamTrack = false; var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; if (typeof RTCPeerConnection !== 'undefined') { DetectRTC.RTCPeerConnection = Object.keys(RTCPeerConnection.prototype); } else DetectRTC.RTCPeerConnection = false; window.DetectRTC = DetectRTC; if (true) { module.exports = DetectRTC; } if (true) { !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function () { return DetectRTC; }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } })(); //# sourceMappingURL=DetectRTC.js.map /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__("./node_modules/process/browser.js"), __webpack_require__("./node_modules/webpack/buildin/global.js"))) /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/LocalRecorderState.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2018 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. * */ exports.__esModule = true; var LocalRecoderState; (function (LocalRecoderState) { LocalRecoderState["READY"] = "READY"; LocalRecoderState["RECORDING"] = "RECORDING"; LocalRecoderState["PAUSED"] = "PAUSED"; LocalRecoderState["FINISHED"] = "FINISHED"; })(LocalRecoderState = exports.LocalRecoderState || (exports.LocalRecoderState = {})); //# sourceMappingURL=LocalRecorderState.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/OpenViduError.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2018 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. * */ exports.__esModule = 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["SCREEN_SHARING_NOT_SUPPORTED"] = "SCREEN_SHARING_NOT_SUPPORTED"; OpenViduErrorName["SCREEN_EXTENSION_NOT_INSTALLED"] = "SCREEN_EXTENSION_NOT_INSTALLED"; OpenViduErrorName["INPUT_VIDEO_DEVICE_NOT_FOUND"] = "INPUT_VIDEO_DEVICE_NOT_FOUND"; OpenViduErrorName["INPUT_AUDIO_DEVICE_NOT_FOUND"] = "INPUT_AUDIO_DEVICE_NOT_FOUND"; OpenViduErrorName["NO_INPUT_SOURCE_SET"] = "NO_INPUT_SOURCE_SET"; OpenViduErrorName["PUBLISHER_PROPERTIES_ERROR"] = "PUBLISHER_PROPERTIES_ERROR"; OpenViduErrorName["OPENVIDU_PERMISSION_DENIED"] = "OPENVIDU_PERMISSION_DENIED"; OpenViduErrorName["GENERIC_ERROR"] = "GENERIC_ERROR"; })(OpenViduErrorName = exports.OpenViduErrorName || (exports.OpenViduErrorName = {})); /** * Simple object to identify runtime errors on the client side */ var OpenViduError = /** @class */ (function () { /** * @hidden */ function OpenViduError(name, message) { this.name = name; this.message = message; } return OpenViduError; }()); exports.OpenViduError = OpenViduError; //# sourceMappingURL=OpenViduError.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/Enums/VideoInsertMode.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2018 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. * */ exports.__esModule = true; var VideoInsertMode; (function (VideoInsertMode) { /** * Video inserted after the target element (as next sibling) */ VideoInsertMode["AFTER"] = "AFTER"; /** * Video inserted as last child of the target element */ VideoInsertMode["APPEND"] = "APPEND"; /** * Video inserted before the target element (as previous sibling) */ VideoInsertMode["BEFORE"] = "BEFORE"; /** * Video inserted as first child of the target element */ VideoInsertMode["PREPEND"] = "PREPEND"; /** * Video replaces target element */ VideoInsertMode["REPLACE"] = "REPLACE"; })(VideoInsertMode = exports.VideoInsertMode || (exports.VideoInsertMode = {})); //# sourceMappingURL=VideoInsertMode.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/Mapper.js": /***/ (function(module, exports) { function Mapper() { var sources = {}; this.forEach = function (callback) { for (var key in sources) { var source = sources[key]; for (var key2 in source) callback(source[key2]); } ; }; this.get = function (id, source) { var ids = sources[source]; if (ids == undefined) return undefined; return ids[id]; }; this.remove = function (id, source) { var ids = sources[source]; if (ids == undefined) return; delete ids[id]; for (var i in ids) { return false; } delete sources[source]; }; this.set = function (value, id, source) { if (value == undefined) return this.remove(id, source); var ids = sources[source]; if (ids == undefined) sources[source] = ids = {}; ids[id] = value; }; } ; Mapper.prototype.pop = function (id, source) { var value = this.get(id, source); if (value == undefined) return undefined; this.remove(id, source); return value; }; module.exports = Mapper; //# sourceMappingURL=Mapper.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/index.js": /***/ (function(module, exports, __webpack_require__) { var JsonRpcClient = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/jsonrpcclient.js"); exports.JsonRpcClient = JsonRpcClient; //# sourceMappingURL=index.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/jsonrpcclient.js": /***/ (function(module, exports, __webpack_require__) { var RpcBuilder = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/index.js"); var WebSocketWithReconnection = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/transports/webSocketWithReconnection.js"); Date.now = Date.now || function () { return +new Date; }; var PING_INTERVAL = 5000; var RECONNECTING = 'RECONNECTING'; var CONNECTED = 'CONNECTED'; var DISCONNECTED = 'DISCONNECTED'; var Logger = console; 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"); } } 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.forceClose = function (millis) { ws.forceClose(millis); }; this.reconnect = function () { ws.reconnectWs(); }; } module.exports = JsonRpcClient; //# sourceMappingURL=jsonrpcclient.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/transports/index.js": /***/ (function(module, exports, __webpack_require__) { var WebSocketWithReconnection = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/transports/webSocketWithReconnection.js"); exports.WebSocketWithReconnection = WebSocketWithReconnection; //# sourceMappingURL=index.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/transports/webSocketWithReconnection.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(global) { var BrowserWebSocket = global.WebSocket || global.MozWebSocket; var Logger = console; var MAX_RETRIES = 2000; var RETRY_TIME_MS = 3000; var CONNECTING = 0; var OPEN = 1; var CLOSING = 2; var CLOSED = 3; 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); } } } 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.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; //# sourceMappingURL=webSocketWithReconnection.js.map /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__("./node_modules/webpack/buildin/global.js"))) /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/index.js": /***/ (function(module, exports, __webpack_require__) { var defineProperty_IE8 = false; if (Object.defineProperty) { try { Object.defineProperty({}, "x", {}); } catch (e) { defineProperty_IE8 = true; } } if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== '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 = __webpack_require__("./node_modules/events/events.js").EventEmitter; var inherits = __webpack_require__("../../../../../openvidu-browser2/node_modules/inherits/inherits_browser.js"); var packers = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/packers/index.js"); var Mapper = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/Mapper.js"); 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; if (transport instanceof Function) return { send: transport }; if (transport.send instanceof Function) return transport; if (transport.postMessage instanceof Function) { transport.send = transport.postMessage; return transport; } if (transport.write instanceof Function) { transport.send = transport.write; return transport; } if (transport.onmessage !== undefined) return; if (transport.pause instanceof Function) return; throw new SyntaxError("Transport is not a function nor a valid object"); } ; 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 }); } } ; 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) { if (transport) { if (transport.removeEventListener) transport.removeEventListener('message', transportMessage); else if (transport.removeListener) transport.removeListener('data', transportMessage); } ; if (value) { 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 = {}; function storeResponse(message, id, dest) { var response = { message: message, timeout: setTimeout(function () { responses.remove(id, dest); }, response_timeout) }; responses.set(response, id, dest); } ; function storeProcessedResponse(ack, from) { var timeout = setTimeout(function () { processedResponses.remove(ack, from); }, duplicates_timeout); processedResponses.set(timeout, ack, from); } ; 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); 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); this.reply = function (error, result, transport) { 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); if (response) clearTimeout(response.timeout); if (from != undefined) { if (error) error.dest = from; if (result) result.dest = from; } ; var message; if (error || result != undefined) { if (self.peerID != undefined) { if (error) error.from = self.peerID; else result.from = self.peerID; } 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); storeResponse(message, id, from); 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); storeProcessedResponse(key.id, key.dest); } ; this.cancel = function (message) { if (message) return cancel(message); for (var message in message2Key) cancel(message); }; this.close = function () { var transport = this.getTransport(); if (transport && transport.close) transport.close(); this.cancel(); processedResponses.forEach(clearTimeout); responses.forEach(function (response) { clearTimeout(response.timeout); }); }; this.encode = function (method, params, dest, transport, callback) { 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; } ; 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); } ; message = packer.pack(message); transport = transport || this.getTransport(); if (transport) return transport.send(message); return message; }; this.decode = function (message, transport) { if (!message) throw new TypeError("Message is not defined"); try { message = packer.unpack(message); } catch (e) { 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; if (self.peerID != undefined && from == self.peerID) return; if (id == undefined && ack == undefined) { var notification = new RpcNotification(method, params); if (self.emit('request', notification)) return; return notification; } ; function processRequest() { 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); clearTimeout(timeout); storeProcessedResponse(ack, from); } ; if (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); } return processRequest(); } ; var error = message.error; var result = message.result; if (error && error.dest && error.dest != self.peerID) return; if (result && result.dest && result.dest != self.peerID) return; 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); } ; processResponse(request, error, result); }; } ; inherits(RpcBuilder, EventEmitter); RpcBuilder.RpcNotification = RpcNotification; module.exports = RpcBuilder; var clients = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/index.js"); var transports = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/clients/transports/index.js"); RpcBuilder.clients = clients; RpcBuilder.clients.transports = transports; RpcBuilder.packers = packers; //# sourceMappingURL=index.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/packers/JsonRPC.js": /***/ (function(module, exports) { function pack(message, id) { var result = { jsonrpc: "2.0" }; if (message.method) { result.method = message.method; if (message.params) result.params = message.params; 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); } ; function unpack(message) { var result = message; if (typeof message === 'string' || message instanceof String) { result = JSON.parse(message); } var version = result.jsonrpc; if (version !== '2.0') throw new TypeError("Invalid JsonRPC version '" + version + "': " + message); 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; 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 result; } ; exports.pack = pack; exports.unpack = unpack; //# sourceMappingURL=JsonRPC.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/packers/XmlRPC.js": /***/ (function(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; //# sourceMappingURL=XmlRPC.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/packers/index.js": /***/ (function(module, exports, __webpack_require__) { var JsonRPC = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/packers/JsonRPC.js"); var XmlRPC = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-jsonrpc/packers/XmlRPC.js"); exports.JsonRPC = JsonRPC; exports.XmlRPC = XmlRPC; //# sourceMappingURL=index.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-utils-js/WebRtcPeer.js": /***/ (function(module, exports, __webpack_require__) { var freeice = __webpack_require__("../../../../../openvidu-browser2/node_modules/freeice/index.js"); var inherits = __webpack_require__("../../../../../openvidu-browser2/node_modules/inherits/inherits_browser.js"); var UAParser = __webpack_require__("../../../../../openvidu-browser2/node_modules/ua-parser-js/src/ua-parser.js"); var uuid = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/index.js"); var hark = __webpack_require__("../../../../../openvidu-browser2/node_modules/hark/hark.js"); var EventEmitter = __webpack_require__("./node_modules/events/events.js").EventEmitter; var recursive = __webpack_require__("../../../../../openvidu-browser2/node_modules/merge/merge.js").recursive.bind(undefined, true); var sdpTranslator = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-translator/lib/index.js"); var logger = window.Logger || console; var MEDIA_CONSTRAINTS = { audio: true, video: { width: 640, framerate: 15 } }; 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); } 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(); pc.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 }); } }; } 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'); } 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 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; } }, 'currentFrame': { get: function () { 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; } } }); if (!pc) { pc = new RTCPeerConnection(configuration); } 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) { candidatesQueueOut.push(candidate); if (!candidate) candidategatheringdone = true; } }); pc.onaddstream = 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); 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; 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) }; 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) { remoteVideo.pause(); var stream = pc.getRemoteStreams()[0]; remoteVideo.srcObject = stream; logger.debug('Remote stream:', stream); remoteVideo.load(); } } this.showLocalVideo = function () { localVideo.srcObject = videoStream; localVideo.muted = true; }; 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); }; 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; } 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); } 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.srcObject = null; localVideo.load(); localVideo.muted = false; } if (remoteVideo) { remoteVideo.pause(); remoteVideo.srcObject = null; 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 () { 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]; } }; WebRtcPeer.prototype.dispose = function () { logger.debug('Disposing WebRtcPeer'); var pc = this.peerConnection; try { if (pc) { if (pc.signalingState === 'closed') return; pc.getLocalStreams().forEach(streamStop); pc.close(); } } catch (err) { logger.warn('Exception disposing webrtc peer ' + err); } this.emit('_dispose'); }; 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; //# sourceMappingURL=WebRtcPeer.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-utils-js/index.js": /***/ (function(module, exports, __webpack_require__) { var WebRtcPeer = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/KurentoUtils/kurento-utils-js/WebRtcPeer.js"); exports.WebRtcPeer = WebRtcPeer; //# sourceMappingURL=index.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/ScreenSharing/Screen-Capturing-Auto.js": /***/ (function(module, exports) { window.getScreenId = function (callback) { if (!!navigator.mozGetUserMedia) { callback(null, 'firefox', { video: { mozMediaSource: 'window', mediaSource: 'window' } }); return; } window.addEventListener('message', onIFrameCallback); function onIFrameCallback(event) { if (!event.data) return; if (event.data.chromeMediaSourceId) { if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { callback('permission-denied'); } else callback(null, event.data.chromeMediaSourceId, getScreenConstraints(null, event.data.chromeMediaSourceId)); } if (event.data.chromeExtensionStatus) { callback(event.data.chromeExtensionStatus, null, getScreenConstraints(event.data.chromeExtensionStatus)); } window.removeEventListener('message', onIFrameCallback); } setTimeout(postGetSourceIdMessage, 100); }; function getScreenConstraints(error, sourceId) { var screen_constraints = { audio: false, video: { mandatory: { chromeMediaSource: error ? 'screen' : 'desktop', maxWidth: window.screen.width > 1920 ? window.screen.width : 1920, maxHeight: window.screen.height > 1080 ? window.screen.height : 1080 }, optional: [] } }; if (sourceId) { screen_constraints.video.mandatory.chromeMediaSourceId = sourceId; } return screen_constraints; } function postGetSourceIdMessage() { if (!iframe) { loadIFrame(postGetSourceIdMessage); return; } if (!iframe.isLoaded) { setTimeout(postGetSourceIdMessage, 100); return; } iframe.contentWindow.postMessage({ captureSourceId: true }, '*'); } var iframe; window.getScreenConstraints = function (callback) { loadIFrame(function () { getScreenId(function (error, sourceId, screen_constraints) { callback(error, screen_constraints.video); }); }); }; function loadIFrame(loadCallback) { if (iframe) { loadCallback(); return; } iframe = document.createElement('iframe'); iframe.onload = function () { iframe.isLoaded = true; loadCallback(); }; iframe.src = 'https://www.webrtc-experiment.com/getSourceId/'; iframe.style.display = 'none'; (document.body || document.documentElement).appendChild(iframe); } window.getChromeExtensionStatus = function (callback) { if (!!navigator.mozGetUserMedia) { callback('installed-enabled'); return; } window.addEventListener('message', onIFrameCallback); function onIFrameCallback(event) { if (!event.data) return; if (event.data.chromeExtensionStatus) { callback(event.data.chromeExtensionStatus); } window.removeEventListener('message', onIFrameCallback); } setTimeout(postGetChromeExtensionStatusMessage, 100); }; function postGetChromeExtensionStatusMessage() { if (!iframe) { loadIFrame(postGetChromeExtensionStatusMessage); return; } if (!iframe.isLoaded) { setTimeout(postGetChromeExtensionStatusMessage, 100); return; } iframe.contentWindow.postMessage({ getChromeExtensionStatus: true }, '*'); } exports.getScreenId = getScreenId; exports.getChromeExtensionStatus = getChromeExtensionStatus; //# sourceMappingURL=Screen-Capturing-Auto.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/OpenViduInternal/WebRtcStats/WebRtcStats.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* * (C) Copyright 2017-2018 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. * */ exports.__esModule = true; var DetectRTC = __webpack_require__("../../../../../openvidu-browser2/lib/OpenViduInternal/DetectRTC/DetectRTC.js"); var WebRtcStats = /** @class */ (function () { function WebRtcStats(stream) { this.stream = stream; this.webRtcStatsEnabled = false; this.statsInterval = 1; this.stats = { inbound: { audio: { bytesReceived: 0, packetsReceived: 0, packetsLost: 0 }, video: { bytesReceived: 0, packetsReceived: 0, packetsLost: 0, framesDecoded: 0, nackCount: 0 } }, outbound: { audio: { bytesSent: 0, packetsSent: 0 }, video: { bytesSent: 0, packetsSent: 0, framesEncoded: 0, nackCount: 0 } } }; } WebRtcStats.prototype.isEnabled = function () { return this.webRtcStatsEnabled; }; WebRtcStats.prototype.initWebRtcStats = function () { var _this = this; var elastestInstrumentation = localStorage.getItem('elastest-instrumentation'); if (elastestInstrumentation) { // ElasTest instrumentation object found in local storage console.warn('WebRtc stats enabled for stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); this.webRtcStatsEnabled = true; var instrumentation_1 = JSON.parse(elastestInstrumentation); this.statsInterval = instrumentation_1.webrtc.interval; // Interval in seconds console.warn('localStorage item: ' + JSON.stringify(instrumentation_1)); this.webRtcStatsIntervalId = setInterval(function () { _this.sendStatsToHttpEndpoint(instrumentation_1); }, this.statsInterval * 1000); return; } console.debug('WebRtc stats not enabled'); }; WebRtcStats.prototype.stopWebRtcStats = function () { if (this.webRtcStatsEnabled) { clearInterval(this.webRtcStatsIntervalId); console.warn('WebRtc stats stopped for disposed stream ' + this.stream.streamId + ' of connection ' + this.stream.connection.connectionId); } }; WebRtcStats.prototype.sendStatsToHttpEndpoint = function (instrumentation) { var _this = this; var sendPost = function (json) { var http = new XMLHttpRequest(); var url = instrumentation.webrtc.httpEndpoint; http.open('POST', url, true); http.setRequestHeader('Content-type', 'application/json'); http.onreadystatechange = function () { if (http.readyState === 4 && http.status === 200) { console.log('WebRtc stats succesfully sent to ' + url + ' for stream ' + _this.stream.streamId + ' of connection ' + _this.stream.connection.connectionId); } }; http.send(json); }; var f = function (stats) { if (DetectRTC.browser.name === 'Firefox') { stats.forEach(function (stat) { var json = {}; if ((stat.type === 'inbound-rtp') && ( // Avoid firefox empty outbound-rtp statistics stat.nackCount !== null && stat.isRemote === false && stat.id.startsWith('inbound') && stat.remoteId.startsWith('inbound'))) { var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; var jit = stat.jitter * 1000; var metrics = { bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, jitter: jit, packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval }; var units = { bytesReceived: 'bytes', jitter: 'ms', packetsReceived: 'packets', packetsLost: 'packets' }; if (stat.mediaType === 'video') { metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; metrics['nackCount'] = (stat.nackCount - _this.stats.inbound.video.nackCount) / _this.statsInterval; units['framesDecoded'] = 'frames'; units['nackCount'] = 'packets'; _this.stats.inbound.video.framesDecoded = stat.framesDecoded; _this.stats.inbound.video.nackCount = stat.nackCount; } _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; json = { '@timestamp': new Date(stat.timestamp).toISOString(), 'exec': instrumentation.exec, 'component': instrumentation.component, 'stream': 'webRtc', 'type': metricId, 'stream_type': 'composed_metrics', 'units': units }; json[metricId] = metrics; sendPost(JSON.stringify(json)); } else if ((stat.type === 'outbound-rtp') && ( // Avoid firefox empty inbound-rtp statistics stat.isRemote === false && stat.id.toLowerCase().includes('outbound'))) { var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; var metrics = { bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval }; var units = { bytesSent: 'bytes', packetsSent: 'packets' }; if (stat.mediaType === 'video') { metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; units['framesEncoded'] = 'frames'; _this.stats.outbound.video.framesEncoded = stat.framesEncoded; } _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; json = { '@timestamp': new Date(stat.timestamp).toISOString(), 'exec': instrumentation.exec, 'component': instrumentation.component, 'stream': 'webRtc', 'type': metricId, 'stream_type': 'composed_metrics', 'units': units }; json[metricId] = metrics; sendPost(JSON.stringify(json)); } }); } else if (DetectRTC.browser.name === 'Chrome') { for (var _i = 0, _a = Object.keys(stats); _i < _a.length; _i++) { var key = _a[_i]; var stat = stats[key]; if (stat.type === 'ssrc') { var json = {}; if ('bytesReceived' in stat && ((stat.mediaType === 'audio' && 'audioOutputLevel' in stat) || (stat.mediaType === 'video' && 'qpSum' in stat))) { // inbound-rtp var metricId = 'webrtc_inbound_' + stat.mediaType + '_' + stat.ssrc; var metrics = { bytesReceived: (stat.bytesReceived - _this.stats.inbound[stat.mediaType].bytesReceived) / _this.statsInterval, jitter: stat.googJitterBufferMs, packetsReceived: (stat.packetsReceived - _this.stats.inbound[stat.mediaType].packetsReceived) / _this.statsInterval, packetsLost: (stat.packetsLost - _this.stats.inbound[stat.mediaType].packetsLost) / _this.statsInterval }; var units = { bytesReceived: 'bytes', jitter: 'ms', packetsReceived: 'packets', packetsLost: 'packets' }; if (stat.mediaType === 'video') { metrics['framesDecoded'] = (stat.framesDecoded - _this.stats.inbound.video.framesDecoded) / _this.statsInterval; metrics['nackCount'] = (stat.googNacksSent - _this.stats.inbound.video.nackCount) / _this.statsInterval; units['framesDecoded'] = 'frames'; units['nackCount'] = 'packets'; _this.stats.inbound.video.framesDecoded = stat.framesDecoded; _this.stats.inbound.video.nackCount = stat.googNacksSent; } _this.stats.inbound[stat.mediaType].bytesReceived = stat.bytesReceived; _this.stats.inbound[stat.mediaType].packetsReceived = stat.packetsReceived; _this.stats.inbound[stat.mediaType].packetsLost = stat.packetsLost; json = { '@timestamp': new Date(stat.timestamp).toISOString(), 'exec': instrumentation.exec, 'component': instrumentation.component, 'stream': 'webRtc', 'type': metricId, 'stream_type': 'composed_metrics', 'units': units }; json[metricId] = metrics; sendPost(JSON.stringify(json)); } else if ('bytesSent' in stat) { // outbound-rtp var metricId = 'webrtc_outbound_' + stat.mediaType + '_' + stat.ssrc; var metrics = { bytesSent: (stat.bytesSent - _this.stats.outbound[stat.mediaType].bytesSent) / _this.statsInterval, packetsSent: (stat.packetsSent - _this.stats.outbound[stat.mediaType].packetsSent) / _this.statsInterval }; var units = { bytesSent: 'bytes', packetsSent: 'packets' }; if (stat.mediaType === 'video') { metrics['framesEncoded'] = (stat.framesEncoded - _this.stats.outbound.video.framesEncoded) / _this.statsInterval; units['framesEncoded'] = 'frames'; _this.stats.outbound.video.framesEncoded = stat.framesEncoded; } _this.stats.outbound[stat.mediaType].bytesSent = stat.bytesSent; _this.stats.outbound[stat.mediaType].packetsSent = stat.packetsSent; json = { '@timestamp': new Date(stat.timestamp).toISOString(), 'exec': instrumentation.exec, 'component': instrumentation.component, 'stream': 'webRtc', 'type': metricId, 'stream_type': 'composed_metrics', 'units': units }; json[metricId] = metrics; sendPost(JSON.stringify(json)); } } } } }; this.getStatsAgnostic(this.stream.getRTCPeerConnection(), f, function (error) { console.log(error); }); }; WebRtcStats.prototype.standardizeReport = function (response) { if (DetectRTC.browser.name === 'Firefox') { return response; } var standardReport = {}; response.result().forEach(function (report) { var standardStats = { id: report.id, timestamp: report.timestamp, type: report.type }; report.names().forEach(function (name) { standardStats[name] = report.stat(name); }); standardReport[standardStats.id] = standardStats; }); return standardReport; }; WebRtcStats.prototype.getStatsAgnostic = function (pc, successCb, failureCb) { var _this = this; if (DetectRTC.browser.name === 'Firefox') { // getStats takes args in different order in Chrome and Firefox return pc.getStats(null, function (response) { var report = _this.standardizeReport(response); successCb(report); }, failureCb); } else if (DetectRTC.browser.name === 'Chrome') { // In Chrome, the first two arguments are reversed return pc.getStats(function (response) { var report = _this.standardizeReport(response); successCb(report); }, null, failureCb); } }; return WebRtcStats; }()); exports.WebRtcStats = WebRtcStats; //# sourceMappingURL=WebRtcStats.js.map /***/ }), /***/ "../../../../../openvidu-browser2/lib/index.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; exports.__esModule = true; var OpenVidu_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/OpenVidu.js"); exports.OpenVidu = OpenVidu_1.OpenVidu; var Session_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/Session.js"); exports.Session = Session_1.Session; var Publisher_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/Publisher.js"); exports.Publisher = Publisher_1.Publisher; var Subscriber_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/Subscriber.js"); exports.Subscriber = Subscriber_1.Subscriber; var Stream_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/Stream.js"); exports.Stream = Stream_1.Stream; var Connection_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/Connection.js"); exports.Connection = Connection_1.Connection; var LocalRecorder_1 = __webpack_require__("../../../../../openvidu-browser2/lib/OpenVidu/LocalRecorder.js"); exports.LocalRecorder = LocalRecorder_1.LocalRecorder; //# sourceMappingURL=index.js.map /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/freeice/index.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* jshint node: true */ var normalice = __webpack_require__("../../../../../openvidu-browser2/node_modules/normalice/index.js"); /** # freeice The `freeice` module is a simple way of getting random STUN or TURN server for your WebRTC application. The list of servers (just STUN at this stage) were sourced from this [gist](https://gist.github.com/zziuni/3741933). ## Example Use The following demonstrates how you can use `freeice` with [rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect): <<< examples/quickconnect.js As the `freeice` module generates ice servers in a list compliant with the WebRTC spec you will be able to use it with raw `RTCPeerConnection` constructors and other WebRTC libraries. ## Hey, don't use my STUN/TURN server! If for some reason your free STUN or TURN server ends up in the list of servers ([stun](https://github.com/DamonOehlman/freeice/blob/master/stun.json) or [turn](https://github.com/DamonOehlman/freeice/blob/master/turn.json)) that is used in this module, you can feel free to open an issue on this repository and those servers will be removed within 24 hours (or sooner). This is the quickest and probably the most polite way to have something removed (and provides us some visibility if someone opens a pull request requesting that a server is added). ## Please add my server! If you have a server that you wish to add to the list, that's awesome! I'm sure I speak on behalf of a whole pile of WebRTC developers who say thanks. To get it into the list, feel free to either open a pull request or if you find that process a bit daunting then just create an issue requesting the addition of the server (make sure you provide all the details, and if you have a Terms of Service then including that in the PR/issue would be awesome). ## I know of a free server, can I add it? Sure, if you do your homework and make sure it is ok to use (I'm currently in the process of reviewing the terms of those STUN servers included from the original list). If it's ok to go, then please see the previous entry for how to add it. ## Current List of Servers * current as at the time of last `README.md` file generation ### STUN <<< stun.json ### TURN <<< turn.json **/ var freeice = module.exports = function(opts) { // if a list of servers has been provided, then use it instead of defaults var servers = { stun: (opts || {}).stun || __webpack_require__("../../../../../openvidu-browser2/node_modules/freeice/stun.json"), turn: (opts || {}).turn || __webpack_require__("../../../../../openvidu-browser2/node_modules/freeice/turn.json") }; var stunCount = (opts || {}).stunCount || 2; var turnCount = (opts || {}).turnCount || 0; var selected; function getServers(type, count) { var out = []; var input = [].concat(servers[type]); var idx; while (input.length && out.length < count) { idx = (Math.random() * input.length) | 0; out = out.concat(input.splice(idx, 1)); } return out.map(function(url) { //If it's a not a string, don't try to "normalice" it otherwise using type:url will screw it up if ((typeof url !== 'string') && (! (url instanceof String))) { return url; } else { return normalice(type + ':' + url); } }); } // add stun servers selected = [].concat(getServers('stun', stunCount)); if (turnCount) { selected = selected.concat(getServers('turn', turnCount)); } return selected; }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/freeice/stun.json": /***/ (function(module, exports) { module.exports = ["stun.l.google.com:19302","stun1.l.google.com:19302","stun2.l.google.com:19302","stun3.l.google.com:19302","stun4.l.google.com:19302","stun.ekiga.net","stun.ideasip.com","stun.schlund.de","stun.stunprotocol.org:3478","stun.voiparound.com","stun.voipbuster.com","stun.voipstunt.com","stun.voxgratia.org","stun.services.mozilla.com"] /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/freeice/turn.json": /***/ (function(module, exports) { module.exports = [] /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/hark/hark.js": /***/ (function(module, exports, __webpack_require__) { var WildEmitter = __webpack_require__("../../../../../openvidu-browser2/node_modules/wildemitter/wildemitter.js"); function getMaxVolume (analyser, fftBins) { var maxVolume = -Infinity; analyser.getFloatFrequencyData(fftBins); for(var i=4, ii=fftBins.length; i < ii; i++) { if (fftBins[i] > maxVolume && fftBins[i] < 0) { maxVolume = fftBins[i]; } }; return maxVolume; } var audioContextType; if (typeof window !== 'undefined') { audioContextType = window.AudioContext || window.webkitAudioContext; } // use a single audio context due to hardware limits var audioContext = null; module.exports = function(stream, options) { var harker = new WildEmitter(); // make it not break in non-supported browsers if (!audioContextType) return harker; //Config var options = options || {}, smoothing = (options.smoothing || 0.1), interval = (options.interval || 50), threshold = options.threshold, play = options.play, history = options.history || 10, running = true; //Setup Audio Context if (!audioContext) { audioContext = new audioContextType(); } var sourceNode, fftBins, analyser; analyser = audioContext.createAnalyser(); analyser.fftSize = 512; analyser.smoothingTimeConstant = smoothing; fftBins = new Float32Array(analyser.frequencyBinCount); if (stream.jquery) stream = stream[0]; if (stream instanceof HTMLAudioElement || stream instanceof HTMLVideoElement) { //Audio Tag sourceNode = audioContext.createMediaElementSource(stream); if (typeof play === 'undefined') play = true; threshold = threshold || -50; } else { //WebRTC Stream sourceNode = audioContext.createMediaStreamSource(stream); threshold = threshold || -50; } sourceNode.connect(analyser); if (play) analyser.connect(audioContext.destination); harker.speaking = false; harker.suspend = function() { audioContext.suspend(); } harker.resume = function() { audioContext.resume(); } Object.defineProperty(harker, 'state', { get: function() { return audioContext.state; }}); audioContext.onstatechange = function() { harker.emit('state_change', audioContext.state); } harker.setThreshold = function(t) { threshold = t; }; harker.setInterval = function(i) { interval = i; }; harker.stop = function() { running = false; harker.emit('volume_change', -100, threshold); if (harker.speaking) { harker.speaking = false; harker.emit('stopped_speaking'); } analyser.disconnect(); sourceNode.disconnect(); }; harker.speakingHistory = []; for (var i = 0; i < history; i++) { harker.speakingHistory.push(0); } // Poll the analyser node to determine if speaking // and emit events if changed var looper = function() { setTimeout(function() { //check if stop has been called if(!running) { return; } var currentVolume = getMaxVolume(analyser, fftBins); harker.emit('volume_change', currentVolume, threshold); var history = 0; if (currentVolume > threshold && !harker.speaking) { // trigger quickly, short history for (var i = harker.speakingHistory.length - 3; i < harker.speakingHistory.length; i++) { history += harker.speakingHistory[i]; } if (history >= 2) { harker.speaking = true; harker.emit('speaking'); } } else if (currentVolume < threshold && harker.speaking) { for (var i = 0; i < harker.speakingHistory.length; i++) { history += harker.speakingHistory[i]; } if (history == 0) { harker.speaking = false; harker.emit('stopped_speaking'); } } harker.speakingHistory.shift(); harker.speakingHistory.push(0 + (currentVolume > threshold)); looper(); }, interval); }; looper(); return harker; } /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/inherits/inherits_browser.js": /***/ (function(module, exports) { if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, enumerable: false, writable: true, configurable: true } }); }; } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { ctor.super_ = superCtor var TempCtor = function () {} TempCtor.prototype = superCtor.prototype ctor.prototype = new TempCtor() ctor.prototype.constructor = ctor } } /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/merge/merge.js": /***/ (function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(module) {/*! * @name JavaScript/NodeJS Merge v1.2.0 * @author yeikos * @repository https://github.com/yeikos/js.merge * Copyright 2014 yeikos - MIT license * https://raw.github.com/yeikos/js.merge/master/LICENSE */ ;(function(isNode) { /** * Merge one or more objects * @param bool? clone * @param mixed,... arguments * @return object */ var Public = function(clone) { return merge(clone === true, false, arguments); }, publicName = 'merge'; /** * Merge two or more objects recursively * @param bool? clone * @param mixed,... arguments * @return object */ Public.recursive = function(clone) { return merge(clone === true, true, arguments); }; /** * Clone the input removing any reference * @param mixed input * @return mixed */ Public.clone = function(input) { var output = input, type = typeOf(input), index, size; if (type === 'array') { output = []; size = input.length; for (index=0;index 1) { url = parts[1]; parts = parts[0].split(':'); // add the output credential and username output.username = parts[0]; output.credential = (input || {}).credential || parts[1] || ''; } output.url = protocol + url; output.urls = [ output.url ]; return output; }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-transform/lib/grammar.js": /***/ (function(module, exports) { var grammar = module.exports = { v: [{ name: 'version', reg: /^(\d*)$/ }], o: [{ //o=- 20518 0 IN IP4 203.0.113.1 // NB: sessionId will be a String in most cases because it is huge name: 'origin', reg: /^(\S*) (\d*) (\d*) (\S*) IP(\d) (\S*)/, names: ['username', 'sessionId', 'sessionVersion', 'netType', 'ipVer', 'address'], format: "%s %s %d %s IP%d %s" }], // default parsing of these only (though some of these feel outdated) s: [{ name: 'name' }], i: [{ name: 'description' }], u: [{ name: 'uri' }], e: [{ name: 'email' }], p: [{ name: 'phone' }], z: [{ name: 'timezones' }], // TODO: this one can actually be parsed properly.. r: [{ name: 'repeats' }], // TODO: this one can also be parsed properly //k: [{}], // outdated thing ignored t: [{ //t=0 0 name: 'timing', reg: /^(\d*) (\d*)/, names: ['start', 'stop'], format: "%d %d" }], c: [{ //c=IN IP4 10.47.197.26 name: 'connection', reg: /^IN IP(\d) (\S*)/, names: ['version', 'ip'], format: "IN IP%d %s" }], b: [{ //b=AS:4000 push: 'bandwidth', reg: /^(TIAS|AS|CT|RR|RS):(\d*)/, names: ['type', 'limit'], format: "%s:%s" }], m: [{ //m=video 51744 RTP/AVP 126 97 98 34 31 // NB: special - pushes to session // TODO: rtp/fmtp should be filtered by the payloads found here? reg: /^(\w*) (\d*) ([\w\/]*)(?: (.*))?/, names: ['type', 'port', 'protocol', 'payloads'], format: "%s %d %s %s" }], a: [ { //a=rtpmap:110 opus/48000/2 push: 'rtp', reg: /^rtpmap:(\d*) ([\w\-]*)(?:\s*\/(\d*)(?:\s*\/(\S*))?)?/, names: ['payload', 'codec', 'rate', 'encoding'], format: function (o) { return (o.encoding) ? "rtpmap:%d %s/%s/%s": o.rate ? "rtpmap:%d %s/%s": "rtpmap:%d %s"; } }, { //a=fmtp:108 profile-level-id=24;object=23;bitrate=64000 //a=fmtp:111 minptime=10; useinbandfec=1 push: 'fmtp', reg: /^fmtp:(\d*) ([\S| ]*)/, names: ['payload', 'config'], format: "fmtp:%d %s" }, { //a=control:streamid=0 name: 'control', reg: /^control:(.*)/, format: "control:%s" }, { //a=rtcp:65179 IN IP4 193.84.77.194 name: 'rtcp', reg: /^rtcp:(\d*)(?: (\S*) IP(\d) (\S*))?/, names: ['port', 'netType', 'ipVer', 'address'], format: function (o) { return (o.address != null) ? "rtcp:%d %s IP%d %s": "rtcp:%d"; } }, { //a=rtcp-fb:98 trr-int 100 push: 'rtcpFbTrrInt', reg: /^rtcp-fb:(\*|\d*) trr-int (\d*)/, names: ['payload', 'value'], format: "rtcp-fb:%d trr-int %d" }, { //a=rtcp-fb:98 nack rpsi push: 'rtcpFb', reg: /^rtcp-fb:(\*|\d*) ([\w-_]*)(?: ([\w-_]*))?/, names: ['payload', 'type', 'subtype'], format: function (o) { return (o.subtype != null) ? "rtcp-fb:%s %s %s": "rtcp-fb:%s %s"; } }, { //a=extmap:2 urn:ietf:params:rtp-hdrext:toffset //a=extmap:1/recvonly URI-gps-string push: 'ext', reg: /^extmap:([\w_\/]*) (\S*)(?: (\S*))?/, names: ['value', 'uri', 'config'], // value may include "/direction" suffix format: function (o) { return (o.config != null) ? "extmap:%s %s %s": "extmap:%s %s"; } }, { //a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:PS1uQCVeeCFCanVmcjkpPywjNWhcYD0mXXtxaVBR|2^20|1:32 push: 'crypto', reg: /^crypto:(\d*) ([\w_]*) (\S*)(?: (\S*))?/, names: ['id', 'suite', 'config', 'sessionConfig'], format: function (o) { return (o.sessionConfig != null) ? "crypto:%d %s %s %s": "crypto:%d %s %s"; } }, { //a=setup:actpass name: 'setup', reg: /^setup:(\w*)/, format: "setup:%s" }, { //a=mid:1 name: 'mid', reg: /^mid:([^\s]*)/, format: "mid:%s" }, { //a=msid:0c8b064d-d807-43b4-b434-f92a889d8587 98178685-d409-46e0-8e16-7ef0db0db64a name: 'msid', reg: /^msid:(.*)/, format: "msid:%s" }, { //a=ptime:20 name: 'ptime', reg: /^ptime:(\d*)/, format: "ptime:%d" }, { //a=maxptime:60 name: 'maxptime', reg: /^maxptime:(\d*)/, format: "maxptime:%d" }, { //a=sendrecv name: 'direction', reg: /^(sendrecv|recvonly|sendonly|inactive)/ }, { //a=ice-lite name: 'icelite', reg: /^(ice-lite)/ }, { //a=ice-ufrag:F7gI name: 'iceUfrag', reg: /^ice-ufrag:(\S*)/, format: "ice-ufrag:%s" }, { //a=ice-pwd:x9cml/YzichV2+XlhiMu8g name: 'icePwd', reg: /^ice-pwd:(\S*)/, format: "ice-pwd:%s" }, { //a=fingerprint:SHA-1 00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33 name: 'fingerprint', reg: /^fingerprint:(\S*) (\S*)/, names: ['type', 'hash'], format: "fingerprint:%s %s" }, { //a=candidate:0 1 UDP 2113667327 203.0.113.1 54400 typ host //a=candidate:1162875081 1 udp 2113937151 192.168.34.75 60017 typ host generation 0 //a=candidate:3289912957 2 udp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 generation 0 //a=candidate:229815620 1 tcp 1518280447 192.168.150.19 60017 typ host tcptype active generation 0 //a=candidate:3289912957 2 tcp 1845501695 193.84.77.194 60017 typ srflx raddr 192.168.34.75 rport 60017 tcptype passive generation 0 push:'candidates', reg: /^candidate:(\S*) (\d*) (\S*) (\d*) (\S*) (\d*) typ (\S*)(?: raddr (\S*) rport (\d*))?(?: tcptype (\S*))?(?: generation (\d*))?/, names: ['foundation', 'component', 'transport', 'priority', 'ip', 'port', 'type', 'raddr', 'rport', 'tcptype', 'generation'], format: function (o) { var str = "candidate:%s %d %s %d %s %d typ %s"; str += (o.raddr != null) ? " raddr %s rport %d" : "%v%v"; // NB: candidate has three optional chunks, so %void middles one if it's missing str += (o.tcptype != null) ? " tcptype %s" : "%v"; if (o.generation != null) { str += " generation %d"; } return str; } }, { //a=end-of-candidates (keep after the candidates line for readability) name: 'endOfCandidates', reg: /^(end-of-candidates)/ }, { //a=remote-candidates:1 203.0.113.1 54400 2 203.0.113.1 54401 ... name: 'remoteCandidates', reg: /^remote-candidates:(.*)/, format: "remote-candidates:%s" }, { //a=ice-options:google-ice name: 'iceOptions', reg: /^ice-options:(\S*)/, format: "ice-options:%s" }, { //a=ssrc:2566107569 cname:t9YU8M1UxTF8Y1A1 push: "ssrcs", reg: /^ssrc:(\d*) ([\w_]*):(.*)/, names: ['id', 'attribute', 'value'], format: "ssrc:%d %s:%s" }, { //a=ssrc-group:FEC 1 2 push: "ssrcGroups", reg: /^ssrc-group:(\w*) (.*)/, names: ['semantics', 'ssrcs'], format: "ssrc-group:%s %s" }, { //a=msid-semantic: WMS Jvlam5X3SX1OP6pn20zWogvaKJz5Hjf9OnlV name: "msidSemantic", reg: /^msid-semantic:\s?(\w*) (\S*)/, names: ['semantic', 'token'], format: "msid-semantic: %s %s" // space after ":" is not accidental }, { //a=group:BUNDLE audio video push: 'groups', reg: /^group:(\w*) (.*)/, names: ['type', 'mids'], format: "group:%s %s" }, { //a=rtcp-mux name: 'rtcpMux', reg: /^(rtcp-mux)/ }, { //a=rtcp-rsize name: 'rtcpRsize', reg: /^(rtcp-rsize)/ }, { // any a= that we don't understand is kepts verbatim on media.invalid push: 'invalid', names: ["value"] } ] }; // set sensible defaults to avoid polluting the grammar with boring details Object.keys(grammar).forEach(function (key) { var objs = grammar[key]; objs.forEach(function (obj) { if (!obj.reg) { obj.reg = /(.*)/; } if (!obj.format) { obj.format = "%s"; } }); }); /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-transform/lib/index.js": /***/ (function(module, exports, __webpack_require__) { var parser = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-transform/lib/parser.js"); var writer = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-transform/lib/writer.js"); exports.write = writer; exports.parse = parser.parse; exports.parseFmtpConfig = parser.parseFmtpConfig; exports.parsePayloads = parser.parsePayloads; exports.parseRemoteCandidates = parser.parseRemoteCandidates; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-transform/lib/parser.js": /***/ (function(module, exports, __webpack_require__) { var toIntIfInt = function (v) { return String(Number(v)) === v ? Number(v) : v; }; var attachProperties = function (match, location, names, rawName) { if (rawName && !names) { location[rawName] = toIntIfInt(match[1]); } else { for (var i = 0; i < names.length; i += 1) { if (match[i+1] != null) { location[names[i]] = toIntIfInt(match[i+1]); } } } }; var parseReg = function (obj, location, content) { var needsBlank = obj.name && obj.names; if (obj.push && !location[obj.push]) { location[obj.push] = []; } else if (needsBlank && !location[obj.name]) { location[obj.name] = {}; } var keyLocation = obj.push ? {} : // blank object that will be pushed needsBlank ? location[obj.name] : location; // otherwise, named location or root attachProperties(content.match(obj.reg), keyLocation, obj.names, obj.name); if (obj.push) { location[obj.push].push(keyLocation); } }; var grammar = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-transform/lib/grammar.js"); var validLine = RegExp.prototype.test.bind(/^([a-z])=(.*)/); exports.parse = function (sdp) { var session = {} , media = [] , location = session; // points at where properties go under (one of the above) // parse lines we understand sdp.split(/(\r\n|\r|\n)/).filter(validLine).forEach(function (l) { var type = l[0]; var content = l.slice(2); if (type === 'm') { media.push({rtp: [], fmtp: []}); location = media[media.length-1]; // point at latest media line } for (var j = 0; j < (grammar[type] || []).length; j += 1) { var obj = grammar[type][j]; if (obj.reg.test(content)) { return parseReg(obj, location, content); } } }); session.media = media; // link it up return session; }; var fmtpReducer = function (acc, expr) { var s = expr.split('='); if (s.length === 2) { acc[s[0]] = toIntIfInt(s[1]); } return acc; }; exports.parseFmtpConfig = function (str) { return str.split(/\;\s?/).reduce(fmtpReducer, {}); }; exports.parsePayloads = function (str) { return str.split(' ').map(Number); }; exports.parseRemoteCandidates = function (str) { var candidates = []; var parts = str.split(' ').map(toIntIfInt); for (var i = 0; i < parts.length; i += 3) { candidates.push({ component: parts[i], ip: parts[i + 1], port: parts[i + 2] }); } return candidates; }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-transform/lib/writer.js": /***/ (function(module, exports, __webpack_require__) { var grammar = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-transform/lib/grammar.js"); // customized util.format - discards excess arguments and can void middle ones var formatRegExp = /%[sdv%]/g; var format = function (formatStr) { var i = 1; var args = arguments; var len = args.length; return formatStr.replace(formatRegExp, function (x) { if (i >= len) { return x; // missing argument } var arg = args[i]; i += 1; switch (x) { case '%%': return '%'; case '%s': return String(arg); case '%d': return Number(arg); case '%v': return ''; } }); // NB: we discard excess arguments - they are typically undefined from makeLine }; var makeLine = function (type, obj, location) { var str = obj.format instanceof Function ? (obj.format(obj.push ? location : location[obj.name])) : obj.format; var args = [type + '=' + str]; if (obj.names) { for (var i = 0; i < obj.names.length; i += 1) { var n = obj.names[i]; if (obj.name) { args.push(location[obj.name][n]); } else { // for mLine and push attributes args.push(location[obj.names[i]]); } } } else { args.push(location[obj.name]); } return format.apply(null, args); }; // RFC specified order // TODO: extend this with all the rest var defaultOuterOrder = [ 'v', 'o', 's', 'i', 'u', 'e', 'p', 'c', 'b', 't', 'r', 'z', 'a' ]; var defaultInnerOrder = ['i', 'c', 'b', 'a']; module.exports = function (session, opts) { opts = opts || {}; // ensure certain properties exist if (session.version == null) { session.version = 0; // "v=0" must be there (only defined version atm) } if (session.name == null) { session.name = " "; // "s= " must be there if no meaningful name set } session.media.forEach(function (mLine) { if (mLine.payloads == null) { mLine.payloads = ""; } }); var outerOrder = opts.outerOrder || defaultOuterOrder; var innerOrder = opts.innerOrder || defaultInnerOrder; var sdp = []; // loop through outerOrder for matching properties on session outerOrder.forEach(function (type) { grammar[type].forEach(function (obj) { if (obj.name in session && session[obj.name] != null) { sdp.push(makeLine(type, obj, session)); } else if (obj.push in session && session[obj.push] != null) { session[obj.push].forEach(function (el) { sdp.push(makeLine(type, obj, el)); }); } }); }); // then for each media line, follow the innerOrder session.media.forEach(function (mLine) { sdp.push(makeLine('m', grammar.m[0], mLine)); innerOrder.forEach(function (type) { grammar[type].forEach(function (obj) { if (obj.name in mLine && mLine[obj.name] != null) { sdp.push(makeLine(type, obj, mLine)); } else if (obj.push in mLine && mLine[obj.push] != null) { mLine[obj.push].forEach(function (el) { sdp.push(makeLine(type, obj, el)); }); } }); }); }); return sdp.join('\r\n') + '\r\n'; }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-translator/lib/array-equals.js": /***/ (function(module, exports) { /* Copyright @ 2015 Atlassian Pty Ltd * * 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. */ module.exports = function arrayEquals(array) { // if the other array is a falsy value, return if (!array) return false; // compare lengths - can save a lot of time if (this.length != array.length) return false; for (var i = 0, l = this.length; i < l; i++) { // Check if we have nested arrays if (this[i] instanceof Array && array[i] instanceof Array) { // recurse into the nested arrays if (!arrayEquals.apply(this[i], [array[i]])) return false; } else if (this[i] != array[i]) { // Warning - two different object instances will never be equal: // {x:20} != {x:20} return false; } } return true; }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-translator/lib/index.js": /***/ (function(module, exports, __webpack_require__) { /* Copyright @ 2015 Atlassian Pty Ltd * * 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. */ exports.Interop = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-translator/lib/interop.js"); /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-translator/lib/interop.js": /***/ (function(module, exports, __webpack_require__) { "use strict"; /* Copyright @ 2015 Atlassian Pty Ltd * * 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. */ /* global RTCSessionDescription */ /* global RTCIceCandidate */ /* jshint -W097 */ var transform = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-translator/lib/transform.js"); var arrayEquals = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-translator/lib/array-equals.js"); function Interop() { /** * This map holds the most recent Unified Plan offer/answer SDP that was * converted to Plan B, with the SDP type ('offer' or 'answer') as keys and * the SDP string as values. * * @type {{}} */ this.cache = { mlB2UMap : {}, mlU2BMap : {} }; } module.exports = Interop; /** * Changes the candidate args to match with the related Unified Plan */ Interop.prototype.candidateToUnifiedPlan = function(candidate) { var cand = new RTCIceCandidate(candidate); cand.sdpMLineIndex = this.cache.mlB2UMap[cand.sdpMLineIndex]; /* TODO: change sdpMid to (audio|video)-SSRC */ return cand; }; /** * Changes the candidate args to match with the related Plan B */ Interop.prototype.candidateToPlanB = function(candidate) { var cand = new RTCIceCandidate(candidate); if (cand.sdpMid.indexOf('audio') === 0) { cand.sdpMid = 'audio'; } else if (cand.sdpMid.indexOf('video') === 0) { cand.sdpMid = 'video'; } else { throw new Error('candidate with ' + cand.sdpMid + ' not allowed'); } cand.sdpMLineIndex = this.cache.mlU2BMap[cand.sdpMLineIndex]; return cand; }; /** * Returns the index of the first m-line with the given media type and with a * direction which allows sending, in the last Unified Plan description with * type "answer" converted to Plan B. Returns {null} if there is no saved * answer, or if none of its m-lines with the given type allow sending. * @param type the media type ("audio" or "video"). * @returns {*} */ Interop.prototype.getFirstSendingIndexFromAnswer = function(type) { if (!this.cache.answer) { return null; } var session = transform.parse(this.cache.answer); if (session && session.media && Array.isArray(session.media)){ for (var i = 0; i < session.media.length; i++) { if (session.media[i].type == type && (!session.media[i].direction /* default to sendrecv */ || session.media[i].direction === 'sendrecv' || session.media[i].direction === 'sendonly')){ return i; } } } return null; }; /** * This method transforms a Unified Plan SDP to an equivalent Plan B SDP. A * PeerConnection wrapper transforms the SDP to Plan B before passing it to the * application. * * @param desc * @returns {*} */ Interop.prototype.toPlanB = function(desc) { var self = this; //#region Preliminary input validation. if (typeof desc !== 'object' || desc === null || typeof desc.sdp !== 'string') { console.warn('An empty description was passed as an argument.'); return desc; } // Objectify the SDP for easier manipulation. var session = transform.parse(desc.sdp); // If the SDP contains no media, there's nothing to transform. if (typeof session.media === 'undefined' || !Array.isArray(session.media) || session.media.length === 0) { console.warn('The description has no media.'); return desc; } // Try some heuristics to "make sure" this is a Unified Plan SDP. Plan B // SDP has a video, an audio and a data "channel" at most. if (session.media.length <= 3 && session.media.every(function(m) { return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; })) { console.warn('This description does not look like Unified Plan.'); return desc; } //#endregion // HACK https://bugzilla.mozilla.org/show_bug.cgi?id=1113443 var sdp = desc.sdp; var rewrite = false; for (var i = 0; i < session.media.length; i++) { var uLine = session.media[i]; uLine.rtp.forEach(function(rtp) { if (rtp.codec === 'NULL') { rewrite = true; var offer = transform.parse(self.cache.offer); rtp.codec = offer.media[i].rtp[0].codec; } }); } if (rewrite) { sdp = transform.write(session); } // Unified Plan SDP is our "precious". Cache it for later use in the Plan B // -> Unified Plan transformation. this.cache[desc.type] = sdp; //#region Convert from Unified Plan to Plan B. // We rebuild the session.media array. var media = session.media; session.media = []; // Associative array that maps channel types to channel objects for fast // access to channel objects by their type, e.g. type2bl['audio']->channel // obj. var type2bl = {}; // Used to build the group:BUNDLE value after the channels construction // loop. var types = []; media.forEach(function(uLine) { // rtcp-mux is required in the Plan B SDP. if ((typeof uLine.rtcpMux !== 'string' || uLine.rtcpMux !== 'rtcp-mux') && uLine.direction !== 'inactive') { throw new Error('Cannot convert to Plan B because m-lines ' + 'without the rtcp-mux attribute were found.'); } // If we don't have a channel for this uLine.type OR the selected is // inactive, then select this uLine as the channel basis. if (typeof type2bl[uLine.type] === 'undefined' || type2bl[uLine.type].direction === 'inactive') { type2bl[uLine.type] = uLine; } if (uLine.protocol != type2bl[uLine.type].protocol) { throw new Error('Cannot convert to Plan B because m-lines ' + 'have different protocols and this library does not have ' + 'support for that'); } if (uLine.payloads != type2bl[uLine.type].payloads) { throw new Error('Cannot convert to Plan B because m-lines ' + 'have different payloads and this library does not have ' + 'support for that'); } }); // Implode the Unified Plan m-lines/tracks into Plan B channels. media.forEach(function(uLine) { if (uLine.type === 'application') { session.media.push(uLine); types.push(uLine.mid); return; } // Add sources to the channel and handle a=msid. if (typeof uLine.sources === 'object') { Object.keys(uLine.sources).forEach(function(ssrc) { if (typeof type2bl[uLine.type].sources !== 'object') type2bl[uLine.type].sources = {}; // Assign the sources to the channel. type2bl[uLine.type].sources[ssrc] = uLine.sources[ssrc]; if (typeof uLine.msid !== 'undefined') { // In Plan B the msid is an SSRC attribute. Also, we don't // care about the obsolete label and mslabel attributes. // // Note that it is not guaranteed that the uLine will // have an msid. recvonly channels in particular don't have // one. type2bl[uLine.type].sources[ssrc].msid = uLine.msid; } // NOTE ssrcs in ssrc groups will share msids, as // draft-uberti-rtcweb-plan-00 mandates. }); } // Add ssrc groups to the channel. if (typeof uLine.ssrcGroups !== 'undefined' && Array.isArray(uLine.ssrcGroups)) { // Create the ssrcGroups array, if it's not defined. if (typeof type2bl[uLine.type].ssrcGroups === 'undefined' || !Array.isArray(type2bl[uLine.type].ssrcGroups)) { type2bl[uLine.type].ssrcGroups = []; } type2bl[uLine.type].ssrcGroups = type2bl[uLine.type].ssrcGroups.concat( uLine.ssrcGroups); } if (type2bl[uLine.type] === uLine) { // Plan B mids are in ['audio', 'video', 'data'] uLine.mid = uLine.type; // Plan B doesn't support/need the bundle-only attribute. delete uLine.bundleOnly; // In Plan B the msid is an SSRC attribute. delete uLine.msid; if (uLine.type == media[0].type) { types.unshift(uLine.type); // Add the channel to the new media array. session.media.unshift(uLine); } else { types.push(uLine.type); // Add the channel to the new media array. session.media.push(uLine); } } }); if (typeof session.groups !== 'undefined') { // We regenerate the BUNDLE group with the new mids. session.groups.some(function(group) { if (group.type === 'BUNDLE') { group.mids = types.join(' '); return true; } }); } // msid semantic session.msidSemantic = { semantic: 'WMS', token: '*' }; var resStr = transform.write(session); return new RTCSessionDescription({ type: desc.type, sdp: resStr }); //#endregion }; /* follow rules defined in RFC4145 */ function addSetupAttr(uLine) { if (typeof uLine.setup === 'undefined') { return; } if (uLine.setup === "active") { uLine.setup = "passive"; } else if (uLine.setup === "passive") { uLine.setup = "active"; } } /** * This method transforms a Plan B SDP to an equivalent Unified Plan SDP. A * PeerConnection wrapper transforms the SDP to Unified Plan before passing it * to FF. * * @param desc * @returns {*} */ Interop.prototype.toUnifiedPlan = function(desc) { var self = this; //#region Preliminary input validation. if (typeof desc !== 'object' || desc === null || typeof desc.sdp !== 'string') { console.warn('An empty description was passed as an argument.'); return desc; } var session = transform.parse(desc.sdp); // If the SDP contains no media, there's nothing to transform. if (typeof session.media === 'undefined' || !Array.isArray(session.media) || session.media.length === 0) { console.warn('The description has no media.'); return desc; } // Try some heuristics to "make sure" this is a Plan B SDP. Plan B SDP has // a video, an audio and a data "channel" at most. if (session.media.length > 3 || !session.media.every(function(m) { return ['video', 'audio', 'data'].indexOf(m.mid) !== -1; })) { console.warn('This description does not look like Plan B.'); return desc; } // Make sure this Plan B SDP can be converted to a Unified Plan SDP. var mids = []; session.media.forEach(function(m) { mids.push(m.mid); }); var hasBundle = false; if (typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { hasBundle = session.groups.every(function(g) { return g.type !== 'BUNDLE' || arrayEquals.apply(g.mids.sort(), [mids.sort()]); }); } if (!hasBundle) { var mustBeBundle = false; session.media.forEach(function(m) { if (m.direction !== 'inactive') { mustBeBundle = true; } }); if (mustBeBundle) { throw new Error("Cannot convert to Unified Plan because m-lines that" + " are not bundled were found."); } } //#endregion //#region Convert from Plan B to Unified Plan. // Unfortunately, a Plan B offer/answer doesn't have enough information to // rebuild an equivalent Unified Plan offer/answer. // // For example, if this is a local answer (in Unified Plan style) that we // convert to Plan B prior to handing it over to the application (the // PeerConnection wrapper called us, for instance, after a successful // createAnswer), we want to remember the m-line at which we've seen the // (local) SSRC. That's because when the application wants to do call the // SLD method, forcing us to do the inverse transformation (from Plan B to // Unified Plan), we need to know to which m-line to assign the (local) // SSRC. We also need to know all the other m-lines that the original // answer had and include them in the transformed answer as well. // // Another example is if this is a remote offer that we convert to Plan B // prior to giving it to the application, we want to remember the mid at // which we've seen the (remote) SSRC. // // In the iteration that follows, we use the cached Unified Plan (if it // exists) to assign mids to ssrcs. var type; if (desc.type === 'answer') { type = 'offer'; } else if (desc.type === 'offer') { type = 'answer'; } else { throw new Error("Type '" + desc.type + "' not supported."); } var cached; if (typeof this.cache[type] !== 'undefined') { cached = transform.parse(this.cache[type]); } var recvonlySsrcs = { audio: {}, video: {} }; // A helper map that sends mids to m-line objects. We use it later to // rebuild the Unified Plan style session.media array. var mid2ul = {}; var bIdx = 0; var uIdx = 0; var sources2ul = {}; var candidates; var iceUfrag; var icePwd; var fingerprint; var payloads = {}; var rtcpFb = {}; var rtp = {}; session.media.forEach(function(bLine) { if ((typeof bLine.rtcpMux !== 'string' || bLine.rtcpMux !== 'rtcp-mux') && bLine.direction !== 'inactive') { throw new Error("Cannot convert to Unified Plan because m-lines " + "without the rtcp-mux attribute were found."); } if (bLine.type === 'application') { mid2ul[bLine.mid] = bLine; return; } // With rtcp-mux and bundle all the channels should have the same ICE // stuff. var sources = bLine.sources; var ssrcGroups = bLine.ssrcGroups; var port = bLine.port; /* Chrome adds different candidates even using bundle, so we concat the candidates list */ if (typeof bLine.candidates != 'undefined') { if (typeof candidates != 'undefined') { candidates = candidates.concat(bLine.candidates); } else { candidates = bLine.candidates; } } if ((typeof iceUfrag != 'undefined') && (typeof bLine.iceUfrag != 'undefined') && (iceUfrag != bLine.iceUfrag)) { throw new Error("Only BUNDLE supported, iceUfrag must be the same for all m-lines.\n" + "\tLast iceUfrag: " + iceUfrag + "\n" + "\tNew iceUfrag: " + bLine.iceUfrag ); } if (typeof bLine.iceUfrag != 'undefined') { iceUfrag = bLine.iceUfrag; } if ((typeof icePwd != 'undefined') && (typeof bLine.icePwd != 'undefined') && (icePwd != bLine.icePwd)) { throw new Error("Only BUNDLE supported, icePwd must be the same for all m-lines.\n" + "\tLast icePwd: " + icePwd + "\n" + "\tNew icePwd: " + bLine.icePwd ); } if (typeof bLine.icePwd != 'undefined') { icePwd = bLine.icePwd; } if ((typeof fingerprint != 'undefined') && (typeof bLine.fingerprint != 'undefined') && (fingerprint.type != bLine.fingerprint.type || fingerprint.hash != bLine.fingerprint.hash)) { throw new Error("Only BUNDLE supported, fingerprint must be the same for all m-lines.\n" + "\tLast fingerprint: " + JSON.stringify(fingerprint) + "\n" + "\tNew fingerprint: " + JSON.stringify(bLine.fingerprint) ); } if (typeof bLine.fingerprint != 'undefined') { fingerprint = bLine.fingerprint; } payloads[bLine.type] = bLine.payloads; rtcpFb[bLine.type] = bLine.rtcpFb; rtp[bLine.type] = bLine.rtp; // inverted ssrc group map var ssrc2group = {}; if (typeof ssrcGroups !== 'undefined' && Array.isArray(ssrcGroups)) { ssrcGroups.forEach(function (ssrcGroup) { // XXX This might brake if an SSRC is in more than one group // for some reason. if (typeof ssrcGroup.ssrcs !== 'undefined' && Array.isArray(ssrcGroup.ssrcs)) { ssrcGroup.ssrcs.forEach(function (ssrc) { if (typeof ssrc2group[ssrc] === 'undefined') { ssrc2group[ssrc] = []; } ssrc2group[ssrc].push(ssrcGroup); }); } }); } // ssrc to m-line index. var ssrc2ml = {}; if (typeof sources === 'object') { // We'll use the "bLine" object as a prototype for each new "mLine" // that we create, but first we need to clean it up a bit. delete bLine.sources; delete bLine.ssrcGroups; delete bLine.candidates; delete bLine.iceUfrag; delete bLine.icePwd; delete bLine.fingerprint; delete bLine.port; delete bLine.mid; // Explode the Plan B channel sources with one m-line per source. Object.keys(sources).forEach(function(ssrc) { // The (unified) m-line for this SSRC. We either create it from // scratch or, if it's a grouped SSRC, we re-use a related // mline. In other words, if the source is grouped with another // source, put the two together in the same m-line. var uLine; // We assume here that we are the answerer in the O/A, so any // offers which we translate come from the remote side, while // answers are local. So the check below is to make that we // handle receive-only SSRCs in a special way only if they come // from the remote side. if (desc.type==='offer') { // We want to detect SSRCs which are used by a remote peer // in an m-line with direction=recvonly (i.e. they are // being used for RTCP only). // This information would have gotten lost if the remote // peer used Unified Plan and their local description was // translated to Plan B. So we use the lack of an MSID // attribute to deduce a "receive only" SSRC. if (!sources[ssrc].msid) { recvonlySsrcs[bLine.type][ssrc] = sources[ssrc]; // Receive-only SSRCs must not create new m-lines. We // will assign them to an existing m-line later. return; } } if (typeof ssrc2group[ssrc] !== 'undefined' && Array.isArray(ssrc2group[ssrc])) { ssrc2group[ssrc].some(function (ssrcGroup) { // ssrcGroup.ssrcs *is* an Array, no need to check // again here. return ssrcGroup.ssrcs.some(function (related) { if (typeof ssrc2ml[related] === 'object') { uLine = ssrc2ml[related]; return true; } }); }); } if (typeof uLine === 'object') { // the m-line already exists. Just add the source. uLine.sources[ssrc] = sources[ssrc]; delete sources[ssrc].msid; } else { // Use the "bLine" as a prototype for the "uLine". uLine = Object.create(bLine); ssrc2ml[ssrc] = uLine; if (typeof sources[ssrc].msid !== 'undefined') { // Assign the msid of the source to the m-line. Note // that it is not guaranteed that the source will have // msid. In particular "recvonly" sources don't have an // msid. Note that "recvonly" is a term only defined // for m-lines. uLine.msid = sources[ssrc].msid; delete sources[ssrc].msid; } // We assign one SSRC per media line. uLine.sources = {}; uLine.sources[ssrc] = sources[ssrc]; uLine.ssrcGroups = ssrc2group[ssrc]; // Use the cached Unified Plan SDP (if it exists) to assign // SSRCs to mids. if (typeof cached !== 'undefined' && typeof cached.media !== 'undefined' && Array.isArray(cached.media)) { cached.media.forEach(function (m) { if (typeof m.sources === 'object') { Object.keys(m.sources).forEach(function (s) { if (s === ssrc) { uLine.mid = m.mid; } }); } }); } if (typeof uLine.mid === 'undefined') { // If this is an SSRC that we see for the first time // assign it a new mid. This is typically the case when // this method is called to transform a remote // description for the first time or when there is a // new SSRC in the remote description because a new // peer has joined the conference. Local SSRCs should // have already been added to the map in the toPlanB // method. // // Because FF generates answers in Unified Plan style, // we MUST already have a cached answer with all the // local SSRCs mapped to some m-line/mid. uLine.mid = [bLine.type, '-', ssrc].join(''); } // Include the candidates in the 1st media line. uLine.candidates = candidates; uLine.iceUfrag = iceUfrag; uLine.icePwd = icePwd; uLine.fingerprint = fingerprint; uLine.port = port; mid2ul[uLine.mid] = uLine; sources2ul[uIdx] = uLine.sources; self.cache.mlU2BMap[uIdx] = bIdx; if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { self.cache.mlB2UMap[bIdx] = uIdx; } uIdx++; } }); } else { var uLine = bLine; uLine.candidates = candidates; uLine.iceUfrag = iceUfrag; uLine.icePwd = icePwd; uLine.fingerprint = fingerprint; uLine.port = port; mid2ul[uLine.mid] = uLine; self.cache.mlU2BMap[uIdx] = bIdx; if (typeof self.cache.mlB2UMap[bIdx] === 'undefined') { self.cache.mlB2UMap[bIdx] = uIdx; } } bIdx++; }); // Rebuild the media array in the right order and add the missing mLines // (missing from the Plan B SDP). session.media = []; mids = []; // reuse if (desc.type === 'answer') { // The media lines in the answer must match the media lines in the // offer. The order is important too. Here we assume that Firefox is // the answerer, so we merely have to use the reconstructed (unified) // answer to update the cached (unified) answer accordingly. // // In the general case, one would have to use the cached (unified) // offer to find the m-lines that are missing from the reconstructed // answer, potentially grabbing them from the cached (unified) answer. // One has to be careful with this approach because inactive m-lines do // not always have an mid, making it tricky (impossible?) to find where // exactly and which m-lines are missing from the reconstructed answer. for (var i = 0; i < cached.media.length; i++) { var uLine = cached.media[i]; delete uLine.msid; delete uLine.sources; delete uLine.ssrcGroups; if (typeof sources2ul[i] === 'undefined') { if (!uLine.direction || uLine.direction === 'sendrecv') uLine.direction = 'recvonly'; else if (uLine.direction === 'sendonly') uLine.direction = 'inactive'; } else { if (!uLine.direction || uLine.direction === 'sendrecv') uLine.direction = 'sendrecv'; else if (uLine.direction === 'recvonly') uLine.direction = 'sendonly'; } uLine.sources = sources2ul[i]; uLine.candidates = candidates; uLine.iceUfrag = iceUfrag; uLine.icePwd = icePwd; uLine.fingerprint = fingerprint; uLine.rtp = rtp[uLine.type]; uLine.payloads = payloads[uLine.type]; uLine.rtcpFb = rtcpFb[uLine.type]; session.media.push(uLine); if (typeof uLine.mid === 'string') { // inactive lines don't/may not have an mid. mids.push(uLine.mid); } } } else { // SDP offer/answer (and the JSEP spec) forbids removing an m-section // under any circumstances. If we are no longer interested in sending a // track, we just remove the msid and ssrc attributes and set it to // either a=recvonly (as the reofferer, we must use recvonly if the // other side was previously sending on the m-section, but we can also // leave the possibility open if it wasn't previously in use), or // a=inactive. if (typeof cached !== 'undefined' && typeof cached.media !== 'undefined' && Array.isArray(cached.media)) { cached.media.forEach(function(uLine) { mids.push(uLine.mid); if (typeof mid2ul[uLine.mid] !== 'undefined') { session.media.push(mid2ul[uLine.mid]); } else { delete uLine.msid; delete uLine.sources; delete uLine.ssrcGroups; if (!uLine.direction || uLine.direction === 'sendrecv') { uLine.direction = 'sendonly'; } if (!uLine.direction || uLine.direction === 'recvonly') { uLine.direction = 'inactive'; } addSetupAttr (uLine); session.media.push(uLine); } }); } // Add all the remaining (new) m-lines of the transformed SDP. Object.keys(mid2ul).forEach(function(mid) { if (mids.indexOf(mid) === -1) { mids.push(mid); if (mid2ul[mid].direction === 'recvonly') { // This is a remote recvonly channel. Add its SSRC to the // appropriate sendrecv or sendonly channel. // TODO(gp) what if we don't have sendrecv/sendonly // channel? var done = false; session.media.some(function (uLine) { if ((uLine.direction === 'sendrecv' || uLine.direction === 'sendonly') && uLine.type === mid2ul[mid].type) { // mid2ul[mid] shouldn't have any ssrc-groups Object.keys(mid2ul[mid].sources).forEach( function (ssrc) { uLine.sources[ssrc] = mid2ul[mid].sources[ssrc]; }); done = true; return true; } }); if (!done) { session.media.push(mid2ul[mid]); } } else { session.media.push(mid2ul[mid]); } } }); } // After we have constructed the Plan Unified m-lines we can figure out // where (in which m-line) to place the 'recvonly SSRCs'. // Note: we assume here that we are the answerer in the O/A, so any offers // which we translate come from the remote side, while answers are local // (and so our last local description is cached as an 'answer'). ["audio", "video"].forEach(function (type) { if (!session || !session.media || !Array.isArray(session.media)) return; var idx = null; if (Object.keys(recvonlySsrcs[type]).length > 0) { idx = self.getFirstSendingIndexFromAnswer(type); if (idx === null){ // If this is the first offer we receive, we don't have a // cached answer. Assume that we will be sending media using // the first m-line for each media type. for (var i = 0; i < session.media.length; i++) { if (session.media[i].type === type) { idx = i; break; } } } } if (idx && session.media.length > idx) { var mLine = session.media[idx]; Object.keys(recvonlySsrcs[type]).forEach(function(ssrc) { if (mLine.sources && mLine.sources[ssrc]) { console.warn("Replacing an existing SSRC."); } if (!mLine.sources) { mLine.sources = {}; } mLine.sources[ssrc] = recvonlySsrcs[type][ssrc]; }); } }); if (typeof session.groups !== 'undefined') { // We regenerate the BUNDLE group (since we regenerated the mids) session.groups.some(function(group) { if (group.type === 'BUNDLE') { group.mids = mids.join(' '); return true; } }); } // msid semantic session.msidSemantic = { semantic: 'WMS', token: '*' }; var resStr = transform.write(session); // Cache the transformed SDP (Unified Plan) for later re-use in this // function. this.cache[desc.type] = resStr; return new RTCSessionDescription({ type: desc.type, sdp: resStr }); //#endregion }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/sdp-translator/lib/transform.js": /***/ (function(module, exports, __webpack_require__) { /* Copyright @ 2015 Atlassian Pty Ltd * * 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 transform = __webpack_require__("../../../../../openvidu-browser2/node_modules/sdp-transform/lib/index.js"); exports.write = function(session, opts) { if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && Array.isArray(session.media)) { session.media.forEach(function (mLine) { // expand sources to ssrcs if (typeof mLine.sources !== 'undefined' && Object.keys(mLine.sources).length !== 0) { mLine.ssrcs = []; Object.keys(mLine.sources).forEach(function (ssrc) { var source = mLine.sources[ssrc]; Object.keys(source).forEach(function (attribute) { mLine.ssrcs.push({ id: ssrc, attribute: attribute, value: source[attribute] }); }); }); delete mLine.sources; } // join ssrcs in ssrc groups if (typeof mLine.ssrcGroups !== 'undefined' && Array.isArray(mLine.ssrcGroups)) { mLine.ssrcGroups.forEach(function (ssrcGroup) { if (typeof ssrcGroup.ssrcs !== 'undefined' && Array.isArray(ssrcGroup.ssrcs)) { ssrcGroup.ssrcs = ssrcGroup.ssrcs.join(' '); } }); } }); } // join group mids if (typeof session !== 'undefined' && typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { session.groups.forEach(function (g) { if (typeof g.mids !== 'undefined' && Array.isArray(g.mids)) { g.mids = g.mids.join(' '); } }); } return transform.write(session, opts); }; exports.parse = function(sdp) { var session = transform.parse(sdp); if (typeof session !== 'undefined' && typeof session.media !== 'undefined' && Array.isArray(session.media)) { session.media.forEach(function (mLine) { // group sources attributes by ssrc if (typeof mLine.ssrcs !== 'undefined' && Array.isArray(mLine.ssrcs)) { mLine.sources = {}; mLine.ssrcs.forEach(function (ssrc) { if (!mLine.sources[ssrc.id]) mLine.sources[ssrc.id] = {}; mLine.sources[ssrc.id][ssrc.attribute] = ssrc.value; }); delete mLine.ssrcs; } // split ssrcs in ssrc groups if (typeof mLine.ssrcGroups !== 'undefined' && Array.isArray(mLine.ssrcGroups)) { mLine.ssrcGroups.forEach(function (ssrcGroup) { if (typeof ssrcGroup.ssrcs === 'string') { ssrcGroup.ssrcs = ssrcGroup.ssrcs.split(' '); } }); } }); } // split group mids if (typeof session !== 'undefined' && typeof session.groups !== 'undefined' && Array.isArray(session.groups)) { session.groups.forEach(function (g) { if (typeof g.mids === 'string') { g.mids = g.mids.split(' '); } }); } return session; }; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/ua-parser-js/src/ua-parser.js": /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_RESULT__;/** * UAParser.js v0.7.17 * Lightweight JavaScript-based User-Agent string parser * https://github.com/faisalman/ua-parser-js * * Copyright © 2012-2016 Faisal Salman * Dual licensed under GPLv2 & MIT */ (function (window, undefined) { 'use strict'; ////////////// // Constants ///////////// var LIBVERSION = '0.7.17', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', UNDEF_TYPE = 'undefined', OBJ_TYPE = 'object', STR_TYPE = 'string', MAJOR = 'major', // deprecated MODEL = 'model', NAME = 'name', TYPE = 'type', VENDOR = 'vendor', VERSION = 'version', ARCHITECTURE= 'architecture', CONSOLE = 'console', MOBILE = 'mobile', TABLET = 'tablet', SMARTTV = 'smarttv', WEARABLE = 'wearable', EMBEDDED = 'embedded'; /////////// // Helper ////////// var util = { extend : function (regexes, extensions) { var margedRegexes = {}; for (var i in regexes) { if (extensions[i] && extensions[i].length % 2 === 0) { margedRegexes[i] = extensions[i].concat(regexes[i]); } else { margedRegexes[i] = regexes[i]; } } return margedRegexes; }, has : function (str1, str2) { if (typeof str1 === "string") { return str2.toLowerCase().indexOf(str1.toLowerCase()) !== -1; } else { return false; } }, lowerize : function (str) { return str.toLowerCase(); }, major : function (version) { return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g,'').split(".")[0] : undefined; }, trim : function (str) { return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); } }; /////////////// // Map helper ////////////// var mapper = { rgx : function (ua, arrays) { //var result = {}, var i = 0, j, k, p, q, matches, match;//, args = arguments; /*// construct object barebones for (p = 0; p < args[1].length; p++) { q = args[1][p]; result[typeof q === OBJ_TYPE ? q[0] : q] = undefined; }*/ // loop through all regexes maps while (i < arrays.length && !matches) { var regex = arrays[i], // even sequence (0,2,4,..) props = arrays[i + 1]; // odd sequence (1,3,5,..) j = k = 0; // try matching uastring with regexes while (j < regex.length && !matches) { matches = regex[j++].exec(ua); if (!!matches) { for (p = 0; p < props.length; p++) { match = matches[++k]; q = props[p]; // check if given property is actually array if (typeof q === OBJ_TYPE && q.length > 0) { if (q.length == 2) { if (typeof q[1] == FUNC_TYPE) { // assign modified match this[q[0]] = q[1].call(this, match); } else { // assign given value, ignore regex match this[q[0]] = q[1]; } } else if (q.length == 3) { // check whether function or regex if (typeof q[1] === FUNC_TYPE && !(q[1].exec && q[1].test)) { // call function (usually string mapper) this[q[0]] = match ? q[1].call(this, match, q[2]) : undefined; } else { // sanitize match using given regex this[q[0]] = match ? match.replace(q[1], q[2]) : undefined; } } else if (q.length == 4) { this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : undefined; } } else { this[q] = match ? match : undefined; } } } } i += 2; } // console.log(this); //return this; }, str : function (str, map) { for (var i in map) { // check if array if (typeof map[i] === OBJ_TYPE && map[i].length > 0) { for (var j = 0; j < map[i].length; j++) { if (util.has(map[i][j], str)) { return (i === UNKNOWN) ? undefined : i; } } } else if (util.has(map[i], str)) { return (i === UNKNOWN) ? undefined : i; } } return str; } }; /////////////// // String map ////////////// var maps = { browser : { oldsafari : { version : { '1.0' : '/8', '1.2' : '/1', '1.3' : '/3', '2.0' : '/412', '2.0.2' : '/416', '2.0.3' : '/417', '2.0.4' : '/419', '?' : '/' } } }, device : { amazon : { model : { 'Fire Phone' : ['SD', 'KF'] } }, sprint : { model : { 'Evo Shift 4G' : '7373KT' }, vendor : { 'HTC' : 'APA', 'Sprint' : 'Sprint' } } }, os : { windows : { version : { 'ME' : '4.90', 'NT 3.11' : 'NT3.51', 'NT 4.0' : 'NT4.0', '2000' : 'NT 5.0', 'XP' : ['NT 5.1', 'NT 5.2'], 'Vista' : 'NT 6.0', '7' : 'NT 6.1', '8' : 'NT 6.2', '8.1' : 'NT 6.3', '10' : ['NT 6.4', 'NT 10.0'], 'RT' : 'ARM' } } } }; ////////////// // Regex map ///////////// var regexes = { browser : [[ // Presto based /(opera\smini)\/([\w\.-]+)/i, // Opera Mini /(opera\s[mobiletab]+).+version\/([\w\.-]+)/i, // Opera Mobi/Tablet /(opera).+version\/([\w\.]+)/i, // Opera > 9.80 /(opera)[\/\s]+([\w\.]+)/i // Opera < 9.80 ], [NAME, VERSION], [ /(opios)[\/\s]+([\w\.]+)/i // Opera mini on iphone >= 8.0 ], [[NAME, 'Opera Mini'], VERSION], [ /\s(opr)\/([\w\.]+)/i // Opera Webkit ], [[NAME, 'Opera'], VERSION], [ // Mixed /(kindle)\/([\w\.]+)/i, // Kindle /(lunascape|maxthon|netfront|jasmine|blazer)[\/\s]?([\w\.]+)*/i, // Lunascape/Maxthon/Netfront/Jasmine/Blazer // Trident based /(avant\s|iemobile|slim|baidu)(?:browser)?[\/\s]?([\w\.]*)/i, // Avant/IEMobile/SlimBrowser/Baidu /(?:ms|\()(ie)\s([\w\.]+)/i, // Internet Explorer // Webkit/KHTML based /(rekonq)\/([\w\.]+)*/i, // Rekonq /(chromium|flock|rockmelt|midori|epiphany|silk|skyfire|ovibrowser|bolt|iron|vivaldi|iridium|phantomjs|bowser)\/([\w\.-]+)/i // Chromium/Flock/RockMelt/Midori/Epiphany/Silk/Skyfire/Bolt/Iron/Iridium/PhantomJS/Bowser ], [NAME, VERSION], [ /(trident).+rv[:\s]([\w\.]+).+like\sgecko/i // IE11 ], [[NAME, 'IE'], VERSION], [ /(edge)\/((\d+)?[\w\.]+)/i // Microsoft Edge ], [NAME, VERSION], [ /(yabrowser)\/([\w\.]+)/i // Yandex ], [[NAME, 'Yandex'], VERSION], [ /(puffin)\/([\w\.]+)/i // Puffin ], [[NAME, 'Puffin'], VERSION], [ /((?:[\s\/])uc?\s?browser|(?:juc.+)ucweb)[\/\s]?([\w\.]+)/i // UCBrowser ], [[NAME, 'UCBrowser'], VERSION], [ /(comodo_dragon)\/([\w\.]+)/i // Comodo Dragon ], [[NAME, /_/g, ' '], VERSION], [ /(micromessenger)\/([\w\.]+)/i // WeChat ], [[NAME, 'WeChat'], VERSION], [ /(QQ)\/([\d\.]+)/i // QQ, aka ShouQ ], [NAME, VERSION], [ /m?(qqbrowser)[\/\s]?([\w\.]+)/i // QQBrowser ], [NAME, VERSION], [ /xiaomi\/miuibrowser\/([\w\.]+)/i // MIUI Browser ], [VERSION, [NAME, 'MIUI Browser']], [ /;fbav\/([\w\.]+);/i // Facebook App for iOS & Android ], [VERSION, [NAME, 'Facebook']], [ /headlesschrome(?:\/([\w\.]+)|\s)/i // Chrome Headless ], [VERSION, [NAME, 'Chrome Headless']], [ /\swv\).+(chrome)\/([\w\.]+)/i // Chrome WebView ], [[NAME, /(.+)/, '$1 WebView'], VERSION], [ /((?:oculus|samsung)browser)\/([\w\.]+)/i ], [[NAME, /(.+(?:g|us))(.+)/, '$1 $2'], VERSION], [ // Oculus / Samsung Browser /android.+version\/([\w\.]+)\s+(?:mobile\s?safari|safari)*/i // Android Browser ], [VERSION, [NAME, 'Android Browser']], [ /(chrome|omniweb|arora|[tizenoka]{5}\s?browser)\/v?([\w\.]+)/i // Chrome/OmniWeb/Arora/Tizen/Nokia ], [NAME, VERSION], [ /(dolfin)\/([\w\.]+)/i // Dolphin ], [[NAME, 'Dolphin'], VERSION], [ /((?:android.+)crmo|crios)\/([\w\.]+)/i // Chrome for Android/iOS ], [[NAME, 'Chrome'], VERSION], [ /(coast)\/([\w\.]+)/i // Opera Coast ], [[NAME, 'Opera Coast'], VERSION], [ /fxios\/([\w\.-]+)/i // Firefox for iOS ], [VERSION, [NAME, 'Firefox']], [ /version\/([\w\.]+).+?mobile\/\w+\s(safari)/i // Mobile Safari ], [VERSION, [NAME, 'Mobile Safari']], [ /version\/([\w\.]+).+?(mobile\s?safari|safari)/i // Safari & Safari Mobile ], [VERSION, NAME], [ /webkit.+?(gsa)\/([\w\.]+).+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Google Search Appliance on iOS ], [[NAME, 'GSA'], VERSION], [ /webkit.+?(mobile\s?safari|safari)(\/[\w\.]+)/i // Safari < 3.0 ], [NAME, [VERSION, mapper.str, maps.browser.oldsafari.version]], [ /(konqueror)\/([\w\.]+)/i, // Konqueror /(webkit|khtml)\/([\w\.]+)/i ], [NAME, VERSION], [ // Gecko based /(navigator|netscape)\/([\w\.-]+)/i // Netscape ], [[NAME, 'Netscape'], VERSION], [ /(swiftfox)/i, // Swiftfox /(icedragon|iceweasel|camino|chimera|fennec|maemo\sbrowser|minimo|conkeror)[\/\s]?([\w\.\+]+)/i, // IceDragon/Iceweasel/Camino/Chimera/Fennec/Maemo/Minimo/Conkeror /(firefox|seamonkey|k-meleon|icecat|iceape|firebird|phoenix)\/([\w\.-]+)/i, // Firefox/SeaMonkey/K-Meleon/IceCat/IceApe/Firebird/Phoenix /(mozilla)\/([\w\.]+).+rv\:.+gecko\/\d+/i, // Mozilla // Other /(polaris|lynx|dillo|icab|doris|amaya|w3m|netsurf|sleipnir)[\/\s]?([\w\.]+)/i, // Polaris/Lynx/Dillo/iCab/Doris/Amaya/w3m/NetSurf/Sleipnir /(links)\s\(([\w\.]+)/i, // Links /(gobrowser)\/?([\w\.]+)*/i, // GoBrowser /(ice\s?browser)\/v?([\w\._]+)/i, // ICE Browser /(mosaic)[\/\s]([\w\.]+)/i // Mosaic ], [NAME, VERSION] /* ///////////////////// // Media players BEGIN //////////////////////// , [ /(apple(?:coremedia|))\/((\d+)[\w\._]+)/i, // Generic Apple CoreMedia /(coremedia) v((\d+)[\w\._]+)/i ], [NAME, VERSION], [ /(aqualung|lyssna|bsplayer)\/((\d+)?[\w\.-]+)/i // Aqualung/Lyssna/BSPlayer ], [NAME, VERSION], [ /(ares|ossproxy)\s((\d+)[\w\.-]+)/i // Ares/OSSProxy ], [NAME, VERSION], [ /(audacious|audimusicstream|amarok|bass|core|dalvik|gnomemplayer|music on console|nsplayer|psp-internetradioplayer|videos)\/((\d+)[\w\.-]+)/i, // Audacious/AudiMusicStream/Amarok/BASS/OpenCORE/Dalvik/GnomeMplayer/MoC // NSPlayer/PSP-InternetRadioPlayer/Videos /(clementine|music player daemon)\s((\d+)[\w\.-]+)/i, // Clementine/MPD /(lg player|nexplayer)\s((\d+)[\d\.]+)/i, /player\/(nexplayer|lg player)\s((\d+)[\w\.-]+)/i // NexPlayer/LG Player ], [NAME, VERSION], [ /(nexplayer)\s((\d+)[\w\.-]+)/i // Nexplayer ], [NAME, VERSION], [ /(flrp)\/((\d+)[\w\.-]+)/i // Flip Player ], [[NAME, 'Flip Player'], VERSION], [ /(fstream|nativehost|queryseekspider|ia-archiver|facebookexternalhit)/i // FStream/NativeHost/QuerySeekSpider/IA Archiver/facebookexternalhit ], [NAME], [ /(gstreamer) souphttpsrc (?:\([^\)]+\)){0,1} libsoup\/((\d+)[\w\.-]+)/i // Gstreamer ], [NAME, VERSION], [ /(htc streaming player)\s[\w_]+\s\/\s((\d+)[\d\.]+)/i, // HTC Streaming Player /(java|python-urllib|python-requests|wget|libcurl)\/((\d+)[\w\.-_]+)/i, // Java/urllib/requests/wget/cURL /(lavf)((\d+)[\d\.]+)/i // Lavf (FFMPEG) ], [NAME, VERSION], [ /(htc_one_s)\/((\d+)[\d\.]+)/i // HTC One S ], [[NAME, /_/g, ' '], VERSION], [ /(mplayer)(?:\s|\/)(?:(?:sherpya-){0,1}svn)(?:-|\s)(r\d+(?:-\d+[\w\.-]+){0,1})/i // MPlayer SVN ], [NAME, VERSION], [ /(mplayer)(?:\s|\/|[unkow-]+)((\d+)[\w\.-]+)/i // MPlayer ], [NAME, VERSION], [ /(mplayer)/i, // MPlayer (no other info) /(yourmuze)/i, // YourMuze /(media player classic|nero showtime)/i // Media Player Classic/Nero ShowTime ], [NAME], [ /(nero (?:home|scout))\/((\d+)[\w\.-]+)/i // Nero Home/Nero Scout ], [NAME, VERSION], [ /(nokia\d+)\/((\d+)[\w\.-]+)/i // Nokia ], [NAME, VERSION], [ /\s(songbird)\/((\d+)[\w\.-]+)/i // Songbird/Philips-Songbird ], [NAME, VERSION], [ /(winamp)3 version ((\d+)[\w\.-]+)/i, // Winamp /(winamp)\s((\d+)[\w\.-]+)/i, /(winamp)mpeg\/((\d+)[\w\.-]+)/i ], [NAME, VERSION], [ /(ocms-bot|tapinradio|tunein radio|unknown|winamp|inlight radio)/i // OCMS-bot/tap in radio/tunein/unknown/winamp (no other info) // inlight radio ], [NAME], [ /(quicktime|rma|radioapp|radioclientapplication|soundtap|totem|stagefright|streamium)\/((\d+)[\w\.-]+)/i // QuickTime/RealMedia/RadioApp/RadioClientApplication/ // SoundTap/Totem/Stagefright/Streamium ], [NAME, VERSION], [ /(smp)((\d+)[\d\.]+)/i // SMP ], [NAME, VERSION], [ /(vlc) media player - version ((\d+)[\w\.]+)/i, // VLC Videolan /(vlc)\/((\d+)[\w\.-]+)/i, /(xbmc|gvfs|xine|xmms|irapp)\/((\d+)[\w\.-]+)/i, // XBMC/gvfs/Xine/XMMS/irapp /(foobar2000)\/((\d+)[\d\.]+)/i, // Foobar2000 /(itunes)\/((\d+)[\d\.]+)/i // iTunes ], [NAME, VERSION], [ /(wmplayer)\/((\d+)[\w\.-]+)/i, // Windows Media Player /(windows-media-player)\/((\d+)[\w\.-]+)/i ], [[NAME, /-/g, ' '], VERSION], [ /windows\/((\d+)[\w\.-]+) upnp\/[\d\.]+ dlnadoc\/[\d\.]+ (home media server)/i // Windows Media Server ], [VERSION, [NAME, 'Windows']], [ /(com\.riseupradioalarm)\/((\d+)[\d\.]*)/i // RiseUP Radio Alarm ], [NAME, VERSION], [ /(rad.io)\s((\d+)[\d\.]+)/i, // Rad.io /(radio.(?:de|at|fr))\s((\d+)[\d\.]+)/i ], [[NAME, 'rad.io'], VERSION] ////////////////////// // Media players END ////////////////////*/ ], cpu : [[ /(?:(amd|x(?:(?:86|64)[_-])?|wow|win)64)[;\)]/i // AMD64 ], [[ARCHITECTURE, 'amd64']], [ /(ia32(?=;))/i // IA32 (quicktime) ], [[ARCHITECTURE, util.lowerize]], [ /((?:i[346]|x)86)[;\)]/i // IA32 ], [[ARCHITECTURE, 'ia32']], [ // PocketPC mistakenly identified as PowerPC /windows\s(ce|mobile);\sppc;/i ], [[ARCHITECTURE, 'arm']], [ /((?:ppc|powerpc)(?:64)?)(?:\smac|;|\))/i // PowerPC ], [[ARCHITECTURE, /ower/, '', util.lowerize]], [ /(sun4\w)[;\)]/i // SPARC ], [[ARCHITECTURE, 'sparc']], [ /((?:avr32|ia64(?=;))|68k(?=\))|arm(?:64|(?=v\d+;))|(?=atmel\s)avr|(?:irix|mips|sparc)(?:64)?(?=;)|pa-risc)/i // IA64, 68K, ARM/64, AVR/32, IRIX/64, MIPS/64, SPARC/64, PA-RISC ], [[ARCHITECTURE, util.lowerize]] ], device : [[ /\((ipad|playbook);[\w\s\);-]+(rim|apple)/i // iPad/PlayBook ], [MODEL, VENDOR, [TYPE, TABLET]], [ /applecoremedia\/[\w\.]+ \((ipad)/ // iPad ], [MODEL, [VENDOR, 'Apple'], [TYPE, TABLET]], [ /(apple\s{0,1}tv)/i // Apple TV ], [[MODEL, 'Apple TV'], [VENDOR, 'Apple']], [ /(archos)\s(gamepad2?)/i, // Archos /(hp).+(touchpad)/i, // HP TouchPad /(hp).+(tablet)/i, // HP Tablet /(kindle)\/([\w\.]+)/i, // Kindle /\s(nook)[\w\s]+build\/(\w+)/i, // Nook /(dell)\s(strea[kpr\s\d]*[\dko])/i // Dell Streak ], [VENDOR, MODEL, [TYPE, TABLET]], [ /(kf[A-z]+)\sbuild\/[\w\.]+.*silk\//i // Kindle Fire HD ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ /(sd|kf)[0349hijorstuw]+\sbuild\/[\w\.]+.*silk\//i // Fire Phone ], [[MODEL, mapper.str, maps.device.amazon.model], [VENDOR, 'Amazon'], [TYPE, MOBILE]], [ /\((ip[honed|\s\w*]+);.+(apple)/i // iPod/iPhone ], [MODEL, VENDOR, [TYPE, MOBILE]], [ /\((ip[honed|\s\w*]+);/i // iPod/iPhone ], [MODEL, [VENDOR, 'Apple'], [TYPE, MOBILE]], [ /(blackberry)[\s-]?(\w+)/i, // BlackBerry /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus|dell|meizu|motorola|polytron)[\s_-]?([\w-]+)*/i, // BenQ/Palm/Sony-Ericsson/Acer/Asus/Dell/Meizu/Motorola/Polytron /(hp)\s([\w\s]+\w)/i, // HP iPAQ /(asus)-?(\w+)/i // Asus ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /\(bb10;\s(\w+)/i // BlackBerry 10 ], [MODEL, [VENDOR, 'BlackBerry'], [TYPE, MOBILE]], [ // Asus Tablets /android.+(transfo[prime\s]{4,10}\s\w+|eeepc|slider\s\w+|nexus 7|padfone)/i ], [MODEL, [VENDOR, 'Asus'], [TYPE, TABLET]], [ /(sony)\s(tablet\s[ps])\sbuild\//i, // Sony /(sony)?(?:sgp.+)\sbuild\//i ], [[VENDOR, 'Sony'], [MODEL, 'Xperia Tablet'], [TYPE, TABLET]], [ /android.+\s([c-g]\d{4}|so[-l]\w+)\sbuild\//i ], [MODEL, [VENDOR, 'Sony'], [TYPE, MOBILE]], [ /\s(ouya)\s/i, // Ouya /(nintendo)\s([wids3u]+)/i // Nintendo ], [VENDOR, MODEL, [TYPE, CONSOLE]], [ /android.+;\s(shield)\sbuild/i // Nvidia ], [MODEL, [VENDOR, 'Nvidia'], [TYPE, CONSOLE]], [ /(playstation\s[34portablevi]+)/i // Playstation ], [MODEL, [VENDOR, 'Sony'], [TYPE, CONSOLE]], [ /(sprint\s(\w+))/i // Sprint Phones ], [[VENDOR, mapper.str, maps.device.sprint.vendor], [MODEL, mapper.str, maps.device.sprint.model], [TYPE, MOBILE]], [ /(lenovo)\s?(S(?:5000|6000)+(?:[-][\w+]))/i // Lenovo tablets ], [VENDOR, MODEL, [TYPE, TABLET]], [ /(htc)[;_\s-]+([\w\s]+(?=\))|\w+)*/i, // HTC /(zte)-(\w+)*/i, // ZTE /(alcatel|geeksphone|lenovo|nexian|panasonic|(?=;\s)sony)[_\s-]?([\w-]+)*/i // Alcatel/GeeksPhone/Lenovo/Nexian/Panasonic/Sony ], [VENDOR, [MODEL, /_/g, ' '], [TYPE, MOBILE]], [ /(nexus\s9)/i // HTC Nexus 9 ], [MODEL, [VENDOR, 'HTC'], [TYPE, TABLET]], [ /d\/huawei([\w\s-]+)[;\)]/i, /(nexus\s6p)/i // Huawei ], [MODEL, [VENDOR, 'Huawei'], [TYPE, MOBILE]], [ /(microsoft);\s(lumia[\s\w]+)/i // Microsoft Lumia ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /[\s\(;](xbox(?:\sone)?)[\s\);]/i // Microsoft Xbox ], [MODEL, [VENDOR, 'Microsoft'], [TYPE, CONSOLE]], [ /(kin\.[onetw]{3})/i // Microsoft Kin ], [[MODEL, /\./g, ' '], [VENDOR, 'Microsoft'], [TYPE, MOBILE]], [ // Motorola /\s(milestone|droid(?:[2-4x]|\s(?:bionic|x2|pro|razr))?(:?\s4g)?)[\w\s]+build\//i, /mot[\s-]?(\w+)*/i, /(XT\d{3,4}) build\//i, /(nexus\s6)/i ], [MODEL, [VENDOR, 'Motorola'], [TYPE, MOBILE]], [ /android.+\s(mz60\d|xoom[\s2]{0,2})\sbuild\//i ], [MODEL, [VENDOR, 'Motorola'], [TYPE, TABLET]], [ /hbbtv\/\d+\.\d+\.\d+\s+\([\w\s]*;\s*(\w[^;]*);([^;]*)/i // HbbTV devices ], [[VENDOR, util.trim], [MODEL, util.trim], [TYPE, SMARTTV]], [ /hbbtv.+maple;(\d+)/i ], [[MODEL, /^/, 'SmartTV'], [VENDOR, 'Samsung'], [TYPE, SMARTTV]], [ /\(dtv[\);].+(aquos)/i // Sharp ], [MODEL, [VENDOR, 'Sharp'], [TYPE, SMARTTV]], [ /android.+((sch-i[89]0\d|shw-m380s|gt-p\d{4}|gt-n\d+|sgh-t8[56]9|nexus 10))/i, /((SM-T\w+))/i ], [[VENDOR, 'Samsung'], MODEL, [TYPE, TABLET]], [ // Samsung /smart-tv.+(samsung)/i ], [VENDOR, [TYPE, SMARTTV], MODEL], [ /((s[cgp]h-\w+|gt-\w+|galaxy\snexus|sm-\w[\w\d]+))/i, /(sam[sung]*)[\s-]*(\w+-?[\w-]*)*/i, /sec-((sgh\w+))/i ], [[VENDOR, 'Samsung'], MODEL, [TYPE, MOBILE]], [ /sie-(\w+)*/i // Siemens ], [MODEL, [VENDOR, 'Siemens'], [TYPE, MOBILE]], [ /(maemo|nokia).*(n900|lumia\s\d+)/i, // Nokia /(nokia)[\s_-]?([\w-]+)*/i ], [[VENDOR, 'Nokia'], MODEL, [TYPE, MOBILE]], [ /android\s3\.[\s\w;-]{10}(a\d{3})/i // Acer ], [MODEL, [VENDOR, 'Acer'], [TYPE, TABLET]], [ /android.+([vl]k\-?\d{3})\s+build/i // LG Tablet ], [MODEL, [VENDOR, 'LG'], [TYPE, TABLET]], [ /android\s3\.[\s\w;-]{10}(lg?)-([06cv9]{3,4})/i // LG Tablet ], [[VENDOR, 'LG'], MODEL, [TYPE, TABLET]], [ /(lg) netcast\.tv/i // LG SmartTV ], [VENDOR, MODEL, [TYPE, SMARTTV]], [ /(nexus\s[45])/i, // LG /lg[e;\s\/-]+(\w+)*/i, /android.+lg(\-?[\d\w]+)\s+build/i ], [MODEL, [VENDOR, 'LG'], [TYPE, MOBILE]], [ /android.+(ideatab[a-z0-9\-\s]+)/i // Lenovo ], [MODEL, [VENDOR, 'Lenovo'], [TYPE, TABLET]], [ /linux;.+((jolla));/i // Jolla ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /((pebble))app\/[\d\.]+\s/i // Pebble ], [VENDOR, MODEL, [TYPE, WEARABLE]], [ /android.+;\s(oppo)\s?([\w\s]+)\sbuild/i // OPPO ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /crkey/i // Google Chromecast ], [[MODEL, 'Chromecast'], [VENDOR, 'Google']], [ /android.+;\s(glass)\s\d/i // Google Glass ], [MODEL, [VENDOR, 'Google'], [TYPE, WEARABLE]], [ /android.+;\s(pixel c)\s/i // Google Pixel C ], [MODEL, [VENDOR, 'Google'], [TYPE, TABLET]], [ /android.+;\s(pixel xl|pixel)\s/i // Google Pixel ], [MODEL, [VENDOR, 'Google'], [TYPE, MOBILE]], [ /android.+(\w+)\s+build\/hm\1/i, // Xiaomi Hongmi 'numeric' models /android.+(hm[\s\-_]*note?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Hongmi /android.+(mi[\s\-_]*(?:one|one[\s_]plus|note lte)?[\s_]*(?:\d\w)?)\s+build/i, // Xiaomi Mi /android.+(redmi[\s\-_]*(?:note)?(?:[\s_]*[\w\s]+)?)\s+build/i // Redmi Phones ], [[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, MOBILE]], [ /android.+(mi[\s\-_]*(?:pad)?(?:[\s_]*[\w\s]+)?)\s+build/i // Mi Pad tablets ],[[MODEL, /_/g, ' '], [VENDOR, 'Xiaomi'], [TYPE, TABLET]], [ /android.+;\s(m[1-5]\snote)\sbuild/i // Meizu Tablet ], [MODEL, [VENDOR, 'Meizu'], [TYPE, TABLET]], [ /android.+a000(1)\s+build/i // OnePlus ], [MODEL, [VENDOR, 'OnePlus'], [TYPE, MOBILE]], [ /android.+[;\/]\s*(RCT[\d\w]+)\s+build/i // RCA Tablets ], [MODEL, [VENDOR, 'RCA'], [TYPE, TABLET]], [ /android.+[;\/]\s*(Venue[\d\s]*)\s+build/i // Dell Venue Tablets ], [MODEL, [VENDOR, 'Dell'], [TYPE, TABLET]], [ /android.+[;\/]\s*(Q[T|M][\d\w]+)\s+build/i // Verizon Tablet ], [MODEL, [VENDOR, 'Verizon'], [TYPE, TABLET]], [ /android.+[;\/]\s+(Barnes[&\s]+Noble\s+|BN[RT])(V?.*)\s+build/i // Barnes & Noble Tablet ], [[VENDOR, 'Barnes & Noble'], MODEL, [TYPE, TABLET]], [ /android.+[;\/]\s+(TM\d{3}.*\b)\s+build/i // Barnes & Noble Tablet ], [MODEL, [VENDOR, 'NuVision'], [TYPE, TABLET]], [ /android.+[;\/]\s*(zte)?.+(k\d{2})\s+build/i // ZTE K Series Tablet ], [[VENDOR, 'ZTE'], MODEL, [TYPE, TABLET]], [ /android.+[;\/]\s*(gen\d{3})\s+build.*49h/i // Swiss GEN Mobile ], [MODEL, [VENDOR, 'Swiss'], [TYPE, MOBILE]], [ /android.+[;\/]\s*(zur\d{3})\s+build/i // Swiss ZUR Tablet ], [MODEL, [VENDOR, 'Swiss'], [TYPE, TABLET]], [ /android.+[;\/]\s*((Zeki)?TB.*\b)\s+build/i // Zeki Tablets ], [MODEL, [VENDOR, 'Zeki'], [TYPE, TABLET]], [ /(android).+[;\/]\s+([YR]\d{2}x?.*)\s+build/i, /android.+[;\/]\s+(Dragon[\-\s]+Touch\s+|DT)(.+)\s+build/i // Dragon Touch Tablet ], [[VENDOR, 'Dragon Touch'], MODEL, [TYPE, TABLET]], [ /android.+[;\/]\s*(NS-?.+)\s+build/i // Insignia Tablets ], [MODEL, [VENDOR, 'Insignia'], [TYPE, TABLET]], [ /android.+[;\/]\s*((NX|Next)-?.+)\s+build/i // NextBook Tablets ], [MODEL, [VENDOR, 'NextBook'], [TYPE, TABLET]], [ /android.+[;\/]\s*(Xtreme\_?)?(V(1[045]|2[015]|30|40|60|7[05]|90))\s+build/i ], [[VENDOR, 'Voice'], MODEL, [TYPE, MOBILE]], [ // Voice Xtreme Phones /android.+[;\/]\s*(LVTEL\-?)?(V1[12])\s+build/i // LvTel Phones ], [[VENDOR, 'LvTel'], MODEL, [TYPE, MOBILE]], [ /android.+[;\/]\s*(V(100MD|700NA|7011|917G).*\b)\s+build/i // Envizen Tablets ], [MODEL, [VENDOR, 'Envizen'], [TYPE, TABLET]], [ /android.+[;\/]\s*(Le[\s\-]+Pan)[\s\-]+(.*\b)\s+build/i // Le Pan Tablets ], [VENDOR, MODEL, [TYPE, TABLET]], [ /android.+[;\/]\s*(Trio[\s\-]*.*)\s+build/i // MachSpeed Tablets ], [MODEL, [VENDOR, 'MachSpeed'], [TYPE, TABLET]], [ /android.+[;\/]\s*(Trinity)[\-\s]*(T\d{3})\s+build/i // Trinity Tablets ], [VENDOR, MODEL, [TYPE, TABLET]], [ /android.+[;\/]\s*TU_(1491)\s+build/i // Rotor Tablets ], [MODEL, [VENDOR, 'Rotor'], [TYPE, TABLET]], [ /android.+(KS(.+))\s+build/i // Amazon Kindle Tablets ], [MODEL, [VENDOR, 'Amazon'], [TYPE, TABLET]], [ /android.+(Gigaset)[\s\-]+(Q.+)\s+build/i // Gigaset Tablets ], [VENDOR, MODEL, [TYPE, TABLET]], [ /\s(tablet|tab)[;\/]/i, // Unidentifiable Tablet /\s(mobile)(?:[;\/]|\ssafari)/i // Unidentifiable Mobile ], [[TYPE, util.lowerize], VENDOR, MODEL], [ /(android.+)[;\/].+build/i // Generic Android Device ], [MODEL, [VENDOR, 'Generic']] /*////////////////////////// // TODO: move to string map //////////////////////////// /(C6603)/i // Sony Xperia Z C6603 ], [[MODEL, 'Xperia Z C6603'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ /(C6903)/i // Sony Xperia Z 1 ], [[MODEL, 'Xperia Z 1'], [VENDOR, 'Sony'], [TYPE, MOBILE]], [ /(SM-G900[F|H])/i // Samsung Galaxy S5 ], [[MODEL, 'Galaxy S5'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ /(SM-G7102)/i // Samsung Galaxy Grand 2 ], [[MODEL, 'Galaxy Grand 2'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ /(SM-G530H)/i // Samsung Galaxy Grand Prime ], [[MODEL, 'Galaxy Grand Prime'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ /(SM-G313HZ)/i // Samsung Galaxy V ], [[MODEL, 'Galaxy V'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ /(SM-T805)/i // Samsung Galaxy Tab S 10.5 ], [[MODEL, 'Galaxy Tab S 10.5'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ /(SM-G800F)/i // Samsung Galaxy S5 Mini ], [[MODEL, 'Galaxy S5 Mini'], [VENDOR, 'Samsung'], [TYPE, MOBILE]], [ /(SM-T311)/i // Samsung Galaxy Tab 3 8.0 ], [[MODEL, 'Galaxy Tab 3 8.0'], [VENDOR, 'Samsung'], [TYPE, TABLET]], [ /(T3C)/i // Advan Vandroid T3C ], [MODEL, [VENDOR, 'Advan'], [TYPE, TABLET]], [ /(ADVAN T1J\+)/i // Advan Vandroid T1J+ ], [[MODEL, 'Vandroid T1J+'], [VENDOR, 'Advan'], [TYPE, TABLET]], [ /(ADVAN S4A)/i // Advan Vandroid S4A ], [[MODEL, 'Vandroid S4A'], [VENDOR, 'Advan'], [TYPE, MOBILE]], [ /(V972M)/i // ZTE V972M ], [MODEL, [VENDOR, 'ZTE'], [TYPE, MOBILE]], [ /(i-mobile)\s(IQ\s[\d\.]+)/i // i-mobile IQ ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /(IQ6.3)/i // i-mobile IQ IQ 6.3 ], [[MODEL, 'IQ 6.3'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ /(i-mobile)\s(i-style\s[\d\.]+)/i // i-mobile i-STYLE ], [VENDOR, MODEL, [TYPE, MOBILE]], [ /(i-STYLE2.1)/i // i-mobile i-STYLE 2.1 ], [[MODEL, 'i-STYLE 2.1'], [VENDOR, 'i-mobile'], [TYPE, MOBILE]], [ /(mobiistar touch LAI 512)/i // mobiistar touch LAI 512 ], [[MODEL, 'Touch LAI 512'], [VENDOR, 'mobiistar'], [TYPE, MOBILE]], [ ///////////// // END TODO ///////////*/ ], engine : [[ /windows.+\sedge\/([\w\.]+)/i // EdgeHTML ], [VERSION, [NAME, 'EdgeHTML']], [ /(presto)\/([\w\.]+)/i, // Presto /(webkit|trident|netfront|netsurf|amaya|lynx|w3m)\/([\w\.]+)/i, // WebKit/Trident/NetFront/NetSurf/Amaya/Lynx/w3m /(khtml|tasman|links)[\/\s]\(?([\w\.]+)/i, // KHTML/Tasman/Links /(icab)[\/\s]([23]\.[\d\.]+)/i // iCab ], [NAME, VERSION], [ /rv\:([\w\.]+).*(gecko)/i // Gecko ], [VERSION, NAME] ], os : [[ // Windows based /microsoft\s(windows)\s(vista|xp)/i // Windows (iTunes) ], [NAME, VERSION], [ /(windows)\snt\s6\.2;\s(arm)/i, // Windows RT /(windows\sphone(?:\sos)*)[\s\/]?([\d\.\s]+\w)*/i, // Windows Phone /(windows\smobile|windows)[\s\/]?([ntce\d\.\s]+\w)/i ], [NAME, [VERSION, mapper.str, maps.os.windows.version]], [ /(win(?=3|9|n)|win\s9x\s)([nt\d\.]+)/i ], [[NAME, 'Windows'], [VERSION, mapper.str, maps.os.windows.version]], [ // Mobile/Embedded OS /\((bb)(10);/i // BlackBerry 10 ], [[NAME, 'BlackBerry'], VERSION], [ /(blackberry)\w*\/?([\w\.]+)*/i, // Blackberry /(tizen)[\/\s]([\w\.]+)/i, // Tizen /(android|webos|palm\sos|qnx|bada|rim\stablet\sos|meego|contiki)[\/\s-]?([\w\.]+)*/i, // Android/WebOS/Palm/QNX/Bada/RIM/MeeGo/Contiki /linux;.+(sailfish);/i // Sailfish OS ], [NAME, VERSION], [ /(symbian\s?os|symbos|s60(?=;))[\/\s-]?([\w\.]+)*/i // Symbian ], [[NAME, 'Symbian'], VERSION], [ /\((series40);/i // Series 40 ], [NAME], [ /mozilla.+\(mobile;.+gecko.+firefox/i // Firefox OS ], [[NAME, 'Firefox OS'], VERSION], [ // Console /(nintendo|playstation)\s([wids34portablevu]+)/i, // Nintendo/Playstation // GNU/Linux based /(mint)[\/\s\(]?(\w+)*/i, // Mint /(mageia|vectorlinux)[;\s]/i, // Mageia/VectorLinux /(joli|[kxln]?ubuntu|debian|[open]*suse|gentoo|(?=\s)arch|slackware|fedora|mandriva|centos|pclinuxos|redhat|zenwalk|linpus)[\/\s-]?(?!chrom)([\w\.-]+)*/i, // Joli/Ubuntu/Debian/SUSE/Gentoo/Arch/Slackware // Fedora/Mandriva/CentOS/PCLinuxOS/RedHat/Zenwalk/Linpus /(hurd|linux)\s?([\w\.]+)*/i, // Hurd/Linux /(gnu)\s?([\w\.]+)*/i // GNU ], [NAME, VERSION], [ /(cros)\s[\w]+\s([\w\.]+\w)/i // Chromium OS ], [[NAME, 'Chromium OS'], VERSION],[ // Solaris /(sunos)\s?([\w\.]+\d)*/i // Solaris ], [[NAME, 'Solaris'], VERSION], [ // BSD based /\s([frentopc-]{0,4}bsd|dragonfly)\s?([\w\.]+)*/i // FreeBSD/NetBSD/OpenBSD/PC-BSD/DragonFly ], [NAME, VERSION],[ /(haiku)\s(\w+)/i // Haiku ], [NAME, VERSION],[ /cfnetwork\/.+darwin/i, /ip[honead]+(?:.*os\s([\w]+)\slike\smac|;\sopera)/i // iOS ], [[VERSION, /_/g, '.'], [NAME, 'iOS']], [ /(mac\sos\sx)\s?([\w\s\.]+\w)*/i, /(macintosh|mac(?=_powerpc)\s)/i // Mac OS ], [[NAME, 'Mac OS'], [VERSION, /_/g, '.']], [ // Other /((?:open)?solaris)[\/\s-]?([\w\.]+)*/i, // Solaris /(aix)\s((\d)(?=\.|\)|\s)[\w\.]*)*/i, // AIX /(plan\s9|minix|beos|os\/2|amigaos|morphos|risc\sos|openvms)/i, // Plan9/Minix/BeOS/OS2/AmigaOS/MorphOS/RISCOS/OpenVMS /(unix)\s?([\w\.]+)*/i // UNIX ], [NAME, VERSION] ] }; ///////////////// // Constructor //////////////// /* var Browser = function (name, version) { this[NAME] = name; this[VERSION] = version; }; var CPU = function (arch) { this[ARCHITECTURE] = arch; }; var Device = function (vendor, model, type) { this[VENDOR] = vendor; this[MODEL] = model; this[TYPE] = type; }; var Engine = Browser; var OS = Browser; */ var UAParser = function (uastring, extensions) { if (typeof uastring === 'object') { extensions = uastring; uastring = undefined; } if (!(this instanceof UAParser)) { return new UAParser(uastring, extensions).getResult(); } var ua = uastring || ((window && window.navigator && window.navigator.userAgent) ? window.navigator.userAgent : EMPTY); var rgxmap = extensions ? util.extend(regexes, extensions) : regexes; //var browser = new Browser(); //var cpu = new CPU(); //var device = new Device(); //var engine = new Engine(); //var os = new OS(); this.getBrowser = function () { var browser = { name: undefined, version: undefined }; mapper.rgx.call(browser, ua, rgxmap.browser); browser.major = util.major(browser.version); // deprecated return browser; }; this.getCPU = function () { var cpu = { architecture: undefined }; mapper.rgx.call(cpu, ua, rgxmap.cpu); return cpu; }; this.getDevice = function () { var device = { vendor: undefined, model: undefined, type: undefined }; mapper.rgx.call(device, ua, rgxmap.device); return device; }; this.getEngine = function () { var engine = { name: undefined, version: undefined }; mapper.rgx.call(engine, ua, rgxmap.engine); return engine; }; this.getOS = function () { var os = { name: undefined, version: undefined }; mapper.rgx.call(os, ua, rgxmap.os); return os; }; this.getResult = function () { return { ua : this.getUA(), browser : this.getBrowser(), engine : this.getEngine(), os : this.getOS(), device : this.getDevice(), cpu : this.getCPU() }; }; this.getUA = function () { return ua; }; this.setUA = function (uastring) { ua = uastring; //browser = new Browser(); //cpu = new CPU(); //device = new Device(); //engine = new Engine(); //os = new OS(); return this; }; return this; }; UAParser.VERSION = LIBVERSION; UAParser.BROWSER = { NAME : NAME, MAJOR : MAJOR, // deprecated VERSION : VERSION }; UAParser.CPU = { ARCHITECTURE : ARCHITECTURE }; UAParser.DEVICE = { MODEL : MODEL, VENDOR : VENDOR, TYPE : TYPE, CONSOLE : CONSOLE, MOBILE : MOBILE, SMARTTV : SMARTTV, TABLET : TABLET, WEARABLE: WEARABLE, EMBEDDED: EMBEDDED }; UAParser.ENGINE = { NAME : NAME, VERSION : VERSION }; UAParser.OS = { NAME : NAME, VERSION : VERSION }; //UAParser.Utils = util; /////////// // Export ////////// // check js environment if (typeof(exports) !== UNDEF_TYPE) { // nodejs env if (typeof module !== UNDEF_TYPE && module.exports) { exports = module.exports = UAParser; } // TODO: test!!!!!!!! /* if (require && require.main === module && process) { // cli var jsonize = function (arr) { var res = []; for (var i in arr) { res.push(new UAParser(arr[i]).getResult()); } process.stdout.write(JSON.stringify(res, null, 2) + '\n'); }; if (process.stdin.isTTY) { // via args jsonize(process.argv.slice(2)); } else { // via pipe var str = ''; process.stdin.on('readable', function() { var read = process.stdin.read(); if (read !== null) { str += read; } }); process.stdin.on('end', function () { jsonize(str.replace(/\n$/, '').split('\n')); }); } } */ exports.UAParser = UAParser; } else { // requirejs env (optional) if ("function" === FUNC_TYPE && __webpack_require__("./node_modules/webpack/buildin/amd-options.js")) { !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () { return UAParser; }).call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else if (window) { // browser env window.UAParser = UAParser; } } // jQuery/Zepto specific (optional) // Note: // In AMD env the global scope should be kept clean, but jQuery is an exception. // jQuery always exports to global scope, unless jQuery.noConflict(true) is used, // and we should catch that. var $ = window && (window.jQuery || window.Zepto); if (typeof $ !== UNDEF_TYPE) { var parser = new UAParser(); $.ua = parser.getResult(); $.ua.get = function () { return parser.getUA(); }; $.ua.set = function (uastring) { parser.setUA(uastring); var result = parser.getResult(); for (var prop in result) { $.ua[prop] = result[prop]; } }; } })(typeof window === 'object' ? window : this); /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/uuid/index.js": /***/ (function(module, exports, __webpack_require__) { var v1 = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/v1.js"); var v4 = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/v4.js"); var uuid = v4; uuid.v1 = v1; uuid.v4 = v4; module.exports = uuid; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/uuid/lib/bytesToUuid.js": /***/ (function(module, exports) { /** * Convert array of 16 byte values to UUID string format of the form: * XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ var byteToHex = []; for (var i = 0; i < 256; ++i) { byteToHex[i] = (i + 0x100).toString(16).substr(1); } function bytesToUuid(buf, offset) { var i = offset || 0; var bth = byteToHex; return bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + '-' + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]] + bth[buf[i++]]; } module.exports = bytesToUuid; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/uuid/lib/rng-browser.js": /***/ (function(module, exports) { // Unique ID creation requires a high quality random # generator. In the // browser this is a little complicated due to unknown quality of Math.random() // and inconsistent support for the `crypto` API. We do the best we can via // feature-detection // getRandomValues needs to be invoked in a context where "this" is a Crypto implementation. var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues.bind(crypto)) || (typeof(msCrypto) != 'undefined' && msCrypto.getRandomValues.bind(msCrypto)); if (getRandomValues) { // WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef module.exports = function whatwgRNG() { getRandomValues(rnds8); return rnds8; }; } else { // Math.random()-based (RNG) // // If all else fails, use Math.random(). It's fast, but is of unspecified // quality. var rnds = new Array(16); module.exports = function mathRNG() { for (var i = 0, r; i < 16; i++) { if ((i & 0x03) === 0) r = Math.random() * 0x100000000; rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; } return rnds; }; } /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/uuid/v1.js": /***/ (function(module, exports, __webpack_require__) { var rng = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/lib/rng-browser.js"); var bytesToUuid = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/lib/bytesToUuid.js"); // **`v1()` - Generate time-based UUID** // // Inspired by https://github.com/LiosK/UUID.js // and http://docs.python.org/library/uuid.html var _nodeId; var _clockseq; // Previous uuid creation time var _lastMSecs = 0; var _lastNSecs = 0; // See https://github.com/broofa/node-uuid for API details function v1(options, buf, offset) { var i = buf && offset || 0; var b = buf || []; options = options || {}; var node = options.node || _nodeId; var clockseq = options.clockseq !== undefined ? options.clockseq : _clockseq; // node and clockseq need to be initialized to random values if they're not // specified. We do this lazily to minimize issues related to insufficient // system entropy. See #189 if (node == null || clockseq == null) { var seedBytes = rng(); if (node == null) { // Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) node = _nodeId = [ seedBytes[0] | 0x01, seedBytes[1], seedBytes[2], seedBytes[3], seedBytes[4], seedBytes[5] ]; } if (clockseq == null) { // Per 4.2.2, randomize (14 bit) clockseq clockseq = _clockseq = (seedBytes[6] << 8 | seedBytes[7]) & 0x3fff; } } // UUID timestamps are 100 nano-second units since the Gregorian epoch, // (1582-10-15 00:00). JSNumbers aren't precise enough for this, so // time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' // (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. var msecs = options.msecs !== undefined ? options.msecs : new Date().getTime(); // Per 4.2.1.2, use count of uuid's generated during the current clock // cycle to simulate higher resolution clock var nsecs = options.nsecs !== undefined ? options.nsecs : _lastNSecs + 1; // Time since last uuid creation (in msecs) var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; // Per 4.2.1.2, Bump clockseq on clock regression if (dt < 0 && options.clockseq === undefined) { clockseq = clockseq + 1 & 0x3fff; } // Reset nsecs if clock regresses (new clockseq) or we've moved onto a new // time interval if ((dt < 0 || msecs > _lastMSecs) && options.nsecs === undefined) { nsecs = 0; } // Per 4.2.1.2 Throw error if too many uuids are requested if (nsecs >= 10000) { throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); } _lastMSecs = msecs; _lastNSecs = nsecs; _clockseq = clockseq; // Per 4.1.4 - Convert from unix epoch to Gregorian epoch msecs += 12219292800000; // `time_low` var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; b[i++] = tl >>> 24 & 0xff; b[i++] = tl >>> 16 & 0xff; b[i++] = tl >>> 8 & 0xff; b[i++] = tl & 0xff; // `time_mid` var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; b[i++] = tmh >>> 8 & 0xff; b[i++] = tmh & 0xff; // `time_high_and_version` b[i++] = tmh >>> 24 & 0xf | 0x10; // include version b[i++] = tmh >>> 16 & 0xff; // `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) b[i++] = clockseq >>> 8 | 0x80; // `clock_seq_low` b[i++] = clockseq & 0xff; // `node` for (var n = 0; n < 6; ++n) { b[i + n] = node[n]; } return buf ? buf : bytesToUuid(b); } module.exports = v1; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/uuid/v4.js": /***/ (function(module, exports, __webpack_require__) { var rng = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/lib/rng-browser.js"); var bytesToUuid = __webpack_require__("../../../../../openvidu-browser2/node_modules/uuid/lib/bytesToUuid.js"); function v4(options, buf, offset) { var i = buf && offset || 0; if (typeof(options) == 'string') { buf = options === 'binary' ? new Array(16) : null; options = null; } options = options || {}; var rnds = options.random || (options.rng || rng)(); // Per 4.4, set bits for version and `clock_seq_hi_and_reserved` rnds[6] = (rnds[6] & 0x0f) | 0x40; rnds[8] = (rnds[8] & 0x3f) | 0x80; // Copy bytes to buffer, if provided if (buf) { for (var ii = 0; ii < 16; ++ii) { buf[i + ii] = rnds[ii]; } } return buf || bytesToUuid(rnds); } module.exports = v4; /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/wildemitter/wildemitter.js": /***/ (function(module, exports) { /* WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based on @visionmedia's Emitter from UI Kit. Why? I wanted it standalone. I also wanted support for wildcard emitters like this: emitter.on('*', function (eventName, other, event, payloads) { }); emitter.on('somenamespace*', function (eventName, payloads) { }); Please note that callbacks triggered by wildcard registered events also get the event name as the first argument. */ module.exports = WildEmitter; function WildEmitter() { } WildEmitter.mixin = function (constructor) { var prototype = constructor.prototype || constructor; prototype.isWildEmitter= true; // Listen on the given `event` with `fn`. Store a group name if present. prototype.on = function (event, groupName, fn) { this.callbacks = this.callbacks || {}; var hasGroup = (arguments.length === 3), group = hasGroup ? arguments[1] : undefined, func = hasGroup ? arguments[2] : arguments[1]; func._groupName = group; (this.callbacks[event] = this.callbacks[event] || []).push(func); return this; }; // Adds an `event` listener that will be invoked a single // time then automatically removed. prototype.once = function (event, groupName, fn) { var self = this, hasGroup = (arguments.length === 3), group = hasGroup ? arguments[1] : undefined, func = hasGroup ? arguments[2] : arguments[1]; function on() { self.off(event, on); func.apply(this, arguments); } this.on(event, group, on); return this; }; // Unbinds an entire group prototype.releaseGroup = function (groupName) { this.callbacks = this.callbacks || {}; var item, i, len, handlers; for (item in this.callbacks) { handlers = this.callbacks[item]; for (i = 0, len = handlers.length; i < len; i++) { if (handlers[i]._groupName === groupName) { //console.log('removing'); // remove it and shorten the array we're looping through handlers.splice(i, 1); i--; len--; } } } return this; }; // Remove the given callback for `event` or all // registered callbacks. prototype.off = function (event, fn) { this.callbacks = this.callbacks || {}; var callbacks = this.callbacks[event], i; if (!callbacks) return this; // remove all handlers if (arguments.length === 1) { delete this.callbacks[event]; return this; } // remove specific handler i = callbacks.indexOf(fn); callbacks.splice(i, 1); if (callbacks.length === 0) { delete this.callbacks[event]; } return this; }; /// Emit `event` with the given args. // also calls any `*` handlers prototype.emit = function (event) { this.callbacks = this.callbacks || {}; var args = [].slice.call(arguments, 1), callbacks = this.callbacks[event], specialCallbacks = this.getWildcardCallbacks(event), i, len, item, listeners; if (callbacks) { listeners = callbacks.slice(); for (i = 0, len = listeners.length; i < len; ++i) { if (!listeners[i]) { break; } listeners[i].apply(this, args); } } if (specialCallbacks) { len = specialCallbacks.length; listeners = specialCallbacks.slice(); for (i = 0, len = listeners.length; i < len; ++i) { if (!listeners[i]) { break; } listeners[i].apply(this, [event].concat(args)); } } return this; }; // Helper for for finding special wildcard event handlers that match the event prototype.getWildcardCallbacks = function (eventName) { this.callbacks = this.callbacks || {}; var item, split, result = []; for (item in this.callbacks) { split = item.split('*'); if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { result = result.concat(this.callbacks[item]); } } return result; }; }; WildEmitter.mixin(WildEmitter); /***/ }), /***/ "../../../../../openvidu-browser2/node_modules/wolfy87-eventemitter/EventEmitter.js": /***/ (function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_RESULT__;/*! * EventEmitter v5.2.4 - git.io/ee * Unlicense - http://unlicense.org/ * Oliver Caldwell - http://oli.me.uk/ * @preserve */ ;(function (exports) { 'use strict'; /** * Class for managing events. * Can be extended to provide event functionality in other classes. * * @class EventEmitter Manages event registering and emitting. */ function EventEmitter() {} // Shortcuts to improve speed and size var proto = EventEmitter.prototype; var originalGlobalValue = exports.EventEmitter; /** * Finds the index of the listener for the event in its storage array. * * @param {Function[]} listeners Array of listeners to search through. * @param {Function} listener Method to look for. * @return {Number} Index of the specified listener, -1 if not found * @api private */ function indexOfListener(listeners, listener) { var i = listeners.length; while (i--) { if (listeners[i].listener === listener) { return i; } } return -1; } /** * Alias a method while keeping the context correct, to allow for overwriting of target method. * * @param {String} name The name of the target method. * @return {Function} The aliased method * @api private */ function alias(name) { return function aliasClosure() { return this[name].apply(this, arguments); }; } /** * Returns the listener array for the specified event. * Will initialise the event object and listener arrays if required. * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. * Each property in the object response is an array of listener functions. * * @param {String|RegExp} evt Name of the event to return the listeners from. * @return {Function[]|Object} All listener functions for the event. */ proto.getListeners = function getListeners(evt) { var events = this._getEvents(); var response; var key; // Return a concatenated array of all matching events if // the selector is a regular expression. if (evt instanceof RegExp) { response = {}; for (key in events) { if (events.hasOwnProperty(key) && evt.test(key)) { response[key] = events[key]; } } } else { response = events[evt] || (events[evt] = []); } return response; }; /** * Takes a list of listener objects and flattens it into a list of listener functions. * * @param {Object[]} listeners Raw listener objects. * @return {Function[]} Just the listener functions. */ proto.flattenListeners = function flattenListeners(listeners) { var flatListeners = []; var i; for (i = 0; i < listeners.length; i += 1) { flatListeners.push(listeners[i].listener); } return flatListeners; }; /** * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. * * @param {String|RegExp} evt Name of the event to return the listeners from. * @return {Object} All listener functions for an event in an object. */ proto.getListenersAsObject = function getListenersAsObject(evt) { var listeners = this.getListeners(evt); var response; if (listeners instanceof Array) { response = {}; response[evt] = listeners; } return response || listeners; }; function isValidListener (listener) { if (typeof listener === 'function' || listener instanceof RegExp) { return true } else if (listener && typeof listener === 'object') { return isValidListener(listener.listener) } else { return false } } /** * Adds a listener function to the specified event. * The listener will not be added if it is a duplicate. * If the listener returns true then it will be removed after it is called. * If you pass a regular expression as the event name then the listener will be added to all events that match it. * * @param {String|RegExp} evt Name of the event to attach the listener to. * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. * @return {Object} Current instance of EventEmitter for chaining. */ proto.addListener = function addListener(evt, listener) { if (!isValidListener(listener)) { throw new TypeError('listener must be a function'); } var listeners = this.getListenersAsObject(evt); var listenerIsWrapped = typeof listener === 'object'; var key; for (key in listeners) { if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { listeners[key].push(listenerIsWrapped ? listener : { listener: listener, once: false }); } } return this; }; /** * Alias of addListener */ proto.on = alias('addListener'); /** * Semi-alias of addListener. It will add a listener that will be * automatically removed after its first execution. * * @param {String|RegExp} evt Name of the event to attach the listener to. * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. * @return {Object} Current instance of EventEmitter for chaining. */ proto.addOnceListener = function addOnceListener(evt, listener) { return this.addListener(evt, { listener: listener, once: true }); }; /** * Alias of addOnceListener. */ proto.once = alias('addOnceListener'); /** * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. * You need to tell it what event names should be matched by a regex. * * @param {String} evt Name of the event to create. * @return {Object} Current instance of EventEmitter for chaining. */ proto.defineEvent = function defineEvent(evt) { this.getListeners(evt); return this; }; /** * Uses defineEvent to define multiple events. * * @param {String[]} evts An array of event names to define. * @return {Object} Current instance of EventEmitter for chaining. */ proto.defineEvents = function defineEvents(evts) { for (var i = 0; i < evts.length; i += 1) { this.defineEvent(evts[i]); } return this; }; /** * Removes a listener function from the specified event. * When passed a regular expression as the event name, it will remove the listener from all events that match it. * * @param {String|RegExp} evt Name of the event to remove the listener from. * @param {Function} listener Method to remove from the event. * @return {Object} Current instance of EventEmitter for chaining. */ proto.removeListener = function removeListener(evt, listener) { var listeners = this.getListenersAsObject(evt); var index; var key; for (key in listeners) { if (listeners.hasOwnProperty(key)) { index = indexOfListener(listeners[key], listener); if (index !== -1) { listeners[key].splice(index, 1); } } } return this; }; /** * Alias of removeListener */ proto.off = alias('removeListener'); /** * Adds listeners in bulk using the manipulateListeners method. * If you pass an object as the first argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. * You can also pass it a regular expression to add the array of listeners to all events that match it. * Yeah, this function does quite a bit. That's probably a bad thing. * * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. * @param {Function[]} [listeners] An optional array of listener functions to add. * @return {Object} Current instance of EventEmitter for chaining. */ proto.addListeners = function addListeners(evt, listeners) { // Pass through to manipulateListeners return this.manipulateListeners(false, evt, listeners); }; /** * Removes listeners in bulk using the manipulateListeners method. * If you pass an object as the first argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. * You can also pass it an event name and an array of listeners to be removed. * You can also pass it a regular expression to remove the listeners from all events that match it. * * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. * @param {Function[]} [listeners] An optional array of listener functions to remove. * @return {Object} Current instance of EventEmitter for chaining. */ proto.removeListeners = function removeListeners(evt, listeners) { // Pass through to manipulateListeners return this.manipulateListeners(true, evt, listeners); }; /** * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. * The first argument will determine if the listeners are removed (true) or added (false). * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. * You can also pass it an event name and an array of listeners to be added/removed. * You can also pass it a regular expression to manipulate the listeners of all events that match it. * * @param {Boolean} remove True if you want to remove listeners, false if you want to add. * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. * @param {Function[]} [listeners] An optional array of listener functions to add/remove. * @return {Object} Current instance of EventEmitter for chaining. */ proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { var i; var value; var single = remove ? this.removeListener : this.addListener; var multiple = remove ? this.removeListeners : this.addListeners; // If evt is an object then pass each of its properties to this method if (typeof evt === 'object' && !(evt instanceof RegExp)) { for (i in evt) { if (evt.hasOwnProperty(i) && (value = evt[i])) { // Pass the single listener straight through to the singular method if (typeof value === 'function') { single.call(this, i, value); } else { // Otherwise pass back to the multiple function multiple.call(this, i, value); } } } } else { // So evt must be a string // And listeners must be an array of listeners // Loop over it and pass each one to the multiple method i = listeners.length; while (i--) { single.call(this, evt, listeners[i]); } } return this; }; /** * Removes all listeners from a specified event. * If you do not specify an event then all listeners will be removed. * That means every event will be emptied. * You can also pass a regex to remove all events that match it. * * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. * @return {Object} Current instance of EventEmitter for chaining. */ proto.removeEvent = function removeEvent(evt) { var type = typeof evt; var events = this._getEvents(); var key; // Remove different things depending on the state of evt if (type === 'string') { // Remove all listeners for the specified event delete events[evt]; } else if (evt instanceof RegExp) { // Remove all events matching the regex. for (key in events) { if (events.hasOwnProperty(key) && evt.test(key)) { delete events[key]; } } } else { // Remove all listeners in all events delete this._events; } return this; }; /** * Alias of removeEvent. * * Added to mirror the node API. */ proto.removeAllListeners = alias('removeEvent'); /** * Emits an event of your choice. * When emitted, every listener attached to that event will be executed. * If you pass the optional argument array then those arguments will be passed to every listener upon execution. * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. * So they will not arrive within the array on the other side, they will be separate. * You can also pass a regular expression to emit to all events that match it. * * @param {String|RegExp} evt Name of the event to emit and execute listeners for. * @param {Array} [args] Optional array of arguments to be passed to each listener. * @return {Object} Current instance of EventEmitter for chaining. */ proto.emitEvent = function emitEvent(evt, args) { var listenersMap = this.getListenersAsObject(evt); var listeners; var listener; var i; var key; var response; for (key in listenersMap) { if (listenersMap.hasOwnProperty(key)) { listeners = listenersMap[key].slice(0); for (i = 0; i < listeners.length; i++) { // If the listener returns true then it shall be removed from the event // The function is executed either with a basic call or an apply if there is an args array listener = listeners[i]; if (listener.once === true) { this.removeListener(evt, listener.listener); } response = listener.listener.apply(this, args || []); if (response === this._getOnceReturnValue()) { this.removeListener(evt, listener.listener); } } } } return this; }; /** * Alias of emitEvent */ proto.trigger = alias('emitEvent'); /** * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. * * @param {String|RegExp} evt Name of the event to emit and execute listeners for. * @param {...*} Optional additional arguments to be passed to each listener. * @return {Object} Current instance of EventEmitter for chaining. */ proto.emit = function emit(evt) { var args = Array.prototype.slice.call(arguments, 1); return this.emitEvent(evt, args); }; /** * Sets the current value to check against when executing listeners. If a * listeners return value matches the one set here then it will be removed * after execution. This value defaults to true. * * @param {*} value The new value to check for when executing listeners. * @return {Object} Current instance of EventEmitter for chaining. */ proto.setOnceReturnValue = function setOnceReturnValue(value) { this._onceReturnValue = value; return this; }; /** * Fetches the current value to check against when executing listeners. If * the listeners return value matches this one then it should be removed * automatically. It will return true by default. * * @return {*|Boolean} The current value to check for or the default, true. * @api private */ proto._getOnceReturnValue = function _getOnceReturnValue() { if (this.hasOwnProperty('_onceReturnValue')) { return this._onceReturnValue; } else { return true; } }; /** * Fetches the events object and creates one if required. * * @return {Object} The events storage object. * @api private */ proto._getEvents = function _getEvents() { return this._events || (this._events = {}); }; /** * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. * * @return {Function} Non conflicting EventEmitter class. */ EventEmitter.noConflict = function noConflict() { exports.EventEmitter = originalGlobalValue; return EventEmitter; }; // Expose the class either via AMD, CommonJS or the global object if (true) { !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () { return EventEmitter; }).call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); } else if (typeof module === 'object' && module.exports){ module.exports = EventEmitter; } else { exports.EventEmitter = EventEmitter; } }(this || {})); /***/ }), /***/ "./src/$$_lazy_route_resource lazy recursive": /***/ (function(module, exports) { function webpackEmptyAsyncContext(req) { // Here Promise.resolve().then() is used instead of new Promise() to prevent // uncatched exception popping up in devtools return Promise.resolve().then(function() { throw new Error("Cannot find module '" + req + "'."); }); } webpackEmptyAsyncContext.keys = function() { return []; }; webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext; module.exports = webpackEmptyAsyncContext; webpackEmptyAsyncContext.id = "./src/$$_lazy_route_resource lazy recursive"; /***/ }), /***/ "./src/app/app.component.css": /***/ (function(module, exports) { module.exports = "" /***/ }), /***/ "./src/app/app.component.html": /***/ (function(module, exports) { module.exports = "
\n \n
" /***/ }), /***/ "./src/app/app.component.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AppComponent; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var AppComponent = (function () { function AppComponent() { } AppComponent = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ selector: 'app-root', template: __webpack_require__("./src/app/app.component.html"), styles: [__webpack_require__("./src/app/app.component.css")] }) ], AppComponent); return AppComponent; }()); /***/ }), /***/ "./src/app/app.material.module.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AppMaterialModule; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_animations__ = __webpack_require__("./node_modules/@angular/platform-browser/esm5/animations.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__angular_material__ = __webpack_require__("./node_modules/@angular/material/esm5/material.es5.js"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var AppMaterialModule = (function () { function AppMaterialModule() { } AppMaterialModule = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["K" /* NgModule */])({ imports: [ __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_animations__["a" /* BrowserAnimationsModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["a" /* MatButtonModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["f" /* MatIconModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["c" /* MatCheckboxModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["b" /* MatCardModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["g" /* MatInputModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["i" /* MatProgressSpinnerModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["k" /* MatTooltipModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["e" /* MatDialogModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["j" /* MatSlideToggleModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["h" /* MatListModule */] ], exports: [ __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_animations__["a" /* BrowserAnimationsModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["a" /* MatButtonModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["f" /* MatIconModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["c" /* MatCheckboxModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["b" /* MatCardModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["g" /* MatInputModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["i" /* MatProgressSpinnerModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["k" /* MatTooltipModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["e" /* MatDialogModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["j" /* MatSlideToggleModule */], __WEBPACK_IMPORTED_MODULE_2__angular_material__["h" /* MatListModule */] ], }) ], AppMaterialModule); return AppMaterialModule; }()); /***/ }), /***/ "./src/app/app.module.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return AppModule; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_platform_browser__ = __webpack_require__("./node_modules/@angular/platform-browser/esm5/platform-browser.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_flex_layout__ = __webpack_require__("./node_modules/@angular/flex-layout/esm5/flex-layout.es5.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__angular_forms__ = __webpack_require__("./node_modules/@angular/forms/esm5/forms.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__angular_http__ = __webpack_require__("./node_modules/@angular/http/esm5/http.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_hammerjs__ = __webpack_require__("./node_modules/hammerjs/hammer.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_hammerjs___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_hammerjs__); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_6__app_routing__ = __webpack_require__("./src/app/app.routing.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_app_app_material_module__ = __webpack_require__("./src/app/app.material.module.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_8__services_info_service__ = __webpack_require__("./src/app/services/info.service.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_9__services_rest_service__ = __webpack_require__("./src/app/services/rest.service.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_10__app_component__ = __webpack_require__("./src/app/app.component.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_11__components_dashboard_dashboard_component__ = __webpack_require__("./src/app/components/dashboard/dashboard.component.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_12__components_session_details_session_details_component__ = __webpack_require__("./src/app/components/session-details/session-details.component.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_13__components_dashboard_credentials_dialog_component__ = __webpack_require__("./src/app/components/dashboard/credentials-dialog.component.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_14__components_layouts_layout_best_fit_layout_best_fit_component__ = __webpack_require__("./src/app/components/layouts/layout-best-fit/layout-best-fit.component.ts"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var AppModule = (function () { function AppModule() { } AppModule = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_2__angular_core__["K" /* NgModule */])({ declarations: [ __WEBPACK_IMPORTED_MODULE_10__app_component__["a" /* AppComponent */], __WEBPACK_IMPORTED_MODULE_11__components_dashboard_dashboard_component__["a" /* DashboardComponent */], __WEBPACK_IMPORTED_MODULE_12__components_session_details_session_details_component__["a" /* SessionDetailsComponent */], __WEBPACK_IMPORTED_MODULE_13__components_dashboard_credentials_dialog_component__["a" /* CredentialsDialogComponent */], __WEBPACK_IMPORTED_MODULE_14__components_layouts_layout_best_fit_layout_best_fit_component__["a" /* LayoutBestFitComponent */], ], imports: [ __WEBPACK_IMPORTED_MODULE_0__angular_platform_browser__["a" /* BrowserModule */], __WEBPACK_IMPORTED_MODULE_3__angular_forms__["c" /* FormsModule */], __WEBPACK_IMPORTED_MODULE_4__angular_http__["a" /* HttpModule */], __WEBPACK_IMPORTED_MODULE_6__app_routing__["a" /* routing */], __WEBPACK_IMPORTED_MODULE_7_app_app_material_module__["a" /* AppMaterialModule */], __WEBPACK_IMPORTED_MODULE_1__angular_flex_layout__["a" /* FlexLayoutModule */] ], entryComponents: [ __WEBPACK_IMPORTED_MODULE_13__components_dashboard_credentials_dialog_component__["a" /* CredentialsDialogComponent */], ], providers: [__WEBPACK_IMPORTED_MODULE_8__services_info_service__["a" /* InfoService */], __WEBPACK_IMPORTED_MODULE_9__services_rest_service__["a" /* RestService */]], bootstrap: [__WEBPACK_IMPORTED_MODULE_10__app_component__["a" /* AppComponent */]] }) ], AppModule); return AppModule; }()); /***/ }), /***/ "./src/app/app.routing.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return routing; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_router__ = __webpack_require__("./node_modules/@angular/router/esm5/router.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_app_components_dashboard_dashboard_component__ = __webpack_require__("./src/app/components/dashboard/dashboard.component.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_app_components_session_details_session_details_component__ = __webpack_require__("./src/app/components/session-details/session-details.component.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_app_components_layouts_layout_best_fit_layout_best_fit_component__ = __webpack_require__("./src/app/components/layouts/layout-best-fit/layout-best-fit.component.ts"); var appRoutes = [ { path: '', component: __WEBPACK_IMPORTED_MODULE_1_app_components_dashboard_dashboard_component__["a" /* DashboardComponent */], pathMatch: 'full' }, { path: 'session/:sessionId', component: __WEBPACK_IMPORTED_MODULE_2_app_components_session_details_session_details_component__["a" /* SessionDetailsComponent */], pathMatch: 'full' }, { path: 'layout-best-fit/:sessionId/:secret', component: __WEBPACK_IMPORTED_MODULE_3_app_components_layouts_layout_best_fit_layout_best_fit_component__["a" /* LayoutBestFitComponent */], pathMatch: 'full' } ]; var routing = __WEBPACK_IMPORTED_MODULE_0__angular_router__["b" /* RouterModule */].forRoot(appRoutes, { useHash: true }); /***/ }), /***/ "./src/app/components/dashboard/credentials-dialog.component.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return CredentialsDialogComponent; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var CredentialsDialogComponent = (function () { function CredentialsDialogComponent() { } CredentialsDialogComponent.prototype.testVideo = function () { this.myReference.close(this.secret); }; CredentialsDialogComponent = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ selector: 'app-credentials-dialog', template: "\n
\n

\n Insert your secret\n

\n
\n \n \n \n \n \n \n \n \n \n
\n
\n ", styles: ["\n #quality-div {\n margin-top: 20px;\n }\n #join-div {\n margin-top: 25px;\n margin-bottom: 20px;\n }\n #quality-tag {\n display: block;\n }\n h5 {\n margin-bottom: 10px;\n text-align: left;\n }\n #joinWithVideo {\n margin-right: 50px;\n }\n mat-dialog-actions {\n display: block;\n }\n #join-btn {\n float: right;\n }\n "], }), __metadata("design:paramtypes", []) ], CredentialsDialogComponent); return CredentialsDialogComponent; }()); /***/ }), /***/ "./src/app/components/dashboard/dashboard.component.css": /***/ (function(module, exports) { module.exports = "#dashboard-div {\n padding: 20px;\n}\n\n#log {\n height: 90%;\n}\n\n#log-content {\n height: 90%;\n font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace;\n overflow-y: auto;\n overflow-x: hidden\n}\n\nul {\n margin: 0;\n}\n\n#test-btn {\n text-transform: uppercase;\n float: right;\n}\n\nmat-card-title button.blue {\n color: #ffffff;\n background-color: #0088aa;\n}\n\nmat-card-title button.yellow {\n color: rgba(0, 0, 0, 0.87);\n background-color: #ffcc00;\n}\n\nmat-spinner {\n position: absolute;\n top: 50%;\n left: 50%;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n}\n\n#tick-div {\n width: 100px;\n height: 100px;\n z-index: 1;\n position: absolute;\n top: 50%;\n left: 50%;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n}\n\n#tooltip-tick {\n position: absolute;\n width: 100%;\n height: 100%;\n z-index: 2;\n}\n\n.circ {\n opacity: 0;\n stroke-dasharray: 130;\n stroke-dashoffset: 130;\n -webkit-transition: all 1s;\n transition: all 1s;\n}\n\n.tick {\n stroke-dasharray: 50;\n stroke-dashoffset: 50;\n -webkit-transition: stroke-dashoffset 1s 0.5s ease-out;\n transition: stroke-dashoffset 1s 0.5s ease-out;\n}\n\n.drawn+svg .path {\n opacity: 1;\n stroke-dashoffset: 0;\n}\n\n#mirrored-video {\n position: relative;\n}\n\n/* Pure CSS loader */\n\n#loader {\n width: 100px;\n height: 100px;\n z-index: 1;\n position: absolute;\n top: 50%;\n left: 50%;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n}\n\n#loader * {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n#loader ::after {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n#loader ::before {\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n}\n\n.loader-1 {\n height: 100px;\n width: 100px;\n -webkit-animation: loader-1-1 4.8s linear infinite;\n animation: loader-1-1 4.8s linear infinite;\n}\n\n@-webkit-keyframes loader-1-1 {\n 0% {\n -webkit-transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n }\n}\n\n@keyframes loader-1-1 {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n.loader-1 span {\n display: block;\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n margin: auto;\n height: 100px;\n width: 100px;\n clip: rect(0, 100px, 100px, 50px);\n -webkit-animation: loader-1-2 1.2s linear infinite;\n animation: loader-1-2 1.2s linear infinite;\n}\n\n@-webkit-keyframes loader-1-2 {\n 0% {\n -webkit-transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(220deg);\n }\n}\n\n@keyframes loader-1-2 {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(220deg);\n transform: rotate(220deg);\n }\n}\n\n.loader-1 span::after {\n content: \"\";\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n margin: auto;\n height: 100px;\n width: 100px;\n clip: rect(0, 100px, 100px, 50px);\n border: 8px solid #4d4d4d;\n border-radius: 50%;\n -webkit-animation: loader-1-3 1.2s cubic-bezier(0.770, 0.000, 0.175, 1.000) infinite;\n animation: loader-1-3 1.2s cubic-bezier(0.770, 0.000, 0.175, 1.000) infinite;\n}\n\n@-webkit-keyframes loader-1-3 {\n 0% {\n -webkit-transform: rotate(-140deg);\n }\n 50% {\n -webkit-transform: rotate(-160deg);\n }\n 100% {\n -webkit-transform: rotate(140deg);\n }\n}\n\n@keyframes loader-1-3 {\n 0% {\n -webkit-transform: rotate(-140deg);\n transform: rotate(-140deg);\n }\n 50% {\n -webkit-transform: rotate(-160deg);\n transform: rotate(-160deg);\n }\n 100% {\n -webkit-transform: rotate(140deg);\n transform: rotate(140deg);\n }\n}" /***/ }), /***/ "./src/app/components/dashboard/dashboard.component.html": /***/ (function(module, exports) { module.exports = "
\n\n
\n \n Server events\n \n lock_outline\n \n \n \n \n
    \n
  • \n

    {{i}}

    \n
  • \n
\n
\n
\n
\n\n
\n \n Test the connection\n \n \n \n
\n
\n
\n
\n
\n
\n
\n \n \n \n \n
\n
\n

{{msg}}

\n
\n
\n
\n
\n" /***/ }), /***/ "./src/app/components/dashboard/dashboard.component.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return DashboardComponent; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_material__ = __webpack_require__("./node_modules/@angular/material/esm5/material.es5.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__services_info_service__ = __webpack_require__("./src/app/services/info.service.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__services_rest_service__ = __webpack_require__("./src/app/services/rest.service.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_openvidu_browser__ = __webpack_require__("../../../../../openvidu-browser2/lib/index.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_openvidu_browser___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_openvidu_browser__); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_5__credentials_dialog_component__ = __webpack_require__("./src/app/components/dashboard/credentials-dialog.component.ts"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var DashboardComponent = (function () { function DashboardComponent(infoService, restService, dialog) { var _this = this; this.infoService = infoService; this.restService = restService; this.dialog = dialog; this.lockScroll = false; this.info = []; this.testStatus = 'DISCONNECTED'; this.testButton = 'Test'; this.tickClass = 'trigger'; this.showSpinner = false; this.msgChain = []; // Subscription to info updated event raised by InfoService this.infoSubscription = this.infoService.newInfo$.subscribe(function (info) { _this.info.push(info); _this.scrollToBottom(); }); } DashboardComponent.prototype.ngOnInit = function () { var _this = this; var protocol = location.protocol.includes('https') ? 'wss://' : 'ws://'; var port = (location.port) ? (':' + location.port) : ''; this.websocket = new WebSocket(protocol + location.hostname + port + '/info'); this.websocket.onopen = function (event) { console.log('Info websocket connected'); }; this.websocket.onclose = function (event) { console.log('Info websocket closed'); }; this.websocket.onerror = function (event) { console.log('Info websocket error'); }; this.websocket.onmessage = function (event) { console.log('Info websocket message'); console.log(event.data); _this.infoService.updateInfo(event.data); }; this.restService.getOpenViduPublicUrl() .then(function (url) { _this.openviduPublicUrl = url.replace('https://', 'wss://').replace('http://', 'ws://'); }) .catch(function (error) { console.error(error); }); }; DashboardComponent.prototype.beforeunloadHandler = function () { // On window closed leave test session and close info websocket if (this.session) { this.endTestVideo(); } this.websocket.close(); }; DashboardComponent.prototype.ngOnDestroy = function () { // On component destroyed leave test session and close info websocket if (this.session) { this.endTestVideo(); } this.websocket.close(); }; DashboardComponent.prototype.toggleTestVideo = function () { if (!this.session) { this.testVideo(); } else { this.endTestVideo(); } }; DashboardComponent.prototype.testVideo = function () { var _this = this; var dialogRef; dialogRef = this.dialog.open(__WEBPACK_IMPORTED_MODULE_5__credentials_dialog_component__["a" /* CredentialsDialogComponent */]); dialogRef.componentInstance.myReference = dialogRef; dialogRef.afterClosed().subscribe(function (secret) { if (secret) { if (!_this.openviduPublicUrl) { _this.restService.getOpenViduPublicUrl() .then((function (url) { _this.openviduPublicUrl = url.replace('https://', 'wss://').replace('http://', 'ws://'); _this.connectToSession(_this.openviduPublicUrl + 'testSession?secret=' + secret); })) .catch(function (error) { console.error(error); }); } else { _this.connectToSession(_this.openviduPublicUrl + 'testSession?secret=' + secret); } } }); }; DashboardComponent.prototype.connectToSession = function (mySessionId) { var _this = this; this.msgChain = []; var OV = new __WEBPACK_IMPORTED_MODULE_4_openvidu_browser__["OpenVidu"](); this.session = OV.initSession(mySessionId); this.testStatus = 'CONNECTING'; this.testButton = 'Testing...'; this.session.connect('token', function (error) { if (!error) { _this.testStatus = 'CONNECTED'; var publisherRemote = OV.initPublisher('mirrored-video', { audio: true, video: true, audioActive: true, videoActive: true, quality: 'MEDIUM' }, function (e) { if (!!e) { console.error(e); } }); publisherRemote.on('accessAllowed', function () { _this.msgChain.push('Camera access allowed'); }); publisherRemote.on('accessDenied', function () { _this.endTestVideo(); _this.msgChain.push('Camera access denied'); }); publisherRemote.on('videoElementCreated', function (video) { _this.showSpinner = true; _this.msgChain.push('Video element created'); }); publisherRemote.on('remoteVideoPlaying', function (video) { _this.msgChain.push('Remote video playing'); _this.testButton = 'End test'; _this.testStatus = 'PLAYING'; _this.showSpinner = false; }); publisherRemote.subscribeToRemote(); _this.session.publish(publisherRemote); } else { if (error.code === 401) { _this.endTestVideo(); var dialogRef = void 0; dialogRef = _this.dialog.open(__WEBPACK_IMPORTED_MODULE_5__credentials_dialog_component__["a" /* CredentialsDialogComponent */]); dialogRef.componentInstance.myReference = dialogRef; dialogRef.afterClosed().subscribe(function (secret) { if (secret) { _this.connectToSession('wss://' + location.hostname + ':8443/testSession?secret=' + secret); } }); } else { console.error(error); } } }); }; DashboardComponent.prototype.endTestVideo = function () { this.session.disconnect(); this.session = null; this.testStatus = 'DISCONNECTED'; this.testButton = 'Test'; this.showSpinner = false; this.info = []; this.msgChain = []; }; DashboardComponent.prototype.scrollToBottom = function () { try { if (!this.lockScroll) { this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight; } } catch (err) { console.error('[Error]:' + err.toString()); } }; __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["_12" /* ViewChild */])('scrollMe'), __metadata("design:type", __WEBPACK_IMPORTED_MODULE_0__angular_core__["u" /* ElementRef */]) ], DashboardComponent.prototype, "myScrollContainer", void 0); __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["A" /* HostListener */])('window:beforeunload'), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DashboardComponent.prototype, "beforeunloadHandler", null); DashboardComponent = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ selector: 'app-dashboard', template: __webpack_require__("./src/app/components/dashboard/dashboard.component.html"), styles: [__webpack_require__("./src/app/components/dashboard/dashboard.component.css")], }), __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_2__services_info_service__["a" /* InfoService */], __WEBPACK_IMPORTED_MODULE_3__services_rest_service__["a" /* RestService */], __WEBPACK_IMPORTED_MODULE_1__angular_material__["d" /* MatDialog */]]) ], DashboardComponent); return DashboardComponent; }()); /***/ }), /***/ "./src/app/components/layouts/layout-best-fit/layout-best-fit.component.css": /***/ (function(module, exports) { module.exports = ".bounds {\n background-color: black;\n overflow: hidden;\n cursor: none !important;\n position: absolute;\n left: 0;\n right: 0;\n top: 0;\n bottom: 0;\n}\n\nvideo {\n -o-object-fit: cover;\n object-fit: cover;\n display: block;\n position: absolute;\n width: 100%;\n height: 100%;\n color: #ffffff;\n margin: 0;\n padding: 0;\n border: 0;\n font-size: 100%;\n font-family: Arial, Helvetica, sans-serif;\n}\n\n/*!\n * Copyright (c) 2017 TokBox, Inc.\n * Released under the MIT license\n * http://opensource.org/licenses/MIT\n */\n\n.custom-class {\n min-height: 0px !important;\n}\n\n/**\n * OT Base styles\n */\n\n/* Root OT object, this is where our CSS reset happens */\n\n.OT_root,\n.OT_root * {\n color: #ffffff;\n margin: 0;\n padding: 0;\n border: 0;\n font-size: 100%;\n font-family: Arial, Helvetica, sans-serif;\n vertical-align: baseline;\n}\n\n.OT_dialog-centering {\n display: table;\n width: 100%;\n height: 100%;\n}\n\n.OT_dialog-centering-child {\n display: table-cell;\n vertical-align: middle;\n}\n\n.OT_dialog {\n position: relative;\n\n -webkit-box-sizing: border-box;\n\n box-sizing: border-box;\n max-width: 576px;\n margin-right: auto;\n margin-left: auto;\n padding: 36px;\n text-align: center; /* centers all the inline content */\n\n background-color: #363636;\n color: #fff;\n -webkit-box-shadow: 2px 4px 6px #999;\n box-shadow: 2px 4px 6px #999;\n font-family: 'Didact Gothic', sans-serif;\n font-size: 13px;\n line-height: 1.4;\n}\n\n.OT_dialog * {\n font-family: inherit;\n -webkit-box-sizing: inherit;\n box-sizing: inherit;\n}\n\n.OT_closeButton {\n color: #999999;\n cursor: pointer;\n font-size: 32px;\n line-height: 36px;\n position: absolute;\n right: 18px;\n top: 0;\n}\n\n.OT_dialog-messages {\n text-align: center;\n}\n\n.OT_dialog-messages-main {\n margin-bottom: 36px;\n line-height: 36px;\n\n font-weight: 300;\n font-size: 24px;\n}\n\n.OT_dialog-messages-minor {\n margin-bottom: 18px;\n\n font-size: 13px;\n line-height: 18px;\n color: #A4A4A4;\n}\n\n.OT_dialog-messages-minor strong {\n color: #ffffff;\n}\n\n.OT_dialog-actions-card {\n display: inline-block;\n}\n\n.OT_dialog-button-title {\n margin-bottom: 18px;\n line-height: 18px;\n\n font-weight: 300;\n text-align: center;\n font-size: 14px;\n color: #999999;\n}\n\n.OT_dialog-button-title label {\n color: #999999;\n}\n\n.OT_dialog-button-title a,\n.OT_dialog-button-title a:link,\n.OT_dialog-button-title a:active {\n color: #02A1DE;\n}\n\n.OT_dialog-button-title strong {\n color: #ffffff;\n font-weight: 100;\n display: block;\n}\n\n.OT_dialog-button {\n display: inline-block;\n\n margin-bottom: 18px;\n padding: 0 1em;\n\n background-color: #1CA3DC;\n text-align: center;\n cursor: pointer;\n}\n\n.OT_dialog-button:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.OT_dialog-button-large {\n line-height: 36px;\n padding-top: 9px;\n padding-bottom: 9px;\n\n font-weight: 100;\n font-size: 24px;\n}\n\n.OT_dialog-button-small {\n line-height: 18px;\n padding-top: 9px;\n padding-bottom: 9px;\n\n background-color: #444444;\n color: #999999;\n font-size: 16px;\n}\n\n.OT_dialog-progress-bar {\n display: inline-block; /* prevents margin collapse */\n width: 100%;\n margin-top: 5px;\n margin-bottom: 41px;\n\n border: 1px solid #4E4E4E;\n height: 8px;\n}\n\n.OT_dialog-progress-bar-fill {\n height: 100%;\n\n background-color: #29A4DA;\n}\n\n.OT_dialog-plugin-upgrading .OT_dialog-plugin-upgrade-percentage {\n line-height: 54px;\n\n font-size: 48px;\n font-weight: 100;\n}\n\n/* Helpers */\n\n.OT_centered {\n position: fixed;\n left: 50%;\n top: 50%;\n margin: 0;\n}\n\n.OT_dialog-hidden {\n display: none;\n}\n\n.OT_dialog-button-block {\n display: block;\n}\n\n.OT_dialog-no-natural-margin {\n margin-bottom: 0;\n}\n\n/* Publisher and Subscriber styles */\n\n.OT_publisher, .OT_subscriber {\n position: relative;\n min-width: 48px;\n min-height: 48px;\n}\n\n.OT_publisher .OT_video-element,\n.OT_subscriber .OT_video-element {\n display: block;\n position: absolute;\n width: 100%;\n height: 100%;\n\n -webkit-transform-origin: 0 0;\n\n transform-origin: 0 0;\n}\n\n/* Styles that are applied when the video element should be mirrored */\n\n.OT_publisher.OT_mirrored .OT_video-element {\n -webkit-transform: scale(-1, 1);\n transform: scale(-1, 1);\n -webkit-transform-origin: 50% 50%;\n transform-origin: 50% 50%;\n}\n\n.OT_subscriber_error {\n background-color: #000;\n color: #fff;\n text-align: center;\n}\n\n.OT_subscriber_error > p {\n padding: 20px;\n}\n\n/* The publisher/subscriber name/mute background */\n\n.OT_publisher .OT_bar,\n.OT_subscriber .OT_bar,\n.OT_publisher .OT_name,\n.OT_subscriber .OT_name,\n.OT_publisher .OT_archiving,\n.OT_subscriber .OT_archiving,\n.OT_publisher .OT_archiving-status,\n.OT_subscriber .OT_archiving-status,\n.OT_publisher .OT_archiving-light-box,\n.OT_subscriber .OT_archiving-light-box {\n -webkit-box-sizing: border-box;\n -ms-box-sizing: border-box;\n box-sizing: border-box;\n top: 0;\n left: 0;\n right: 0;\n display: block;\n height: 34px;\n position: absolute;\n}\n\n.OT_publisher .OT_bar,\n.OT_subscriber .OT_bar {\n background: rgba(0, 0, 0, 0.4);\n}\n\n.OT_publisher .OT_edge-bar-item,\n.OT_subscriber .OT_edge-bar-item {\n z-index: 1; /* required to get audio level meter underneath */\n}\n\n/* The publisher/subscriber name panel/archiving status bar */\n\n.OT_publisher .OT_name,\n.OT_subscriber .OT_name {\n background-color: transparent;\n color: #ffffff;\n font-size: 15px;\n line-height: 34px;\n font-weight: normal;\n padding: 0 4px 0 36px;\n}\n\n.OT_publisher .OT_archiving-status,\n.OT_subscriber .OT_archiving-status {\n background: rgba(0, 0, 0, 0.4);\n top: auto;\n bottom: 0;\n left: 34px;\n padding: 0 4px;\n color: rgba(255, 255, 255, 0.8);\n font-size: 15px;\n line-height: 34px;\n font-weight: normal;\n}\n\n.OT_micro .OT_archiving-status,\n.OT_micro:hover .OT_archiving-status,\n.OT_mini .OT_archiving-status,\n.OT_mini:hover .OT_archiving-status {\n display: none;\n}\n\n.OT_publisher .OT_archiving-light-box,\n.OT_subscriber .OT_archiving-light-box {\n background: rgba(0, 0, 0, 0.4);\n top: auto;\n bottom: 0;\n right: auto;\n width: 34px;\n height: 34px;\n}\n\n.OT_archiving-light {\n width: 7px;\n height: 7px;\n border-radius: 30px;\n position: absolute;\n top: 14px;\n left: 14px;\n background-color: #575757;\n -webkit-box-shadow: 0 0 5px 1px #575757;\n box-shadow: 0 0 5px 1px #575757;\n}\n\n.OT_archiving-light.OT_active {\n background-color: #970d13;\n animation: OT_pulse 1.3s ease-in;\n -webkit-animation: OT_pulse 1.3s ease-in;\n -moz-animation: OT_pulse 1.3s ease-in;\n -webkit-animation: OT_pulse 1.3s ease-in;\n animation-iteration-count: infinite;\n -webkit-animation-iteration-count: infinite;\n -moz-animation-iteration-count: infinite;\n -webkit-animation-iteration-count: infinite;\n}\n\n@-webkit-keyframes OT_pulse {\n 0% {\n -webkit-box-shadow: 0 0 0px 0px #c70019;\n box-shadow: 0 0 0px 0px #c70019;\n }\n\n 30% {\n -webkit-box-shadow: 0 0 5px 1px #c70019;\n box-shadow: 0 0 5px 1px #c70019;\n }\n\n 50% {\n -webkit-box-shadow: 0 0 5px 1px #c70019;\n box-shadow: 0 0 5px 1px #c70019;\n }\n\n 80% {\n -webkit-box-shadow: 0 0 0px 0px #c70019;\n box-shadow: 0 0 0px 0px #c70019;\n }\n\n 100% {\n -webkit-box-shadow: 0 0 0px 0px #c70019;\n box-shadow: 0 0 0px 0px #c70019;\n }\n}\n\n@-webkit-keyframes OT_pulse {\n 0% {\n -webkit-box-shadow: 0 0 0px 0px #c70019;\n box-shadow: 0 0 0px 0px #c70019;\n }\n\n 30% {\n -webkit-box-shadow: 0 0 5px 1px #c70019;\n box-shadow: 0 0 5px 1px #c70019;\n }\n\n 50% {\n -webkit-box-shadow: 0 0 5px 1px #c70019;\n box-shadow: 0 0 5px 1px #c70019;\n }\n\n 80% {\n -webkit-box-shadow: 0 0 0px 0px #c70019;\n box-shadow: 0 0 0px 0px #c70019;\n }\n\n 100% {\n -webkit-box-shadow: 0 0 0px 0px #c70019;\n box-shadow: 0 0 0px 0px #c70019;\n }\n}\n\n.OT_mini .OT_bar,\n.OT_bar.OT_mode-mini,\n.OT_bar.OT_mode-mini-auto {\n bottom: 0;\n height: auto;\n}\n\n.OT_mini .OT_name.OT_mode-off,\n.OT_mini .OT_name.OT_mode-on,\n.OT_mini .OT_name.OT_mode-auto,\n.OT_mini:hover .OT_name.OT_mode-auto {\n display: none;\n}\n\n.OT_publisher .OT_name,\n.OT_subscriber .OT_name {\n left: 10px;\n right: 37px;\n height: 34px;\n padding-left: 0;\n}\n\n.OT_publisher .OT_mute,\n.OT_subscriber .OT_mute {\n border: none;\n cursor: pointer;\n display: block;\n position: absolute;\n text-align: center;\n text-indent: -9999em;\n background-color: transparent;\n background-repeat: no-repeat;\n}\n\n.OT_publisher .OT_mute,\n.OT_subscriber .OT_mute {\n right: 0;\n top: 0;\n border-left: 1px solid rgba(255, 255, 255, 0.2);\n height: 36px;\n width: 37px;\n}\n\n.OT_mini .OT_mute,\n.OT_publisher.OT_mini .OT_mute.OT_mode-auto.OT_mode-on-hold,\n.OT_subscriber.OT_mini .OT_mute.OT_mode-auto.OT_mode-on-hold {\n top: 50%;\n left: 50%;\n right: auto;\n margin-top: -18px;\n margin-left: -18.5px;\n border-left: none;\n}\n\n.OT_publisher .OT_mute {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAcCAMAAAC02HQrAAAA1VBMVEUAAAD3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pn3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pn3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj3+Pj39/j3+Pj3+Pn4+Pk/JRMlAAAAQ3RSTlMABAUHCQoLDhAQERwdHiAjLjAxOD9ASFBRVl1mbnZ6fH2LjI+QkaWqrrC1uLzAwcXJycrL1NXj5Ofo6u3w9fr7/P3+d4M3+QAAAQBJREFUGBlVwYdCglAABdCLlr5Unijm3hMUtBzlBLSr//9JgUToOQgVJgceJgU8aHgMeA38K50ZOpcQmTPwcyXn+JM8M3JJIqQypiIkeXelTyIkGZPwKS1NMia1lgKTVkaE3oQQGYsmHNqSMWnTgUFbMiZtGlD2dpaxrL1XgM0i4ZK8MeAmFhsAs29MGZniawagS63oMOQUNXYB5D0D1RMDpyoMLw/fiE2og/V+PVDR5AiBl0/2Uwik+vx4xV3a5G5Ye68Nd1czjUjZckm6VhmPciRzeCZICjwTJAViQq+3e+St167rAoHK8sLYZVkBYPCZAZ/eGa+2R5LH7Wrc0YFf/O9J3yBDFaoAAAAASUVORK5CYII=);\n background-position: 9px 5px;\n}\n\n.OT_publisher .OT_mute.OT_active {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAdCAYAAABFRCf7AAADcElEQVRIiaWVXWhcRRTHf7NNd2aDtUKMIjTpg4ufFIuiUOmDEWm0Vi3VYhXRqIggQh4sWJFSig9+oOhTKSpIRUWMIBIr2kptoTbgU6ooxCiIjR+14kcJmf9sNceHnd3ebnc3Uv9wuXfOzPzmnDMz5zozGwdWAbc65w5RUJQ8cC2wDJgFJioh/MJCMrNxq2vOzK4HmIvRRemxKP0RJWt53o7S+d2Yzsx6gQ+AIUDAnUqpBLzXZd4RYFUlhB/bdZacc3PAOmAcCMC7wfvFwLNdoAPAyx09bXyYWRl4E7gDmAdGlNKFwLYu8GolhO9O87RJd64GbMrgEvB68P4osMWdXLtVV7czlooNpVRWSs8DO7NpR/B+3rBHsvetCgtCMTxwQCm9BbyQrc8F7/uBex3uRCeXO0PrUZ4NfKyUPgWeyj3bg/crDNsIRGwBaJQGorQ3Svdn2wHgc2BUKb0DPJHtjwfvbwRucc7tz+N+i9LFUdoXpfVN36I0CVwBTFI/q9e1LPxT8P4qYEdu70q12mYzWw1MYQzjeJF6zq+shHC4B7jklOBPP/TzSunh4P0DwKvAfb5c9krpe+CcwsEoZdbhEvBM9wxRAl5RShcA9wAngE3B+8tLpdLuwrhp4MNmK0pfRWkySr7NXS8+L5nZbWZWy/Vin1IaitJnUTqvwevJ71lgSSWEFKUfHG7Q2m/xqFJaGry/GXgfGPLl8mJgrXPur2JoUC8Qy3OpG+sAbGhEKT0ErAWOA6uBPWbW1wr9BOgFbgKezot0kAPYqJQA1gC/A9cA+82svzksSn1R+jNKX0SpnM/e1x3yqig92JhrZivM7FjO8bSZLSuCR/Ok16K0KMNHojQWpYko7Y7S1igN5PE3ROl4lNaZ2UVmNpPBU01orvZvZPCeKFXbBR+lEKVtUapFaSZKg9njqpl9aWYTrmXCImA7sCWb9lK/jj9TrwkrgA1AH3AQuKsSwkzbrLfxpgpsBtYDxf/R3xm2ExirhNCuHHZXTsmRwiat+S/zSt06eysVA/4pmGr/G3qm6ik28v29FKgCg8BS6pvS0KNRGgZ+Bb4FpsxsOkfUlMuwDcBWYOUZOHYM2AU8WQmhBifDv70O7PjX7KZ+4G7g3FM8zd6uBIaBy4AqxnIcZwFLCovPAhE4Sj38b4BDwEeVEFKD9S94Khjn486v3QAAAABJRU5ErkJggg==);\n background-position: 9px 4px;\n}\n\n.OT_subscriber .OT_mute {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAATCAYAAAB7u5a2AAABx0lEQVQ4jaWUv48NURiGn3ONmCs32ZBd28ht1gqyZAkF21ylQkEiSp2ehpDlD1BoFGqqVdJohYKI7MaPxMoVNghCWMF+7ybLUewnOXfcMWO9yeQ857zne8+XmZOBGjJpr0kvTIomvTZpS526UCO4DUwD64FjwCFgqZnnR+oc8LfgzKQ73vGsr42ZtGjSQFV9o8KfBCacZwCaef4YmAf2rzjcpN3A2WSpm/AssKcqPDNpDBjs410CViXzTwk/A7b1C4wxDgOngAsZcAXY2buDfp/6S4F3lDS8DjgBzDWAjX/Y/e/QgYS/AhsKHa+OMQ6GEJ4Cj4BOAxgq6aCowyZtdf4OtAr+FHDO+R4wWnVbihr3cQnICt4boO38GWj9a/icjwOACt4m4K3zEPA+AxaAtTWCnwN3lzHkEL8V/OPAGud9wK2GF9XR1Wae/1zG2AI+pGYI4VUIoRtjHAc2A9cz4LRPevYCZ+i9/4sJt4GXJU10gaPAzdI2TTro/5Tfz8XEe2LSZGmxq/SDNvP8BnA5WRrx4BwYBe6vONx1EnjovGvBLAAd4Adwuyq8UiaNmDTvr+a8SQ9MuvbfwckBHZPe+QEfTdpep+4XZmPBHiHgz74AAAAASUVORK5CYII=);\n background-position: 8px 7px;\n}\n\n.OT_subscriber .OT_mute.OT_active {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAYAAACXtf2DAAACtklEQVQ4jZ2VSYiURxTHf+/T9Nc9iRrBuYySmIsXUU9iFMEFERRBvAjJLUQi5ioiHvSScfTmgqC4XAT1ZIgLuJHkICaaQAgKI2hAUBT30bjUq7bbv4eukXK029F3+eqtv/fqK6qQdEnSNUmT6CDB/bvgfjO4N9zj2RD8007xg1IABkwEzkma0qb4PGAPMBZYLtSD8eNwAEjqTlNI0gNJM4YU7w7ut4O7gvuhZFsR3C8NC5BBLiTIY0mzM8AvqbiC++pk+zLpE95XuwAws3vAQuBPYDRwWtL84P4tsDSLv5oaug4EYOawAMF9jMdoLxqNZcDvQA04UVYqL4G/svj7AF21mhJscrvCksYBFO7xc2AAGGg2mrdjvf4rcAyomNn+slLZmUEGBgsYdh945xZJmgvckDSrEJpK6ySBgV6q12O8ABwGPjGzfWWlsjdN9rpjoSfA+DYDXARGAksK4Is3XC1Ub4z1f4CDQGFmu6tleQSYk0U+p7WVeefLJc00s4fAeWB6Qeunvj0m2ugx9gO7kmlrtSxvBfcy6fXUZS6rgG/S+jLQUwCVNmMC9HqM14EtSe+rluWazN8YEv8IqKZ1E1qnaIDO0ucx3gX6kv6TpM3AM+D/IbGjgP60/gq4WQA33gMA2OQxPgHWJX1ttSwL4FAeZGYLgB2SasBs4A8L7qOBf9M0uXQB3a+TMYSmVctyDrA9mfcBK82smSdKWgCcAaa1bTm4fxbc/8uuCQX3RanAD5Ka6Wo5IGnE0HxJPZ03pQX5Org3MsD3AO5xXLPZXJ9BjkrqdFg6QjZkgG3Jtsw93pG0VFI9QU5K6voYQBHcTydAfwheBI9HgvvPAJIWS3qeIL9JGvUxkO7gfi1BrqTvwkG/pPmSnibIqTzXPgAyEVgBjAEu1qrVPbk/PVTHgb/NbPGg/RVIzOQqzSTBaQAAAABJRU5ErkJggg==);\n background-position: 7px 7px;\n}\n\n/**\n * Styles for display modes\n *\n * Note: It's important that these completely control the display and opacity\n * attributes, no other selectors should atempt to change them.\n */\n\n/* Default display mode transitions for various chrome elements */\n\n.OT_publisher .OT_edge-bar-item,\n.OT_subscriber .OT_edge-bar-item {\n -webkit-transition-property: top, bottom, opacity;\n transition-property: top, bottom, opacity;\n -webkit-transition-duration: 0.5s;\n transition-duration: 0.5s;\n -webkit-transition-timing-function: ease-in;\n transition-timing-function: ease-in;\n}\n\n.OT_publisher .OT_edge-bar-item.OT_mode-off,\n.OT_subscriber .OT_edge-bar-item.OT_mode-off,\n.OT_publisher .OT_edge-bar-item.OT_mode-auto,\n.OT_subscriber .OT_edge-bar-item.OT_mode-auto,\n.OT_publisher .OT_edge-bar-item.OT_mode-mini-auto,\n.OT_subscriber .OT_edge-bar-item.OT_mode-mini-auto {\n top: -25px;\n opacity: 0;\n}\n\n.OT_publisher .OT_edge-bar-item.OT_mode-off,\n.OT_subscriber .OT_edge-bar-item.OT_mode-off {\n display: none;\n}\n\n.OT_mini .OT_mute.OT_mode-auto,\n.OT_publisher .OT_mute.OT_mode-mini-auto,\n.OT_subscriber .OT_mute.OT_mode-mini-auto {\n top: 50%;\n}\n\n.OT_publisher .OT_edge-bar-item.OT_edge-bottom.OT_mode-off,\n.OT_subscriber .OT_edge-bar-item.OT_edge-bottom.OT_mode-off,\n.OT_publisher .OT_edge-bar-item.OT_edge-bottom.OT_mode-auto,\n.OT_subscriber .OT_edge-bar-item.OT_edge-bottom.OT_mode-auto,\n.OT_publisher .OT_edge-bar-item.OT_edge-bottom.OT_mode-mini-auto,\n.OT_subscriber .OT_edge-bar-item.OT_edge-bottom.OT_mode-mini-auto {\n top: auto;\n bottom: -25px;\n}\n\n.OT_publisher .OT_edge-bar-item.OT_mode-on,\n.OT_subscriber .OT_edge-bar-item.OT_mode-on,\n.OT_publisher .OT_edge-bar-item.OT_mode-auto.OT_mode-on-hold,\n.OT_subscriber .OT_edge-bar-item.OT_mode-auto.OT_mode-on-hold,\n.OT_publisher:hover .OT_edge-bar-item.OT_mode-auto,\n.OT_subscriber:hover .OT_edge-bar-item.OT_mode-auto,\n.OT_publisher:hover .OT_edge-bar-item.OT_mode-mini-auto,\n.OT_subscriber:hover .OT_edge-bar-item.OT_mode-mini-auto {\n top: 0;\n opacity: 1;\n}\n\n.OT_mini .OT_mute.OT_mode-on,\n.OT_mini:hover .OT_mute.OT_mode-auto,\n.OT_mute.OT_mode-mini,\n.OT_root:hover .OT_mute.OT_mode-mini-auto {\n top: 50%;\n}\n\n.OT_publisher .OT_edge-bar-item.OT_edge-bottom.OT_mode-on,\n.OT_subscriber .OT_edge-bar-item.OT_edge-bottom.OT_mode-on,\n.OT_publisher:hover .OT_edge-bar-item.OT_edge-bottom.OT_mode-auto,\n.OT_subscriber:hover .OT_edge-bar-item.OT_edge-bottom.OT_mode-auto {\n top: auto;\n bottom: 0;\n opacity: 1;\n}\n\n/* Contains the video element, used to fix video letter-boxing */\n\n.OT_widget-container {\n width: 100%;\n height: 100%;\n position: absolute;\n background-color: #000000;\n overflow: hidden;\n}\n\n/* Load animation */\n\n.OT_root .OT_video-loading {\n position: absolute;\n z-index: 1;\n width: 100%;\n height: 100%;\n display: none;\n\n background-color: rgba(0, 0, 0, .75);\n}\n\n.OT_root .OT_video-loading .OT_video-loading-spinner {\n background: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9Ii0yMCAtMjAgMjQwIDI0MCI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJhIiB4Mj0iMCIgeTI9IjEiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2ZmZiIgc3RvcC1vcGFjaXR5PSIwIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9IjAiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iYiIgeDE9IjEiIHgyPSIwIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9IjAiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iLjA4Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImMiIHgxPSIxIiB4Mj0iMCIgeTE9IjEiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2ZmZiIgc3RvcC1vcGFjaXR5PSIuMDgiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iLjE2Ii8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImQiIHgyPSIwIiB5MT0iMSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii4xNiIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ZmZiIgc3RvcC1vcGFjaXR5PSIuMzMiLz48L2xpbmVhckdyYWRpZW50PjxsaW5lYXJHcmFkaWVudCBpZD0iZSIgeDI9IjEiIHkxPSIxIj48c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iLjMzIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZmZmIiBzdG9wLW9wYWNpdHk9Ii42NiIvPjwvbGluZWFyR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJmIiB4Mj0iMSIgeTI9IjEiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2ZmZiIgc3RvcC1vcGFjaXR5PSIuNjYiLz48c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNmZmYiLz48L2xpbmVhckdyYWRpZW50PjxtYXNrIGlkPSJnIj48ZyBmaWxsPSJub25lIiBzdHJva2Utd2lkdGg9IjQwIj48cGF0aCBzdHJva2U9InVybCgjYSkiIGQ9Ik04Ni42LTUwYTEwMCAxMDAgMCAwIDEgMCAxMDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwMCAxMDApIi8+PHBhdGggc3Ryb2tlPSJ1cmwoI2IpIiBkPSJNODYuNiA1MEExMDAgMTAwIDAgMCAxIDAgMTAwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDAgMTAwKSIvPjxwYXRoIHN0cm9rZT0idXJsKCNjKSIgZD0iTTAgMTAwYTEwMCAxMDAgMCAwIDEtODYuNi01MCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAwIDEwMCkiLz48cGF0aCBzdHJva2U9InVybCgjZCkiIGQ9Ik0tODYuNiA1MGExMDAgMTAwIDAgMCAxIDAtMTAwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDAgMTAwKSIvPjxwYXRoIHN0cm9rZT0idXJsKCNlKSIgZD0iTS04Ni42LTUwQTEwMCAxMDAgMCAwIDEgMC0xMDAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwMCAxMDApIi8+PHBhdGggc3Ryb2tlPSJ1cmwoI2YpIiBkPSJNMC0xMDBhMTAwIDEwMCAwIDAgMSA4Ni42IDUwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDAgMTAwKSIvPjwvZz48L21hc2s+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHg9Ii0yMCIgeT0iLTIwIiBtYXNrPSJ1cmwoI2cpIiBmaWxsPSIjZmZmIi8+PC9zdmc+) no-repeat;\n position: absolute;\n width: 32px;\n height: 32px;\n left: 50%;\n top: 50%;\n margin-left: -16px;\n margin-top: -16px;\n -webkit-animation: OT_spin 2s linear infinite;\n animation: OT_spin 2s linear infinite;\n}\n\n@-webkit-keyframes OT_spin {\n 100% {\n -webkit-transform: rotate(360deg);\n }\n}\n\n@keyframes OT_spin {\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n.OT_publisher.OT_loading .OT_video-loading,\n.OT_subscriber.OT_loading .OT_video-loading {\n display: block;\n}\n\n.OT_video-centering {\n display: table;\n width: 100%;\n height: 100%;\n}\n\n.OT_video-container {\n display: table-cell;\n vertical-align: middle;\n}\n\n.OT_video-poster {\n position: absolute;\n z-index: 1;\n width: 100%;\n height: 100%;\n display: none;\n\n opacity: .25;\n\n background-repeat: no-repeat;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNDcxIDQ2NCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48bGluZWFyR3JhZGllbnQgaWQ9ImEiIHgyPSIwIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PSI2Ni42NiUiIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iMCIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCNhKSIgZD0iTTc5IDMwOGMxNC4yNS02LjUgNTQuMjUtMTkuNzUgNzEtMjkgOS0zLjI1IDI1LTIxIDI1LTIxczMuNzUtMTMgMy0yMmMtMS43NS02Ljc1LTE1LTQzLTE1LTQzLTIuNSAzLTQuNzQxIDMuMjU5LTcgMS0zLjI1LTcuNS0yMC41LTQ0LjUtMTYtNTcgMS4yNS03LjUgMTAtNiAxMC02LTExLjI1LTMzLjc1LTgtNjctOC02N3MuMDczLTcuMzQ2IDYtMTVjLTMuNDguNjM3LTkgNC05IDQgMi41NjMtMTEuNzI3IDE1LTIxIDE1LTIxIC4xNDgtLjMxMi0xLjMyMS0xLjQ1NC0xMCAxIDEuNS0yLjc4IDE2LjY3NS04LjY1NCAzMC0xMSAzLjc4Ny05LjM2MSAxMi43ODItMTcuMzk4IDIyLTIyLTIuMzY1IDMuMTMzLTMgNi0zIDZzMTUuNjQ3LTguMDg4IDQxLTZjLTE5Ljc1IDItMjQgNi0yNCA2czc0LjUtMTAuNzUgMTA0IDM3YzcuNSA5LjUgMjQuNzUgNTUuNzUgMTAgODkgMy43NS0xLjUgNC41LTQuNSA5IDEgLjI1IDE0Ljc1LTExLjUgNjMtMTkgNjItMi43NSAxLTQtMy00LTMtMTAuNzUgMjkuNS0xNCAzOC0xNCAzOC0yIDQuMjUtMy43NSAxOC41LTEgMjIgMS4yNSA0LjUgMjMgMjMgMjMgMjNsMTI3IDUzYzM3IDM1IDIzIDEzNSAyMyAxMzVMMCA0NjRzLTMtOTYuNzUgMTQtMTIwYzUuMjUtNi4yNSAyMS43NS0xOS43NSA2NS0zNnoiLz48L3N2Zz4=);\n background-size: auto 76%;\n}\n\n.OT_fit-mode-cover .OT_video-element {\n -o-object-fit: cover;\n object-fit: cover;\n}\n\n/* Workaround for iOS freezing issue when cropping videos */\n\n/* https://bugs.webkit.org/show_bug.cgi?id=176439 */\n\n@media only screen\n and (orientation: portrait) {\n .OT_subscriber.OT_ForceContain.OT_fit-mode-cover .OT_video-element {\n -o-object-fit: contain !important;\n object-fit: contain !important;\n }\n}\n\n.OT_fit-mode-contain .OT_video-element {\n -o-object-fit: contain;\n object-fit: contain;\n}\n\n.OT_fit-mode-cover .OT_video-poster {\n background-position: center bottom;\n}\n\n.OT_fit-mode-contain .OT_video-poster {\n background-position: center;\n}\n\n.OT_audio-level-meter {\n position: absolute;\n width: 25%;\n max-width: 224px;\n min-width: 21px;\n top: 0;\n right: 0;\n overflow: hidden;\n}\n\n.OT_audio-level-meter:before {\n /* makes the height of the container equals its width */\n content: '';\n display: block;\n padding-top: 100%;\n}\n\n.OT_audio-level-meter__bar {\n position: absolute;\n width: 192%; /* meter value can overflow of 8% */\n height: 192%;\n top: -96% /* half of the size */;\n right: -96%;\n border-radius: 50%;\n\n background-color: rgba(0, 0, 0, .8);\n}\n\n.OT_audio-level-meter__audio-only-img {\n position: absolute;\n top: 22%;\n right: 15%;\n width: 40%;\n\n opacity: .7;\n\n background: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgNzkgODYiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgZmlsbD0iI2ZmZiI+PHBhdGggZD0iTTkuNzU3IDQwLjkyNGMzLjczOC01LjE5MSAxMi43MTEtNC4zMDggMTIuNzExLTQuMzA4IDIuMjIzIDMuMDE0IDUuMTI2IDI0LjU4NiAzLjYyNCAyOC43MTgtMS40MDEgMS4zMDEtMTEuNjExIDEuNjI5LTEzLjM4LTEuNDM2LTEuMjI2LTguODA0LTIuOTU1LTIyLjk3NS0yLjk1NS0yMi45NzV6bTU4Ljc4NSAwYy0zLjczNy01LjE5MS0xMi43MTEtNC4zMDgtMTIuNzExLTQuMzA4LTIuMjIzIDMuMDE0LTUuMTI2IDI0LjU4Ni0zLjYyNCAyOC43MTggMS40MDEgMS4zMDEgMTEuNjExIDEuNjI5IDEzLjM4LTEuNDM2IDEuMjI2LTguODA0IDIuOTU1LTIyLjk3NSAyLjk1NS0yMi45NzV6Ii8+PHBhdGggZD0iTTY4LjY0NyA1OC42Yy43MjktNC43NTMgMi4zOC05LjU2MSAyLjM4LTE0LjgwNCAwLTIxLjQxMi0xNC4xMTUtMzguNzctMzEuNTI4LTM4Ljc3LTE3LjQxMiAwLTMxLjUyNyAxNy4zNTgtMzEuNTI3IDM4Ljc3IDAgNC41NDEuNTE1IDguOTM2IDEuODAyIDEyLjk1IDEuNjk4IDUuMjk1LTUuNTQyIDYuOTkxLTYuNjE2IDIuMDczQzIuNDEgNTUuMzk0IDAgNTEuNzg3IDAgNDguMTAzIDAgMjEuNTM2IDE3LjY4NSAwIDM5LjUgMCA2MS4zMTYgMCA3OSAyMS41MzYgNzkgNDguMTAzYzAgLjcxOC0yLjg5OSA5LjY5My0zLjI5MiAxMS40MDgtLjc1NCAzLjI5My03Ljc1MSAzLjU4OS03LjA2MS0uOTEyeiIvPjxwYXRoIGQ9Ik01LjA4NCA1MS4zODVjLS44MDQtMy43ODIuNTY5LTcuMzM1IDMuMTM0LTcuOTIxIDIuNjM2LS42MDMgNS40ODUgMi4xNSA2LjI4OSA2LjEzMi43OTcgMy45NDgtLjc1MiA3LjQ1Ny0zLjM4OCA3Ljg1OS0yLjU2Ni4zOTEtNS4yMzctMi4zMTgtNi4wMzQtNi4wN3ptNjguODM0IDBjLjgwNC0zLjc4Mi0uNTY4LTcuMzM1LTMuMTMzLTcuOTIxLTIuNjM2LS42MDMtNS40ODUgMi4xNS02LjI4OSA2LjEzMi0uNzk3IDMuOTQ4Ljc1MiA3LjQ1NyAzLjM4OSA3Ljg1OSAyLjU2NS4zOTEgNS4yMzctMi4zMTggNi4wMzQtNi4wN3ptLTIuMDM4IDguMjg4Yy0uOTI2IDE5LjY1OS0xNS4xMTIgMjQuNzU5LTI1Ljg1OSAyMC40NzUtNS40MDUtLjYwNi0zLjAzNCAxLjI2Mi0zLjAzNCAxLjI2MiAxMy42NjEgMy41NjIgMjYuMTY4IDMuNDk3IDMxLjI3My0yMC41NDktLjU4NS00LjUxMS0yLjM3OS0xLjE4Ny0yLjM3OS0xLjE4N3oiLz48cGF0aCBkPSJNNDEuNjYyIDc4LjQyMmw3LjU1My41NWMxLjE5Mi4xMDcgMi4xMiAxLjE1MyAyLjA3MiAyLjMzNWwtLjEwOSAyLjczOGMtLjA0NyAxLjE4Mi0xLjA1MSAyLjA1NC0yLjI0MyAxLjk0NmwtNy41NTMtLjU1Yy0xLjE5MS0uMTA3LTIuMTE5LTEuMTUzLTIuMDcyLTIuMzM1bC4xMDktMi43MzdjLjA0Ny0xLjE4MiAxLjA1Mi0yLjA1NCAyLjI0My0xLjk0N3oiLz48L2c+PC9zdmc+) no-repeat center;\n}\n\n.OT_audio-level-meter__audio-only-img:before {\n /* makes the height of the container equals its width */\n content: '';\n display: block;\n padding-top: 100%;\n}\n\n.OT_audio-level-meter__value {\n position: absolute;\n border-radius: 50%;\n background-image: radial-gradient(circle, rgba(151, 206, 0, 1) 0%, rgba(151, 206, 0, 0) 100%);\n}\n\n.OT_audio-level-meter.OT_mode-off {\n display: none;\n}\n\n.OT_audio-level-meter.OT_mode-on,\n.OT_audio-only .OT_audio-level-meter.OT_mode-auto {\n display: block;\n}\n\n.OT_audio-only.OT_publisher .OT_video-element,\n.OT_audio-only.OT_subscriber .OT_video-element {\n display: none;\n}\n\n.OT_video-disabled-indicator {\n opacity: 1;\n border: none;\n display: none;\n position: absolute;\n background-color: transparent;\n background-repeat: no-repeat;\n background-position: bottom right;\n pointer-events: none;\n top: 0;\n left: 0;\n bottom: 3px;\n right: 3px;\n}\n\n.OT_video-disabled {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAAAoCAYAAABtla08AAAINUlEQVR42u2aaUxUVxTHcRBmAAEBRVTK4sKwDIsg+wCK7CqIw1CN1YobbbS2qYlJ06Qx1UpdqMbYWq2pSzWmH6ytNbXWJY1Lq7VuqBERtW64V0XFLYae0/xvcp3MMAMzDz6IyT/ge2ce5/7ucpY3Ts3NzZ1ygF57AJ0gO0G2jyZPmdbFyclJSAV1EeoEaUUSLGdSV5KLLFxzFmA7QVqGqDqjixhWkxCVeyRVl38wM6bwj6yYItYK47BAuu9B0gCqs6Ng2r494KQtkj/Dz2jHraw6qw2fdSE4rNmcCPCvZONP8iF1I6kdBdMaQJWZLeJqRWa2kPJAxXY+GxE+zxLI03GRh8lGSwoi9WCY8FWlCEh+8JOnT7MfPGjMuXX7Tt61hoaCi/9cKmKdv3BxeEtim/UbNpnbQiqF4MmT7kqrbr4lkMcTo46TTSpJB5g+8NHuVWnWuaampvhmO/7duHmrGluoO4C6OsJZGRrkDIld43ZqUOTnlkDSmXmabAoBU0vqBf+6KgFSxQ9++uzZ8rZApM81TJ8xM5me0Z/UF7PuBmdVdkGEb5gYDeQmyZNW3SJLIP9Kj64lGyMpmxRN6sOfIbkoAhKOdnv2/PmB1kB88eLFo+olyyrps3rSINIAzLonnqlqK8R9w+L86vtrt5L2nhug3Vc3ULu/Liz8AOuXESlZZONH6kmr7gtLIA9lRNeRzVukAvj3BslLnJNKgfScO69K+/Lly0ZbQW7e8tNK+pwBjqaSIjDrXgJkW1ciAZvbQjQ+RDahpBBKd5ZZsqN758hmImk4KQHnpDd8UwSkCyJarx07d4+3BeKJmlMHyX4qaRxpBCmNFE4KENvHDpAutVERn1kCVBMfeRRgYvZnx62wZPdnZkw92VQA5GClQXYRBze2S+iJmpPVVoJLA9l9QKokjcWKTCT1R5rhLg70NuSsziT16diIKkuAjibrTpJNDkn/e17CahtAjlAWJAYkb29Sb1LE9Rs391kILk8mVkyuIpuZcLKUlEmKkra1WuSTNuesEPzwoEploSVAh9Oiz+BIyd9dOHhtx4OEpFpVg6gbNK3yXX1j48N6U5Dz5i/gc/FDrMY3sTLiSMEkXxGxzUEUAGnbxlPaksMlHUXWAlHS8URCPseSohZbCSLjSSU7ixLXdzhIWVKq4Y7t2a/2bN0qGeKly1fYsVmk6RgIDz4J0bonyUOcjeYqm/8hRoYbWkigV2NH9CHAS60EkUkkw47hSRs6FqT1LR5AVcsrueXlK1d5AO+RpmBrZZEiefByytPCanRGNLZY0uF52gNDYr9sCRB8MHY0SJu2OJWKS2WQV65e4y31DmkCImEi0hBfufRime0RIhpbKen0/Ny9OYNW2ghyYytABjNIaxNuKttAWk6HPLn0k0FevdZwFinPWFIuKZbUV16NVko6jbWSDoPO3pOf8K0jQWLSQ0S9bdpkYck+m7vfWpAiHfKgBsZiGSSt0FqcTeU8WETqAHE2CgcAVd3Gkm4MD3xXYeI6B4NMItvKbcUpQ9gP+KMWnSsW+TaYJtoo+avBWLoKoK0CCSDud+7eXWQGZAXqV3YoQjQCfixJ8+fzj9ta3JHhlUeJ8wJOY2ws6eRKpPS3oqTvHAESEz9ya0naXL5WH6pt3FqSOhTHkTcKEXc6k1POh4Q9YJu/03TT4a8PoGMFI4i2EqSbOZAYaBkpCyD92RkG6KCSbjI/H0HEISBnlOZPFdcEzI2GTO4KBZICGKyAKLTEmJOB2txf5MbgohBINCl4FTqmpJMB2W+HiRn1Q2l6lXyPmiEP6VVE2TfGoaMYrHyPdtAnyI0jEOn9RLWmNEhvBBE7SjpFQZaShtLK+1S+T12lRwxUvrZlVPp8jE1PikeO7C/nyEqBDCB1t7+kUx4kKUWclea0yZC5BIGpiJSNSD9QgFR0RQKkL6KxHSWdsiARHJNYewoGrzG1/bk4dTPSunL2EyDjcbb7MQ+lQfZmkKiN7SjpFAM5CWAyGcwyY84YsZ1lUcbRNNtQMAdtQWGvQ0DyVjzYAKQfQFodeAeC1C8vzymXIZqD+ZEh/2OyLSalS/3VbnJZ+VqDXGjMrTCFuK4s66vVZUNfqaDolcbjOcb899sLpEE+I20GifywXe2QR3KElu99PzqjGufhREqB1pjCnG3IL3fY1v733r2FMsiGhutn0LAoJWWIGbPxjKwgjUbF0m52mPhigrpdXOecEq9pR6MkHbu2LOtrcZ9y3d0ODTb15y9MePz48aF79+8fvXnr9sljx2u2I7KNxDuaMPGVECoRs7mC4eT7SIruFNfNHK15MKuM2evwNq+4qjxvGnd5CHwNNynawW4cOlUZdG8b55IIJHmkItwrZHH6QxB3OSL9kTtAGpIvZiQB3Z4SKBfXQtEE9sashWAW87Bt3sYZNR6zn4uzJwWDKUKXfaKCdqUoBpLxSjYe9nqGiwWRBGipuGZ3Qm76itYLbbJI/PEhUApfw73uOIy9xfse3M9F9BuFJHcYrseSouGkHtCVtkuGTTikI8XgZzhg9SeF4VqcvSWiaSvNHQ8JwkNjIfEHemCmNLD1RaEfLs18mlgNuN6PFALHo7CyU5W2g00gFAQF4ozvibH04muwDbWraSFAyt/AAMzewgGR8uCeWn77xzBxPxgzPRCDDMZ14bQ/3jqGKGoHf2Hjgx3kw5LbaJDYWb52t9FMgw4AuWNWukNeuOYqOsmQi2jgws4PA/DD/z0B2x0/veCs4naw0cgybezid7X9jV3rX2RSs0wfLkll4pBGcgifg+NYxe1kJ2ycTaRq66uG/wBOl0vjcw70xwAAAABJRU5ErkJggg==);\n background-size: 33px auto;\n}\n\n.OT_video-disabled-warning {\n background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIAAAAoCAYAAABtla08AAAGMElEQVR4Ae2aA7D0yBaAc7oH12vbRmlLaxYWb23btm3btm2899a2bWuYtPZ01cmtU9lJrib315yqr9I3Oem/5/s7acwEnehEJzoxCcX2O+wEeIgRBDDaGjAZOgQ6ihRpLklHZDJIXK1WWymMIhGGkVBKCWMM+Iv/f/b5t7faYtM/sGgIS7j8RNLjceUVl41GvGN1BFiHy9sgtRWaYbhvuVQ6o1VOvV5/tLe3dyssKoZuh8xClkDEi2MMS6ZjR0cScxdK/+HgnJsmLccYOx0e/PUGUqfTJDEHkV5go9lcMQoj4R8RpSIRRUr4a9baTJFCCNfqESKJ7RYJibK0xoi05EhFRTxMi1Rit6xHAuLaKRLwEVi6q1x+EhlVpd3d3Wfh4VQkQhRhxthYLg7SRGqdLlIp7UVOHf+JhEhEMscUolVje3p63saeeOFoKsT7fjj++BNuw2I/0ouUENmGaQcQEilQvUU6xuWC0kqmVWCt8df6kG7WLoFA20VSCOyNh0RKPT+SyrTWtQsvuvTYCy84z3+oAdbgAiLGIvHjTz6bFuu/B3lKKfVkFKknwih6EnnipZdfXQZzepAupXSGSCfwUGZtkrx3t/0dSQGnnXbmdocdetArQoj+4VR23wMP3bj/vnv9Sv/rBmkish09ca655thHSrlWq4TFF1vkNDxsgjiUnPqZnHPABIq47jx7pPMcecShfz7x1DO7D6eit99576X1113nVd8rqLGAuDaNitJonTGIqHgQGQjDsJglMrUH5iDSEQbRa6y2yrNvv/PuWVmV/PTzLz8steTit1B9FtGJeZrJksmWdBzBMcami4xUkaY1A1Qe94WIaPGBApJhaERrLrXkElf8+NPPz6YMLs1DDjn0Wn9PnI/UiQadM4jNEkhzVsEGE8nIHESM1j5/KqRX+/IEiOQ/yifNBlEkpnb00cccesbpp13T3983H88/48xzrrvm6it/8U5JXgX5G6nSvSq1R5LATR7aYGkwMG1RSwkWABH+4jUb3vT/uJ1Z0xpjraTBRltrxUQhksIRmgTJyy69+Pv99tv3qYX6FxgU+fU33352xGEHf5wisU7nNWJpZRMkAjZ6aIN1mwV7h29Jo2wCHlveu/GV169z65E+T6koexCh6c+EEiky3lnxQKFjUeVyOeI5AOBzIiayRhJryd7YYnkIHgvB0qk9Tdql6N3XH4bRUIOIIIKJSiRb0hkSEpZKRd1CpEq8GxtIyCVmDSgFl94GacTgaJw1rUlYhYng0c4ewaUsmKRIJjpiqMSOCh9QeI+UYECmtQIsxEu6OorEcv6Rl0gu0woh8MhFkmSCTXVI4pC704WCFRJvSRNJSzrMMEZO2iKZTCHAZYnmvXCny7ed5vfZK3viHSBdIFCKEFj2+nt+73nw8m2uedcLJlktA++VNMEPaR45aYukcKnnCfY3/DFbZS8t7eHxNgsPM0N1hXhJJwwM1QbpoQFlog2R13a/zBxEYHAQEUYUM6qiVwEyBYoM6JFNF2kFLelI5KQf+fVI4dJFCguDS7oAyx2R6SFQJKRedSDj/cMg/RXQ6ZE05GSIDAaXdCi1I3L021SQWNJ1RLY5OiIdL4/yvuw8ADfWPFrSciaMyH8tEQPwf1uGG54g5+KlJGTmsrxsQdl5PKidnPFe2QS///7Hu+VS6WX/HYnf0sevGL7lXydwod2/9DykZq0s5yff0sgSWCigNOH7TPHL7ufj+/TH8P/+qYpL4HkBDiRYpEXeM8/89/9zzjn7EtY64dfd1nqccM7Bs8+9MKy8555/8TnKS+5MufH6EZVASkgPzf+mJXroet17JirU0ALST3nT0y5ONyLpeo1y64ih+vuQfsoTOeRFSJXa+SvyB90TUmdw49EjLaKpMQ0mzEeTzkWsd/oI6fzfiKM8gWg6X6OjpXstu5ZHnmIb0GFiu29MIUfUewkmVrEN3RqVQ/bY8FzNcquMBv/pCNUZ5pHHem01KdN/I/DG66/lLhKSvTO5M84kav5C5z2ZfyAivi9i9VGd45RH7UWJbjwGG/7NYsRECt7jiOToHedKAui8SW4CsxyRc54mKH/8f7ELhCCACyNcIl/wI+FaAJyc8yzRtinQPzWzuFZrFHq/AAAAAElFTkSuQmCC);\n background-size: 33px auto;\n}\n\n.OT_video-disabled-indicator.OT_active {\n display: block;\n}\n\n.OT_audio-blocked-indicator {\n opacity: 1;\n border: none;\n display: none;\n position: absolute;\n background-color: transparent;\n background-repeat: no-repeat;\n background-position: center;\n pointer-events: none;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n}\n\n.OT_audio-blocked {\n background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTUwIiBoZWlnaHQ9IjkwIj48ZGVmcz48cGF0aCBkPSJNNjcgMTJMNi40NDggNzIuNTUyIDAgMzFWMThMMjYgMGw0MSAxMnptMyA3bDYgNDctMjkgMTgtMzUuNTAyLTYuNDk4TDcwIDE5eiIgaWQ9ImEiLz48L2RlZnM+PHJlY3Qgd2lkdGg9IjE1MCIgaGVpZ2h0PSI5MCIgcng9IjM1IiByeT0iNDUiIG9wYWNpdHk9Ii41Ii8+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzNikiPjxtYXNrIGlkPSJiIiBmaWxsPSIjZmZmIj48dXNlIHhsaW5rOmhyZWY9IiNhIi8+PC9tYXNrPjxwYXRoIGQ9Ik0zOS4yNDkgNTEuMzEyYy42OTcgMTAuMzcgMi43ODUgMTcuODk3IDUuMjUxIDE3Ljg5NyAzLjAzOCAwIDUuNS0xMS40MTcgNS41LTI1LjVzLTIuNDYyLTI1LjUtNS41LTI1LjVjLTIuNTEgMC00LjYyOCA3Ljc5Ny01LjI4NyAxOC40NTNBOC45ODkgOC45ODkgMCAwIDEgNDMgNDRhOC45ODggOC45ODggMCAwIDEtMy43NTEgNy4zMTJ6TTIwLjk4NSAzMi4yMjRsMTUuNzQ2LTE2Ljg3N2E3LjM4NSA3LjM4NSAwIDAgMSAxMC4zNzQtLjQyQzUxLjcwMiAxOS4xMTQgNTQgMjkuMjA4IDU0IDQ1LjIwOGMwIDE0LjUyNy0yLjM0MyAyMy44OC03LjAzIDI4LjA1OGE3LjI4IDcuMjggMCAwIDEtMTAuMTY4LS40NjhMMjAuNDA1IDU1LjIyNEgxMmE1IDUgMCAwIDEtNS01di0xM2E1IDUgMCAwIDEgNS01aDguOTg1eiIgZmlsbD0iI0ZGRiIgbWFzaz0idXJsKCNiKSIvPjwvZz48cGF0aCBkPSJNMTA2LjUgMTMuNUw0NC45OTggNzUuMDAyIiBzdHJva2U9IiNGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9nPjwvc3ZnPg==);\n background-size: 90px auto;\n}\n\n.OT_container-audio-blocked {\n cursor: pointer;\n}\n\n.OT_container-audio-blocked.OT_mini .OT_edge-bar-item {\n display: none;\n}\n\n.OT_container-audio-blocked .OT_mute {\n display: none;\n}\n\n.OT_audio-blocked-indicator.OT_active {\n display: block;\n}\n\n.OT_video-unsupported {\n opacity: 1;\n border: none;\n display: none;\n position: absolute;\n background-color: transparent;\n background-repeat: no-repeat;\n background-position: center;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOTciIGhlaWdodD0iOTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxwYXRoIGQ9Ik03MCAxMkw5LjQ0OCA3Mi41NTIgMCA2MmwzLTQ0TDI5IDBsNDEgMTJ6bTggMmwxIDUyLTI5IDE4LTM1LjUwMi02LjQ5OEw3OCAxNHoiIGlkPSJhIi8+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCAzKSI+PG1hc2sgaWQ9ImIiIGZpbGw9IiNmZmYiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48L21hc2s+PHBhdGggZD0iTTkuMTEgMjAuOTY4SDQ4LjFhNSA1IDAgMCAxIDUgNVY1OC4xOGE1IDUgMCAwIDEtNSA1SDkuMTFhNSA1IDAgMCAxLTUtNVYyNS45N2E1IDUgMCAwIDEgNS01em00Ny4wOCAxMy4zOTRjMC0uMzQ1IDUuNDcyLTMuMTU5IDE2LjQxNS04LjQ0M2EzIDMgMCAwIDEgNC4zMDQgMi43MDJ2MjYuODM1YTMgMyAwIDAgMS00LjMwNSAyLjcwMWMtMTAuOTQyLTUuMjg2LTE2LjQxMy04LjEtMTYuNDEzLTguNDQ2VjM0LjM2MnoiIGZpbGw9IiNGRkYiIG1hc2s9InVybCgjYikiLz48L2c+PHBhdGggZD0iTTgxLjUgMTYuNUwxOS45OTggNzguMDAyIiBzdHJva2U9IiNGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9nPjwvc3ZnPg==);\n background-size: 58px auto;\n pointer-events: none;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n margin-top: -30px;\n}\n\n.OT_video-unsupported-bar {\n display: none;\n position: absolute;\n width: 192%; /* copy the size of the audio meter bar for symmetry */\n height: 192%;\n top: -96% /* half of the size */;\n left: -96%;\n border-radius: 50%;\n\n background-color: rgba(0, 0, 0, .8);\n}\n\n.OT_video-unsupported-img {\n display: none;\n position: absolute;\n top: 11%;\n left: 15%;\n width: 70%;\n opacity: .7;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOTciIGhlaWdodD0iOTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPjxkZWZzPjxwYXRoIGQ9Ik03MCAxMkw5LjQ0OCA3Mi41NTIgMCA2MmwzLTQ0TDI5IDBsNDEgMTJ6bTggMmwxIDUyLTI5IDE4LTM1LjUwMi02LjQ5OEw3OCAxNHoiIGlkPSJhIi8+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCAzKSI+PG1hc2sgaWQ9ImIiIGZpbGw9IiNmZmYiPjx1c2UgeGxpbms6aHJlZj0iI2EiLz48L21hc2s+PHBhdGggZD0iTTkuMTEgMjAuOTY4SDQ4LjFhNSA1IDAgMCAxIDUgNVY1OC4xOGE1IDUgMCAwIDEtNSA1SDkuMTFhNSA1IDAgMCAxLTUtNVYyNS45N2E1IDUgMCAwIDEgNS01em00Ny4wOCAxMy4zOTRjMC0uMzQ1IDUuNDcyLTMuMTU5IDE2LjQxNS04LjQ0M2EzIDMgMCAwIDEgNC4zMDQgMi43MDJ2MjYuODM1YTMgMyAwIDAgMS00LjMwNSAyLjcwMWMtMTAuOTQyLTUuMjg2LTE2LjQxMy04LjEtMTYuNDEzLTguNDQ2VjM0LjM2MnoiIGZpbGw9IiNGRkYiIG1hc2s9InVybCgjYikiLz48L2c+PHBhdGggZD0iTTgxLjUgMTYuNUwxOS45OTggNzguMDAyIiBzdHJva2U9IiNGRkYiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+PC9nPjwvc3ZnPg==);\n background-repeat: no-repeat;\n background-position: center;\n background-size: 100% auto;\n}\n\n.OT_video-unsupported-img:before {\n /* makes the height of the container 93% of its width (90/97 px) */\n content: '';\n display: block;\n padding-top: 93%;\n}\n\n.OT_video-unsupported-text {\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-pack: center;\n -ms-flex-pack: center;\n justify-content: center;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n text-align: center;\n height: 100%;\n margin-top: 40px;\n}\n" /***/ }), /***/ "./src/app/components/layouts/layout-best-fit/layout-best-fit.component.html": /***/ (function(module, exports) { module.exports = "
\n
\n
\n \n
\n
\n
\n" /***/ }), /***/ "./src/app/components/layouts/layout-best-fit/layout-best-fit.component.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return LayoutBestFitComponent; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_router__ = __webpack_require__("./node_modules/@angular/router/esm5/router.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_openvidu_browser__ = __webpack_require__("../../../../../openvidu-browser2/lib/index.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_openvidu_browser___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_openvidu_browser__); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__openvidu_layout__ = __webpack_require__("./src/app/components/layouts/openvidu-layout.ts"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var LayoutBestFitComponent = (function () { function LayoutBestFitComponent(route, appRef) { var _this = this; this.route = route; this.appRef = appRef; this.streams = []; this.route.params.subscribe(function (params) { _this.sessionId = params.sessionId; _this.secret = params.secret; }); } LayoutBestFitComponent.prototype.beforeunloadHandler = function () { this.leaveSession(); }; LayoutBestFitComponent.prototype.sizeChange = function (event) { var _this = this; clearTimeout(this.resizeTimeout); this.resizeTimeout = setTimeout(function () { _this.openviduLayout.updateLayout(); }, 20); }; LayoutBestFitComponent.prototype.ngOnDestroy = function () { this.leaveSession(); }; LayoutBestFitComponent.prototype.ngOnInit = function () { var _this = this; var OV = new __WEBPACK_IMPORTED_MODULE_2_openvidu_browser__["OpenVidu"](); var fullSessionId = 'wss://' + location.hostname + ':8443/' + this.sessionId + '?secret=' + this.secret + '&recorder=true'; this.session = OV.initSession(fullSessionId); this.session.on('streamCreated', function (event) { var subscriber = _this.session.subscribe(event.stream, ''); _this.addRemoteStream(event.stream); }); this.session.on('streamDestroyed', function (event) { event.preventDefault(); _this.deleteRemoteStream(event.stream); _this.openviduLayout.updateLayout(); }); this.session.connect(null, function (error) { if (error) { console.error(error); } }); this.openviduLayout = new __WEBPACK_IMPORTED_MODULE_3__openvidu_layout__["a" /* OpenViduLayout */](); this.openviduLayout.initLayoutContainer(document.getElementById('layout'), { maxRatio: 3 / 2, minRatio: 9 / 16, fixedRatio: false, bigClass: 'OV_big', bigPercentage: 0.8, bigFixedRatio: false, bigMaxRatio: 3 / 2, bigMinRatio: 9 / 16, bigFirst: true, animate: true // Whether you want to animate the transitions }); }; LayoutBestFitComponent.prototype.addRemoteStream = function (stream) { this.streams.push(stream); this.appRef.tick(); }; LayoutBestFitComponent.prototype.deleteRemoteStream = function (stream) { var index = -1; for (var i = 0; i < this.streams.length; i++) { if (this.streams[i].streamId === stream.streamId) { index = i; break; } } if (index > -1) { this.streams.splice(index, 1); } this.appRef.tick(); }; LayoutBestFitComponent.prototype.leaveSession = function () { if (this.session) { this.session.disconnect(); } ; this.streams = []; this.session = null; }; LayoutBestFitComponent.prototype.onVideoPlaying = function (event) { var video = event.target; video.parentElement.parentElement.classList.remove('custom-class'); this.openviduLayout.updateLayout(); }; __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["A" /* HostListener */])('window:beforeunload'), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], LayoutBestFitComponent.prototype, "beforeunloadHandler", null); __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["A" /* HostListener */])('window:resize', ['$event']), __metadata("design:type", Function), __metadata("design:paramtypes", [Object]), __metadata("design:returntype", void 0) ], LayoutBestFitComponent.prototype, "sizeChange", null); LayoutBestFitComponent = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ selector: 'app-layout-best-fit', template: __webpack_require__("./src/app/components/layouts/layout-best-fit/layout-best-fit.component.html"), styles: [__webpack_require__("./src/app/components/layouts/layout-best-fit/layout-best-fit.component.css")], encapsulation: __WEBPACK_IMPORTED_MODULE_0__angular_core__["_15" /* ViewEncapsulation */].None }), __metadata("design:paramtypes", [__WEBPACK_IMPORTED_MODULE_1__angular_router__["a" /* ActivatedRoute */], __WEBPACK_IMPORTED_MODULE_0__angular_core__["g" /* ApplicationRef */]]) ], LayoutBestFitComponent); return LayoutBestFitComponent; }()); /***/ }), /***/ "./src/app/components/layouts/openvidu-layout.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return OpenViduLayout; }); var OpenViduLayout = (function () { function OpenViduLayout() { } OpenViduLayout.prototype.fixAspectRatio = function (elem, width) { var sub = elem.querySelector('.OT_root'); if (sub) { // If this is the parent of a subscriber or publisher then we need // to force the mutation observer on the publisher or subscriber to // trigger to get it to fix it's layout var oldWidth = sub.style.width; sub.style.width = width + 'px'; // sub.style.height = height + 'px'; sub.style.width = oldWidth || ''; } }; OpenViduLayout.prototype.positionElement = function (elem, x, y, width, height, animate) { var _this = this; var targetPosition = { left: x + 'px', top: y + 'px', width: width + 'px', height: height + 'px' }; this.fixAspectRatio(elem, width); if (animate && $) { $(elem).stop(); $(elem).animate(targetPosition, animate.duration || 200, animate.easing || 'swing', function () { _this.fixAspectRatio(elem, width); if (animate.complete) { animate.complete.call(_this); } }); } else { $(elem).css(targetPosition); } this.fixAspectRatio(elem, width); }; OpenViduLayout.prototype.getVideoRatio = function (elem) { if (!elem) { return 3 / 4; } var video = elem.querySelector('video'); if (video && video.videoHeight && video.videoWidth) { return video.videoHeight / video.videoWidth; } else if (elem.videoHeight && elem.videoWidth) { return elem.videoHeight / elem.videoWidth; } return 3 / 4; }; OpenViduLayout.prototype.getCSSNumber = function (elem, prop) { var cssStr = $(elem).css(prop); return cssStr ? parseInt(cssStr, 10) : 0; }; // Really cheap UUID function OpenViduLayout.prototype.cheapUUID = function () { return (Math.random() * 100000000).toFixed(0); }; OpenViduLayout.prototype.getHeight = function (elem) { var heightStr = $(elem).css('height'); return heightStr ? parseInt(heightStr, 10) : 0; }; OpenViduLayout.prototype.getWidth = function (elem) { var widthStr = $(elem).css('width'); return widthStr ? parseInt(widthStr, 10) : 0; }; OpenViduLayout.prototype.getBestDimensions = function (minR, maxR, count, WIDTH, HEIGHT, targetHeight) { var maxArea, targetCols, targetRows, targetWidth, tWidth, tHeight, tRatio; // Iterate through every possible combination of rows and columns // and see which one has the least amount of whitespace for (var i = 1; i <= count; i++) { var colsAux = i; var rowsAux = Math.ceil(count / colsAux); // Try taking up the whole height and width tHeight = Math.floor(HEIGHT / rowsAux); tWidth = Math.floor(WIDTH / colsAux); tRatio = tHeight / tWidth; if (tRatio > maxR) { // We went over decrease the height tRatio = maxR; tHeight = tWidth * tRatio; } else if (tRatio < minR) { // We went under decrease the width tRatio = minR; tWidth = tHeight / tRatio; } var area = (tWidth * tHeight) * count; // If this width and height takes up the most space then we're going with that if (maxArea === undefined || (area > maxArea)) { maxArea = area; targetHeight = tHeight; targetWidth = tWidth; targetCols = colsAux; targetRows = rowsAux; } } return { maxArea: maxArea, targetCols: targetCols, targetRows: targetRows, targetHeight: targetHeight, targetWidth: targetWidth, ratio: targetHeight / targetWidth }; }; ; OpenViduLayout.prototype.arrange = function (children, WIDTH, HEIGHT, offsetLeft, offsetTop, fixedRatio, minRatio, maxRatio, animate) { var targetHeight; var count = children.length; var dimensions; if (!fixedRatio) { dimensions = this.getBestDimensions(minRatio, maxRatio, count, WIDTH, HEIGHT, targetHeight); } else { // Use the ratio of the first video element we find to approximate var ratio = this.getVideoRatio(children.length > 0 ? children[0] : null); dimensions = this.getBestDimensions(ratio, ratio, count, WIDTH, HEIGHT, targetHeight); } // Loop through each stream in the container and place it inside var x = 0, y = 0; var rows = []; var row; // Iterate through the children and create an array with a new item for each row // and calculate the width of each row so that we know if we go over the size and need // to adjust for (var i = 0; i < children.length; i++) { if (i % dimensions.targetCols === 0) { // This is a new row row = { children: [], width: 0, height: 0 }; rows.push(row); } var elem = children[i]; row.children.push(elem); var targetWidth = dimensions.targetWidth; targetHeight = dimensions.targetHeight; // If we're using a fixedRatio then we need to set the correct ratio for this element if (fixedRatio) { targetWidth = targetHeight / this.getVideoRatio(elem); } row.width += targetWidth; row.height = targetHeight; } // Calculate total row height adjusting if we go too wide var totalRowHeight = 0; var remainingShortRows = 0; for (var i = 0; i < rows.length; i++) { row = rows[i]; if (row.width > WIDTH) { // Went over on the width, need to adjust the height proportionally row.height = Math.floor(row.height * (WIDTH / row.width)); row.width = WIDTH; } else if (row.width < WIDTH) { remainingShortRows += 1; } totalRowHeight += row.height; } if (totalRowHeight < HEIGHT && remainingShortRows > 0) { // We can grow some of the rows, we're not taking up the whole height var remainingHeightDiff = HEIGHT - totalRowHeight; totalRowHeight = 0; for (var i = 0; i < rows.length; i++) { row = rows[i]; if (row.width < WIDTH) { // Evenly distribute the extra height between the short rows var extraHeight = remainingHeightDiff / remainingShortRows; if ((extraHeight / row.height) > ((WIDTH - row.width) / row.width)) { // We can't go that big or we'll go too wide extraHeight = Math.floor(((WIDTH - row.width) / row.width) * row.height); } row.width += Math.floor((extraHeight / row.height) * row.width); row.height += extraHeight; remainingHeightDiff -= extraHeight; remainingShortRows -= 1; } totalRowHeight += row.height; } } // vertical centering y = ((HEIGHT - (totalRowHeight)) / 2); // Iterate through each row and place each child for (var i = 0; i < rows.length; i++) { row = rows[i]; // center the row var rowMarginLeft = ((WIDTH - row.width) / 2); x = rowMarginLeft; for (var j = 0; j < row.children.length; j++) { var elem = row.children[j]; var targetWidth = dimensions.targetWidth; targetHeight = row.height; // If we're using a fixedRatio then we need to set the correct ratio for this element if (fixedRatio) { targetWidth = Math.floor(targetHeight / this.getVideoRatio(elem)); } elem.style.position = 'absolute'; // $(elem).css('position', 'absolute'); var actualWidth = targetWidth - this.getCSSNumber(elem, 'paddingLeft') - this.getCSSNumber(elem, 'paddingRight') - this.getCSSNumber(elem, 'marginLeft') - this.getCSSNumber(elem, 'marginRight') - this.getCSSNumber(elem, 'borderLeft') - this.getCSSNumber(elem, 'borderRight'); var actualHeight = targetHeight - this.getCSSNumber(elem, 'paddingTop') - this.getCSSNumber(elem, 'paddingBottom') - this.getCSSNumber(elem, 'marginTop') - this.getCSSNumber(elem, 'marginBottom') - this.getCSSNumber(elem, 'borderTop') - this.getCSSNumber(elem, 'borderBottom'); this.positionElement(elem, x + offsetLeft, y + offsetTop, actualWidth, actualHeight, animate); x += targetWidth; } y += targetHeight; } }; OpenViduLayout.prototype.filterDisplayNone = function (element) { return element.style.display !== 'none'; }; OpenViduLayout.prototype.updateLayout = function () { if (this.layoutContainer.style.display === 'none') { return; } var id = this.layoutContainer.id; if (!id) { id = 'OT_' + this.cheapUUID(); this.layoutContainer.id = id; } var HEIGHT = this.getHeight(this.layoutContainer) - this.getCSSNumber(this.layoutContainer, 'borderTop') - this.getCSSNumber(this.layoutContainer, 'borderBottom'); var WIDTH = this.getWidth(this.layoutContainer) - this.getCSSNumber(this.layoutContainer, 'borderLeft') - this.getCSSNumber(this.layoutContainer, 'borderRight'); var availableRatio = HEIGHT / WIDTH; var offsetLeft = 0; var offsetTop = 0; var bigOffsetTop = 0; var bigOffsetLeft = 0; var bigOnes = Array.prototype.filter.call(this.layoutContainer.querySelectorAll('#' + id + '>.' + this.opts.bigClass), this.filterDisplayNone); var smallOnes = Array.prototype.filter.call(this.layoutContainer.querySelectorAll('#' + id + '>*:not(.' + this.opts.bigClass + ')'), this.filterDisplayNone); if (bigOnes.length > 0 && smallOnes.length > 0) { var bigWidth = void 0, bigHeight = void 0; if (availableRatio > this.getVideoRatio(bigOnes[0])) { // We are tall, going to take up the whole width and arrange small // guys at the bottom bigWidth = WIDTH; bigHeight = Math.floor(HEIGHT * this.opts.bigPercentage); offsetTop = bigHeight; bigOffsetTop = HEIGHT - offsetTop; } else { // We are wide, going to take up the whole height and arrange the small // guys on the right bigHeight = HEIGHT; bigWidth = Math.floor(WIDTH * this.opts.bigPercentage); offsetLeft = bigWidth; bigOffsetLeft = WIDTH - offsetLeft; } if (this.opts.bigFirst) { this.arrange(bigOnes, bigWidth, bigHeight, 0, 0, this.opts.bigFixedRatio, this.opts.bigMinRatio, this.opts.bigMaxRatio, this.opts.animate); this.arrange(smallOnes, WIDTH - offsetLeft, HEIGHT - offsetTop, offsetLeft, offsetTop, this.opts.fixedRatio, this.opts.minRatio, this.opts.maxRatio, this.opts.animate); } else { this.arrange(smallOnes, WIDTH - offsetLeft, HEIGHT - offsetTop, 0, 0, this.opts.fixedRatio, this.opts.minRatio, this.opts.maxRatio, this.opts.animate); this.arrange(bigOnes, bigWidth, bigHeight, bigOffsetLeft, bigOffsetTop, this.opts.bigFixedRatio, this.opts.bigMinRatio, this.opts.bigMaxRatio, this.opts.animate); } } else if (bigOnes.length > 0 && smallOnes.length === 0) { this. // We only have one bigOne just center it arrange(bigOnes, WIDTH, HEIGHT, 0, 0, this.opts.bigFixedRatio, this.opts.bigMinRatio, this.opts.bigMaxRatio, this.opts.animate); } else { this.arrange(smallOnes, WIDTH - offsetLeft, HEIGHT - offsetTop, offsetLeft, offsetTop, this.opts.fixedRatio, this.opts.minRatio, this.opts.maxRatio, this.opts.animate); } }; OpenViduLayout.prototype.initLayoutContainer = function (container, opts) { this.opts = { maxRatio: (opts.maxRatio != null) ? opts.maxRatio : 3 / 2, minRatio: (opts.minRatio != null) ? opts.minRatio : 9 / 16, fixedRatio: (opts.fixedRatio != null) ? opts.fixedRatio : false, animate: (opts.animate != null) ? opts.animate : false, bigClass: (opts.bigClass != null) ? opts.bigClass : 'OT_big', bigPercentage: (opts.bigPercentage != null) ? opts.bigPercentage : 0.8, bigFixedRatio: (opts.bigFixedRatio != null) ? opts.bigFixedRatio : false, bigMaxRatio: (opts.bigMaxRatio != null) ? opts.bigMaxRatio : 3 / 2, bigMinRatio: (opts.bigMinRatio != null) ? opts.bigMinRatio : 9 / 16, bigFirst: (opts.bigFirst != null) ? opts.bigFirst : true }; this.layoutContainer = typeof (container) === 'string' ? $(container) : container; }; OpenViduLayout.prototype.setLayoutOptions = function (options) { this.opts = options; }; return OpenViduLayout; }()); /***/ }), /***/ "./src/app/components/session-details/session-details.component.css": /***/ (function(module, exports) { module.exports = "" /***/ }), /***/ "./src/app/components/session-details/session-details.component.html": /***/ (function(module, exports) { module.exports = "

\n session-details works!\n

\n" /***/ }), /***/ "./src/app/components/session-details/session-details.component.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return SessionDetailsComponent; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var SessionDetailsComponent = (function () { function SessionDetailsComponent() { } SessionDetailsComponent.prototype.ngOnInit = function () { }; SessionDetailsComponent = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["n" /* Component */])({ selector: 'app-session-details', template: __webpack_require__("./src/app/components/session-details/session-details.component.html"), styles: [__webpack_require__("./src/app/components/session-details/session-details.component.css")] }), __metadata("design:paramtypes", []) ], SessionDetailsComponent); return SessionDetailsComponent; }()); /***/ }), /***/ "./src/app/services/info.service.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return InfoService; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_rxjs_Subject__ = __webpack_require__("./node_modules/rxjs/_esm5/Subject.js"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var InfoService = (function () { function InfoService() { this.newInfo$ = new __WEBPACK_IMPORTED_MODULE_1_rxjs_Subject__["a" /* Subject */](); } InfoService.prototype.getInfo = function () { return this.info; }; InfoService.prototype.updateInfo = function (info) { this.info = info; this.newInfo$.next(info); }; InfoService = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["C" /* Injectable */])(), __metadata("design:paramtypes", []) ], InfoService); return InfoService; }()); /***/ }), /***/ "./src/app/services/rest.service.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return RestService; }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var RestService = (function () { function RestService() { } RestService.prototype.getOpenViduPublicUrl = function () { var _this = this; return new Promise(function (resolve, reject) { if (!!_this.openviduPublicUrl) { resolve(_this.openviduPublicUrl); } else { var url = location.protocol + '//' + location.hostname + ((!!location.port) ? (':' + location.port) : '') + '/config/openvidu-publicurl'; var http_1 = new XMLHttpRequest(); http_1.onreadystatechange = function () { if (http_1.readyState === 4) { if (http_1.status === 200) { _this.openviduPublicUrl = http_1.responseText; resolve(http_1.responseText); } else { reject('Error getting OpenVidu publicurl'); } } ; }; http_1.open('GET', url, true); http_1.send(); } }); }; RestService = __decorate([ Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["C" /* Injectable */])() ], RestService); return RestService; }()); /***/ }), /***/ "./src/environments/environment.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return environment; }); // The file contents for the current environment will overwrite these during build. // The build system defaults to the dev environment which uses `environment.ts`, but if you do // `ng build --env=prod` then `environment.prod.ts` will be used instead. // The list of which env maps to which file can be found in `.angular-cli.json`. var environment = { production: false }; /***/ }), /***/ "./src/main.ts": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__angular_core__ = __webpack_require__("./node_modules/@angular/core/esm5/core.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__ = __webpack_require__("./node_modules/@angular/platform-browser-dynamic/esm5/platform-browser-dynamic.js"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__app_app_module__ = __webpack_require__("./src/app/app.module.ts"); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__environments_environment__ = __webpack_require__("./src/environments/environment.ts"); if (__WEBPACK_IMPORTED_MODULE_3__environments_environment__["a" /* environment */].production) { Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["_18" /* enableProdMode */])(); } Object(__WEBPACK_IMPORTED_MODULE_1__angular_platform_browser_dynamic__["a" /* platformBrowserDynamic */])().bootstrapModule(__WEBPACK_IMPORTED_MODULE_2__app_app_module__["a" /* AppModule */]); /***/ }), /***/ 0: /***/ (function(module, exports, __webpack_require__) { module.exports = __webpack_require__("./src/main.ts"); /***/ }) },[0]); //# sourceMappingURL=main.bundle.js.map