@reactoo/watchtogether-sdk-js 2.5.85 → 2.5.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* @reactoo/watchtogether-sdk-js
|
|
3
|
-
* @version 2.5.
|
|
3
|
+
* @version 2.5.87
|
|
4
4
|
*/
|
|
5
5
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
6
6
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
@@ -9495,7 +9495,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var aws_
|
|
|
9495
9495
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
|
9496
9496
|
|
|
9497
9497
|
"use strict";
|
|
9498
|
-
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! webrtc-adapter */ \"./node_modules/webrtc-adapter/src/js/adapter_core.js\");\n/* harmony import */ var _wt_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./wt-emitter */ \"./src/modules/wt-emitter.js\");\n/* harmony import */ var _wt_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./wt-utils */ \"./src/modules/wt-utils.js\");\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n// Watch together janus webrtc library\n\n\n\n\nclass Room {\n constructor(debug) {\n this.debug = debug;\n this.sessions = [];\n this.safariVp8 = false;\n this.browser = webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser;\n this.browserDetails = webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails;\n this.webrtcSupported = Room.isWebrtcSupported();\n this.safariVp8TestPromise = Room.testSafariVp8();\n this.safariVp8 = null;\n this.safariVp8TestPromise.then(safariVp8 => {\n this.safariVp8 = safariVp8;\n });\n\n // Let's get it started\n this.whenInitialized = this.initialize();\n }\n initialize() {\n return this.safariVp8TestPromise.then(() => this);\n }\n createSession() {\n let constructId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'reactooroom';\n let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return new RoomSession(constructId, type, {\n debug: this.debug,\n ...options\n });\n }\n static testSafariVp8() {\n return new Promise(resolve => {\n if (webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser === 'safari' && webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.version >= 605) {\n if (RTCRtpSender && RTCRtpSender.getCapabilities && RTCRtpSender.getCapabilities(\"video\") && RTCRtpSender.getCapabilities(\"video\").codecs && RTCRtpSender.getCapabilities(\"video\").codecs.length) {\n var isVp8 = false;\n for (var i in RTCRtpSender.getCapabilities(\"video\").codecs) {\n var codec = RTCRtpSender.getCapabilities(\"video\").codecs[i];\n if (codec && codec.mimeType && codec.mimeType.toLowerCase() === \"video/vp8\") {\n isVp8 = true;\n break;\n }\n }\n resolve(isVp8);\n } else {\n // We do it in a very ugly way, as there's no alternative...\n // We create a PeerConnection to see if VP8 is in an offer\n var testpc = new RTCPeerConnection({}, {});\n testpc.createOffer({\n offerToReceiveVideo: true\n }).then(function (offer) {\n let result = offer.sdp.indexOf(\"VP8\") !== -1;\n testpc.close();\n testpc = null;\n resolve(result);\n });\n }\n } else resolve(false);\n });\n }\n static isWebrtcSupported() {\n return window.RTCPeerConnection !== undefined && window.RTCPeerConnection !== null && navigator.mediaDevices !== undefined && navigator.mediaDevices !== null && navigator.mediaDevices.getUserMedia !== undefined && navigator.mediaDevices.getUserMedia !== null;\n }\n}\nclass RoomSession {\n static noop() {}\n static randomString(len) {\n var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n var randomString = '';\n for (var i = 0; i < len; i++) {\n var randomPoz = Math.floor(Math.random() * charSet.length);\n randomString += charSet.substring(randomPoz, randomPoz + 1);\n }\n return randomString;\n }\n\n //TODO: solve\n // #eventList = ['error', 'kicked', 'addLocalParticipant', ,'addRemoteInstructor','addRemoteParticipant','addRemoteTalkback', 'addRemoteObserver', 'removeRemoteInstructor', 'removeLocalParticipant', 'removeRemoteParticipant', 'removeRemoteTalkback', 'removeRemoteObserver', 'localMuted', 'localHasVideo', 'localHasAudio', 'data', 'iceState', 'connectionState', 'joined', 'joining', 'dataChannel', 'disconnect', 'observerIds', 'talkbackIds', 'instructorId', 'published', 'publishing', 'remoteTrackMuted', 'streamingStatus', 'streaming', 'streamStarting'];\n //\n\n constructor() {\n let constructId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'reactooroom';\n let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n Object.assign(this, Object(_wt_emitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"])());\n this.options = {\n ...options\n };\n this.defaultDataChannelLabel = 'JanusDataChannel';\n this.server = null;\n this.iceServers = null;\n this.token = null;\n this.roomId = null;\n this.streamId = null;\n this.pin = null;\n this.userId = null;\n this.sessiontype = type;\n this.initialBitrate = 0;\n this.simulcast = false;\n this.simulcastBitrates = {\n high: 900000,\n medium: 300000,\n low: 100000\n };\n this.recordingFilename = null;\n this.pluginName = RoomSession.sessionTypes[type];\n this.id = null;\n this.privateId = null;\n this.constructId = constructId || RoomSession.randomString(16);\n this.sessionId = null;\n this.handleId = null;\n this.ws = null;\n this.isRestarting = false;\n this.isConnecting = false;\n this.isDisconnecting = false;\n this.isConnected = false;\n this.isPublished = false;\n this.isReclaiming = false;\n this.isStreaming = false;\n this._retries = 0;\n this._maxRetries = 3;\n this._keepAliveId = null;\n this._participants = [];\n this._roomType = 'watchparty';\n this._isDataChannelOpen = false;\n this._abortController = null;\n this.isAudioMuted = false;\n this.isVideoMuted = false;\n this.isVideoEnabled = false;\n this.isAudioEnabed = false;\n this.subscriptionRules = {\n ...RoomSession.subscriptionRules,\n ...(this.options.subscriptionRules || {})\n };\n this._log = RoomSession.noop;\n if (this.options.debug) {\n this._enableDebug();\n }\n }\n _participantShouldSubscribe(userId) {\n const myUser = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display);\n const remoteUser = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(userId);\n let localUserRole = (myUser === null || myUser === void 0 ? void 0 : myUser.role) || 'participant';\n let remoteUserRole = (remoteUser === null || remoteUser === void 0 ? void 0 : remoteUser.role) || 'participant';\n return this.subscriptionRules[localUserRole][this._roomType || 'watchparty'].indexOf(remoteUserRole) > -1;\n }\n _getAddParticipantEventName(handleId) {\n var _decodeJanusDisplay;\n let handle = this._getHandle(handleId);\n if (!handle) {\n this.emit('error', {\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'getParticipantEventName']\n });\n }\n const participantRole = (_decodeJanusDisplay = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay === void 0 ? void 0 : _decodeJanusDisplay.role;\n switch (participantRole) {\n case 'participant':\n return 'addRemoteParticipant';\n case 'talkback':\n return 'addRemoteTalkback';\n case 'monitor':\n return 'addRemoteTalkback';\n case 'observer':\n case 'observerSolo1':\n case 'observerSolo2':\n case 'observerSolo3':\n return 'addRemoteObserver';\n case 'host':\n return 'addRemoteInstructor';\n case 'companionTV':\n return 'addRemoteCompanionTV';\n case 'companionPhone':\n return 'addRemoteCompanionPhone';\n default:\n return 'addRemoteParticipant';\n }\n }\n _getRemoveParticipantEventName(handleId) {\n var _decodeJanusDisplay2;\n let handle = this._getHandle(handleId);\n if (!handle) {\n this.emit('error', {\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'getParticipantEventName']\n });\n }\n const participantRole = (_decodeJanusDisplay2 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay2 === void 0 ? void 0 : _decodeJanusDisplay2.role;\n switch (participantRole) {\n case 'participant':\n return 'removeRemoteParticipant';\n case 'talkback':\n return 'removeRemoteTalkback';\n case 'monitor':\n return 'removeRemoteTalkback';\n case 'observer':\n case 'observerSolo1':\n case 'observerSolo2':\n case 'observerSolo3':\n return 'removeRemoteObserver';\n case 'host':\n return 'removeRemoteInstructor';\n case 'companionTV':\n return 'removeRemoteCompanionTV';\n case 'companionPhone':\n return 'removeRemoteCompanionPhone';\n default:\n return 'removeRemoteParticipant';\n }\n }\n sendMessage(handleId) {\n let message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n body: 'Example Body'\n };\n let dontWait = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let dontResolveOnAck = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n return this._send({\n \"janus\": \"message\",\n \"handle_id\": handleId,\n ...message\n }, dontWait, dontResolveOnAck).then(json => {\n if (json && json[\"janus\"] === \"success\") {\n let plugindata = json[\"plugindata\"] || {};\n let data = plugindata[\"data\"];\n return Promise.resolve(data);\n }\n return Promise.resolve();\n }).catch(json => {\n if (json && json[\"error\"]) {\n return Promise.reject({\n type: 'warning',\n id: 1,\n message: 'sendMessage failed',\n data: json[\"error\"]\n });\n } else {\n return Promise.reject({\n type: 'warning',\n id: 1,\n message: 'sendMessage failed',\n data: json\n });\n }\n });\n }\n _send() {\n let request = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n let ignoreResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n let dontResolveOnAck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let transaction = RoomSession.randomString(12);\n let requestData = {\n ...request,\n transaction,\n token: this.token,\n ...(this.sessionId && {\n 'session_id': this.sessionId\n } || {})\n };\n this._log(requestData);\n return new Promise((resolve, reject) => {\n let messageTimeoutId = null;\n let abortResponse = () => {\n this._abortController.signal.removeEventListener('abort', abortResponse);\n clearTimeout(messageTimeoutId);\n this.ws.removeEventListener('message', parseResponse);\n reject({\n type: 'warning',\n id: 17,\n message: 'connection cancelled'\n });\n };\n let parseResponse = event => {\n let json = JSON.parse(event.data);\n let r_transaction = json['transaction'];\n if (r_transaction === transaction && (!dontResolveOnAck || json['janus'] !== 'ack')) {\n clearTimeout(messageTimeoutId);\n this._abortController.signal.removeEventListener('abort', abortResponse);\n this.ws.removeEventListener('message', parseResponse);\n if (json['janus'] === 'error') {\n var _json$error;\n if ((json === null || json === void 0 ? void 0 : (_json$error = json.error) === null || _json$error === void 0 ? void 0 : _json$error.code) == 403) {\n this.disconnect(true);\n }\n reject({\n type: 'error',\n id: 2,\n message: 'send failed',\n data: json,\n requestData\n });\n } else {\n resolve(json);\n }\n }\n };\n if (ignoreResponse) {\n if (this.ws && this.ws.readyState === 1) {\n this.ws.send(JSON.stringify(requestData));\n }\n resolve();\n } else {\n if (this.ws && this.ws.readyState === 1) {\n this.ws.addEventListener('message', parseResponse);\n messageTimeoutId = setTimeout(() => {\n this.ws.removeEventListener('message', parseResponse);\n this._abortController.signal.removeEventListener('abort', abortResponse);\n reject({\n type: 'error',\n id: 3,\n message: 'send timeout',\n data: requestData\n });\n }, 10000);\n this._abortController.signal.addEventListener('abort', abortResponse);\n this.ws.send(JSON.stringify(requestData));\n } else {\n reject({\n type: 'warning',\n id: 29,\n message: 'No connection to WebSockets',\n data: requestData\n });\n }\n }\n });\n }\n _connectionClosed() {\n if (!this.isConnected || this.isConnecting || this.isDisconnecting) {\n return;\n }\n if (this._retries < this._maxRetries) {\n setTimeout(() => {\n this._retries++;\n this._reconnect().catch(e => {\n this.emit('error', e);\n });\n }, 3000 * this._retries);\n } else {\n if (this.sessiontype === 'reactooroom') {\n this.disconnect(true);\n } else if (this.sessiontype === 'streaming') {\n this.stopStream();\n }\n this.emit('error', {\n type: 'error',\n id: 4,\n message: 'Lost connection to WebSockets',\n data: null\n });\n }\n }\n _wipeListeners() {\n if (this.ws) {\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n }\n }\n _startKeepAlive() {\n this._send({\n \"janus\": \"keepalive\"\n }).then(json => {\n if (json[\"janus\"] !== 'ack') {\n this.emit('error', {\n type: 'warning',\n id: 5,\n message: 'keepalive response suspicious',\n data: json[\"janus\"]\n });\n }\n }).catch(e => {\n this.emit('error', {\n type: 'warning',\n id: 6,\n message: 'keepalive dead',\n data: e\n });\n this._connectionClosed();\n });\n this._keepAliveId = setTimeout(() => {\n this._startKeepAlive();\n }, 30000);\n }\n _stopKeepAlive() {\n clearTimeout(this._keepAliveId);\n }\n _handleWsEvents(event) {\n let json = JSON.parse(event.data);\n var sender = json[\"sender\"];\n var type = json[\"janus\"];\n let handle = this._getHandle(sender);\n if (!handle) {\n return;\n }\n if (type === \"trickle\") {\n let candidate = json[\"candidate\"];\n let config = handle.webrtcStuff;\n if (config.pc && config.remoteSdp) {\n if (!candidate || candidate.completed === true) {\n config.pc.addIceCandidate(null);\n } else {\n config.pc.addIceCandidate(candidate);\n }\n } else {\n if (!config.candidates) {\n config.candidates = [];\n }\n config.candidates.push(candidate);\n }\n } else if (type === \"webrtcup\") {\n //none universal\n } else if (type === \"hangup\") {\n this._log('hangup on', handle.handleId);\n this._removeParticipant(handle.handleId, null, false);\n } else if (type === \"detached\") {\n this._log('detached on', handle.handleId);\n this._removeParticipant(handle.handleId, null, true);\n } else if (type === \"media\") {\n this._log('Media event:', handle.handleId, json[\"type\"], json[\"receiving\"], json[\"mid\"]);\n } else if (type === \"slowlink\") {\n this._log('Slowlink', handle.handleId, json[\"uplink\"], json[\"lost\"], json[\"mid\"]);\n } else if (type === \"event\") {\n //none universal\n } else if (type === 'timeout') {\n this.ws.close(3504, \"Gateway timeout\");\n } else if (type === 'success' || type === 'error') {\n // we're capturing those elsewhere\n } else {\n this._log(`Unknown event: ${type} on session: ${this.sessionId}`);\n }\n\n // LOCAL\n\n if (sender === this.handleId) {\n if (type === \"event\") {\n var plugindata = json[\"plugindata\"] || {};\n var msg = plugindata[\"data\"] || {};\n var jsep = json[\"jsep\"];\n let result = msg[\"result\"] || null;\n let event = msg[\"videoroom\"] || null;\n let list = msg[\"publishers\"] || {};\n let leaving = msg[\"leaving\"];\n let kicked = msg[\"kicked\"];\n\n //let joining = msg[\"joining\"];\n let unpublished = msg[\"unpublished\"];\n let error = msg[\"error\"];\n if (event === \"joined\") {\n this.id = msg[\"id\"];\n this.privateId = msg[\"private_id\"];\n this.isConnected = true;\n this.emit('joined', true);\n this._log('We have successfully joined Room');\n for (let f in list) {\n let userId = list[f][\"display\"];\n let streams = list[f][\"streams\"] || [];\n let id = list[f][\"id\"];\n for (let i in streams) {\n streams[i][\"id\"] = id;\n streams[i][\"display\"] = userId;\n }\n this._log('Remote userId: ', userId);\n if (this._participantShouldSubscribe(userId)) {\n this._log('Creating user: ', userId);\n this._createParticipant(userId, id).then(handle => {\n return this.sendMessage(handle.handleId, {\n body: {\n \"request\": \"join\",\n \"room\": this.roomId,\n \"ptype\": \"subscriber\",\n streams: streams.map(stream => ({\n feed: stream.id,\n mid: stream.mid\n })),\n //\"feed\": id,\n \"private_id\": this.privateId,\n ...(this.webrtcVersion > 1000 ? {\n id: this.userId\n } : {}),\n pin: this.pin\n }\n });\n }).catch(err => {\n this.emit('error', err);\n });\n }\n }\n } else if (event === \"event\") {\n if (msg[\"streams\"] !== undefined && msg[\"streams\"] !== null) {\n this._log('Got my own streams back', msg[\"streams\"]);\n }\n for (let f in list) {\n let userId = list[f][\"display\"];\n let streams = list[f][\"streams\"] || [];\n let id = list[f][\"id\"];\n for (let i in streams) {\n streams[i][\"id\"] = id;\n streams[i][\"display\"] = userId;\n }\n this._log('Remote userId: ', userId);\n if (this._participantShouldSubscribe(userId)) {\n this._log('Creating user: ', userId);\n this._createParticipant(userId, id).then(handle => {\n return this.sendMessage(handle.handleId, {\n body: {\n \"request\": \"join\",\n \"room\": this.roomId,\n \"ptype\": \"subscriber\",\n streams: streams.map(stream => ({\n feed: stream.id,\n mid: stream.mid\n })),\n \"private_id\": this.privateId,\n ...(this.webrtcVersion > 1000 ? {\n id: this.userId\n } : {}),\n pin: this.pin\n }\n });\n }).catch(err => {\n this.emit('error', err);\n });\n }\n }\n if (leaving === 'ok') {\n this._log('leaving', this.handleId, 'this is us');\n this._removeParticipant(this.handleId);\n if (msg['reason'] === 'kicked') {\n this.emit('kicked');\n this.disconnect().catch(() => {});\n }\n } else if (leaving) {\n //TODO: shouldnt we detach?\n this._log('leaving', leaving);\n this._removeParticipant(null, leaving, true);\n }\n if (unpublished === 'ok') {\n this._log('unpublished', this.handleId, 'this is us');\n this._removeParticipant(this.handleId, null, false); // we do just hangup\n } else if (unpublished) {\n this._log('unpublished', unpublished);\n this._removeParticipant(null, unpublished, true); // we do hangup and detach\n }\n\n if (kicked === 'ok') {\n // this case shouldn't exist\n } else if (kicked) {\n this._log('kicked', kicked);\n this._removeParticipant(null, kicked, true); // we do hangup and detach\n }\n\n if (error) {\n this.emit('error', {\n type: 'error',\n id: 7,\n message: 'local participant error',\n data: [sender, msg]\n });\n }\n }\n\n // Streaming related\n else if (result && result[\"status\"]) {\n this.emit('streamingStatus', result[\"status\"]);\n if (result[\"status\"] === 'stopped') {\n this.stopStream();\n }\n if (result[\"status\"] === 'started') {\n this.emit('streaming', true);\n this.isStreaming = true;\n }\n }\n if (jsep !== undefined && jsep !== null) {\n if (this.sessiontype === 'reactooroom') {\n this._webrtcPeer(this.handleId, jsep).catch(err => {\n this.emit('error', err);\n });\n } else if (this.sessiontype === 'streaming') {\n this._publishRemote(this.handleId, jsep).catch(err => {\n this.emit('error', err);\n });\n }\n }\n } else if (type === \"webrtcup\") {\n if (this.simulcast) {\n return;\n }\n this._log('Configuring bitrate: ' + this.initialBitrate);\n if (this.initialBitrate > 0) {\n this.sendMessage(this.handleId, {\n \"body\": {\n \"request\": \"configure\",\n \"bitrate\": this.initialBitrate\n }\n }).catch(() => null);\n }\n }\n }\n\n //REMOTE\n else {\n let plugindata = json[\"plugindata\"] || {};\n let msg = plugindata[\"data\"] || {};\n let jsep = json[\"jsep\"];\n let event = msg[\"videoroom\"];\n let error = msg[\"error\"];\n let substream = msg[\"substream\"];\n if (event === \"attached\") {\n var _decodeJanusDisplay3, _decodeJanusDisplay4;\n this._log('Remote have successfully joined Room', msg);\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay3 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay3 === void 0 ? void 0 : _decodeJanusDisplay3.userId,\n role: (_decodeJanusDisplay4 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay4 === void 0 ? void 0 : _decodeJanusDisplay4.role,\n stream: null,\n track: null,\n adding: false,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: false,\n hasVideoTrack: false\n });\n }\n if (error) {\n this.emit('error', {\n type: 'warning',\n id: 8,\n message: 'remote participant error',\n data: [sender, msg]\n });\n }\n if (jsep) {\n this._publishRemote(handle.handleId, jsep).catch(err => {\n this.emit('error', err);\n });\n }\n }\n }\n _handleDataEvents(handleId, type, data) {\n let handle = this._getHandle(handleId);\n if (type === 'state') {\n this._log(` - Data channel status - `, `UID: ${handleId}`, `STATUS: ${JSON.stringify(data)}`, `ME: ${handleId === this.handleId}`);\n if (handle) {\n let config = handle.webrtcStuff;\n config.dataChannelOpen = this.defaultDataChannelLabel === (data === null || data === void 0 ? void 0 : data.label) && (data === null || data === void 0 ? void 0 : data.state) === 'open';\n }\n if (handleId === this.handleId && this.defaultDataChannelLabel === (data === null || data === void 0 ? void 0 : data.label)) {\n this._isDataChannelOpen = (data === null || data === void 0 ? void 0 : data.state) === 'open';\n this.emit('dataChannel', (data === null || data === void 0 ? void 0 : data.state) === 'open');\n }\n }\n if (type === 'error') {\n this.emit('error', {\n type: 'warning',\n id: 9,\n message: 'data event warning',\n data: [handleId, data]\n });\n if (handle) {\n let config = handle.webrtcStuff;\n if (this.defaultDataChannelLabel === data.label) {\n config.dataChannelOpen = false;\n }\n }\n if (handleId === this.handleId && this.defaultDataChannelLabel === data.label) {\n this._isDataChannelOpen = false;\n this.emit('dataChannel', false);\n }\n }\n if (handleId === this.handleId && type === 'message') {\n let d = null;\n try {\n d = JSON.parse(data);\n } catch (e) {\n this.emit('error', {\n type: 'warning',\n id: 10,\n message: 'data message parse error',\n data: [handleId, e]\n });\n return;\n }\n this.emit('data', d);\n }\n }\n\n //removeHandle === true -> hangup, detach, removeHandle === false -> hangup\n _removeParticipant(handleId, rfid) {\n let removeHandle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n let handle = this._getHandle(handleId, rfid);\n if (!handle) {\n return Promise.resolve();\n } else {\n handleId = handle.handleId;\n }\n return this._send({\n \"janus\": \"hangup\",\n \"handle_id\": handleId\n }, true).then(() => removeHandle ? this._send({\n \"janus\": \"detach\",\n \"handle_id\": handleId\n }, true) : Promise.resolve()).finally(() => {\n try {\n if (handle.webrtcStuff.stream) {\n if (!this.isRestarting) {\n handle.webrtcStuff.stream.getTracks().forEach(track => track.stop());\n } else {\n handle.webrtcStuff.stream.getTracks().forEach(track => track.onended = null);\n }\n }\n } catch (e) {\n // Do nothing\n }\n handle.webrtcStuff.stream = null;\n if (handle.webrtcStuff.dataChannel) {\n Object.keys(handle.webrtcStuff.dataChannel).forEach(label => {\n handle.webrtcStuff.dataChannel[label].onmessage = null;\n handle.webrtcStuff.dataChannel[label].onopen = null;\n handle.webrtcStuff.dataChannel[label].onclose = null;\n handle.webrtcStuff.dataChannel[label].onerror = null;\n });\n }\n if (handle.webrtcStuff.pc) {\n handle.webrtcStuff.pc.onicecandidate = null;\n handle.webrtcStuff.pc.ontrack = null;\n handle.webrtcStuff.pc.ondatachannel = null;\n handle.webrtcStuff.pc.onconnectionstatechange = null;\n handle.webrtcStuff.pc.oniceconnectionstatechange = null;\n }\n try {\n handle.webrtcStuff.pc.close();\n } catch (e) {}\n handle.webrtcStuff = {\n stream: null,\n mySdp: null,\n mediaConstraints: null,\n pc: null,\n dataChannelOpen: false,\n dataChannel: null,\n dtmfSender: null,\n trickle: true,\n iceDone: false\n };\n if (handleId === this.handleId) {\n var _decodeJanusDisplay5, _decodeJanusDisplay6;\n this._isDataChannelOpen = false;\n this.isPublished = false;\n this.emit('published', {\n status: false,\n hasStream: false\n });\n this.emit('removeLocalParticipant', {\n id: handleId,\n userId: (_decodeJanusDisplay5 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay5 === void 0 ? void 0 : _decodeJanusDisplay5.userId,\n role: (_decodeJanusDisplay6 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay6 === void 0 ? void 0 : _decodeJanusDisplay6.role\n });\n } else {\n var _decodeJanusDisplay7, _decodeJanusDisplay8;\n this.emit(this._getRemoveParticipantEventName(handleId), {\n id: handleId,\n userId: (_decodeJanusDisplay7 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay7 === void 0 ? void 0 : _decodeJanusDisplay7.userId,\n role: (_decodeJanusDisplay8 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay8 === void 0 ? void 0 : _decodeJanusDisplay8.role\n });\n }\n if (removeHandle) {\n let handleIndex = this._participants.findIndex(p => p.handleId === handleId);\n this._participants.splice(handleIndex, 1);\n }\n return true;\n });\n }\n _createParticipant() {\n let userId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let rfid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n return this._send({\n \"janus\": \"attach\",\n \"plugin\": this.pluginName\n }).then(json => {\n let handleId = json.data[\"id\"];\n let handle = {\n handleId,\n rfid,\n userId,\n webrtcStuff: {\n stream: null,\n mySdp: null,\n mediaConstraints: null,\n pc: null,\n dataChannelOpen: false,\n dataChannel: null,\n dtmfSender: null,\n trickle: true,\n iceDone: false,\n isIceRestarting: false\n }\n };\n this._participants.push(handle);\n return handle;\n });\n }\n _joinRoom(roomId, pin, userId, display) {\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"join\",\n \"room\": roomId,\n \"pin\": pin,\n \"ptype\": \"publisher\",\n \"display\": display,\n ...(this.webrtcVersion > 1000 ? {\n id: userId\n } : {})\n }\n }, false, true);\n }\n _watchStream(id) {\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"watch\",\n id: parseInt(id)\n }\n }, false, true);\n }\n _leaveRoom() {\n let dontWait = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n return this.isConnected ? this.sendMessage(this.handleId, {\n body: {\n \"request\": \"leave\"\n }\n }, dontWait).finally(() => {\n this.isConnected = false;\n this.emit('joined', false);\n }) : Promise.resolve();\n }\n\n // internal reconnect\n\n _reconnect() {\n if (this.isReclaiming) {\n return Promise.resolve();\n }\n if (this.ws) {\n this._wipeListeners();\n if (this.ws.readyState === 1) {\n this.ws.close();\n }\n }\n this._stopKeepAlive();\n this.isReclaiming = true;\n this.emit('joining', true);\n return new Promise((resolve, reject) => {\n let abortReconnect = () => {\n this._abortController.signal.removeEventListener('abort', abortReconnect);\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.isReclaiming = false;\n this.emit('joining', false);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled',\n data: e\n });\n };\n this.ws = new WebSocket(this.server, 'janus-protocol');\n this.__connectionClosedBoundFn = this._connectionClosed.bind(this);\n this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);\n this.ws.addEventListener('close', this.__connectionClosedBoundFn);\n this.ws.addEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = () => {\n this._abortController.signal.removeEventListener('abort', abortReconnect);\n this._send({\n \"janus\": \"claim\"\n }).then(json => {\n this.sessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n this._startKeepAlive();\n this.isReclaiming = false;\n this.emit('joining', false);\n this._retries = 0;\n resolve(json);\n }).catch(error => {\n this.isReclaiming = false;\n this.emit('joining', false);\n reject({\n type: 'error',\n id: 11,\n message: 'reconnection error',\n data: error\n });\n });\n };\n\n // this is called before 'close' event callback so it doesn't break reconnect loop\n this.ws.onerror = e => {\n this._abortController.signal.removeEventListener('abort', abortReconnect);\n this.isReclaiming = false;\n this.emit('joining', false);\n reject({\n type: 'warning',\n id: 12,\n message: 'ws reconnection error',\n data: e\n });\n };\n this._abortController.signal.addEventListener('abort', abortReconnect);\n });\n }\n connect(roomId, pin, server, iceServers, token, display, userId) {\n let webrtcVersion = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 0;\n let initialBitrate = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 0;\n let recordingFilename = arguments.length > 9 ? arguments[9] : undefined;\n let simulcast = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;\n let simulcastBitrates = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : {};\n if (this.isConnecting) {\n return Promise.reject({\n type: 'warning',\n id: 16,\n message: 'connection already in progress'\n });\n }\n if (this.ws) {\n this._wipeListeners();\n }\n this._stopKeepAlive();\n this._abortController = new AbortController();\n this.sessionId = null;\n this.server = server;\n this.iceServers = iceServers;\n this.token = token;\n this.roomId = roomId;\n this.pin = pin;\n this.display = display;\n this.userId = userId;\n this.webrtcVersion = webrtcVersion;\n this.initialBitrate = initialBitrate;\n this.recordingFilename = recordingFilename;\n this.isConnecting = true;\n this.simulcast = simulcast;\n this.simulcastBitrates = {\n ...this.simulcastBitrates,\n ...simulcastBitrates\n };\n this.emit('joining', true);\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.server, 'janus-protocol');\n this.__connectionClosedBoundFn = this._connectionClosed.bind(this);\n this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);\n let abortConnect = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.isConnecting = false;\n this.emit('joining', false);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled'\n });\n };\n this.ws.addEventListener('close', this.__connectionClosedBoundFn);\n this.ws.addEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this._retries = 0;\n this._send({\n \"janus\": \"create\"\n }).then(json => {\n this.sessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n this._startKeepAlive();\n return 1;\n }).then(() => this._createParticipant(userId)).then(handle => {\n this.handleId = handle.handleId;\n return 1;\n }).then(() => this._joinRoom(roomId, pin, userId, display)).then(() => {\n this.isConnecting = false;\n this.emit('joining', false);\n resolve(this);\n }).catch(error => {\n this.isConnecting = false;\n this.emit('joining', false);\n reject({\n type: (error === null || error === void 0 ? void 0 : error.type) === 'warning' ? 'warning' : 'error',\n id: 13,\n message: 'connection error',\n data: error\n });\n });\n };\n this.ws.onerror = e => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.isConnecting = false;\n this.emit('joining', false);\n reject({\n type: 'error',\n id: 14,\n message: 'ws connection error',\n data: e\n });\n };\n this._abortController.signal.addEventListener('abort', abortConnect);\n });\n }\n disconnect() {\n var _this$_abortControlle, _this$_abortControlle2;\n if (this.isDisconnecting) {\n return Promise.resolve();\n }\n (_this$_abortControlle = this._abortController) === null || _this$_abortControlle === void 0 ? void 0 : (_this$_abortControlle2 = _this$_abortControlle.abort) === null || _this$_abortControlle2 === void 0 ? void 0 : _this$_abortControlle2.call(_this$_abortControlle);\n this._stopKeepAlive();\n let isConnected = this.isConnected;\n this.isDisconnecting = true;\n return Promise.all(this._participants.map(p => this._removeParticipant(p.handleId))).finally(() => {\n this._wipeListeners();\n if (this.ws && this.ws.readyState === 1) {\n this._send({\n \"janus\": \"destroy\"\n }, true);\n this.ws.close();\n }\n this.sessionId = null;\n this.isPublished = false;\n this.isConnected = false;\n this.isDisconnecting = false;\n this.emit('publishing', false);\n this.emit('published', {\n status: false,\n hasStream: false\n });\n this.emit('joining', false);\n this.emit('joined', false);\n this.emit('disconnect', isConnected);\n return Promise.resolve('Disconnected');\n });\n }\n startStream(streamId, server, iceServers, token, userId) {\n if (this.isConnecting) {\n return Promise.reject({\n type: 'warning',\n id: 16,\n message: 'connection error',\n data: 'Connection is in progress'\n });\n }\n if (this.ws) {\n this._wipeListeners();\n }\n this._stopKeepAlive();\n this._abortController = new AbortController();\n this.server = server;\n this.iceServers = iceServers;\n this.token = token;\n this.streamId = streamId;\n this.userId = userId;\n this.sessionId = null;\n this.isConnecting = true;\n this.emit('streamStarting', true);\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.server, 'janus-protocol');\n this.__connectionClosedBoundFn = this._connectionClosed.bind(this);\n this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);\n let abortConnect = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.isConnecting = false;\n this.emit('streamStarting', false);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled'\n });\n };\n this.ws.addEventListener('close', this.__connectionClosedBoundFn);\n this.ws.addEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this._retries = 0;\n this._send({\n \"janus\": \"create\"\n }).then(json => {\n this.sessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n this._startKeepAlive();\n return 1;\n }).then(() => this._createParticipant(userId)).then(handle => {\n this.handleId = handle.handleId;\n return 1;\n }).then(() => this._watchStream(streamId)).then(() => {\n this.isConnecting = false;\n this.emit('streamStarting', false);\n resolve(this);\n }).catch(error => {\n this.isConnecting = false;\n this.emit('streamStarting', false);\n reject({\n type: 'error',\n id: 13,\n message: 'connection error',\n data: error\n });\n });\n };\n this.ws.onerror = e => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.isConnecting = false;\n this.emit('streamStarting', false);\n reject({\n type: 'error',\n id: 14,\n message: 'ws connection error',\n data: e\n });\n };\n this._abortController.signal.addEventListener('abort', abortConnect);\n });\n }\n stopStream() {\n var _this$_abortControlle3, _this$_abortControlle4;\n if (this.isDisconnecting) {\n return Promise.resolve();\n }\n (_this$_abortControlle3 = this._abortController) === null || _this$_abortControlle3 === void 0 ? void 0 : (_this$_abortControlle4 = _this$_abortControlle3.abort) === null || _this$_abortControlle4 === void 0 ? void 0 : _this$_abortControlle4.call(_this$_abortControlle3);\n this._stopKeepAlive();\n let isStreaming = this.isStreaming;\n this.isDisconnecting = true;\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"stop\"\n }\n }, false, true).then(() => this._removeParticipant(this.handleId)).finally(() => {\n this._wipeListeners();\n this._send({\n \"janus\": \"destroy\"\n }, true);\n if (this.ws && this.ws.readyState === 1) {\n this.ws.close();\n }\n this.sessionId = null;\n this.isDisconnecting = false;\n this.isStreaming = false;\n this.emit('streamStarting', false);\n this.emit('streaming', false);\n this.emit('disconnect', isStreaming);\n return Promise.resolve('Disconnected');\n });\n }\n destroy() {\n if (this.sessiontype === 'reactooroom') {\n return this.disconnect().then(() => {\n this.clear();\n return true;\n });\n } else if (this.sessiontype === 'streaming') {\n return this.stopStream().then(() => {\n this.clear();\n return true;\n });\n }\n }\n _enableDebug() {\n this._log = console.log.bind(console);\n }\n _getHandle(handleId) {\n let rfid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n return this._participants.find(p => p.handleId === handleId || rfid && p.rfid === rfid);\n }\n _getStats() {\n let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n return Promise.all(this._participants.map(participant => {\n let mediaTrack = null;\n if (type === 'video') {\n mediaTrack = participant.webrtcStuff && participant.webrtcStuff.stream && participant.webrtcStuff.stream.getVideoTracks().length && participant.webrtcStuff.stream.getVideoTracks()[0];\n } else if (type === 'audio') {\n mediaTrack = participant.webrtcStuff && participant.webrtcStuff.stream && participant.webrtcStuff.stream.getAudioTracks().length && participant.webrtcStuff.stream.getAudioTracks()[0];\n }\n return participant.webrtcStuff && participant.webrtcStuff.pc && participant.webrtcStuff.pc.getStats(mediaTrack).then(r => ({\n handle: participant,\n stats: r\n })).catch(e => Promise.resolve({\n handle: participant,\n stats: e\n }));\n }));\n }\n _sendTrickleCandidate(handleId, candidate) {\n return this._send({\n \"janus\": \"trickle\",\n \"candidate\": candidate,\n \"handle_id\": handleId\n });\n }\n _webrtc(handleId) {\n let enableOntrack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n let handle = this._getHandle(handleId);\n if (!handle) {\n this.emit('error', {\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'create rtc connection']\n });\n }\n let config = handle.webrtcStuff;\n if (!config.pc) {\n let pc_config = {\n \"iceServers\": this.iceServers,\n \"iceTransportPolicy\": 'all',\n \"bundlePolicy\": undefined\n };\n pc_config[\"sdpSemantics\"] = \"unified-plan\";\n let pc_constraints = {};\n if (webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser === \"edge\") {\n // This is Edge, enable BUNDLE explicitly\n pc_config.bundlePolicy = \"max-bundle\";\n }\n this._log('new RTCPeerConnection', pc_config, pc_constraints);\n config.pc = new RTCPeerConnection(pc_config, pc_constraints);\n config.pc.onconnectionstatechange = () => {\n if (config.pc.connectionState === 'failed') {\n this._iceRestart(handleId);\n }\n this.emit('connectionState', [handleId, handleId === this.handleId, config.pc.connectionState]);\n if (handleId !== this.handleId && config.pc.connectionState === 'connected') {\n var _decodeJanusDisplay9, _decodeJanusDisplay10;\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay9 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay9 === void 0 ? void 0 : _decodeJanusDisplay9.userId,\n role: (_decodeJanusDisplay10 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay10 === void 0 ? void 0 : _decodeJanusDisplay10.role,\n stream: config.stream,\n track: null,\n optional: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: false,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n }\n };\n config.pc.oniceconnectionstatechange = () => {\n if (config.pc.iceConnectionState === 'failed') {\n this._iceRestart(handleId);\n }\n this.emit('iceState', [handleId, handleId === this.handleId, config.pc.iceConnectionState]);\n if (handleId !== this.handleId && (config.pc.iceConnectionState === 'completed' || config.pc.iceConnectionState === 'connected')) {\n var _decodeJanusDisplay11, _decodeJanusDisplay12;\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay11 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay11 === void 0 ? void 0 : _decodeJanusDisplay11.userId,\n role: (_decodeJanusDisplay12 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay12 === void 0 ? void 0 : _decodeJanusDisplay12.role,\n stream: config.stream,\n track: null,\n optional: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: false,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n }\n };\n config.pc.onicecandidate = event => {\n if (event.candidate == null || webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser === 'edge' && event.candidate.candidate.indexOf('endOfCandidates') > 0) {\n config.iceDone = true;\n this._sendTrickleCandidate(handleId, {\n \"completed\": true\n }).catch(e => {\n this.emit('error', e);\n });\n } else {\n // JSON.stringify doesn't work on some WebRTC objects anymore\n // See https://code.google.com/p/chromium/issues/detail?id=467366\n var candidate = {\n \"candidate\": event.candidate.candidate,\n \"sdpMid\": event.candidate.sdpMid,\n \"sdpMLineIndex\": event.candidate.sdpMLineIndex\n };\n this._sendTrickleCandidate(handleId, candidate).catch(e => {\n this.emit('error', e);\n });\n }\n };\n if (enableOntrack) {\n config.pc.ontrack = event => {\n if (!event.streams) return;\n\n //config.stream = event.streams[0];\n\n if (!config.stream) {\n config.stream = new MediaStream();\n }\n if (event.track) {\n var _decodeJanusDisplay13, _decodeJanusDisplay14;\n let mid = event.transceiver ? event.transceiver.mid : event.track.id;\n config.stream.addTrack(event.track);\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n mid,\n id: handle.handleId,\n userId: (_decodeJanusDisplay13 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay13 === void 0 ? void 0 : _decodeJanusDisplay13.userId,\n role: (_decodeJanusDisplay14 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay14 === void 0 ? void 0 : _decodeJanusDisplay14.role,\n stream: config.stream,\n track: event.track,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: true,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n if (event.track.onended) return;\n event.track.onended = ev => {\n var _config$pc, _config$pc$getTransce;\n let transceiver = (_config$pc = config.pc) === null || _config$pc === void 0 ? void 0 : (_config$pc$getTransce = _config$pc.getTransceivers()) === null || _config$pc$getTransce === void 0 ? void 0 : _config$pc$getTransce.find(t => t.receiver.track === ev.target);\n let mid = (transceiver === null || transceiver === void 0 ? void 0 : transceiver.mid) || ev.target.id;\n if (config.stream) {\n var _decodeJanusDisplay15, _decodeJanusDisplay16;\n config.stream && config.stream.removeTrack(ev.target);\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n mid,\n userId: (_decodeJanusDisplay15 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay15 === void 0 ? void 0 : _decodeJanusDisplay15.userId,\n role: (_decodeJanusDisplay16 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay16 === void 0 ? void 0 : _decodeJanusDisplay16.role,\n stream: config.stream,\n track: ev.target,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: false,\n removing: true,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n }\n };\n event.track.onmute = ev => {\n var _decodeJanusDisplay17, _decodeJanusDisplay18;\n this._log('remoteTrackMuted', 'onmute');\n let transceiver = config.pc.getTransceivers().find(t => t.receiver.track === ev.target);\n let mid = transceiver.mid || ev.target.id;\n this.emit('remoteTrackMuted', {\n id: handle.handleId,\n mid,\n userId: (_decodeJanusDisplay17 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay17 === void 0 ? void 0 : _decodeJanusDisplay17.userId,\n role: (_decodeJanusDisplay18 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay18 === void 0 ? void 0 : _decodeJanusDisplay18.role,\n stream: config.stream,\n kind: ev.target.kind,\n track: ev.target,\n muted: true\n });\n };\n event.track.onunmute = ev => {\n var _decodeJanusDisplay19, _decodeJanusDisplay20;\n this._log('remoteTrackMuted', 'onunmute');\n let transceiver = config.pc.getTransceivers().find(t => t.receiver.track === ev.target);\n let mid = transceiver.mid || ev.target.id;\n this.emit('remoteTrackMuted', {\n id: handle.handleId,\n mid,\n userId: (_decodeJanusDisplay19 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay19 === void 0 ? void 0 : _decodeJanusDisplay19.userId,\n role: (_decodeJanusDisplay20 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay20 === void 0 ? void 0 : _decodeJanusDisplay20.role,\n stream: config.stream,\n kind: ev.target.kind,\n track: ev.target,\n muted: false\n });\n };\n }\n };\n }\n }\n if (!config.dataChannel || !config.dataChannelOpen) {\n config.dataChannel = {};\n var onDataChannelMessage = event => {\n this._handleDataEvents(handleId, 'message', event.data);\n };\n var onDataChannelStateChange = event => {\n let label = event.target.label;\n let protocol = event.target.protocol;\n let state = config.dataChannel[label] ? config.dataChannel[label].readyState : \"null\";\n this._handleDataEvents(handleId, 'state', {\n state,\n label\n });\n };\n //TODO: check this\n var onDataChannelError = error => {\n var _error$channel;\n this._handleDataEvents(handleId, 'error', {\n label: error === null || error === void 0 ? void 0 : (_error$channel = error.channel) === null || _error$channel === void 0 ? void 0 : _error$channel.label,\n error\n });\n };\n const createDataChannel = (label, protocol, incoming) => {\n let options = {\n ordered: true\n };\n if (!incoming) {\n if (protocol) {\n options = {\n ...options,\n protocol\n };\n }\n config.dataChannel[label] = config.pc.createDataChannel(label, options);\n } else {\n config.dataChannel[label] = incoming;\n }\n config.dataChannel[label].onmessage = onDataChannelMessage;\n config.dataChannel[label].onopen = onDataChannelStateChange;\n config.dataChannel[label].onclose = onDataChannelStateChange;\n config.dataChannel[label].onerror = onDataChannelError;\n };\n createDataChannel(this.defaultDataChannelLabel, null, null);\n config.pc.ondatachannel = function (event) {\n createDataChannel(event.channel.label, event.channel.protocol, event.channel);\n };\n }\n }\n _webrtcPeer(handleId, jsep) {\n let handle = this._getHandle(handleId);\n if (!handle) {\n return Promise.reject({\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'rtc peer']\n });\n }\n var config = handle.webrtcStuff;\n if (jsep !== undefined && jsep !== null) {\n if (config.pc === null) {\n this._log(\"No PeerConnection: if this is an answer, use createAnswer and not _webrtcPeer\");\n return Promise.resolve(null);\n }\n return config.pc.setRemoteDescription(jsep).then(() => {\n config.remoteSdp = jsep.sdp;\n // Any trickle candidate we cached?\n if (config.candidates && config.candidates.length > 0) {\n for (var i = 0; i < config.candidates.length; i++) {\n var candidate = config.candidates[i];\n if (!candidate || candidate.completed === true) {\n config.pc.addIceCandidate(null);\n } else {\n config.pc.addIceCandidate(candidate);\n }\n }\n config.candidates = [];\n }\n // Done\n return true;\n });\n } else {\n return Promise.reject({\n type: 'warning',\n id: 22,\n message: 'rtc peer',\n data: [handleId, 'invalid jsep']\n });\n }\n }\n _iceRestart(handleId) {\n let handle = this._getHandle(handleId);\n if (!handle) {\n return;\n }\n var config = handle.webrtcStuff;\n\n // Already restarting;\n if (config.isIceRestarting) {\n return;\n }\n if (this.handleId === handleId) {\n this._log('Performing local ICE restart');\n config.isIceRestarting = true;\n let hasAudio = !!(config.stream && config.stream.getAudioTracks().length > 0);\n let hasVideo = !!(config.stream && config.stream.getVideoTracks().length > 0);\n this._setupTransceivers([hasAudio, false, hasVideo, false]);\n this._createAO('offer', handleId, true).then(jsep => {\n if (!jsep) {\n return null;\n }\n return this.sendMessage(handleId, {\n body: {\n \"request\": \"configure\",\n \"audio\": hasAudio,\n \"video\": hasVideo,\n \"data\": true,\n ...(this.recordingFilename ? {\n filename: this.recordingFilename\n } : {})\n },\n jsep\n });\n }).then(r => {\n config.isIceRestarting = false;\n this._log('ICE restart success');\n }).catch(e => {\n config.isIceRestarting = false;\n this.emit('error', {\n type: 'warning',\n id: 28,\n message: 'iceRestart failed',\n data: e\n });\n });\n } else {\n this._log('Performing remote ICE restart', handleId);\n config.isIceRestarting = true;\n return this.sendMessage(handleId, {\n body: {\n \"request\": \"configure\",\n \"restart\": true\n }\n }).then(() => {\n config.isIceRestarting = false;\n }).catch(() => {\n config.isIceRestarting = false;\n });\n }\n }\n _setupTransceivers(handleId, _ref) {\n let [audioSend, audioRecv, videoSend, videoRecv] = _ref;\n let handle = this._getHandle(handleId);\n if (!handle) {\n return null;\n }\n let config = handle.webrtcStuff;\n let audioTransceiver = null,\n videoTransceiver = null;\n let transceivers = config.pc.getTransceivers();\n if (transceivers && transceivers.length > 0) {\n for (var i in transceivers) {\n var t = transceivers[i];\n if (t.sender && t.sender.track && t.sender.track.kind === \"audio\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"audio\") {\n if (!audioTransceiver) audioTransceiver = t;\n continue;\n }\n if (t.sender && t.sender.track && t.sender.track.kind === \"video\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"video\") {\n if (!videoTransceiver) videoTransceiver = t;\n continue;\n }\n }\n }\n\n // Handle audio (and related changes, if any)\n if (!audioSend && !audioRecv) {\n // Audio disabled: have we removed it?\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"inactive\");\n } else {\n audioTransceiver.direction = \"inactive\";\n }\n }\n } else {\n // Take care of audio m-line\n if (audioSend && audioRecv) {\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"sendrecv\");\n } else {\n audioTransceiver.direction = \"sendrecv\";\n }\n }\n } else if (audioSend && !audioRecv) {\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"sendonly\");\n } else {\n audioTransceiver.direction = \"sendonly\";\n }\n }\n } else if (!audioSend && audioRecv) {\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"recvonly\");\n } else {\n audioTransceiver.direction = \"recvonly\";\n }\n } else {\n // In theory, this is the only case where we might not have a transceiver yet\n config.pc.addTransceiver(\"audio\", {\n direction: \"recvonly\"\n });\n }\n }\n }\n // Handle video (and related changes, if any)\n if (!videoSend && !videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"inactive\");\n } else {\n videoTransceiver.direction = \"inactive\";\n }\n }\n } else {\n // Take care of video m-line\n if (videoSend && videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"sendrecv\");\n } else {\n videoTransceiver.direction = \"sendrecv\";\n }\n }\n } else if (videoSend && !videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"sendonly\");\n } else {\n videoTransceiver.direction = \"sendonly\";\n }\n }\n } else if (!videoSend && videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"recvonly\");\n } else {\n videoTransceiver.direction = \"recvonly\";\n }\n } else {\n // In theory, this is the only case where we might not have a transceiver yet\n config.pc.addTransceiver(\"video\", {\n direction: \"recvonly\"\n });\n }\n }\n }\n }\n _createAO() {\n let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'offer';\n let handleId = arguments.length > 1 ? arguments[1] : undefined;\n let iceRestart = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let handle = this._getHandle(handleId);\n if (!handle) {\n return Promise.reject({\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'createAO', type]\n });\n }\n let methodName = null;\n if (type === 'offer') {\n methodName = 'createOffer';\n } else {\n methodName = 'createAnswer';\n }\n let config = handle.webrtcStuff;\n let mediaConstraints = {};\n if (iceRestart) {\n mediaConstraints[\"iceRestart\"] = true;\n }\n return config.pc[methodName](mediaConstraints).then(function (response) {\n config.mySdp = response.sdp;\n let _p = config.pc.setLocalDescription(response).catch(e => {\n return Promise.reject({\n type: 'warning',\n id: 24,\n message: 'setLocalDescription',\n data: [handleId, e]\n });\n });\n config.mediaConstraints = mediaConstraints;\n if (!config.iceDone && !config.trickle) {\n // Don't do anything until we have all candidates\n return Promise.resolve(null);\n }\n\n // JSON.stringify doesn't work on some WebRTC objects anymore\n // See https://code.google.com/p/chromium/issues/detail?id=467366\n var jsep = {\n \"type\": response.type,\n \"sdp\": response.sdp\n };\n return _p.then(() => jsep);\n }, e => {\n return Promise.reject({\n type: 'warning',\n id: 25,\n message: methodName,\n data: [handleId, e]\n });\n });\n }\n _publishRemote(handleId, jsep) {\n let handle = this._getHandle(handleId);\n if (!handle) {\n return Promise.reject({\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'publish remote participant']\n });\n }\n this._webrtc(handleId, true);\n let config = handle.webrtcStuff;\n if (jsep) {\n return config.pc.setRemoteDescription(jsep).then(() => {\n config.remoteSdp = jsep.sdp;\n // Any trickle candidate we cached?\n if (config.candidates && config.candidates.length > 0) {\n for (var i = 0; i < config.candidates.length; i++) {\n var candidate = config.candidates[i];\n if (!candidate || candidate.completed === true) {\n // end-of-candidates\n config.pc.addIceCandidate(null);\n } else {\n // New candidate\n config.pc.addIceCandidate(candidate);\n }\n }\n config.candidates = [];\n }\n this._setupTransceivers(handleId, [false, true, false, true]);\n\n // Create the answer now\n return this._createAO('answer', handleId, false).then(_jsep => {\n if (!_jsep) {\n this.emit('error', {\n type: 'warning',\n id: 19,\n message: 'publish remote participant',\n data: [handleId, 'no jsep']\n });\n return Promise.resolve();\n }\n return this.sendMessage(handleId, {\n \"body\": {\n \"request\": \"start\",\n ...(this.roomId && {\n \"room\": this.roomId\n }),\n ...(this.pin && {\n pin: this.pin\n })\n },\n \"jsep\": _jsep\n });\n });\n }, e => Promise.reject({\n type: 'warning',\n id: 23,\n message: 'setRemoteDescription',\n data: [handleId, e]\n }));\n } else {\n return Promise.resolve();\n }\n }\n\n //Public methods\n\n publishLocal() {\n let stream = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n if (this.isDisconnecting || !this.isConnected) {\n return Promise.reject({\n type: 'warning',\n id: 18,\n message: 'Either not connected or disconnecting'\n });\n }\n this.emit('publishing', true);\n let handle = this._getHandle(this.handleId);\n if (!handle) {\n return Promise.reject({\n type: 'error',\n id: 21,\n message: 'no local id, connect before publishing',\n data: null\n });\n }\n this._webrtc(this.handleId);\n let config = handle.webrtcStuff;\n let audioTrackReplacePromise = Promise.resolve();\n let videoTrackReplacePromise = Promise.resolve();\n if (!config.stream) {\n var _stream$getTracks;\n config.stream = stream;\n stream === null || stream === void 0 ? void 0 : (_stream$getTracks = stream.getTracks()) === null || _stream$getTracks === void 0 ? void 0 : _stream$getTracks.forEach(track => {\n if (track.kind === 'audio' || !this.simulcast) {\n config.pc.addTrack(track, stream);\n } else {\n // adding simulcast streams\n let bitRates = this.simulcastBitrates;\n if (webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser !== 'firefox') {\n // standard\n\n config.pc.addTransceiver(track, {\n direction: 'sendonly',\n streams: [config.stream],\n sendEncodings: [{\n rid: 'h',\n active: true,\n maxBitrate: bitRates.high\n }, {\n rid: 'm',\n active: true,\n maxBitrate: bitRates.medium,\n scaleResolutionDownBy: 2\n }, {\n rid: 'l',\n active: true,\n maxBitrate: bitRates.low,\n scaleResolutionDownBy: 4\n }]\n });\n } else {\n // firefox\n let transceiver = config.pc.addTransceiver(track, {\n direction: 'sendonly',\n streams: [config.stream]\n });\n let sender = transceiver ? transceiver.sender : null;\n if (sender) {\n let parameters = sender.getParameters() || {};\n parameters.encodings = track.sendEncodings || [{\n rid: 'h',\n active: true,\n maxBitrate: bitRates.high\n }, {\n rid: 'm',\n active: true,\n maxBitrate: bitRates.medium,\n scaleResolutionDownBy: 2\n }, {\n rid: 'l',\n active: true,\n maxBitrate: bitRates.low,\n scaleResolutionDownBy: 4\n }];\n sender.setParameters(parameters);\n }\n }\n }\n });\n } else {\n var _config$stream, _config$stream$getAud, _stream$getAudioTrack, _config$stream2, _config$stream2$getVi, _stream$getVideoTrack;\n let transceivers = config.pc.getTransceivers();\n let audioTransceiver = null;\n let videoTransceiver = null;\n if (transceivers && transceivers.length > 0) {\n for (let i in transceivers) {\n let t = transceivers[i];\n if (t.sender && t.sender.track && t.sender.track.kind === \"audio\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"audio\") {\n audioTransceiver = t;\n break;\n }\n }\n for (let i in transceivers) {\n let t = transceivers[i];\n if (t.sender && t.sender.track && t.sender.track.kind === \"video\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"video\") {\n videoTransceiver = t;\n break;\n }\n }\n }\n\n /* UPDATE Audio */\n // stopping existing tracks\n\n let oldAudioStream = config === null || config === void 0 ? void 0 : (_config$stream = config.stream) === null || _config$stream === void 0 ? void 0 : (_config$stream$getAud = _config$stream.getAudioTracks()) === null || _config$stream$getAud === void 0 ? void 0 : _config$stream$getAud[0];\n if (oldAudioStream) {\n config.stream.removeTrack(oldAudioStream);\n try {\n oldAudioStream.stop();\n } catch (e) {\n this._log(e);\n }\n }\n let replaceAudio = stream === null || stream === void 0 ? void 0 : (_stream$getAudioTrack = stream.getAudioTracks()) === null || _stream$getAudioTrack === void 0 ? void 0 : _stream$getAudioTrack.length;\n if (replaceAudio) {\n config.stream.addTrack(stream.getAudioTracks()[0]);\n if (audioTransceiver && audioTransceiver.sender) {\n audioTrackReplacePromise = audioTransceiver.sender.replaceTrack(stream.getAudioTracks()[0]);\n } else {\n config.pc.addTrack(stream.getAudioTracks()[0], stream);\n }\n } else {\n if (audioTransceiver && audioTransceiver.sender) {\n audioTrackReplacePromise = audioTransceiver.sender.replaceTrack(null);\n }\n }\n\n /* UPDATE Video */\n\n // stopping existing tracks\n\n let oldVideoStream = config === null || config === void 0 ? void 0 : (_config$stream2 = config.stream) === null || _config$stream2 === void 0 ? void 0 : (_config$stream2$getVi = _config$stream2.getVideoTracks()) === null || _config$stream2$getVi === void 0 ? void 0 : _config$stream2$getVi[0];\n if (oldVideoStream) {\n config.stream.removeTrack(oldVideoStream);\n try {\n oldVideoStream.stop();\n } catch (e) {\n this._log(e);\n }\n }\n let replaceVideo = stream === null || stream === void 0 ? void 0 : (_stream$getVideoTrack = stream.getVideoTracks()) === null || _stream$getVideoTrack === void 0 ? void 0 : _stream$getVideoTrack.length;\n if (replaceVideo) {\n config.stream.addTrack(stream.getVideoTracks()[0]);\n if (videoTransceiver && videoTransceiver.sender) {\n videoTrackReplacePromise = videoTransceiver.sender.replaceTrack(stream.getVideoTracks()[0]);\n } else {\n config.pc.addTrack(stream.getVideoTracks()[0], stream);\n }\n } else {\n if (videoTransceiver && videoTransceiver.sender) {\n videoTrackReplacePromise = videoTransceiver.sender.replaceTrack(null);\n }\n }\n }\n let hasAudio = !!(stream && stream.getAudioTracks().length > 0);\n let hasVideo = !!(stream && stream.getVideoTracks().length > 0);\n let isAudioMuted = !stream || stream.getAudioTracks().length === 0 || !stream.getAudioTracks()[0].enabled;\n let isVideoMuted = !stream || stream.getVideoTracks().length === 0 || !stream.getVideoTracks()[0].enabled;\n this.isAudioEnabed = hasAudio;\n this.isVideoEnabled = hasVideo;\n this.isAudioMuted = isAudioMuted;\n this.isVideoMuted = isVideoMuted;\n this._setupTransceivers(this.handleId, [hasAudio, false, hasVideo, false]);\n\n // this should be enough\n if (this.isPublished) {\n return Promise.resolve();\n }\n return Promise.all([audioTrackReplacePromise, videoTrackReplacePromise]).then(() => this._createAO('offer', this.handleId, false)).then(jsep => {\n if (!jsep) {\n return null;\n }\n //HOTFIX: Temporary fix for Safari 13\n if (jsep.sdp && jsep.sdp.indexOf(\"\\r\\na=ice-ufrag\") === -1) {\n jsep.sdp = jsep.sdp.replace(\"\\na=ice-ufrag\", \"\\r\\na=ice-ufrag\");\n }\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"configure\",\n \"audio\": hasAudio,\n \"video\": hasVideo,\n \"data\": true,\n ...(this.recordingFilename ? {\n filename: this.recordingFilename\n } : {})\n },\n jsep\n });\n }).then(r => {\n if (this._isDataChannelOpen) {\n return Promise.resolve(r);\n } else {\n return new Promise((resolve, reject) => {\n let dataChannelTimeoutId = null;\n let _resolve = val => {\n if (val) {\n clearTimeout(dataChannelTimeoutId);\n this._abortController.signal.removeEventListener('abort', _rejectAbort);\n this.off('dataChannel', _resolve, this);\n resolve(this);\n }\n };\n let _rejectTimeout = () => {\n this.off('dataChannel', _resolve, this);\n this._abortController.signal.removeEventListener('abort', _rejectAbort);\n reject({\n type: 'error',\n id: 27,\n message: 'Data channel did not open',\n data: null\n });\n };\n let _rejectAbort = () => {\n this._abortController.signal.removeEventListener('abort', _rejectAbort);\n clearTimeout(dataChannelTimeoutId);\n this.off('dataChannel', _resolve, this);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled'\n });\n };\n dataChannelTimeoutId = setTimeout(_rejectTimeout, 5000);\n this._abortController.signal.addEventListener('abort', _rejectAbort);\n this.on('dataChannel', _resolve, this);\n });\n }\n }).then(r => {\n this.isPublished = true;\n if (config.stream) {\n let tracks = config.stream.getTracks();\n tracks.forEach(track => {\n // used as a flag to not emit tracks that been already emitted\n if (!track.onended) {\n var _decodeJanusDisplay21, _decodeJanusDisplay22;\n this.emit('addLocalParticipant', {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay21 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay21 === void 0 ? void 0 : _decodeJanusDisplay21.userId,\n role: (_decodeJanusDisplay22 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display)) === null || _decodeJanusDisplay22 === void 0 ? void 0 : _decodeJanusDisplay22.role,\n track,\n stream: config.stream,\n adding: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: hasAudio,\n hasVideoTrack: hasVideo\n });\n track.onended = ev => {\n var _decodeJanusDisplay23, _decodeJanusDisplay24;\n this.emit('addLocalParticipant', {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay23 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay23 === void 0 ? void 0 : _decodeJanusDisplay23.userId,\n role: (_decodeJanusDisplay24 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display)) === null || _decodeJanusDisplay24 === void 0 ? void 0 : _decodeJanusDisplay24.role,\n track: ev.target,\n stream: config.stream,\n adding: false,\n removing: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: hasAudio,\n hasVideoTrack: hasVideo\n });\n };\n }\n });\n } else {\n var _decodeJanusDisplay25, _decodeJanusDisplay26;\n this.emit('addLocalParticipant', {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay25 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay25 === void 0 ? void 0 : _decodeJanusDisplay25.userId,\n role: (_decodeJanusDisplay26 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display)) === null || _decodeJanusDisplay26 === void 0 ? void 0 : _decodeJanusDisplay26.role,\n stream: null,\n adding: false,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: hasAudio,\n hasVideoTrack: hasVideo\n });\n }\n this.emit('published', {\n status: true,\n hasStream: !!config.stream\n });\n this.emit('publishing', false);\n this.emit('localHasVideo', hasVideo);\n this.emit('localHasAudio', hasAudio);\n this.emit('localMuted', {\n type: 'video',\n value: isVideoMuted\n });\n this.emit('localMuted', {\n type: 'audio',\n value: isAudioMuted\n });\n return r;\n }).catch(e => {\n this.emit('publishing', false);\n return Promise.reject(e);\n });\n }\n unpublishLocal() {\n let dontWait = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n return this.isPublished ? this.sendMessage(this.handleId, {\n body: {\n \"request\": \"unpublish\"\n }\n }, dontWait).finally(r => {\n this.isPublished = false;\n this.emit('published', {\n status: false,\n hasStream: false\n });\n return r;\n }) : Promise.resolve();\n }\n toggleAudio() {\n let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let mid = arguments.length > 1 ? arguments[1] : undefined;\n let handle = this._getHandle(this.handleId);\n if (!handle) {\n return Promise.reject({\n type: 'error',\n id: 21,\n message: 'no local id, connect first',\n data: null\n });\n }\n let config = handle.webrtcStuff;\n let transceiver = config.pc.getTransceivers().find(t => t.sender && t.sender.track && t.receiver.track.kind === \"audio\" && (mid ? t.mid === mid : true));\n if (transceiver) {\n transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;\n }\n this.isAudioMuted = !transceiver || !transceiver.sender.track.enabled;\n\n // if (config.stream && config.stream.getAudioTracks().length) {\n // \tconfig.stream.getAudioTracks()[0].enabled = value !== null ? !!value : !config.stream.getAudioTracks()[0].enabled;\n // }\n // this.isAudioMuted = config.stream.getAudioTracks().length === 0 || !config.stream.getAudioTracks()[0].enabled;\n //\n\n this.emit('localMuted', {\n type: 'audio',\n value: this.isAudioMuted,\n mid\n });\n }\n toggleVideo() {\n let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let mid = arguments.length > 1 ? arguments[1] : undefined;\n let handle = this._getHandle(this.handleId);\n if (!handle) {\n return Promise.reject({\n type: 'error',\n id: 21,\n message: 'no local id, connect first',\n data: null\n });\n }\n let config = handle.webrtcStuff;\n let transceiver = config.pc.getTransceivers().find(t => t.sender && t.sender.track && t.receiver.track.kind === \"video\" && (mid ? t.mid === mid : true));\n if (transceiver) {\n transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;\n }\n this.isVideoMuted = !transceiver || !transceiver.sender.track.enabled;\n\n // if (config.stream && config.stream.getVideoTracks().length) {\n // \tconfig.stream.getVideoTracks()[0].enabled = value !== null ? !!value : !config.stream.getVideoTracks()[0].enabled;\n // }\n // this.isVideoMuted = config.stream.getVideoTracks().length === 0 || !config.stream.getVideoTracks()[0].enabled;\n\n this.emit('localMuted', {\n type: 'video',\n value: this.isVideoMuted,\n mid\n });\n }\n selectSubStream(handleId) {\n let substream = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;\n this.sendMessage(this.handleId, {\n \"body\": {\n \"request\": \"configure\",\n \"substream\": substream\n }\n }).catch(() => null);\n }\n setRoomType() {\n let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'watchparty';\n this._roomType = type;\n return this._roomType;\n }\n}\n_defineProperty(RoomSession, \"sessionTypes\", {\n 'reactooroom': 'janus.plugin.reactooroom',\n 'streaming': 'janus.plugin.streaming'\n});\n_defineProperty(RoomSession, \"subscriptionRules\", {\n participant: {\n \"watchparty\": ['participant', 'talkback'],\n \"studio\": ['participant', 'talkback', 'host', 'observer'],\n \"commentary\": ['participant', 'talkback', 'host'],\n \"videowall\": ['host', 'talkback', 'observer', 'observerSolo1', 'observerSolo2', 'observerSolo3'],\n \"videowall-queue\": ['host', 'talkback', 'observer', 'observerSolo1', 'observerSolo2', 'observerSolo3'],\n \"videowall-queue-video\": ['host', 'talkback', 'observer', 'observerSolo1', 'observerSolo2', 'observerSolo3']\n },\n monitor: {\n \"watchparty\": ['participant', 'host'],\n \"studio\": ['participant', 'host'],\n \"commentary\": ['participant', 'host'],\n \"videowall\": ['host', 'participant'],\n \"videowall-queue\": ['host', 'participant'],\n \"videowall-queue-video\": ['host', 'participant']\n },\n talkback: {\n \"watchparty\": ['participant', 'host'],\n \"studio\": ['participant', 'host'],\n \"commentary\": ['host', 'participant'],\n \"videowall\": ['host', 'participant'],\n \"videowall-queue\": ['host', 'participant'],\n \"videowall-queue-video\": ['host', 'participant']\n },\n observer: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n observerSolo1: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n observerSolo2: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n observerSolo3: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n host: {\n \"watchparty\": [],\n \"studio\": [],\n \"commentary\": [],\n \"videowall\": [],\n \"videowall-queue\": [],\n \"videowall-queue-video\": []\n },\n companionTV: {},\n companionPhone: {}\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (Room);\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/modules/wt-room.js?");
|
|
9498
|
+
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! webrtc-adapter */ \"./node_modules/webrtc-adapter/src/js/adapter_core.js\");\n/* harmony import */ var _wt_emitter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./wt-emitter */ \"./src/modules/wt-emitter.js\");\n/* harmony import */ var _wt_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./wt-utils */ \"./src/modules/wt-utils.js\");\nfunction _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }\n// Watch together janus webrtc library\n\n\n\n\nclass Room {\n constructor(debug) {\n this.debug = debug;\n this.sessions = [];\n this.safariVp8 = false;\n this.browser = webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser;\n this.browserDetails = webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails;\n this.webrtcSupported = Room.isWebrtcSupported();\n this.safariVp8TestPromise = Room.testSafariVp8();\n this.safariVp8 = null;\n this.safariVp8TestPromise.then(safariVp8 => {\n this.safariVp8 = safariVp8;\n });\n\n // Let's get it started\n this.whenInitialized = this.initialize();\n }\n initialize() {\n return this.safariVp8TestPromise.then(() => this);\n }\n createSession() {\n let constructId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'reactooroom';\n let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n return new RoomSession(constructId, type, {\n debug: this.debug,\n ...options\n });\n }\n static testSafariVp8() {\n return new Promise(resolve => {\n if (webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser === 'safari' && webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.version >= 605) {\n if (RTCRtpSender && RTCRtpSender.getCapabilities && RTCRtpSender.getCapabilities(\"video\") && RTCRtpSender.getCapabilities(\"video\").codecs && RTCRtpSender.getCapabilities(\"video\").codecs.length) {\n var isVp8 = false;\n for (var i in RTCRtpSender.getCapabilities(\"video\").codecs) {\n var codec = RTCRtpSender.getCapabilities(\"video\").codecs[i];\n if (codec && codec.mimeType && codec.mimeType.toLowerCase() === \"video/vp8\") {\n isVp8 = true;\n break;\n }\n }\n resolve(isVp8);\n } else {\n // We do it in a very ugly way, as there's no alternative...\n // We create a PeerConnection to see if VP8 is in an offer\n var testpc = new RTCPeerConnection({}, {});\n testpc.createOffer({\n offerToReceiveVideo: true\n }).then(function (offer) {\n let result = offer.sdp.indexOf(\"VP8\") !== -1;\n testpc.close();\n testpc = null;\n resolve(result);\n });\n }\n } else resolve(false);\n });\n }\n static isWebrtcSupported() {\n return window.RTCPeerConnection !== undefined && window.RTCPeerConnection !== null && navigator.mediaDevices !== undefined && navigator.mediaDevices !== null && navigator.mediaDevices.getUserMedia !== undefined && navigator.mediaDevices.getUserMedia !== null;\n }\n}\nclass RoomSession {\n static noop() {}\n static randomString(len) {\n var charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n var randomString = '';\n for (var i = 0; i < len; i++) {\n var randomPoz = Math.floor(Math.random() * charSet.length);\n randomString += charSet.substring(randomPoz, randomPoz + 1);\n }\n return randomString;\n }\n\n //TODO: solve\n // #eventList = ['error', 'kicked', 'addLocalParticipant', ,'addRemoteInstructor','addRemoteParticipant','addRemoteTalkback', 'addRemoteObserver', 'removeRemoteInstructor', 'removeLocalParticipant', 'removeRemoteParticipant', 'removeRemoteTalkback', 'removeRemoteObserver', 'localMuted', 'localHasVideo', 'localHasAudio', 'data', 'iceState', 'connectionState', 'joined', 'joining', 'dataChannel', 'disconnect', 'observerIds', 'talkbackIds', 'instructorId', 'published', 'publishing', 'remoteTrackMuted', 'streamingStatus', 'streaming', 'streamStarting'];\n //\n\n constructor() {\n let constructId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'reactooroom';\n let options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n Object.assign(this, Object(_wt_emitter__WEBPACK_IMPORTED_MODULE_1__[\"default\"])());\n this.options = {\n ...options\n };\n this.defaultDataChannelLabel = 'JanusDataChannel';\n this.server = null;\n this.iceServers = null;\n this.token = null;\n this.roomId = null;\n this.streamId = null;\n this.pin = null;\n this.userId = null;\n this.sessiontype = type;\n this.initialBitrate = 0;\n this.simulcast = false;\n this.simulcastBitrates = {\n high: 900000,\n medium: 300000,\n low: 100000\n };\n this.recordingFilename = null;\n this.pluginName = RoomSession.sessionTypes[type];\n this.id = null;\n this.privateId = null;\n this.constructId = constructId || RoomSession.randomString(16);\n this.sessionId = null;\n this.handleId = null;\n this.ws = null;\n this.isRestarting = false;\n this.isConnecting = false;\n this.isDisconnecting = false;\n this.isConnected = false;\n this.isPublished = false;\n this.isReclaiming = false;\n this.isStreaming = false;\n this._retries = 0;\n this._maxRetries = 3;\n this._keepAliveId = null;\n this._participants = [];\n this._roomType = 'watchparty';\n this._isDataChannelOpen = false;\n this._abortController = null;\n this.isAudioMuted = false;\n this.isVideoMuted = false;\n this.isVideoEnabled = false;\n this.isAudioEnabed = false;\n this.subscriptionRules = {\n ...RoomSession.subscriptionRules,\n ...(this.options.subscriptionRules || {})\n };\n this._log = RoomSession.noop;\n if (this.options.debug) {\n this._enableDebug();\n }\n }\n _participantShouldSubscribe(userId) {\n const myUser = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display);\n const remoteUser = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(userId);\n let localUserRole = (myUser === null || myUser === void 0 ? void 0 : myUser.role) || 'participant';\n let remoteUserRole = (remoteUser === null || remoteUser === void 0 ? void 0 : remoteUser.role) || 'participant';\n return this.subscriptionRules[localUserRole][this._roomType || 'watchparty'].indexOf(remoteUserRole) > -1;\n }\n _getAddParticipantEventName(handleId) {\n var _decodeJanusDisplay;\n let handle = this._getHandle(handleId);\n if (!handle) {\n this.emit('error', {\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'getParticipantEventName']\n });\n }\n const participantRole = (_decodeJanusDisplay = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay === void 0 ? void 0 : _decodeJanusDisplay.role;\n switch (participantRole) {\n case 'participant':\n return 'addRemoteParticipant';\n case 'talkback':\n return 'addRemoteTalkback';\n case 'monitor':\n return 'addRemoteTalkback';\n case 'observer':\n case 'observerSolo1':\n case 'observerSolo2':\n case 'observerSolo3':\n return 'addRemoteObserver';\n case 'host':\n return 'addRemoteInstructor';\n case 'companionTV':\n return 'addRemoteCompanionTV';\n case 'companionPhone':\n return 'addRemoteCompanionPhone';\n default:\n return 'addRemoteParticipant';\n }\n }\n _getRemoveParticipantEventName(handleId) {\n var _decodeJanusDisplay2;\n let handle = this._getHandle(handleId);\n if (!handle) {\n this.emit('error', {\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'getParticipantEventName']\n });\n }\n const participantRole = (_decodeJanusDisplay2 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay2 === void 0 ? void 0 : _decodeJanusDisplay2.role;\n switch (participantRole) {\n case 'participant':\n return 'removeRemoteParticipant';\n case 'talkback':\n return 'removeRemoteTalkback';\n case 'monitor':\n return 'removeRemoteTalkback';\n case 'observer':\n case 'observerSolo1':\n case 'observerSolo2':\n case 'observerSolo3':\n return 'removeRemoteObserver';\n case 'host':\n return 'removeRemoteInstructor';\n case 'companionTV':\n return 'removeRemoteCompanionTV';\n case 'companionPhone':\n return 'removeRemoteCompanionPhone';\n default:\n return 'removeRemoteParticipant';\n }\n }\n sendMessage(handleId) {\n let message = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {\n body: 'Example Body'\n };\n let dontWait = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let dontResolveOnAck = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n return this._send({\n \"janus\": \"message\",\n \"handle_id\": handleId,\n ...message\n }, dontWait, dontResolveOnAck).then(json => {\n if (json && json[\"janus\"] === \"success\") {\n let plugindata = json[\"plugindata\"] || {};\n let data = plugindata[\"data\"];\n return Promise.resolve(data);\n }\n return Promise.resolve();\n }).catch(json => {\n if (json && json[\"error\"]) {\n return Promise.reject({\n type: 'warning',\n id: 1,\n message: 'sendMessage failed',\n data: json[\"error\"]\n });\n } else {\n return Promise.reject({\n type: 'warning',\n id: 1,\n message: 'sendMessage failed',\n data: json\n });\n }\n });\n }\n _send() {\n let request = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n let ignoreResponse = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n let dontResolveOnAck = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let transaction = RoomSession.randomString(12);\n let requestData = {\n ...request,\n transaction,\n token: this.token,\n ...(this.sessionId && {\n 'session_id': this.sessionId\n } || {})\n };\n this._log(requestData);\n return new Promise((resolve, reject) => {\n let messageTimeoutId = null;\n let abortResponse = () => {\n this._abortController.signal.removeEventListener('abort', abortResponse);\n clearTimeout(messageTimeoutId);\n this.ws.removeEventListener('message', parseResponse);\n reject({\n type: 'warning',\n id: 17,\n message: 'connection cancelled'\n });\n };\n let parseResponse = event => {\n let json = JSON.parse(event.data);\n let r_transaction = json['transaction'];\n if (r_transaction === transaction && (!dontResolveOnAck || json['janus'] !== 'ack')) {\n clearTimeout(messageTimeoutId);\n this._abortController.signal.removeEventListener('abort', abortResponse);\n this.ws.removeEventListener('message', parseResponse);\n if (json['janus'] === 'error') {\n var _json$error;\n if ((json === null || json === void 0 ? void 0 : (_json$error = json.error) === null || _json$error === void 0 ? void 0 : _json$error.code) == 403) {\n this.disconnect(true);\n }\n reject({\n type: 'error',\n id: 2,\n message: 'send failed',\n data: json,\n requestData\n });\n } else {\n resolve(json);\n }\n }\n };\n if (ignoreResponse) {\n if (this.ws && this.ws.readyState === 1) {\n this.ws.send(JSON.stringify(requestData));\n }\n resolve();\n } else {\n if (this.ws && this.ws.readyState === 1) {\n this.ws.addEventListener('message', parseResponse);\n messageTimeoutId = setTimeout(() => {\n this.ws.removeEventListener('message', parseResponse);\n this._abortController.signal.removeEventListener('abort', abortResponse);\n reject({\n type: 'error',\n id: 3,\n message: 'send timeout',\n data: requestData\n });\n }, 10000);\n this._abortController.signal.addEventListener('abort', abortResponse);\n this.ws.send(JSON.stringify(requestData));\n } else {\n reject({\n type: 'warning',\n id: 29,\n message: 'No connection to WebSockets',\n data: requestData\n });\n }\n }\n });\n }\n _connectionClosed() {\n if (!this.isConnected || this.isConnecting || this.isDisconnecting) {\n return;\n }\n if (this._retries < this._maxRetries) {\n setTimeout(() => {\n this._retries++;\n this._reconnect().catch(e => {\n this.emit('error', e);\n });\n }, 3000 * this._retries);\n } else {\n if (this.sessiontype === 'reactooroom') {\n this.disconnect(true);\n } else if (this.sessiontype === 'streaming') {\n this.stopStream();\n }\n this.emit('error', {\n type: 'error',\n id: 4,\n message: 'Lost connection to WebSockets',\n data: null\n });\n }\n }\n _wipeListeners() {\n if (this.ws) {\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n }\n }\n _startKeepAlive() {\n this._send({\n \"janus\": \"keepalive\"\n }).then(json => {\n if (json[\"janus\"] !== 'ack') {\n this.emit('error', {\n type: 'warning',\n id: 5,\n message: 'keepalive response suspicious',\n data: json[\"janus\"]\n });\n }\n }).catch(e => {\n this.emit('error', {\n type: 'warning',\n id: 6,\n message: 'keepalive dead',\n data: e\n });\n this._connectionClosed();\n });\n this._keepAliveId = setTimeout(() => {\n this._startKeepAlive();\n }, 30000);\n }\n _stopKeepAlive() {\n clearTimeout(this._keepAliveId);\n }\n _handleWsEvents(event) {\n let json = JSON.parse(event.data);\n var sender = json[\"sender\"];\n var type = json[\"janus\"];\n let handle = this._getHandle(sender);\n if (!handle) {\n return;\n }\n if (type === \"trickle\") {\n let candidate = json[\"candidate\"];\n let config = handle.webrtcStuff;\n if (config.pc && config.remoteSdp) {\n if (!candidate || candidate.completed === true) {\n config.pc.addIceCandidate(null);\n } else {\n config.pc.addIceCandidate(candidate);\n }\n } else {\n if (!config.candidates) {\n config.candidates = [];\n }\n config.candidates.push(candidate);\n }\n } else if (type === \"webrtcup\") {\n //none universal\n } else if (type === \"hangup\") {\n this._log('hangup on', handle.handleId);\n this._removeParticipant(handle.handleId, null, false);\n } else if (type === \"detached\") {\n this._log('detached on', handle.handleId);\n this._removeParticipant(handle.handleId, null, true);\n } else if (type === \"media\") {\n this._log('Media event:', handle.handleId, json[\"type\"], json[\"receiving\"], json[\"mid\"]);\n } else if (type === \"slowlink\") {\n this._log('Slowlink', handle.handleId, json[\"uplink\"], json[\"lost\"], json[\"mid\"]);\n } else if (type === \"event\") {\n //none universal\n } else if (type === 'timeout') {\n this.ws.close(3504, \"Gateway timeout\");\n } else if (type === 'success' || type === 'error') {\n // we're capturing those elsewhere\n } else {\n this._log(`Unknown event: ${type} on session: ${this.sessionId}`);\n }\n\n // LOCAL\n\n if (sender === this.handleId) {\n if (type === \"event\") {\n var plugindata = json[\"plugindata\"] || {};\n var msg = plugindata[\"data\"] || {};\n var jsep = json[\"jsep\"];\n let result = msg[\"result\"] || null;\n let event = msg[\"videoroom\"] || null;\n let list = msg[\"publishers\"] || {};\n let leaving = msg[\"leaving\"];\n let kicked = msg[\"kicked\"];\n\n //let joining = msg[\"joining\"];\n let unpublished = msg[\"unpublished\"];\n let error = msg[\"error\"];\n if (event === \"joined\") {\n this.id = msg[\"id\"];\n this.privateId = msg[\"private_id\"];\n this.isConnected = true;\n this.emit('joined', true);\n this._log('We have successfully joined Room');\n for (let f in list) {\n let userId = list[f][\"display\"];\n let streams = list[f][\"streams\"] || [];\n let id = list[f][\"id\"];\n for (let i in streams) {\n streams[i][\"id\"] = id;\n streams[i][\"display\"] = userId;\n }\n this._log('Remote userId: ', userId);\n if (this._participantShouldSubscribe(userId)) {\n this._log('Creating user: ', userId);\n this._createParticipant(userId, id).then(handle => {\n return this.sendMessage(handle.handleId, {\n body: {\n \"request\": \"join\",\n \"room\": this.roomId,\n \"ptype\": \"subscriber\",\n streams: streams.map(stream => ({\n feed: stream.id,\n mid: stream.mid\n })),\n //\"feed\": id,\n \"private_id\": this.privateId,\n ...(this.webrtcVersion > 1000 ? {\n id: this.userId\n } : {}),\n pin: this.pin\n }\n });\n }).catch(err => {\n this.emit('error', err);\n });\n }\n }\n } else if (event === \"event\") {\n if (msg[\"streams\"] !== undefined && msg[\"streams\"] !== null) {\n this._log('Got my own streams back', msg[\"streams\"]);\n }\n for (let f in list) {\n let userId = list[f][\"display\"];\n let streams = list[f][\"streams\"] || [];\n let id = list[f][\"id\"];\n for (let i in streams) {\n streams[i][\"id\"] = id;\n streams[i][\"display\"] = userId;\n }\n this._log('Remote userId: ', userId);\n if (this._participantShouldSubscribe(userId)) {\n this._log('Creating user: ', userId);\n this._createParticipant(userId, id).then(handle => {\n return this.sendMessage(handle.handleId, {\n body: {\n \"request\": \"join\",\n \"room\": this.roomId,\n \"ptype\": \"subscriber\",\n streams: streams.map(stream => ({\n feed: stream.id,\n mid: stream.mid\n })),\n \"private_id\": this.privateId,\n ...(this.webrtcVersion > 1000 ? {\n id: this.userId\n } : {}),\n pin: this.pin\n }\n });\n }).catch(err => {\n this.emit('error', err);\n });\n }\n }\n if (leaving === 'ok') {\n this._log('leaving', this.handleId, 'this is us');\n this._removeParticipant(this.handleId);\n if (msg['reason'] === 'kicked') {\n this.emit('kicked');\n this.disconnect().catch(() => {});\n }\n } else if (leaving) {\n //TODO: shouldnt we detach?\n this._log('leaving', leaving);\n this._removeParticipant(null, leaving, true);\n }\n if (unpublished === 'ok') {\n this._log('unpublished', this.handleId, 'this is us');\n this._removeParticipant(this.handleId, null, false); // we do just hangup\n } else if (unpublished) {\n this._log('unpublished', unpublished);\n this._removeParticipant(null, unpublished, true); // we do hangup and detach\n }\n\n if (kicked === 'ok') {\n // this case shouldn't exist\n } else if (kicked) {\n this._log('kicked', kicked);\n this._removeParticipant(null, kicked, true); // we do hangup and detach\n }\n\n if (error) {\n this.emit('error', {\n type: 'error',\n id: 7,\n message: 'local participant error',\n data: [sender, msg]\n });\n }\n }\n\n // Streaming related\n else if (result && result[\"status\"]) {\n this.emit('streamingStatus', result[\"status\"]);\n if (result[\"status\"] === 'stopped') {\n this.stopStream();\n }\n if (result[\"status\"] === 'started') {\n this.emit('streaming', true);\n this.isStreaming = true;\n }\n }\n if (jsep !== undefined && jsep !== null) {\n if (this.sessiontype === 'reactooroom') {\n this._webrtcPeer(this.handleId, jsep).catch(err => {\n this.emit('error', err);\n });\n } else if (this.sessiontype === 'streaming') {\n this._publishRemote(this.handleId, jsep).catch(err => {\n this.emit('error', err);\n });\n }\n }\n } else if (type === \"webrtcup\") {\n if (this.simulcast) {\n return;\n }\n this._log('Configuring bitrate: ' + this.initialBitrate);\n if (this.initialBitrate > 0) {\n this.sendMessage(this.handleId, {\n \"body\": {\n \"request\": \"configure\",\n \"bitrate\": this.initialBitrate\n }\n }).catch(() => null);\n }\n }\n }\n\n //REMOTE\n else {\n let plugindata = json[\"plugindata\"] || {};\n let msg = plugindata[\"data\"] || {};\n let jsep = json[\"jsep\"];\n let event = msg[\"videoroom\"];\n let error = msg[\"error\"];\n let substream = msg[\"substream\"];\n if (event === \"attached\") {\n var _decodeJanusDisplay3, _decodeJanusDisplay4;\n this._log('Remote have successfully joined Room', msg);\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay3 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay3 === void 0 ? void 0 : _decodeJanusDisplay3.userId,\n role: (_decodeJanusDisplay4 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay4 === void 0 ? void 0 : _decodeJanusDisplay4.role,\n stream: null,\n track: null,\n adding: false,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: false,\n hasVideoTrack: false\n });\n }\n if (error) {\n this.emit('error', {\n type: 'warning',\n id: 8,\n message: 'remote participant error',\n data: [sender, msg]\n });\n }\n if (jsep) {\n this._publishRemote(handle.handleId, jsep).catch(err => {\n this.emit('error', err);\n });\n }\n }\n }\n _handleDataEvents(handleId, type, data) {\n let handle = this._getHandle(handleId);\n if (type === 'state') {\n this._log(` - Data channel status - `, `UID: ${handleId}`, `STATUS: ${JSON.stringify(data)}`, `ME: ${handleId === this.handleId}`);\n if (handle) {\n let config = handle.webrtcStuff;\n config.dataChannelOpen = this.defaultDataChannelLabel === (data === null || data === void 0 ? void 0 : data.label) && (data === null || data === void 0 ? void 0 : data.state) === 'open';\n }\n if (handleId === this.handleId && this.defaultDataChannelLabel === (data === null || data === void 0 ? void 0 : data.label)) {\n this._isDataChannelOpen = (data === null || data === void 0 ? void 0 : data.state) === 'open';\n this.emit('dataChannel', (data === null || data === void 0 ? void 0 : data.state) === 'open');\n }\n }\n if (type === 'error') {\n this.emit('error', {\n type: 'warning',\n id: 9,\n message: 'data event warning',\n data: [handleId, data]\n });\n if (handle) {\n let config = handle.webrtcStuff;\n if (this.defaultDataChannelLabel === data.label) {\n config.dataChannelOpen = false;\n }\n }\n if (handleId === this.handleId && this.defaultDataChannelLabel === data.label) {\n this._isDataChannelOpen = false;\n this.emit('dataChannel', false);\n }\n }\n if (handleId === this.handleId && type === 'message') {\n let d = null;\n try {\n d = JSON.parse(data);\n } catch (e) {\n this.emit('error', {\n type: 'warning',\n id: 10,\n message: 'data message parse error',\n data: [handleId, e]\n });\n return;\n }\n this.emit('data', d);\n }\n }\n\n //removeHandle === true -> hangup, detach, removeHandle === false -> hangup\n _removeParticipant(handleId, rfid) {\n let removeHandle = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n let handle = this._getHandle(handleId, rfid);\n if (!handle) {\n return Promise.resolve();\n } else {\n handleId = handle.handleId;\n }\n return this._send({\n \"janus\": \"hangup\",\n \"handle_id\": handleId\n }, true).then(() => removeHandle ? this._send({\n \"janus\": \"detach\",\n \"handle_id\": handleId\n }, true) : Promise.resolve()).finally(() => {\n try {\n if (handle.webrtcStuff.stream) {\n if (!this.isRestarting) {\n handle.webrtcStuff.stream.getTracks().forEach(track => track.stop());\n } else {\n handle.webrtcStuff.stream.getTracks().forEach(track => track.onended = null);\n }\n }\n } catch (e) {\n // Do nothing\n }\n handle.webrtcStuff.stream = null;\n if (handle.webrtcStuff.dataChannel) {\n Object.keys(handle.webrtcStuff.dataChannel).forEach(label => {\n handle.webrtcStuff.dataChannel[label].onmessage = null;\n handle.webrtcStuff.dataChannel[label].onopen = null;\n handle.webrtcStuff.dataChannel[label].onclose = null;\n handle.webrtcStuff.dataChannel[label].onerror = null;\n });\n }\n if (handle.webrtcStuff.pc) {\n handle.webrtcStuff.pc.onicecandidate = null;\n handle.webrtcStuff.pc.ontrack = null;\n handle.webrtcStuff.pc.ondatachannel = null;\n handle.webrtcStuff.pc.onconnectionstatechange = null;\n handle.webrtcStuff.pc.oniceconnectionstatechange = null;\n }\n try {\n handle.webrtcStuff.pc.close();\n } catch (e) {}\n handle.webrtcStuff = {\n stream: null,\n mySdp: null,\n mediaConstraints: null,\n pc: null,\n dataChannelOpen: false,\n dataChannel: null,\n dtmfSender: null,\n trickle: true,\n iceDone: false\n };\n if (handleId === this.handleId) {\n var _decodeJanusDisplay5, _decodeJanusDisplay6;\n this._isDataChannelOpen = false;\n this.isPublished = false;\n this.emit('published', {\n status: false,\n hasStream: false\n });\n this.emit('removeLocalParticipant', {\n id: handleId,\n userId: (_decodeJanusDisplay5 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay5 === void 0 ? void 0 : _decodeJanusDisplay5.userId,\n role: (_decodeJanusDisplay6 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay6 === void 0 ? void 0 : _decodeJanusDisplay6.role\n });\n } else {\n var _decodeJanusDisplay7, _decodeJanusDisplay8;\n this.emit(this._getRemoveParticipantEventName(handleId), {\n id: handleId,\n userId: (_decodeJanusDisplay7 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay7 === void 0 ? void 0 : _decodeJanusDisplay7.userId,\n role: (_decodeJanusDisplay8 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay8 === void 0 ? void 0 : _decodeJanusDisplay8.role\n });\n }\n if (removeHandle) {\n let handleIndex = this._participants.findIndex(p => p.handleId === handleId);\n this._participants.splice(handleIndex, 1);\n }\n return true;\n });\n }\n _createParticipant() {\n let userId = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let rfid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n return this._send({\n \"janus\": \"attach\",\n \"plugin\": this.pluginName\n }).then(json => {\n let handleId = json.data[\"id\"];\n let handle = {\n handleId,\n rfid,\n userId,\n webrtcStuff: {\n stream: null,\n mySdp: null,\n mediaConstraints: null,\n pc: null,\n dataChannelOpen: false,\n dataChannel: null,\n dtmfSender: null,\n trickle: true,\n iceDone: false,\n isIceRestarting: false\n }\n };\n this._participants.push(handle);\n return handle;\n });\n }\n _joinRoom(roomId, pin, userId, display) {\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"join\",\n \"room\": roomId,\n \"pin\": pin,\n \"ptype\": \"publisher\",\n \"display\": display,\n ...(this.webrtcVersion > 1000 ? {\n id: userId\n } : {})\n }\n }, false, true);\n }\n _watchStream(id) {\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"watch\",\n id: parseInt(id)\n }\n }, false, true);\n }\n _leaveRoom() {\n let dontWait = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n return this.isConnected ? this.sendMessage(this.handleId, {\n body: {\n \"request\": \"leave\"\n }\n }, dontWait).finally(() => {\n this.isConnected = false;\n this.emit('joined', false);\n }) : Promise.resolve();\n }\n\n // internal reconnect\n\n _reconnect() {\n if (this.isReclaiming) {\n return Promise.resolve();\n }\n if (this.ws) {\n this._wipeListeners();\n if (this.ws.readyState === 1) {\n this.ws.close();\n }\n }\n this._stopKeepAlive();\n this.isReclaiming = true;\n this.emit('joining', true);\n return new Promise((resolve, reject) => {\n let abortReconnect = () => {\n this._abortController.signal.removeEventListener('abort', abortReconnect);\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.isReclaiming = false;\n this.emit('joining', false);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled',\n data: e\n });\n };\n this.ws = new WebSocket(this.server, 'janus-protocol');\n this.__connectionClosedBoundFn = this._connectionClosed.bind(this);\n this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);\n this.ws.addEventListener('close', this.__connectionClosedBoundFn);\n this.ws.addEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = () => {\n this._abortController.signal.removeEventListener('abort', abortReconnect);\n this._send({\n \"janus\": \"claim\"\n }).then(json => {\n this.sessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n this._startKeepAlive();\n this.isReclaiming = false;\n this.emit('joining', false);\n this._retries = 0;\n resolve(json);\n }).catch(error => {\n this.isReclaiming = false;\n this.emit('joining', false);\n reject({\n type: 'error',\n id: 11,\n message: 'reconnection error',\n data: error\n });\n });\n };\n\n // this is called before 'close' event callback so it doesn't break reconnect loop\n this.ws.onerror = e => {\n this._abortController.signal.removeEventListener('abort', abortReconnect);\n this.isReclaiming = false;\n this.emit('joining', false);\n reject({\n type: 'warning',\n id: 12,\n message: 'ws reconnection error',\n data: e\n });\n };\n this._abortController.signal.addEventListener('abort', abortReconnect);\n });\n }\n connect(roomId, pin, server, iceServers, token, display, userId) {\n let webrtcVersion = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 0;\n let initialBitrate = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : 0;\n let recordingFilename = arguments.length > 9 ? arguments[9] : undefined;\n let simulcast = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : false;\n let simulcastBitrates = arguments.length > 11 && arguments[11] !== undefined ? arguments[11] : {};\n if (this.isConnecting) {\n return Promise.reject({\n type: 'warning',\n id: 16,\n message: 'connection already in progress'\n });\n }\n if (this.ws) {\n this._wipeListeners();\n }\n this._stopKeepAlive();\n this._abortController = new AbortController();\n this.sessionId = null;\n this.server = server;\n this.iceServers = iceServers;\n this.token = token;\n this.roomId = roomId;\n this.pin = pin;\n this.display = display;\n this.userId = userId;\n this.webrtcVersion = webrtcVersion;\n this.initialBitrate = initialBitrate;\n this.recordingFilename = recordingFilename;\n this.isConnecting = true;\n this.simulcast = simulcast;\n this.simulcastBitrates = {\n ...this.simulcastBitrates,\n ...simulcastBitrates\n };\n this.emit('joining', true);\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.server, 'janus-protocol');\n this.__connectionClosedBoundFn = this._connectionClosed.bind(this);\n this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);\n let abortConnect = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.isConnecting = false;\n this.emit('joining', false);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled'\n });\n };\n this.ws.addEventListener('close', this.__connectionClosedBoundFn);\n this.ws.addEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this._retries = 0;\n this._send({\n \"janus\": \"create\"\n }).then(json => {\n this.sessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n this._startKeepAlive();\n return 1;\n }).then(() => this._createParticipant(userId)).then(handle => {\n this.handleId = handle.handleId;\n return 1;\n }).then(() => this._joinRoom(roomId, pin, userId, display)).then(() => {\n this.isConnecting = false;\n this.emit('joining', false);\n resolve(this);\n }).catch(error => {\n this.isConnecting = false;\n this.emit('joining', false);\n reject({\n type: (error === null || error === void 0 ? void 0 : error.type) === 'warning' ? 'warning' : 'error',\n id: 13,\n message: 'connection error',\n data: error\n });\n });\n };\n this.ws.onerror = e => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.isConnecting = false;\n this.emit('joining', false);\n reject({\n type: 'error',\n id: 14,\n message: 'ws connection error',\n data: e\n });\n };\n this._abortController.signal.addEventListener('abort', abortConnect);\n });\n }\n disconnect() {\n var _this$_abortControlle, _this$_abortControlle2;\n if (this.isDisconnecting) {\n return Promise.resolve();\n }\n (_this$_abortControlle = this._abortController) === null || _this$_abortControlle === void 0 ? void 0 : (_this$_abortControlle2 = _this$_abortControlle.abort) === null || _this$_abortControlle2 === void 0 ? void 0 : _this$_abortControlle2.call(_this$_abortControlle);\n this._stopKeepAlive();\n let isConnected = this.isConnected;\n this.isDisconnecting = true;\n return Promise.all(this._participants.map(p => this._removeParticipant(p.handleId))).finally(() => {\n this._wipeListeners();\n if (this.ws && this.ws.readyState === 1) {\n this._send({\n \"janus\": \"destroy\"\n }, true);\n this.ws.close();\n }\n this.sessionId = null;\n this.isPublished = false;\n this.isConnected = false;\n this.isDisconnecting = false;\n this.emit('publishing', false);\n this.emit('published', {\n status: false,\n hasStream: false\n });\n this.emit('joining', false);\n this.emit('joined', false);\n this.emit('disconnect', isConnected);\n return Promise.resolve('Disconnected');\n });\n }\n startStream(streamId, server, iceServers, token, userId) {\n if (this.isConnecting) {\n return Promise.reject({\n type: 'warning',\n id: 16,\n message: 'connection error',\n data: 'Connection is in progress'\n });\n }\n if (this.ws) {\n this._wipeListeners();\n }\n this._stopKeepAlive();\n this._abortController = new AbortController();\n this.server = server;\n this.iceServers = iceServers;\n this.token = token;\n this.streamId = streamId;\n this.userId = userId;\n this.sessionId = null;\n this.isConnecting = true;\n this.emit('streamStarting', true);\n return new Promise((resolve, reject) => {\n this.ws = new WebSocket(this.server, 'janus-protocol');\n this.__connectionClosedBoundFn = this._connectionClosed.bind(this);\n this.__handleWsEventsBoundFn = this._handleWsEvents.bind(this);\n let abortConnect = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.ws.removeEventListener('close', this.__connectionClosedBoundFn);\n this.ws.removeEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.isConnecting = false;\n this.emit('streamStarting', false);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled'\n });\n };\n this.ws.addEventListener('close', this.__connectionClosedBoundFn);\n this.ws.addEventListener('message', this.__handleWsEventsBoundFn);\n this.ws.onopen = () => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this._retries = 0;\n this._send({\n \"janus\": \"create\"\n }).then(json => {\n this.sessionId = json[\"session_id\"] ? json[\"session_id\"] : json.data[\"id\"];\n this._startKeepAlive();\n return 1;\n }).then(() => this._createParticipant(userId)).then(handle => {\n this.handleId = handle.handleId;\n return 1;\n }).then(() => this._watchStream(streamId)).then(() => {\n this.isConnecting = false;\n this.emit('streamStarting', false);\n resolve(this);\n }).catch(error => {\n this.isConnecting = false;\n this.emit('streamStarting', false);\n reject({\n type: 'error',\n id: 13,\n message: 'connection error',\n data: error\n });\n });\n };\n this.ws.onerror = e => {\n this._abortController.signal.removeEventListener('abort', abortConnect);\n this.isConnecting = false;\n this.emit('streamStarting', false);\n reject({\n type: 'error',\n id: 14,\n message: 'ws connection error',\n data: e\n });\n };\n this._abortController.signal.addEventListener('abort', abortConnect);\n });\n }\n stopStream() {\n var _this$_abortControlle3, _this$_abortControlle4;\n if (this.isDisconnecting) {\n return Promise.resolve();\n }\n (_this$_abortControlle3 = this._abortController) === null || _this$_abortControlle3 === void 0 ? void 0 : (_this$_abortControlle4 = _this$_abortControlle3.abort) === null || _this$_abortControlle4 === void 0 ? void 0 : _this$_abortControlle4.call(_this$_abortControlle3);\n this._stopKeepAlive();\n let isStreaming = this.isStreaming;\n this.isDisconnecting = true;\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"stop\"\n }\n }, false, true).then(() => this._removeParticipant(this.handleId)).finally(() => {\n this._wipeListeners();\n this._send({\n \"janus\": \"destroy\"\n }, true);\n if (this.ws && this.ws.readyState === 1) {\n this.ws.close();\n }\n this.sessionId = null;\n this.isDisconnecting = false;\n this.isStreaming = false;\n this.emit('streamStarting', false);\n this.emit('streaming', false);\n this.emit('disconnect', isStreaming);\n return Promise.resolve('Disconnected');\n });\n }\n destroy() {\n if (this.sessiontype === 'reactooroom') {\n return this.disconnect().then(() => {\n this.clear();\n return true;\n });\n } else if (this.sessiontype === 'streaming') {\n return this.stopStream().then(() => {\n this.clear();\n return true;\n });\n }\n }\n _enableDebug() {\n this._log = console.log.bind(console);\n }\n _getHandle(handleId) {\n let rfid = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n return this._participants.find(p => p.handleId === handleId || rfid && p.rfid === rfid);\n }\n _getStats() {\n let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n return Promise.all(this._participants.map(participant => {\n let mediaTrack = null;\n if (type === 'video') {\n mediaTrack = participant.webrtcStuff && participant.webrtcStuff.stream && participant.webrtcStuff.stream.getVideoTracks().length && participant.webrtcStuff.stream.getVideoTracks()[0];\n } else if (type === 'audio') {\n mediaTrack = participant.webrtcStuff && participant.webrtcStuff.stream && participant.webrtcStuff.stream.getAudioTracks().length && participant.webrtcStuff.stream.getAudioTracks()[0];\n }\n return participant.webrtcStuff && participant.webrtcStuff.pc && participant.webrtcStuff.pc.getStats(mediaTrack).then(r => ({\n handle: participant,\n stats: r\n })).catch(e => Promise.resolve({\n handle: participant,\n stats: e\n }));\n }));\n }\n _sendTrickleCandidate(handleId, candidate) {\n return this._send({\n \"janus\": \"trickle\",\n \"candidate\": candidate,\n \"handle_id\": handleId\n });\n }\n _webrtc(handleId) {\n let enableOntrack = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n let handle = this._getHandle(handleId);\n if (!handle) {\n this.emit('error', {\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'create rtc connection']\n });\n }\n let config = handle.webrtcStuff;\n if (!config.pc) {\n let pc_config = {\n \"iceServers\": this.iceServers,\n \"iceTransportPolicy\": 'all',\n \"bundlePolicy\": undefined\n };\n pc_config[\"sdpSemantics\"] = \"unified-plan\";\n let pc_constraints = {};\n if (webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser === \"edge\") {\n // This is Edge, enable BUNDLE explicitly\n pc_config.bundlePolicy = \"max-bundle\";\n }\n this._log('new RTCPeerConnection', pc_config, pc_constraints);\n config.pc = new RTCPeerConnection(pc_config, pc_constraints);\n config.pc.onconnectionstatechange = () => {\n if (config.pc.connectionState === 'failed') {\n this._iceRestart(handleId);\n }\n this.emit('connectionState', [handleId, handleId === this.handleId, config.pc.connectionState]);\n if (handleId !== this.handleId && config.pc.connectionState === 'connected') {\n var _decodeJanusDisplay9, _decodeJanusDisplay10;\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay9 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay9 === void 0 ? void 0 : _decodeJanusDisplay9.userId,\n role: (_decodeJanusDisplay10 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay10 === void 0 ? void 0 : _decodeJanusDisplay10.role,\n stream: config.stream,\n track: null,\n optional: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: false,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n }\n };\n config.pc.oniceconnectionstatechange = () => {\n if (config.pc.iceConnectionState === 'failed') {\n this._iceRestart(handleId);\n }\n this.emit('iceState', [handleId, handleId === this.handleId, config.pc.iceConnectionState]);\n if (handleId !== this.handleId && (config.pc.iceConnectionState === 'completed' || config.pc.iceConnectionState === 'connected')) {\n var _decodeJanusDisplay11, _decodeJanusDisplay12;\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay11 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay11 === void 0 ? void 0 : _decodeJanusDisplay11.userId,\n role: (_decodeJanusDisplay12 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay12 === void 0 ? void 0 : _decodeJanusDisplay12.role,\n stream: config.stream,\n track: null,\n optional: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: false,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n }\n };\n config.pc.onicecandidate = event => {\n if (event.candidate == null || webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser === 'edge' && event.candidate.candidate.indexOf('endOfCandidates') > 0) {\n config.iceDone = true;\n this._sendTrickleCandidate(handleId, {\n \"completed\": true\n }).catch(e => {\n this.emit('error', e);\n });\n } else {\n // JSON.stringify doesn't work on some WebRTC objects anymore\n // See https://code.google.com/p/chromium/issues/detail?id=467366\n var candidate = {\n \"candidate\": event.candidate.candidate,\n \"sdpMid\": event.candidate.sdpMid,\n \"sdpMLineIndex\": event.candidate.sdpMLineIndex\n };\n this._sendTrickleCandidate(handleId, candidate).catch(e => {\n this.emit('error', e);\n });\n }\n };\n if (enableOntrack) {\n config.pc.ontrack = event => {\n if (!event.streams) return;\n\n //config.stream = event.streams[0];\n\n if (!config.stream) {\n config.stream = new MediaStream();\n }\n if (event.track) {\n var _decodeJanusDisplay13, _decodeJanusDisplay14;\n let mid = event.transceiver ? event.transceiver.mid : event.track.id;\n config.stream.addTrack(event.track);\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n mid,\n id: handle.handleId,\n userId: (_decodeJanusDisplay13 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay13 === void 0 ? void 0 : _decodeJanusDisplay13.userId,\n role: (_decodeJanusDisplay14 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay14 === void 0 ? void 0 : _decodeJanusDisplay14.role,\n stream: config.stream,\n track: event.track,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: true,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n if (event.track.onended) return;\n event.track.onended = ev => {\n var _config$pc, _config$pc$getTransce;\n let transceiver = (_config$pc = config.pc) === null || _config$pc === void 0 ? void 0 : (_config$pc$getTransce = _config$pc.getTransceivers()) === null || _config$pc$getTransce === void 0 ? void 0 : _config$pc$getTransce.find(t => t.receiver.track === ev.target);\n let mid = (transceiver === null || transceiver === void 0 ? void 0 : transceiver.mid) || ev.target.id;\n if (config.stream) {\n var _decodeJanusDisplay15, _decodeJanusDisplay16;\n config.stream && config.stream.removeTrack(ev.target);\n this.emit(this._getAddParticipantEventName(handle.handleId), {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n mid,\n userId: (_decodeJanusDisplay15 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay15 === void 0 ? void 0 : _decodeJanusDisplay15.userId,\n role: (_decodeJanusDisplay16 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay16 === void 0 ? void 0 : _decodeJanusDisplay16.role,\n stream: config.stream,\n track: ev.target,\n constructId: this.constructId,\n metaData: this.options.metaData,\n adding: false,\n removing: true,\n hasAudioTrack: !!(config.stream && config.stream.getAudioTracks().length),\n hasVideoTrack: !!(config.stream && config.stream.getVideoTracks().length)\n });\n }\n };\n event.track.onmute = ev => {\n var _decodeJanusDisplay17, _decodeJanusDisplay18;\n this._log('remoteTrackMuted', 'onmute');\n let transceiver = config.pc.getTransceivers().find(t => t.receiver.track === ev.target);\n let mid = transceiver.mid || ev.target.id;\n this.emit('remoteTrackMuted', {\n id: handle.handleId,\n mid,\n userId: (_decodeJanusDisplay17 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay17 === void 0 ? void 0 : _decodeJanusDisplay17.userId,\n role: (_decodeJanusDisplay18 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay18 === void 0 ? void 0 : _decodeJanusDisplay18.role,\n stream: config.stream,\n kind: ev.target.kind,\n track: ev.target,\n muted: true\n });\n };\n event.track.onunmute = ev => {\n var _decodeJanusDisplay19, _decodeJanusDisplay20;\n this._log('remoteTrackMuted', 'onunmute');\n let transceiver = config.pc.getTransceivers().find(t => t.receiver.track === ev.target);\n let mid = transceiver.mid || ev.target.id;\n this.emit('remoteTrackMuted', {\n id: handle.handleId,\n mid,\n userId: (_decodeJanusDisplay19 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay19 === void 0 ? void 0 : _decodeJanusDisplay19.userId,\n role: (_decodeJanusDisplay20 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay20 === void 0 ? void 0 : _decodeJanusDisplay20.role,\n stream: config.stream,\n kind: ev.target.kind,\n track: ev.target,\n muted: false\n });\n };\n }\n };\n }\n }\n if (!config.dataChannel || !config.dataChannelOpen) {\n config.dataChannel = {};\n var onDataChannelMessage = event => {\n this._handleDataEvents(handleId, 'message', event.data);\n };\n var onDataChannelStateChange = event => {\n let label = event.target.label;\n let protocol = event.target.protocol;\n let state = config.dataChannel[label] ? config.dataChannel[label].readyState : \"null\";\n this._handleDataEvents(handleId, 'state', {\n state,\n label\n });\n };\n //TODO: check this\n var onDataChannelError = error => {\n var _error$channel;\n this._handleDataEvents(handleId, 'error', {\n label: error === null || error === void 0 ? void 0 : (_error$channel = error.channel) === null || _error$channel === void 0 ? void 0 : _error$channel.label,\n error\n });\n };\n const createDataChannel = (label, protocol, incoming) => {\n let options = {\n ordered: true\n };\n if (!incoming) {\n if (protocol) {\n options = {\n ...options,\n protocol\n };\n }\n config.dataChannel[label] = config.pc.createDataChannel(label, options);\n } else {\n config.dataChannel[label] = incoming;\n }\n config.dataChannel[label].onmessage = onDataChannelMessage;\n config.dataChannel[label].onopen = onDataChannelStateChange;\n config.dataChannel[label].onclose = onDataChannelStateChange;\n config.dataChannel[label].onerror = onDataChannelError;\n };\n createDataChannel(this.defaultDataChannelLabel, null, null);\n config.pc.ondatachannel = function (event) {\n createDataChannel(event.channel.label, event.channel.protocol, event.channel);\n };\n }\n }\n _webrtcPeer(handleId, jsep) {\n let handle = this._getHandle(handleId);\n if (!handle) {\n return Promise.reject({\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'rtc peer']\n });\n }\n var config = handle.webrtcStuff;\n if (jsep !== undefined && jsep !== null) {\n if (config.pc === null) {\n this._log(\"No PeerConnection: if this is an answer, use createAnswer and not _webrtcPeer\");\n return Promise.resolve(null);\n }\n return config.pc.setRemoteDescription(jsep).then(() => {\n config.remoteSdp = jsep.sdp;\n // Any trickle candidate we cached?\n if (config.candidates && config.candidates.length > 0) {\n for (var i = 0; i < config.candidates.length; i++) {\n var candidate = config.candidates[i];\n if (!candidate || candidate.completed === true) {\n config.pc.addIceCandidate(null);\n } else {\n config.pc.addIceCandidate(candidate);\n }\n }\n config.candidates = [];\n }\n // Done\n return true;\n });\n } else {\n return Promise.reject({\n type: 'warning',\n id: 22,\n message: 'rtc peer',\n data: [handleId, 'invalid jsep']\n });\n }\n }\n _iceRestart(handleId) {\n let handle = this._getHandle(handleId);\n if (!handle) {\n return;\n }\n var config = handle.webrtcStuff;\n\n // Already restarting;\n if (config.isIceRestarting) {\n return;\n }\n if (this.handleId === handleId) {\n this._log('Performing local ICE restart');\n config.isIceRestarting = true;\n let hasAudio = !!(config.stream && config.stream.getAudioTracks().length > 0);\n let hasVideo = !!(config.stream && config.stream.getVideoTracks().length > 0);\n this._setupTransceivers([hasAudio, false, hasVideo, false]);\n this._createAO('offer', handleId, true).then(jsep => {\n if (!jsep) {\n return null;\n }\n return this.sendMessage(handleId, {\n body: {\n \"request\": \"configure\",\n \"audio\": hasAudio,\n \"video\": hasVideo,\n \"data\": true,\n ...(this.recordingFilename ? {\n filename: this.recordingFilename\n } : {})\n },\n jsep\n });\n }).then(r => {\n config.isIceRestarting = false;\n this._log('ICE restart success');\n }).catch(e => {\n config.isIceRestarting = false;\n this.emit('error', {\n type: 'warning',\n id: 28,\n message: 'iceRestart failed',\n data: e\n });\n });\n } else {\n this._log('Performing remote ICE restart', handleId);\n config.isIceRestarting = true;\n return this.sendMessage(handleId, {\n body: {\n \"request\": \"configure\",\n \"restart\": true\n }\n }).then(() => {\n config.isIceRestarting = false;\n }).catch(() => {\n config.isIceRestarting = false;\n });\n }\n }\n _setupTransceivers(handleId, _ref) {\n let [audioSend, audioRecv, videoSend, videoRecv] = _ref;\n let handle = this._getHandle(handleId);\n if (!handle) {\n return null;\n }\n let config = handle.webrtcStuff;\n let audioTransceiver = null,\n videoTransceiver = null;\n let transceivers = config.pc.getTransceivers();\n if (transceivers && transceivers.length > 0) {\n for (var i in transceivers) {\n var t = transceivers[i];\n if (t.sender && t.sender.track && t.sender.track.kind === \"audio\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"audio\") {\n if (!audioTransceiver) audioTransceiver = t;\n continue;\n }\n if (t.sender && t.sender.track && t.sender.track.kind === \"video\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"video\") {\n if (!videoTransceiver) videoTransceiver = t;\n continue;\n }\n }\n }\n\n // Handle audio (and related changes, if any)\n if (!audioSend && !audioRecv) {\n // Audio disabled: have we removed it?\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"inactive\");\n } else {\n audioTransceiver.direction = \"inactive\";\n }\n }\n } else {\n // Take care of audio m-line\n if (audioSend && audioRecv) {\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"sendrecv\");\n } else {\n audioTransceiver.direction = \"sendrecv\";\n }\n }\n } else if (audioSend && !audioRecv) {\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"sendonly\");\n } else {\n audioTransceiver.direction = \"sendonly\";\n }\n }\n } else if (!audioSend && audioRecv) {\n if (audioTransceiver) {\n if (audioTransceiver.setDirection) {\n audioTransceiver.setDirection(\"recvonly\");\n } else {\n audioTransceiver.direction = \"recvonly\";\n }\n } else {\n // In theory, this is the only case where we might not have a transceiver yet\n config.pc.addTransceiver(\"audio\", {\n direction: \"recvonly\"\n });\n }\n }\n }\n // Handle video (and related changes, if any)\n if (!videoSend && !videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"inactive\");\n } else {\n videoTransceiver.direction = \"inactive\";\n }\n }\n } else {\n // Take care of video m-line\n if (videoSend && videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"sendrecv\");\n } else {\n videoTransceiver.direction = \"sendrecv\";\n }\n }\n } else if (videoSend && !videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"sendonly\");\n } else {\n videoTransceiver.direction = \"sendonly\";\n }\n }\n } else if (!videoSend && videoRecv) {\n if (videoTransceiver) {\n if (videoTransceiver.setDirection) {\n videoTransceiver.setDirection(\"recvonly\");\n } else {\n videoTransceiver.direction = \"recvonly\";\n }\n } else {\n // In theory, this is the only case where we might not have a transceiver yet\n config.pc.addTransceiver(\"video\", {\n direction: \"recvonly\"\n });\n }\n }\n }\n }\n _createAO() {\n let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'offer';\n let handleId = arguments.length > 1 ? arguments[1] : undefined;\n let iceRestart = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n let handle = this._getHandle(handleId);\n if (!handle) {\n return Promise.reject({\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'createAO', type]\n });\n }\n let methodName = null;\n if (type === 'offer') {\n methodName = 'createOffer';\n } else {\n methodName = 'createAnswer';\n }\n let config = handle.webrtcStuff;\n let mediaConstraints = {};\n if (iceRestart) {\n mediaConstraints[\"iceRestart\"] = true;\n }\n return config.pc[methodName](mediaConstraints).then(function (response) {\n config.mySdp = response.sdp;\n let _p = config.pc.setLocalDescription(response).catch(e => {\n return Promise.reject({\n type: 'warning',\n id: 24,\n message: 'setLocalDescription',\n data: [handleId, e]\n });\n });\n config.mediaConstraints = mediaConstraints;\n if (!config.iceDone && !config.trickle) {\n // Don't do anything until we have all candidates\n return Promise.resolve(null);\n }\n\n // JSON.stringify doesn't work on some WebRTC objects anymore\n // See https://code.google.com/p/chromium/issues/detail?id=467366\n var jsep = {\n \"type\": response.type,\n \"sdp\": response.sdp\n };\n return _p.then(() => jsep);\n }, e => {\n return Promise.reject({\n type: 'warning',\n id: 25,\n message: methodName,\n data: [handleId, e]\n });\n });\n }\n _publishRemote(handleId, jsep) {\n let handle = this._getHandle(handleId);\n if (!handle) {\n return Promise.reject({\n type: 'warning',\n id: 15,\n message: 'id non-existent',\n data: [handleId, 'publish remote participant']\n });\n }\n this._webrtc(handleId, true);\n let config = handle.webrtcStuff;\n if (jsep) {\n return config.pc.setRemoteDescription(jsep).then(() => {\n config.remoteSdp = jsep.sdp;\n // Any trickle candidate we cached?\n if (config.candidates && config.candidates.length > 0) {\n for (var i = 0; i < config.candidates.length; i++) {\n var candidate = config.candidates[i];\n if (!candidate || candidate.completed === true) {\n // end-of-candidates\n config.pc.addIceCandidate(null);\n } else {\n // New candidate\n config.pc.addIceCandidate(candidate);\n }\n }\n config.candidates = [];\n }\n this._setupTransceivers(handleId, [false, true, false, true]);\n\n // Create the answer now\n return this._createAO('answer', handleId, false).then(_jsep => {\n if (!_jsep) {\n this.emit('error', {\n type: 'warning',\n id: 19,\n message: 'publish remote participant',\n data: [handleId, 'no jsep']\n });\n return Promise.resolve();\n }\n return this.sendMessage(handleId, {\n \"body\": {\n \"request\": \"start\",\n ...(this.roomId && {\n \"room\": this.roomId\n }),\n ...(this.pin && {\n pin: this.pin\n })\n },\n \"jsep\": _jsep\n });\n });\n }, e => Promise.reject({\n type: 'warning',\n id: 23,\n message: 'setRemoteDescription',\n data: [handleId, e]\n }));\n } else {\n return Promise.resolve();\n }\n }\n\n //Public methods\n\n publishLocal() {\n let stream = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n if (this.isDisconnecting || !this.isConnected) {\n return Promise.reject({\n type: 'warning',\n id: 18,\n message: 'Either not connected or disconnecting'\n });\n }\n this.emit('publishing', true);\n let handle = this._getHandle(this.handleId);\n if (!handle) {\n return Promise.reject({\n type: 'error',\n id: 21,\n message: 'no local id, connect before publishing',\n data: null\n });\n }\n this._webrtc(this.handleId);\n let config = handle.webrtcStuff;\n let audioTrackReplacePromise = Promise.resolve();\n let videoTrackReplacePromise = Promise.resolve();\n if (!config.stream) {\n var _stream$getTracks;\n config.stream = stream;\n stream === null || stream === void 0 ? void 0 : (_stream$getTracks = stream.getTracks()) === null || _stream$getTracks === void 0 ? void 0 : _stream$getTracks.forEach(track => {\n if (track.kind === 'audio' || !this.simulcast) {\n config.pc.addTrack(track, stream);\n } else {\n // adding simulcast streams\n let bitRates = this.simulcastBitrates;\n if (webrtc_adapter__WEBPACK_IMPORTED_MODULE_0__[\"default\"].browserDetails.browser !== 'firefox') {\n // standard\n\n config.pc.addTransceiver(track, {\n direction: 'sendonly',\n streams: [config.stream],\n sendEncodings: [{\n rid: 'h',\n active: true,\n maxBitrate: bitRates.high\n }, {\n rid: 'm',\n active: true,\n maxBitrate: bitRates.medium,\n scaleResolutionDownBy: 2\n }, {\n rid: 'l',\n active: true,\n maxBitrate: bitRates.low,\n scaleResolutionDownBy: 4\n }]\n });\n } else {\n // firefox\n let transceiver = config.pc.addTransceiver(track, {\n direction: 'sendonly',\n streams: [config.stream]\n });\n let sender = transceiver ? transceiver.sender : null;\n if (sender) {\n let parameters = sender.getParameters() || {};\n parameters.encodings = track.sendEncodings || [{\n rid: 'h',\n active: true,\n maxBitrate: bitRates.high\n }, {\n rid: 'm',\n active: true,\n maxBitrate: bitRates.medium,\n scaleResolutionDownBy: 2\n }, {\n rid: 'l',\n active: true,\n maxBitrate: bitRates.low,\n scaleResolutionDownBy: 4\n }];\n sender.setParameters(parameters);\n }\n }\n }\n });\n } else {\n var _config$stream, _config$stream$getAud, _stream$getAudioTrack, _config$stream2, _config$stream2$getVi, _stream$getVideoTrack;\n let transceivers = config.pc.getTransceivers();\n let audioTransceiver = null;\n let videoTransceiver = null;\n if (transceivers && transceivers.length > 0) {\n for (let i in transceivers) {\n let t = transceivers[i];\n if (t.sender && t.sender.track && t.sender.track.kind === \"audio\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"audio\") {\n audioTransceiver = t;\n break;\n }\n }\n for (let i in transceivers) {\n let t = transceivers[i];\n if (t.sender && t.sender.track && t.sender.track.kind === \"video\" || t.receiver && t.receiver.track && t.receiver.track.kind === \"video\") {\n videoTransceiver = t;\n break;\n }\n }\n }\n\n /* UPDATE Audio */\n // stopping existing tracks\n\n let oldAudioStream = config === null || config === void 0 ? void 0 : (_config$stream = config.stream) === null || _config$stream === void 0 ? void 0 : (_config$stream$getAud = _config$stream.getAudioTracks()) === null || _config$stream$getAud === void 0 ? void 0 : _config$stream$getAud[0];\n if (oldAudioStream) {\n config.stream.removeTrack(oldAudioStream);\n try {\n oldAudioStream.stop();\n } catch (e) {\n this._log(e);\n }\n }\n let replaceAudio = stream === null || stream === void 0 ? void 0 : (_stream$getAudioTrack = stream.getAudioTracks()) === null || _stream$getAudioTrack === void 0 ? void 0 : _stream$getAudioTrack.length;\n if (replaceAudio) {\n config.stream.addTrack(stream.getAudioTracks()[0]);\n if (audioTransceiver && audioTransceiver.sender) {\n audioTrackReplacePromise = audioTransceiver.sender.replaceTrack(stream.getAudioTracks()[0]);\n } else {\n config.pc.addTrack(stream.getAudioTracks()[0], stream);\n }\n } else {\n if (audioTransceiver && audioTransceiver.sender) {\n audioTrackReplacePromise = audioTransceiver.sender.replaceTrack(null);\n }\n }\n\n /* UPDATE Video */\n\n // stopping existing tracks\n\n let oldVideoStream = config === null || config === void 0 ? void 0 : (_config$stream2 = config.stream) === null || _config$stream2 === void 0 ? void 0 : (_config$stream2$getVi = _config$stream2.getVideoTracks()) === null || _config$stream2$getVi === void 0 ? void 0 : _config$stream2$getVi[0];\n if (oldVideoStream) {\n config.stream.removeTrack(oldVideoStream);\n try {\n oldVideoStream.stop();\n } catch (e) {\n this._log(e);\n }\n }\n let replaceVideo = stream === null || stream === void 0 ? void 0 : (_stream$getVideoTrack = stream.getVideoTracks()) === null || _stream$getVideoTrack === void 0 ? void 0 : _stream$getVideoTrack.length;\n if (replaceVideo) {\n config.stream.addTrack(stream.getVideoTracks()[0]);\n if (videoTransceiver && videoTransceiver.sender) {\n videoTrackReplacePromise = videoTransceiver.sender.replaceTrack(stream.getVideoTracks()[0]);\n } else {\n config.pc.addTrack(stream.getVideoTracks()[0], stream);\n }\n } else {\n if (videoTransceiver && videoTransceiver.sender) {\n videoTrackReplacePromise = videoTransceiver.sender.replaceTrack(null);\n }\n }\n }\n let hasAudio = !!(stream && stream.getAudioTracks().length > 0);\n let hasVideo = !!(stream && stream.getVideoTracks().length > 0);\n let isAudioMuted = !stream || stream.getAudioTracks().length === 0 || !stream.getAudioTracks()[0].enabled;\n let isVideoMuted = !stream || stream.getVideoTracks().length === 0 || !stream.getVideoTracks()[0].enabled;\n this.isAudioEnabed = hasAudio;\n this.isVideoEnabled = hasVideo;\n this.isAudioMuted = isAudioMuted;\n this.isVideoMuted = isVideoMuted;\n this._setupTransceivers(this.handleId, [hasAudio, false, hasVideo, false]);\n const emitEvents = () => {\n this.isPublished = true;\n if (config.stream) {\n let tracks = config.stream.getTracks();\n tracks.forEach(track => {\n // used as a flag to not emit tracks that been already emitted\n if (!track.onended) {\n var _decodeJanusDisplay21, _decodeJanusDisplay22;\n this.emit('addLocalParticipant', {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay21 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay21 === void 0 ? void 0 : _decodeJanusDisplay21.userId,\n role: (_decodeJanusDisplay22 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display)) === null || _decodeJanusDisplay22 === void 0 ? void 0 : _decodeJanusDisplay22.role,\n track,\n stream: config.stream,\n adding: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: hasAudio,\n hasVideoTrack: hasVideo\n });\n track.onended = ev => {\n var _decodeJanusDisplay23, _decodeJanusDisplay24;\n this.emit('addLocalParticipant', {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay23 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay23 === void 0 ? void 0 : _decodeJanusDisplay23.userId,\n role: (_decodeJanusDisplay24 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display)) === null || _decodeJanusDisplay24 === void 0 ? void 0 : _decodeJanusDisplay24.role,\n track: ev.target,\n stream: config.stream,\n adding: false,\n removing: true,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: hasAudio,\n hasVideoTrack: hasVideo\n });\n };\n }\n });\n } else {\n var _decodeJanusDisplay25, _decodeJanusDisplay26;\n this.emit('addLocalParticipant', {\n tid: Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"generateUUID\"])(),\n id: handle.handleId,\n userId: (_decodeJanusDisplay25 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(handle.userId)) === null || _decodeJanusDisplay25 === void 0 ? void 0 : _decodeJanusDisplay25.userId,\n role: (_decodeJanusDisplay26 = Object(_wt_utils__WEBPACK_IMPORTED_MODULE_2__[\"decodeJanusDisplay\"])(this.display)) === null || _decodeJanusDisplay26 === void 0 ? void 0 : _decodeJanusDisplay26.role,\n stream: null,\n adding: false,\n constructId: this.constructId,\n metaData: this.options.metaData,\n hasAudioTrack: hasAudio,\n hasVideoTrack: hasVideo\n });\n }\n this.emit('published', {\n status: true,\n hasStream: !!config.stream\n });\n this.emit('publishing', false);\n this.emit('localHasVideo', hasVideo);\n this.emit('localHasAudio', hasAudio);\n this.emit('localMuted', {\n type: 'video',\n value: isVideoMuted\n });\n this.emit('localMuted', {\n type: 'audio',\n value: isAudioMuted\n });\n return this;\n };\n\n // this should be enough\n if (this.isPublished) {\n return Promise.all([audioTrackReplacePromise, videoTrackReplacePromise]).then(() => emitEvents());\n }\n return Promise.all([audioTrackReplacePromise, videoTrackReplacePromise]).then(() => this._createAO('offer', this.handleId, false)).then(jsep => {\n if (!jsep) {\n return null;\n }\n //HOTFIX: Temporary fix for Safari 13\n if (jsep.sdp && jsep.sdp.indexOf(\"\\r\\na=ice-ufrag\") === -1) {\n jsep.sdp = jsep.sdp.replace(\"\\na=ice-ufrag\", \"\\r\\na=ice-ufrag\");\n }\n return this.sendMessage(this.handleId, {\n body: {\n \"request\": \"configure\",\n \"audio\": hasAudio,\n \"video\": hasVideo,\n \"data\": true,\n ...(this.recordingFilename ? {\n filename: this.recordingFilename\n } : {})\n },\n jsep\n });\n }).then(r => {\n if (this._isDataChannelOpen) {\n return Promise.resolve(r);\n } else {\n return new Promise((resolve, reject) => {\n let dataChannelTimeoutId = null;\n let _resolve = val => {\n if (val) {\n clearTimeout(dataChannelTimeoutId);\n this._abortController.signal.removeEventListener('abort', _rejectAbort);\n this.off('dataChannel', _resolve, this);\n resolve(this);\n }\n };\n let _rejectTimeout = () => {\n this.off('dataChannel', _resolve, this);\n this._abortController.signal.removeEventListener('abort', _rejectAbort);\n reject({\n type: 'error',\n id: 27,\n message: 'Data channel did not open',\n data: null\n });\n };\n let _rejectAbort = () => {\n this._abortController.signal.removeEventListener('abort', _rejectAbort);\n clearTimeout(dataChannelTimeoutId);\n this.off('dataChannel', _resolve, this);\n reject({\n type: 'warning',\n id: 17,\n message: 'Connection cancelled'\n });\n };\n dataChannelTimeoutId = setTimeout(_rejectTimeout, 5000);\n this._abortController.signal.addEventListener('abort', _rejectAbort);\n this.on('dataChannel', _resolve, this);\n });\n }\n }).then(() => emitEvents()).catch(e => {\n this.emit('publishing', false);\n return Promise.reject(e);\n });\n }\n unpublishLocal() {\n let dontWait = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n return this.isPublished ? this.sendMessage(this.handleId, {\n body: {\n \"request\": \"unpublish\"\n }\n }, dontWait).finally(r => {\n this.isPublished = false;\n this.emit('published', {\n status: false,\n hasStream: false\n });\n return r;\n }) : Promise.resolve();\n }\n toggleAudio() {\n let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let mid = arguments.length > 1 ? arguments[1] : undefined;\n let handle = this._getHandle(this.handleId);\n if (!handle) {\n return Promise.reject({\n type: 'error',\n id: 21,\n message: 'no local id, connect first',\n data: null\n });\n }\n let config = handle.webrtcStuff;\n let transceiver = config.pc.getTransceivers().find(t => t.sender && t.sender.track && t.receiver.track.kind === \"audio\" && (mid ? t.mid === mid : true));\n if (transceiver) {\n transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;\n }\n this.isAudioMuted = !transceiver || !transceiver.sender.track.enabled;\n\n // if (config.stream && config.stream.getAudioTracks().length) {\n // \tconfig.stream.getAudioTracks()[0].enabled = value !== null ? !!value : !config.stream.getAudioTracks()[0].enabled;\n // }\n // this.isAudioMuted = config.stream.getAudioTracks().length === 0 || !config.stream.getAudioTracks()[0].enabled;\n //\n\n this.emit('localMuted', {\n type: 'audio',\n value: this.isAudioMuted,\n mid\n });\n }\n toggleVideo() {\n let value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n let mid = arguments.length > 1 ? arguments[1] : undefined;\n let handle = this._getHandle(this.handleId);\n if (!handle) {\n return Promise.reject({\n type: 'error',\n id: 21,\n message: 'no local id, connect first',\n data: null\n });\n }\n let config = handle.webrtcStuff;\n let transceiver = config.pc.getTransceivers().find(t => t.sender && t.sender.track && t.receiver.track.kind === \"video\" && (mid ? t.mid === mid : true));\n if (transceiver) {\n transceiver.sender.track.enabled = value !== null ? !!value : !transceiver.sender.track.enabled;\n }\n this.isVideoMuted = !transceiver || !transceiver.sender.track.enabled;\n\n // if (config.stream && config.stream.getVideoTracks().length) {\n // \tconfig.stream.getVideoTracks()[0].enabled = value !== null ? !!value : !config.stream.getVideoTracks()[0].enabled;\n // }\n // this.isVideoMuted = config.stream.getVideoTracks().length === 0 || !config.stream.getVideoTracks()[0].enabled;\n\n this.emit('localMuted', {\n type: 'video',\n value: this.isVideoMuted,\n mid\n });\n }\n selectSubStream(handleId) {\n let substream = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;\n this.sendMessage(this.handleId, {\n \"body\": {\n \"request\": \"configure\",\n \"substream\": substream\n }\n }).catch(() => null);\n }\n setRoomType() {\n let type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'watchparty';\n this._roomType = type;\n return this._roomType;\n }\n}\n_defineProperty(RoomSession, \"sessionTypes\", {\n 'reactooroom': 'janus.plugin.reactooroom',\n 'streaming': 'janus.plugin.streaming'\n});\n_defineProperty(RoomSession, \"subscriptionRules\", {\n participant: {\n \"watchparty\": ['participant', 'talkback'],\n \"studio\": ['participant', 'talkback', 'host', 'observer'],\n \"commentary\": ['participant', 'talkback', 'host'],\n \"videowall\": ['host', 'talkback', 'observer', 'observerSolo1', 'observerSolo2', 'observerSolo3'],\n \"videowall-queue\": ['host', 'talkback', 'observer', 'observerSolo1', 'observerSolo2', 'observerSolo3'],\n \"videowall-queue-video\": ['host', 'talkback', 'observer', 'observerSolo1', 'observerSolo2', 'observerSolo3']\n },\n monitor: {\n \"watchparty\": ['participant', 'host'],\n \"studio\": ['participant', 'host'],\n \"commentary\": ['participant', 'host'],\n \"videowall\": ['host', 'participant'],\n \"videowall-queue\": ['host', 'participant'],\n \"videowall-queue-video\": ['host', 'participant']\n },\n talkback: {\n \"watchparty\": ['participant', 'host'],\n \"studio\": ['participant', 'host'],\n \"commentary\": ['host', 'participant'],\n \"videowall\": ['host', 'participant'],\n \"videowall-queue\": ['host', 'participant'],\n \"videowall-queue-video\": ['host', 'participant']\n },\n observer: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n observerSolo1: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n observerSolo2: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n observerSolo3: {\n \"watchparty\": ['participant'],\n \"studio\": ['participant'],\n \"commentary\": ['participant'],\n \"videowall\": ['participant'],\n \"videowall-queue\": ['participant'],\n \"videowall-queue-video\": ['participant']\n },\n host: {\n \"watchparty\": [],\n \"studio\": [],\n \"commentary\": [],\n \"videowall\": [],\n \"videowall-queue\": [],\n \"videowall-queue-video\": []\n },\n companionTV: {},\n companionPhone: {}\n});\n/* harmony default export */ __webpack_exports__[\"default\"] = (Room);\n\n//# sourceURL=webpack://WatchTogetherSDK/./src/modules/wt-room.js?");
|
|
9499
9499
|
|
|
9500
9500
|
/***/ }),
|
|
9501
9501
|
|