"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 = require(".."); var OpenViduError_1 = require("../OpenViduInternal/Enums/OpenViduError"); var VideoInsertMode_1 = require("../OpenViduInternal/Enums/VideoInsertMode"); var VersionAdapter_1 = require("../OpenViduInternal/VersionAdapter"); var RpcBuilder = require("../OpenViduInternal/KurentoUtils/kurento-jsonrpc"); var screenSharingAuto = require("../OpenViduInternal/ScreenSharing/Screen-Capturing-Auto"); var screenSharing = require("../OpenViduInternal/ScreenSharing/Screen-Capturing"); var platform = require("platform"); /** * @hidden */ var SECRET_PARAM = '?secret='; /** * @hidden */ 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.secret = ''; this.recorder = false; /** * @hidden */ this.advancedConfiguration = {}; console.info("'OpenVidu' initialized"); } /** * Returns a session with id `sessionId` * @param sessionId Session unique ID generated in openvidu-server */ OpenVidu.prototype.initSession = function (sessionId) { this.session = new __1.Session(sessionId, this); return this.session; }; /** * Returns a new publisher * * #### Events dispatched * * The [[Publisher]] object will dispatch an `accessDialogOpened` event, only if the pop-up shown by the browser to request permissions for the camera is opened. You can use this event to alert the user about granting permissions * for your website. An `accessDialogClosed` event will also be dispatched after user clicks on "Allow" or "Block" in the pop-up. * * The [[Publisher]] object will dispatch an `accessAllowed` or `accessDenied` event once it has been granted access to the requested input devices or not. * * The [[Publisher]] object will dispatch a `videoElementCreated` event once the HTML video element has been added to DOM (if _targetElement_ not null or undefined) * * The [[Publisher]] object will dispatch a `videoPlaying` event once the local video starts playing (only if `videoElementCreated` event has been previously dispatched) * * @param targetElement HTML DOM element (or its `id` attribute) in which the video element of the Publisher will be inserted (see [[PublisherProperties.insertMode]]). If null or undefined no default video will be created for this Publisher * (you can always access the native MediaStream object by calling _Publisher.stream.getMediaStream()_ and use it as _srcObject_ of any HTML video element) * @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, param2, param3) { var properties; if (!!param2 && (typeof param2 !== 'function')) { // Matches 'initPublisher(targetElement, properties)' or 'initPublisher(targetElement, properties, completionHandler)' properties = param2; // DEPRECATED WARNING properties = VersionAdapter_1.adaptPublisherProperties(properties); properties = { audioSource: (typeof properties.audioSource !== 'undefined') ? properties.audioSource : undefined, frameRate: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.frameRate !== 'undefined') ? properties.frameRate : undefined), insertMode: (typeof properties.insertMode !== 'undefined') ? ((typeof properties.insertMode === 'string') ? VideoInsertMode_1.VideoInsertMode[properties.insertMode] : 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: this.isMediaStreamTrack(properties.videoSource) ? undefined : ((typeof properties.resolution !== 'undefined') ? properties.resolution : '640x480'), videoSource: (typeof properties.videoSource !== 'undefined') ? properties.videoSource : undefined }; } else { // Matches 'initPublisher(targetElement)' or 'initPublisher(targetElement, completionHandler)' properties = { insertMode: VideoInsertMode_1.VideoInsertMode.APPEND, mirror: true, publishAudio: true, publishVideo: true, resolution: '640x480' }; } var publisher = new __1.Publisher(targetElement, properties, this); var completionHandler; if (!!param2 && (typeof param2 === 'function')) { completionHandler = param2; } else if (!!param3) { completionHandler = param3; } publisher.initialize() .then(function () { if (completionHandler !== undefined) { completionHandler(undefined); } publisher.emitEvent('accessAllowed', []); })["catch"](function (error) { if (!!completionHandler !== undefined) { completionHandler(error); } publisher.emitEvent('accessDenied', []); }); return publisher; }; OpenVidu.prototype.initPublisherAsync = function (targetElement, properties) { var _this = this; return new Promise(function (resolve, reject) { var publisher; var callback = function (error) { if (!!error) { reject(error); } else { resolve(publisher); } }; if (!!properties) { publisher = _this.initPublisher(targetElement, properties, callback); } else { publisher = _this.initPublisher(targetElement, callback); } }); }; /** * Returns a new local recorder for recording streams straight away from the browser * @param stream Stream to record */ OpenVidu.prototype.initLocalRecorder = function (stream) { return new __1.LocalRecorder(stream); }; /** * Checks if the browser supports OpenVidu * @returns 1 if the browser supports OpenVidu, 0 otherwise */ OpenVidu.prototype.checkSystemRequirements = function () { var browser = platform.name; var version = platform.version; if ((browser !== 'Chrome') && (browser !== 'Chrome Mobile') && (browser !== 'Firefox') && (browser !== 'Firefox Mobile') && (browser !== 'Firefox for iOS') && (browser !== 'Opera') && (browser !== 'Opera Mobile') && (browser !== 'Safari')) { return 0; } else { return 1; } }; /** * 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_ property of the _MediaStream_ value resolved by the Promise as `audioSource` or `videoSource` properties in [[initPublisher]]) * * Parameter `options` is the same as in [[initPublisher]] second parameter (of type [[PublisherProperties]]), but only the following properties will be applied: `audioSource`, `videoSource`, `frameRate`, `resolution` * * To customize the Publisher's video, the API for HTMLCanvasElement is very useful. For example, to get a black-and-white video at 10 fps and HD resolution with no sound: * ``` * var OV = new OpenVidu(); * var FRAME_RATE = 10; * * OV.getUserMedia({ * audioSource: false; * videoSource: undefined, * resolution: '1280x720', * frameRate: FRAME_RATE * }) * .then(mediaStream => { * * var videoTrack = mediaStream.getVideoTracks()[0]; * var video = document.createElement('video'); * video.srcObject = new MediaStream([videoTrack]); * * var canvas = document.createElement('canvas'); * var ctx = canvas.getContext('2d'); * ctx.filter = 'grayscale(100%)'; * * video.addEventListener('play', () => { * var loop = () => { * if (!video.paused && !video.ended) { * ctx.drawImage(video, 0, 0, 300, 170); * setTimeout(loop, 1000/ FRAME_RATE); // Drawing at 10 fps * } * }; * loop(); * }); * video.play(); * * var grayVideoTrack = canvas.captureStream(FRAME_RATE).getVideoTracks()[0]; * var publisher = this.OV.initPublisher( * myHtmlTarget, * { * audioSource: false, * videoSource: grayVideoTrack * }); * }); * ``` */ 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 */ /** * Set OpenVidu advanced configuration options. Currently `configuration` is an object with the following optional properties (see [[OpenViduAdvancedConfiguration]] for more details): * - `iceServers`: set custom STUN/TURN servers to be used by OpenVidu Browser * - `screenShareChromeExtension`: url to a custom screen share extension for Chrome to be used instead of the default one, based on ours [https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension](https://github.com/OpenVidu/openvidu-screen-sharing-chrome-extension) * - `publisherSpeakingEventsOptions`: custom configuration for the [[PublisherSpeakingEvent]] feature */ OpenVidu.prototype.setAdvancedConfiguration = function (configuration) { this.advancedConfiguration = configuration; }; /* 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) { var _this = this; 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') { if (platform.name !== 'Chrome' && platform.name !== 'Firefox') { var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_SHARING_NOT_SUPPORTED, 'You can only screen share in desktop Chrome and Firefox. Detected browser: ' + platform.name); console.error(error); reject(error); } else { if (!!_this.advancedConfiguration.screenShareChromeExtension) { // Custom screen sharing extension for Chrome var extensionId = _this.advancedConfiguration.screenShareChromeExtension.split('/').pop().trim(); screenSharing.getChromeExtensionStatus(extensionId, function (status) { if (status === 'installed-enabled') { screenSharing.getScreenConstraints(function (error, screenConstraints) { if (!!error && error === 'permission-denied') { var error_1 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); console.error(error_1); reject(error_1); } else { mediaConstraints.video = screenConstraints; resolve(mediaConstraints); } }); } if (status === 'installed-disabled') { var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); console.error(error); reject(error); } if (status === 'not-installed') { var error = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, _this.advancedConfiguration.screenShareChromeExtension); console.error(error); reject(error); } }); } else { // Default screen sharing extension for Chrome screenSharingAuto.getScreenId(function (error, sourceId, screenConstraints) { if (!!error) { if (error === 'not-installed') { var error_2 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_NOT_INSTALLED, 'https://chrome.google.com/webstore/detail/screen-capturing/ajhifddimkapgcifgcodmmfdlknahffk'); console.error(error_2); reject(error_2); } else if (error === 'installed-disabled') { var error_3 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_EXTENSION_DISABLED, 'You must enable the screen extension'); console.error(error_3); reject(error_3); } else if (error === 'permission-denied') { var error_4 = new OpenViduError_1.OpenViduError(OpenViduError_1.OpenViduErrorName.SCREEN_CAPTURE_DENIED, 'You must allow access to one window of your desktop'); console.error(error_4); reject(error_4); } } else { mediaConstraints.video = screenConstraints.video; resolve(mediaConstraints); } }); } publisherProperties.videoSource = 'screen'; } } 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: 5000, 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), recordingStarted: this.session.onRecordingStarted.bind(this.session), recordingStopped: this.session.onRecordingStopped.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.closeWs = function () { this.jsonRpcClient.close(); }; /** * @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.isMediaStreamTrack = function (mediaSource) { var is = (!!mediaSource && mediaSource.enabled !== undefined && typeof mediaSource.enabled === 'boolean' && mediaSource.id !== undefined && typeof mediaSource.id === 'string' && mediaSource.kind !== undefined && typeof mediaSource.kind === 'string' && mediaSource.label !== undefined && typeof mediaSource.label === 'string' && mediaSource.muted !== undefined && typeof mediaSource.muted === 'boolean' && mediaSource.readyState !== undefined && typeof mediaSource.readyState === 'string'); return is; }; /** * @hidden */ OpenVidu.prototype.getWsUri = function () { return this.wsUri; }; /** * @hidden */ OpenVidu.prototype.getSecret = function () { return this.secret; }; /** * @hidden */ OpenVidu.prototype.getRecorder = function () { return this.recorder; }; /* 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; }; return OpenVidu; }()); exports.OpenVidu = OpenVidu; //# sourceMappingURL=OpenVidu.js.map