diff --git a/.adxstudio/workspace.json b/.adxstudio/workspace.json index 41a2ba2..23fc8bd 100644 --- a/.adxstudio/workspace.json +++ b/.adxstudio/workspace.json @@ -1 +1 @@ -{"tabs":[{"id":"2cec0e67-0b8f-425c-b0eb-b099d07acf7a","pane":"main","current":true,"path":"C:\\Users\\Quentin\\Documents\\camera_adc\\config.xml","type":"projectSettings","mode":"form"},{"id":"2de4cf48-434e-4f38-9c33-b980bdf9ae44","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\open.html","type":"file"},{"id":"fc889f10-19af-4cca-91e7-e5e9779ff811","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\static\\adc_camera.js","type":"file"},{"id":"bd8fe99e-e996-4240-9fdb-8ce80db2e80c","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\default.css","type":"file"},{"id":"a1efba25-fcc9-4c66-9c29-20846d24d6b1","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\fallback_mobiles_open.html","type":"file"},{"id":"c5657dce-d817-45a9-9127-43cdb8c3a144","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\static\\adc_camera_mobiles.js","type":"file"},{"id":"bfafd1f8-3c81-4b4b-bcbc-2ab1b53ee6cc","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\fallback_open.html","type":"file"},{"id":"b44a24b3-877b-44fe-9f0a-9e5fe2c1078b","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\readme.md","type":"file"},{"id":"7d784d4f-60ed-4d60-ba28-4852c27acb4e","pane":"main","path":"C:\\Users\\Quentin\\Documents\\ADC_Camera\\resources\\static\\adc_camera_mobiles.js","type":"file"},{"id":"6ada7478-961e-4ce5-8c41-168b343e2e71","pane":"main","path":"C:\\Users\\Quentin\\Documents\\ADC_Camera\\resources\\static\\adc_camera.js","type":"file"},{"id":"8a2c5a0f-2da2-4ae0-a5ea-7861d627d220","pane":"main","path":"C:\\Users\\Quentin\\Documents\\ADC_Camera\\resources\\dynamic\\open.html","type":"file"},{"id":"2adb3c8c-0f19-4157-be72-7399cf6f3505","pane":"main","path":"C:\\Users\\Quentin\\Documents\\GitHub\\MyADCs\\Camera\\config.xml","type":"projectSettings","mode":"form","adxVersion":"2.0.0","adxType":"adc"}]} \ No newline at end of file +{"tabs":[{"id":"0a91f9a4-ecba-4b24-a030-bd894ab800ef","pane":"main","current":true,"path":"C:\\Users\\Quentin\\Documents\\camera_adc\\config.xml","type":"projectSettings","mode":"form"},{"id":"d51b30dc-05ae-428e-a441-da1bacc7b447","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\open.html","type":"file"},{"id":"e7cc8a9a-09f2-4e3f-875c-19d6cf1d076f","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\static\\adc_camera.js","type":"file"},{"id":"b7cfe526-9936-4062-a526-9cfdb6d4fd31","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\default.css","type":"file"},{"id":"1028798b-1e9f-4a5a-827a-02f29bf0dcf9","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\fallback_mobiles_open.html","type":"file"},{"id":"1c67e3d3-c4f3-4454-bf5c-aa43f6e300e5","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\static\\adc_camera_mobiles.js","type":"file"},{"id":"ecdb6429-8330-4770-aaa8-aac6a2edf996","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\resources\\dynamic\\fallback_open.html","type":"file"},{"id":"59181ece-2c88-456a-a684-a6fdd0c429bb","pane":"main","path":"C:\\Users\\Quentin\\Documents\\camera_adc\\readme.md","type":"file"},{"id":"e58c731f-a216-46ad-9b4d-fb8e2d982294","pane":"main","path":"C:\\Users\\Quentin\\Documents\\ADC_Camera\\resources\\static\\adc_camera_mobiles.js","type":"file"},{"id":"b20b5873-15ba-40c3-94f6-ca6adad1b3f0","pane":"main","path":"C:\\Users\\Quentin\\Documents\\ADC_Camera\\resources\\static\\adc_camera.js","type":"file"},{"id":"5881a8d2-453f-4a09-b6c7-1580b51b5c1a","pane":"main","path":"C:\\Users\\Quentin\\Documents\\ADC_Camera\\resources\\dynamic\\open.html","type":"file"},{"id":"e17bc251-9b5a-4cfb-be56-3576e58ea01e","pane":"main","path":"C:\\Users\\Quentin\\Documents\\GitHub\\MyADCs\\Camera\\config.xml","type":"projectSettings","mode":"form"},{"id":"c89f74ed-7c49-435e-8e68-57ff07caf5b4","pane":"main","path":"C:\\Users\\JordanGrindle\\Documents\\GitHub\\Camera\\config.xml","type":"projectSettings","mode":"code","adxVersion":"2.0.0","adxType":"adc"}]} \ No newline at end of file diff --git a/bin/Camera.adc b/bin/Camera.adc index 1ff3833..c0ea44e 100644 Binary files a/bin/Camera.adc and b/bin/Camera.adc differ diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..0e48efe --- /dev/null +++ b/changelog.md @@ -0,0 +1,10 @@ + +v1.0.1 - change the `stopRecordingVideo` func code to get the promise instead of a blob + v1.0.2 - image capture issue when uploading - fixed +v1.0.3 - +v1.0.4 - photo button caption disappears when mobile - fixed +v1.1.0 - WebRTC,RecordRTC library update + - Fixed - DOF runtime errors +v2.0.0 - RecordRTC & WebRTC library update +v2.0.1 - fixed/modernized buttons with button instead of input, removed onclick listeners with addeventhandler +v2.0.2 - fixed issue where desktop recording wouldn't function properly diff --git a/config.xml b/config.xml index 866b22b..5b5a0f4 100644 --- a/config.xml +++ b/config.xml @@ -7,15 +7,9 @@ Camera d7c94a7c-10f9-4d31-8e51-82dc9c96c089 - 1.1.0 + 2.0.2 2022-09-29 - + Askia ]]> http://www.askia.com diff --git a/example/Camera.qex b/example/Camera.qex index c6f4ca1..9e6f42e 100644 Binary files a/example/Camera.qex and b/example/Camera.qex differ diff --git a/resources/dynamic/open.html b/resources/dynamic/open.html index c15b471..a333376 100644 --- a/resources/dynamic/open.html +++ b/resources/dynamic/open.html @@ -15,8 +15,8 @@ Dim loop = (CurrentADC.PropValue("loop") = "1") Dim enabledNextAfterUpload = (CurrentADC.PropValue("nextAfterUpload") = "1") - %} + + {%if enabledNextAfterUpload then%} {%EndIf%} + {%if typeOfCapture = "image" Then%} {%EndIf%} + {% if typeOfCapture = "video" then %} {%EndIf%} - -
- +
+
+ {% if typeOfCapture = "video" Then %}
- - -
- + + + + +
+ +
+
+ {%if allowSaveFile then%} - + {%EndIf%} - - + + + + + + {% Endif %} {% if typeOfCapture = "image" Then %} +
- -
- - - + + +
+ + + +
+ {%if allowSaveFile then%} - + {%EndIf%} - - + + + + + -{% EndIf %} + +{% EndIf %} \ No newline at end of file diff --git a/resources/static/RecordRTC.js b/resources/static/RecordRTC.js index 9f5eb92..93c427a 100644 --- a/resources/static/RecordRTC.js +++ b/resources/static/RecordRTC.js @@ -1,9 +1,9 @@ 'use strict'; -// Last time updated: 2022-04-05 11:18:05 AM UTC +// Last time updated: 2024-01-03 12:51:19 PM UTC // ________________ -// RecordRTC v5.6.2 +// RecordRTC v5.6.3 // Open-Sourced: https://github.com/muaz-khan/RecordRTC @@ -16,7 +16,7 @@ // RecordRTC.js /** - * {@link https://github.com/muaz-khan/RecordRTC|RecordRTC} is a WebRTC JavaScript library for audio/video as well as screen activity recording. It supports Chrome, Firefox, Opera, Android, and Microsoft Edge. Platforms: Linux, Mac and Windows. + * {@link https://github.com/muaz-khan/RecordRTC|RecordRTC} is a WebRTC JavaScript library for audio/video as well as screen activity recording. It supports Chrome, Firefox, Opera, Android, and Microsoft Edge. Platforms: Linux, Mac and Windows. * @summary Record audio, video or screen inside the browser. * @license {@link https://github.com/muaz-khan/RecordRTC/blob/master/LICENSE|MIT} * @author {@link https://MuazKhan.com|Muaz Khan} @@ -420,7 +420,7 @@ function RecordRTC(mediaStream, config) { * var blob = this.getBlob(); * video.src = this.toURL(); * }); - * + * * // or otherwise * recorder.setRecordingDuration(fiveMinutes).onRecordingStopped(function() { * var blob = this.getBlob(); @@ -781,7 +781,7 @@ function RecordRTC(mediaStream, config) { * @example * alert(recorder.version); */ - version: '5.6.2' + version: '5.6.3' }; if (!this) { @@ -799,7 +799,7 @@ function RecordRTC(mediaStream, config) { return returnObject; } -RecordRTC.version = '5.6.2'; +RecordRTC.version = '5.6.3'; if (typeof module !== 'undefined' /* && !!module.exports*/ ) { module.exports = RecordRTC; @@ -2460,8 +2460,8 @@ function MediaStreamRecorder(mediaStream, config) { return allStates; }; - // if any Track within the MediaStream is muted or not enabled at any time, - // the browser will only record black frames + // if any Track within the MediaStream is muted or not enabled at any time, + // the browser will only record black frames // or silence since that is the content produced by the Track // so we need to stopRecording as soon as any single track ends. if (typeof config.checkForInactiveTracks === 'undefined') { @@ -2572,8 +2572,8 @@ function StereoAudioRecorder(mediaStream, config) { console.log('StereoAudioRecorder is set to record number of channels: ' + numberOfAudioChannels); } - // if any Track within the MediaStream is muted or not enabled at any time, - // the browser will only record black frames + // if any Track within the MediaStream is muted or not enabled at any time, + // the browser will only record black frames // or silence since that is the content produced by the Track // so we need to stopRecording as soon as any single track ends. if (typeof config.checkForInactiveTracks === 'undefined') { @@ -2732,21 +2732,21 @@ function StereoAudioRecorder(mediaStream, config) { var view = new DataView(buffer); - // RIFF chunk descriptor/identifier + // RIFF chunk descriptor/identifier writeUTFBytes(view, 0, 'RIFF'); // RIFF chunk length // changed "44" to "36" via #401 view.setUint32(4, 36 + interleavedLength * 2, true); - // RIFF type + // RIFF type writeUTFBytes(view, 8, 'WAVE'); - // format chunk identifier + // format chunk identifier // FMT sub-chunk writeUTFBytes(view, 12, 'fmt '); - // format chunk length + // format chunk length view.setUint32(16, 16, true); // sample format (raw) @@ -2755,23 +2755,23 @@ function StereoAudioRecorder(mediaStream, config) { // stereo (2 channels) view.setUint16(22, numberOfAudioChannels, true); - // sample rate + // sample rate view.setUint32(24, sampleRate, true); // byte rate (sample rate * block align) view.setUint32(28, sampleRate * numberOfAudioChannels * 2, true); - // block align (channel count * bytes per sample) + // block align (channel count * bytes per sample) view.setUint16(32, numberOfAudioChannels * 2, true); - // bits per sample + // bits per sample view.setUint16(34, 16, true); // data sub-chunk - // data chunk identifier + // data chunk identifier writeUTFBytes(view, 36, 'data'); - // data chunk length + // data chunk length view.setUint32(40, interleavedLength * 2, true); // write the PCM samples @@ -3326,7 +3326,7 @@ function CanvasRecorder(htmlElement, config) { throw 'captureStream API are NOT available.'; } - // Note: Jan 18, 2016 status is that, + // Note: Jan 18, 2016 status is that, // Firefox MediaRecorder API can't record CanvasCaptureMediaStream object. mediaStreamRecorder = new MediaStreamRecorder(canvasMediaStream, { mimeType: config.mimeType || 'video/webm' @@ -4570,9 +4570,7 @@ if (typeof RecordRTC !== 'undefined') { function GifRecorder(mediaStream, config) { if (typeof GIFEncoder === 'undefined') { - var script = document.createElement('script'); - script.src = 'https://www.webrtc-experiment.com/gif-recorder.js'; - (document.body || document.documentElement).appendChild(script); + throw new Error('Missing https://www.webrtc-experiment.com/gif-recorder.js'); } config = config || {}; @@ -4630,27 +4628,27 @@ function GifRecorder(mediaStream, config) { // external library to record as GIF images gifEncoder = new GIFEncoder(); - // void setRepeat(int iter) - // Sets the number of times the set of GIF frames should be played. + // void setRepeat(int iter) + // Sets the number of times the set of GIF frames should be played. // Default is 1; 0 means play indefinitely. gifEncoder.setRepeat(0); - // void setFrameRate(Number fps) - // Sets frame rate in frames per second. + // void setFrameRate(Number fps) + // Sets frame rate in frames per second. // Equivalent to setDelay(1000/fps). // Using "setDelay" instead of "setFrameRate" gifEncoder.setDelay(config.frameRate || 200); - // void setQuality(int quality) - // Sets quality of color quantization (conversion of images to the - // maximum 256 colors allowed by the GIF specification). - // Lower values (minimum = 1) produce better colors, - // but slow processing significantly. 10 is the default, - // and produces good color mapping at reasonable speeds. + // void setQuality(int quality) + // Sets quality of color quantization (conversion of images to the + // maximum 256 colors allowed by the GIF specification). + // Lower values (minimum = 1) produce better colors, + // but slow processing significantly. 10 is the default, + // and produces good color mapping at reasonable speeds. // Values greater than 20 do not yield significant improvements in speed. gifEncoder.setQuality(config.quality || 10); - // Boolean start() + // Boolean start() // This writes the GIF Header and returns false if it fails. gifEncoder.start(); @@ -5670,7 +5668,7 @@ if (typeof RecordRTC !== 'undefined') { * recorder.startRecording() * .then(successCB) * .catch(errorCB); - * // Note: You can access all RecordRTC API using "recorder.recordRTC" e.g. + * // Note: You can access all RecordRTC API using "recorder.recordRTC" e.g. * recorder.recordRTC.onStateChanged = function(state) {}; * recorder.recordRTC.setRecordingDuration(5000); * @see {@link https://github.com/muaz-khan/RecordRTC|RecordRTC Source Code} @@ -5841,7 +5839,7 @@ function RecordRTCPromisesHandler(mediaStream, options) { * internalRecorder.addStreams([newAudioStream]); * internalRecorder.resetVideoStreams([screenStream]); * } - * @returns {Object} + * @returns {Object} */ this.getInternalRecorder = function() { return new Promise(function(resolve, reject) { @@ -5927,7 +5925,7 @@ function RecordRTCPromisesHandler(mediaStream, options) { * @example * alert(recorder.version); */ - this.version = '5.6.2'; + this.version = '5.6.3'; } if (typeof RecordRTC !== 'undefined') { diff --git a/resources/static/adapter-latest.js b/resources/static/adapter-latest.js index 0ee2b96..314710a 100644 --- a/resources/static/adapter-latest.js +++ b/resources/static/adapter-latest.js @@ -10,46 +10,27 @@ 'use strict'; -var _adapter_factory = require('./adapter_factory.js'); - -var adapter = (0, _adapter_factory.adapterFactory)({ window: typeof window === 'undefined' ? undefined : window }); +var _adapter_factory = require("./adapter_factory.js"); +var adapter = (0, _adapter_factory.adapterFactory)({ + window: typeof window === 'undefined' ? undefined : window +}); module.exports = adapter; // this is the difference from adapter_core. },{"./adapter_factory.js":2}],2:[function(require,module,exports){ -'use strict'; +"use strict"; +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } Object.defineProperty(exports, "__esModule", { value: true }); exports.adapterFactory = adapterFactory; - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -var _chrome_shim = require('./chrome/chrome_shim'); - -var chromeShim = _interopRequireWildcard(_chrome_shim); - -var _firefox_shim = require('./firefox/firefox_shim'); - -var firefoxShim = _interopRequireWildcard(_firefox_shim); - -var _safari_shim = require('./safari/safari_shim'); - -var safariShim = _interopRequireWildcard(_safari_shim); - -var _common_shim = require('./common_shim'); - -var commonShim = _interopRequireWildcard(_common_shim); - -var _sdp = require('sdp'); - -var sdp = _interopRequireWildcard(_sdp); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -// Shimming starts here. +var utils = _interopRequireWildcard(require("./utils")); +var chromeShim = _interopRequireWildcard(require("./chrome/chrome_shim")); +var firefoxShim = _interopRequireWildcard(require("./firefox/firefox_shim")); +var safariShim = _interopRequireWildcard(require("./safari/safari_shim")); +var commonShim = _interopRequireWildcard(require("./common_shim")); +var sdp = _interopRequireWildcard(require("sdp")); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -57,20 +38,21 @@ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; * that can be found in the LICENSE file in the root of the source * tree. */ + +// Browser shims. + +// Shimming starts here. function adapterFactory() { var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, - window = _ref.window; - + window = _ref.window; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { shimChrome: true, shimFirefox: true, shimSafari: true }; - // Utils. var logging = utils.log; var browserDetails = utils.detectBrowser(window); - var adapter = { browserDetails: browserDetails, commonShim: commonShim, @@ -98,18 +80,17 @@ function adapterFactory() { // Must be called before shimPeerConnection. commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails); - + commonShim.shimParameterlessSetLocalDescription(window, browserDetails); chromeShim.shimGetUserMedia(window, browserDetails); chromeShim.shimMediaStream(window, browserDetails); chromeShim.shimPeerConnection(window, browserDetails); chromeShim.shimOnTrack(window, browserDetails); chromeShim.shimAddTrackRemoveTrack(window, browserDetails); chromeShim.shimGetSendersWithDtmf(window, browserDetails); - chromeShim.shimGetStats(window, browserDetails); chromeShim.shimSenderReceiverGetStats(window, browserDetails); chromeShim.fixNegotiationNeeded(window, browserDetails); - commonShim.shimRTCIceCandidate(window, browserDetails); + commonShim.shimRTCIceCandidateRelayProtocol(window, browserDetails); commonShim.shimConnectionState(window, browserDetails); commonShim.shimMaxMessageSize(window, browserDetails); commonShim.shimSendThrowTypeError(window, browserDetails); @@ -126,9 +107,10 @@ function adapterFactory() { // Must be called before shimPeerConnection. commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails); - + commonShim.shimParameterlessSetLocalDescription(window, browserDetails); firefoxShim.shimGetUserMedia(window, browserDetails); firefoxShim.shimPeerConnection(window, browserDetails); + firefoxShim.shimGetStats(window, browserDetails); firefoxShim.shimOnTrack(window, browserDetails); firefoxShim.shimRemoveStream(window, browserDetails); firefoxShim.shimSenderGetStats(window, browserDetails); @@ -138,7 +120,6 @@ function adapterFactory() { firefoxShim.shimGetParameters(window, browserDetails); firefoxShim.shimCreateOffer(window, browserDetails); firefoxShim.shimCreateAnswer(window, browserDetails); - commonShim.shimRTCIceCandidate(window, browserDetails); commonShim.shimConnectionState(window, browserDetails); commonShim.shimMaxMessageSize(window, browserDetails); @@ -155,7 +136,7 @@ function adapterFactory() { // Must be called before shimCallbackAPI. commonShim.shimAddIceCandidateNullOrEmpty(window, browserDetails); - + commonShim.shimParameterlessSetLocalDescription(window, browserDetails); safariShim.shimRTCIceServerUrls(window, browserDetails); safariShim.shimCreateOfferLegacy(window, browserDetails); safariShim.shimCallbacksAPI(window, browserDetails); @@ -164,8 +145,8 @@ function adapterFactory() { safariShim.shimTrackEventTransceiver(window, browserDetails); safariShim.shimGetUserMedia(window, browserDetails); safariShim.shimAudioContext(window, browserDetails); - commonShim.shimRTCIceCandidate(window, browserDetails); + commonShim.shimRTCIceCandidateRelayProtocol(window, browserDetails); commonShim.shimMaxMessageSize(window, browserDetails); commonShim.shimSendThrowTypeError(window, browserDetails); commonShim.removeExtmapAllowMixed(window, browserDetails); @@ -174,13 +155,10 @@ function adapterFactory() { logging('Unsupported browser!'); break; } - return adapter; } -// Browser shims. - -},{"./chrome/chrome_shim":3,"./common_shim":6,"./firefox/firefox_shim":7,"./safari/safari_shim":10,"./utils":11,"sdp":12}],3:[function(require,module,exports){ +},{"./chrome/chrome_shim":3,"./common_shim":5,"./firefox/firefox_shim":6,"./safari/safari_shim":9,"./utils":10,"sdp":11}],3:[function(require,module,exports){ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -194,51 +172,36 @@ function adapterFactory() { Object.defineProperty(exports, "__esModule", { value: true }); -exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined; - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var _getusermedia = require('./getusermedia'); - -Object.defineProperty(exports, 'shimGetUserMedia', { +exports.fixNegotiationNeeded = fixNegotiationNeeded; +exports.shimAddTrackRemoveTrack = shimAddTrackRemoveTrack; +exports.shimAddTrackRemoveTrackWithNative = shimAddTrackRemoveTrackWithNative; +exports.shimGetSendersWithDtmf = shimGetSendersWithDtmf; +Object.defineProperty(exports, "shimGetUserMedia", { enumerable: true, get: function get() { return _getusermedia.shimGetUserMedia; } }); - -var _getdisplaymedia = require('./getdisplaymedia'); - -Object.defineProperty(exports, 'shimGetDisplayMedia', { - enumerable: true, - get: function get() { - return _getdisplaymedia.shimGetDisplayMedia; - } -}); exports.shimMediaStream = shimMediaStream; exports.shimOnTrack = shimOnTrack; -exports.shimGetSendersWithDtmf = shimGetSendersWithDtmf; -exports.shimGetStats = shimGetStats; -exports.shimSenderReceiverGetStats = shimSenderReceiverGetStats; -exports.shimAddTrackRemoveTrackWithNative = shimAddTrackRemoveTrackWithNative; -exports.shimAddTrackRemoveTrack = shimAddTrackRemoveTrack; exports.shimPeerConnection = shimPeerConnection; -exports.fixNegotiationNeeded = fixNegotiationNeeded; - -var _utils = require('../utils.js'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _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; } - +exports.shimSenderReceiverGetStats = shimSenderReceiverGetStats; +var utils = _interopRequireWildcard(require("../utils.js")); +var _getusermedia = require("./getusermedia"); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function shimMediaStream(window) { window.MediaStream = window.MediaStream || window.webkitMediaStream; } - -function shimOnTrack(window) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && !('ontrack' in window.RTCPeerConnection.prototype)) { +function shimOnTrack(window, browserDetails) { + if (browserDetails.version > 102) { + // Unified plan is supported so no need to do anything. + return; + } + if (_typeof(window) === 'object' && window.RTCPeerConnection && !('ontrack' in window.RTCPeerConnection.prototype)) { Object.defineProperty(window.RTCPeerConnection.prototype, 'ontrack', { get: function get() { return this._ontrack; @@ -249,48 +212,53 @@ function shimOnTrack(window) { } this.addEventListener('track', this._ontrack = f); }, - enumerable: true, configurable: true }); var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription() { var _this = this; - if (!this._ontrackpoly) { this._ontrackpoly = function (e) { // onaddstream does not fire when a track is added to an existing // stream. But stream.onaddtrack is implemented so we use that. e.stream.addEventListener('addtrack', function (te) { - var receiver = void 0; + var receiver; if (window.RTCPeerConnection.prototype.getReceivers) { receiver = _this.getReceivers().find(function (r) { return r.track && r.track.id === te.track.id; }); } else { - receiver = { track: te.track }; + receiver = { + track: te.track + }; } - var event = new Event('track'); event.track = te.track; event.receiver = receiver; - event.transceiver = { receiver: receiver }; + event.transceiver = { + receiver: receiver + }; event.streams = [e.stream]; _this.dispatchEvent(event); }); e.stream.getTracks().forEach(function (track) { - var receiver = void 0; + var receiver; if (window.RTCPeerConnection.prototype.getReceivers) { receiver = _this.getReceivers().find(function (r) { return r.track && r.track.id === track.id; }); } else { - receiver = { track: track }; + receiver = { + track: track + }; } var event = new Event('track'); event.track = track; event.receiver = receiver; - event.transceiver = { receiver: receiver }; + event.transceiver = { + receiver: receiver + }; event.streams = [e.stream]; _this.dispatchEvent(event); }); @@ -305,16 +273,19 @@ function shimOnTrack(window) { // to unconditionally wrap the event. utils.wrapPeerConnectionEvent(window, 'track', function (e) { if (!e.transceiver) { - Object.defineProperty(e, 'transceiver', { value: { receiver: e.receiver } }); + Object.defineProperty(e, 'transceiver', { + value: { + receiver: e.receiver + } + }); } return e; }); } } - function shimGetSendersWithDtmf(window) { // Overrides addTrack/removeTrack, depends on shimAddTrackRemoveTrack. - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && !('getSenders' in window.RTCPeerConnection.prototype) && 'createDTMFSender' in window.RTCPeerConnection.prototype) { + if (_typeof(window) === 'object' && window.RTCPeerConnection && !('getSenders' in window.RTCPeerConnection.prototype) && 'createDTMFSender' in window.RTCPeerConnection.prototype) { var shimSenderWithDtmf = function shimSenderWithDtmf(pc, track) { return { track: track, @@ -347,7 +318,6 @@ function shimGetSendersWithDtmf(window) { } return sender; }; - var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) { origRemoveTrack.apply(this, arguments); @@ -360,21 +330,17 @@ function shimGetSendersWithDtmf(window) { var origAddStream = window.RTCPeerConnection.prototype.addStream; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { var _this2 = this; - this._senders = this._senders || []; origAddStream.apply(this, [stream]); stream.getTracks().forEach(function (track) { _this2._senders.push(shimSenderWithDtmf(_this2, track)); }); }; - var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { var _this3 = this; - this._senders = this._senders || []; origRemoveStream.apply(this, [stream]); - stream.getTracks().forEach(function (track) { var sender = _this3._senders.find(function (s) { return s.track === track; @@ -385,18 +351,16 @@ function shimGetSendersWithDtmf(window) { } }); }; - } else if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && 'getSenders' in window.RTCPeerConnection.prototype && 'createDTMFSender' in window.RTCPeerConnection.prototype && window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) { + } else if (_typeof(window) === 'object' && window.RTCPeerConnection && 'getSenders' in window.RTCPeerConnection.prototype && 'createDTMFSender' in window.RTCPeerConnection.prototype && window.RTCRtpSender && !('dtmf' in window.RTCRtpSender.prototype)) { var origGetSenders = window.RTCPeerConnection.prototype.getSenders; window.RTCPeerConnection.prototype.getSenders = function getSenders() { var _this4 = this; - var senders = origGetSenders.apply(this, []); senders.forEach(function (sender) { return sender._pc = _this4; }); return senders; }; - Object.defineProperty(window.RTCRtpSender.prototype, 'dtmf', { get: function get() { if (this._dtmf === undefined) { @@ -411,82 +375,11 @@ function shimGetSendersWithDtmf(window) { }); } } - -function shimGetStats(window) { - if (!window.RTCPeerConnection) { +function shimSenderReceiverGetStats(window, browserDetails) { + if (browserDetails.version >= 67) { return; } - - var origGetStats = window.RTCPeerConnection.prototype.getStats; - window.RTCPeerConnection.prototype.getStats = function getStats() { - var _this5 = this; - - var _arguments = Array.prototype.slice.call(arguments), - selector = _arguments[0], - onSucc = _arguments[1], - onErr = _arguments[2]; - - // If selector is a function then we are in the old style stats so just - // pass back the original getStats format to avoid breaking old users. - - - if (arguments.length > 0 && typeof selector === 'function') { - return origGetStats.apply(this, arguments); - } - - // When spec-style getStats is supported, return those when called with - // either no arguments or the selector argument is null. - if (origGetStats.length === 0 && (arguments.length === 0 || typeof selector !== 'function')) { - return origGetStats.apply(this, []); - } - - var fixChromeStats_ = function fixChromeStats_(response) { - var standardReport = {}; - var reports = response.result(); - reports.forEach(function (report) { - var standardStats = { - id: report.id, - timestamp: report.timestamp, - type: { - localcandidate: 'local-candidate', - remotecandidate: 'remote-candidate' - }[report.type] || report.type - }; - report.names().forEach(function (name) { - standardStats[name] = report.stat(name); - }); - standardReport[standardStats.id] = standardStats; - }); - - return standardReport; - }; - - // shim getStats with maplike support - var makeMapStats = function makeMapStats(stats) { - return new Map(Object.keys(stats).map(function (key) { - return [key, stats[key]]; - })); - }; - - if (arguments.length >= 2) { - var successCallbackWrapper_ = function successCallbackWrapper_(response) { - onSucc(makeMapStats(fixChromeStats_(response))); - }; - - return origGetStats.apply(this, [successCallbackWrapper_, selector]); - } - - // promise-support - return new Promise(function (resolve, reject) { - origGetStats.apply(_this5, [function (response) { - resolve(makeMapStats(fixChromeStats_(response))); - }, reject]); - }).then(onSucc, onErr); - }; -} - -function shimSenderReceiverGetStats(window) { - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && window.RTCRtpSender && window.RTCRtpReceiver)) { + if (!(_typeof(window) === 'object' && window.RTCPeerConnection && window.RTCRtpSender && window.RTCRtpReceiver)) { return; } @@ -495,16 +388,14 @@ function shimSenderReceiverGetStats(window) { var origGetSenders = window.RTCPeerConnection.prototype.getSenders; if (origGetSenders) { window.RTCPeerConnection.prototype.getSenders = function getSenders() { - var _this6 = this; - + var _this5 = this; var senders = origGetSenders.apply(this, []); senders.forEach(function (sender) { - return sender._pc = _this6; + return sender._pc = _this5; }); return senders; }; } - var origAddTrack = window.RTCPeerConnection.prototype.addTrack; if (origAddTrack) { window.RTCPeerConnection.prototype.addTrack = function addTrack() { @@ -532,11 +423,10 @@ function shimSenderReceiverGetStats(window) { var origGetReceivers = window.RTCPeerConnection.prototype.getReceivers; if (origGetReceivers) { window.RTCPeerConnection.prototype.getReceivers = function getReceivers() { - var _this7 = this; - + var _this6 = this; var receivers = origGetReceivers.apply(this, []); receivers.forEach(function (receiver) { - return receiver._pc = _this7; + return receiver._pc = _this6; }); return receivers; }; @@ -552,7 +442,6 @@ function shimSenderReceiverGetStats(window) { }); }; } - if (!('getStats' in window.RTCRtpSender.prototype && 'getStats' in window.RTCRtpReceiver.prototype)) { return; } @@ -562,9 +451,9 @@ function shimSenderReceiverGetStats(window) { window.RTCPeerConnection.prototype.getStats = function getStats() { if (arguments.length > 0 && arguments[0] instanceof window.MediaStreamTrack) { var track = arguments[0]; - var sender = void 0; - var receiver = void 0; - var err = void 0; + var sender; + var receiver; + var err; this.getSenders().forEach(function (s) { if (s.track === track) { if (sender) { @@ -596,27 +485,23 @@ function shimSenderReceiverGetStats(window) { return origGetStats.apply(this, arguments); }; } - function shimAddTrackRemoveTrackWithNative(window) { // shim addTrack/removeTrack with native variants in order to make // the interactions with legacy getLocalStreams behave as in other browsers. // Keeps a mapping stream.id => [stream, rtpsenders...] window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() { - var _this8 = this; - + var _this7 = this; this._shimmedLocalStreams = this._shimmedLocalStreams || {}; return Object.keys(this._shimmedLocalStreams).map(function (streamId) { - return _this8._shimmedLocalStreams[streamId][0]; + return _this7._shimmedLocalStreams[streamId][0]; }); }; - var origAddTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) { if (!stream) { return origAddTrack.apply(this, arguments); } this._shimmedLocalStreams = this._shimmedLocalStreams || {}; - var sender = origAddTrack.apply(this, arguments); if (!this._shimmedLocalStreams[stream.id]) { this._shimmedLocalStreams[stream.id] = [stream, sender]; @@ -625,15 +510,12 @@ function shimAddTrackRemoveTrackWithNative(window) { } return sender; }; - var origAddStream = window.RTCPeerConnection.prototype.addStream; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { - var _this9 = this; - + var _this8 = this; this._shimmedLocalStreams = this._shimmedLocalStreams || {}; - stream.getTracks().forEach(function (track) { - var alreadyExists = _this9.getSenders().find(function (s) { + var alreadyExists = _this8.getSenders().find(function (s) { return s.track === track; }); if (alreadyExists) { @@ -647,34 +529,30 @@ function shimAddTrackRemoveTrackWithNative(window) { }); this._shimmedLocalStreams[stream.id] = [stream].concat(newSenders); }; - var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { this._shimmedLocalStreams = this._shimmedLocalStreams || {}; delete this._shimmedLocalStreams[stream.id]; return origRemoveStream.apply(this, arguments); }; - var origRemoveTrack = window.RTCPeerConnection.prototype.removeTrack; window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) { - var _this10 = this; - + var _this9 = this; this._shimmedLocalStreams = this._shimmedLocalStreams || {}; if (sender) { Object.keys(this._shimmedLocalStreams).forEach(function (streamId) { - var idx = _this10._shimmedLocalStreams[streamId].indexOf(sender); + var idx = _this9._shimmedLocalStreams[streamId].indexOf(sender); if (idx !== -1) { - _this10._shimmedLocalStreams[streamId].splice(idx, 1); + _this9._shimmedLocalStreams[streamId].splice(idx, 1); } - if (_this10._shimmedLocalStreams[streamId].length === 1) { - delete _this10._shimmedLocalStreams[streamId]; + if (_this9._shimmedLocalStreams[streamId].length === 1) { + delete _this9._shimmedLocalStreams[streamId]; } }); } return origRemoveTrack.apply(this, arguments); }; } - function shimAddTrackRemoveTrack(window, browserDetails) { if (!window.RTCPeerConnection) { return; @@ -688,24 +566,20 @@ function shimAddTrackRemoveTrack(window, browserDetails) { // to return the original streams. var origGetLocalStreams = window.RTCPeerConnection.prototype.getLocalStreams; window.RTCPeerConnection.prototype.getLocalStreams = function getLocalStreams() { - var _this11 = this; - + var _this0 = this; var nativeStreams = origGetLocalStreams.apply(this); this._reverseStreams = this._reverseStreams || {}; return nativeStreams.map(function (stream) { - return _this11._reverseStreams[stream.id]; + return _this0._reverseStreams[stream.id]; }); }; - var origAddStream = window.RTCPeerConnection.prototype.addStream; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { - var _this12 = this; - + var _this1 = this; this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; - stream.getTracks().forEach(function (track) { - var alreadyExists = _this12.getSenders().find(function (s) { + var alreadyExists = _this1.getSenders().find(function (s) { return s.track === track; }); if (alreadyExists) { @@ -722,20 +596,16 @@ function shimAddTrackRemoveTrack(window, browserDetails) { } origAddStream.apply(this, [stream]); }; - var origRemoveStream = window.RTCPeerConnection.prototype.removeStream; window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; - origRemoveStream.apply(this, [this._streams[stream.id] || stream]); delete this._reverseStreams[this._streams[stream.id] ? this._streams[stream.id].id : stream.id]; delete this._streams[stream.id]; }; - window.RTCPeerConnection.prototype.addTrack = function addTrack(track, stream) { - var _this13 = this; - + var _this10 = this; if (this.signalingState === 'closed') { throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError'); } @@ -747,14 +617,12 @@ function shimAddTrackRemoveTrack(window, browserDetails) { // [[associated MediaStreams]] internal slot. throw new DOMException('The adapter.js addTrack polyfill only supports a single ' + ' stream which is associated with the specified track.', 'NotSupportedError'); } - var alreadyExists = this.getSenders().find(function (s) { return s.track === track; }); if (alreadyExists) { throw new DOMException('Track already exists.', 'InvalidAccessError'); } - this._streams = this._streams || {}; this._reverseStreams = this._reverseStreams || {}; var oldStream = this._streams[stream.id]; @@ -767,7 +635,7 @@ function shimAddTrackRemoveTrack(window, browserDetails) { // Trigger ONN async. Promise.resolve().then(function () { - _this13.dispatchEvent(new Event('negotiationneeded')); + _this10.dispatchEvent(new Event('negotiationneeded')); }); } else { var newStream = new window.MediaStream([track]); @@ -809,13 +677,12 @@ function shimAddTrackRemoveTrack(window, browserDetails) { ['createOffer', 'createAnswer'].forEach(function (method) { var nativeMethod = window.RTCPeerConnection.prototype[method]; var methodObj = _defineProperty({}, method, function () { - var _this14 = this; - + var _this11 = this; var args = arguments; var isLegacyCall = arguments.length && typeof arguments[0] === 'function'; if (isLegacyCall) { return nativeMethod.apply(this, [function (description) { - var desc = replaceInternalStreamId(_this14, description); + var desc = replaceInternalStreamId(_this11, description); args[0].apply(null, [desc]); }, function (err) { if (args[1]) { @@ -824,12 +691,11 @@ function shimAddTrackRemoveTrack(window, browserDetails) { }, arguments[2]]); } return nativeMethod.apply(this, arguments).then(function (description) { - return replaceInternalStreamId(_this14, description); + return replaceInternalStreamId(_this11, description); }); }); window.RTCPeerConnection.prototype[method] = methodObj[method]; }); - var origSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription; window.RTCPeerConnection.prototype.setLocalDescription = function setLocalDescription() { if (!arguments.length || !arguments[0].type) { @@ -851,10 +717,8 @@ function shimAddTrackRemoveTrack(window, browserDetails) { return replaceInternalStreamId(this, description); } }); - window.RTCPeerConnection.prototype.removeTrack = function removeTrack(sender) { - var _this15 = this; - + var _this12 = this; if (this.signalingState === 'closed') { throw new DOMException('The RTCPeerConnection\'s signalingState is \'closed\'.', 'InvalidStateError'); } @@ -870,16 +734,15 @@ function shimAddTrackRemoveTrack(window, browserDetails) { // Search for the native stream the senders track belongs to. this._streams = this._streams || {}; - var stream = void 0; + var stream; Object.keys(this._streams).forEach(function (streamid) { - var hasTrack = _this15._streams[streamid].getTracks().find(function (track) { + var hasTrack = _this12._streams[streamid].getTracks().find(function (track) { return sender.track === track; }); if (hasTrack) { - stream = _this15._streams[streamid]; + stream = _this12._streams[streamid]; } }); - if (stream) { if (stream.getTracks().length === 1) { // if this is the last track of the stream, remove the stream. This @@ -893,7 +756,6 @@ function shimAddTrackRemoveTrack(window, browserDetails) { } }; } - function shimPeerConnection(window, browserDetails) { if (!window.RTCPeerConnection && window.webkitRTCPeerConnection) { // very basic support for old versions. @@ -918,6 +780,10 @@ function shimPeerConnection(window, browserDetails) { // Attempt to fix ONN in plan-b mode. function fixNegotiationNeeded(window, browserDetails) { + if (browserDetails.version > 102) { + // Plan-B is no longer supported. + return; + } utils.wrapPeerConnectionEvent(window, 'negotiationneeded', function (e) { var pc = e.target; if (browserDetails.version < 72 || pc.getConfiguration && pc.getConfiguration().sdpSemantics === 'plan-b') { @@ -929,58 +795,7 @@ function fixNegotiationNeeded(window, browserDetails) { }); } -},{"../utils.js":11,"./getdisplaymedia":4,"./getusermedia":5}],4:[function(require,module,exports){ -/* - * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. - */ -/* eslint-env node */ -'use strict'; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.shimGetDisplayMedia = shimGetDisplayMedia; -function shimGetDisplayMedia(window, getSourceId) { - if (window.navigator.mediaDevices && 'getDisplayMedia' in window.navigator.mediaDevices) { - return; - } - if (!window.navigator.mediaDevices) { - return; - } - // getSourceId is a function that returns a promise resolving with - // the sourceId of the screen/window/tab to be shared. - if (typeof getSourceId !== 'function') { - console.error('shimGetDisplayMedia: getSourceId argument is not ' + 'a function'); - return; - } - window.navigator.mediaDevices.getDisplayMedia = function getDisplayMedia(constraints) { - return getSourceId(constraints).then(function (sourceId) { - var widthSpecified = constraints.video && constraints.video.width; - var heightSpecified = constraints.video && constraints.video.height; - var frameRateSpecified = constraints.video && constraints.video.frameRate; - constraints.video = { - mandatory: { - chromeMediaSource: 'desktop', - chromeMediaSourceId: sourceId, - maxFrameRate: frameRateSpecified || 3 - } - }; - if (widthSpecified) { - constraints.video.mandatory.maxWidth = widthSpecified; - } - if (heightSpecified) { - constraints.video.mandatory.maxHeight = heightSpecified; - } - return window.navigator.mediaDevices.getUserMedia(constraints); - }); - }; -} - -},{}],5:[function(require,module,exports){ +},{"../utils.js":10,"./getusermedia":4}],4:[function(require,module,exports){ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -994,28 +809,18 @@ function shimGetDisplayMedia(window, getSourceId) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - exports.shimGetUserMedia = shimGetUserMedia; - -var _utils = require('../utils.js'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - +var utils = _interopRequireWildcard(require("../utils.js")); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var logging = utils.log; - function shimGetUserMedia(window, browserDetails) { var navigator = window && window.navigator; - if (!navigator.mediaDevices) { return; } - var constraintsToChrome_ = function constraintsToChrome_(c) { - if ((typeof c === 'undefined' ? 'undefined' : _typeof(c)) !== 'object' || c.mandatory || c.optional) { + if (_typeof(c) !== 'object' || c.mandatory || c.optional) { return c; } var cc = {}; @@ -1023,7 +828,9 @@ function shimGetUserMedia(window, browserDetails) { if (key === 'require' || key === 'advanced' || key === 'mediaSource') { return; } - var r = _typeof(c[key]) === 'object' ? c[key] : { ideal: c[key] }; + var r = _typeof(c[key]) === 'object' ? c[key] : { + ideal: c[key] + }; if (r.exact !== undefined && typeof r.exact === 'number') { r.min = r.max = r.exact; } @@ -1064,7 +871,6 @@ function shimGetUserMedia(window, browserDetails) { } return cc; }; - var shimConstraints_ = function shimConstraints_(constraints, func) { if (browserDetails.version >= 61) { return func(constraints); @@ -1085,12 +891,13 @@ function shimGetUserMedia(window, browserDetails) { if (constraints && _typeof(constraints.video) === 'object') { // Shim facingMode for mobile & surface pro. var face = constraints.video.facingMode; - face = face && ((typeof face === 'undefined' ? 'undefined' : _typeof(face)) === 'object' ? face : { ideal: face }); + face = face && (_typeof(face) === 'object' ? face : { + ideal: face + }); var getSupportedFacingModeLies = browserDetails.version < 66; - if (face && (face.exact === 'user' || face.exact === 'environment' || face.ideal === 'user' || face.ideal === 'environment') && !(navigator.mediaDevices.getSupportedConstraints && navigator.mediaDevices.getSupportedConstraints().facingMode && !getSupportedFacingModeLies)) { delete constraints.video.facingMode; - var matches = void 0; + var matches; if (face.exact === 'environment' || face.ideal === 'environment') { matches = ['back', 'rear']; } else if (face.exact === 'user' || face.ideal === 'user') { @@ -1111,7 +918,11 @@ function shimGetUserMedia(window, browserDetails) { dev = devices[devices.length - 1]; // more likely the back cam } if (dev) { - constraints.video.deviceId = face.exact ? { exact: dev.deviceId } : { ideal: dev.deviceId }; + constraints.video.deviceId = face.exact ? { + exact: dev.deviceId + } : { + ideal: dev.deviceId + }; } constraints.video = constraintsToChrome_(constraints.video); logging('chrome: ' + JSON.stringify(constraints)); @@ -1124,7 +935,6 @@ function shimGetUserMedia(window, browserDetails) { logging('chrome: ' + JSON.stringify(constraints)); return func(constraints); }; - var shimError_ = function shimError_(e) { if (browserDetails.version >= 64) { return e; @@ -1150,7 +960,6 @@ function shimGetUserMedia(window, browserDetails) { } }; }; - var getUserMedia_ = function getUserMedia_(constraints, onSuccess, onError) { shimConstraints_(constraints, function (c) { navigator.webkitGetUserMedia(c, onSuccess, function (e) { @@ -1185,7 +994,7 @@ function shimGetUserMedia(window, browserDetails) { } } -},{"../utils.js":11}],6:[function(require,module,exports){ +},{"../utils.js":10}],5:[function(require,module,exports){ /* * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. * @@ -1199,59 +1008,54 @@ function shimGetUserMedia(window, browserDetails) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -exports.shimRTCIceCandidate = shimRTCIceCandidate; -exports.shimMaxMessageSize = shimMaxMessageSize; -exports.shimSendThrowTypeError = shimSendThrowTypeError; -exports.shimConnectionState = shimConnectionState; exports.removeExtmapAllowMixed = removeExtmapAllowMixed; exports.shimAddIceCandidateNullOrEmpty = shimAddIceCandidateNullOrEmpty; - -var _sdp = require('sdp'); - -var _sdp2 = _interopRequireDefault(_sdp); - -var _utils = require('./utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } - +exports.shimConnectionState = shimConnectionState; +exports.shimMaxMessageSize = shimMaxMessageSize; +exports.shimParameterlessSetLocalDescription = shimParameterlessSetLocalDescription; +exports.shimRTCIceCandidate = shimRTCIceCandidate; +exports.shimRTCIceCandidateRelayProtocol = shimRTCIceCandidateRelayProtocol; +exports.shimSendThrowTypeError = shimSendThrowTypeError; +var _sdp = _interopRequireDefault(require("sdp")); +var utils = _interopRequireWildcard(require("./utils")); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } +function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function shimRTCIceCandidate(window) { // foundation is arbitrarily chosen as an indicator for full support for // https://w3c.github.io/webrtc-pc/#rtcicecandidate-interface if (!window.RTCIceCandidate || window.RTCIceCandidate && 'foundation' in window.RTCIceCandidate.prototype) { return; } - var NativeRTCIceCandidate = window.RTCIceCandidate; window.RTCIceCandidate = function RTCIceCandidate(args) { // Remove the a= which shouldn't be part of the candidate string. - if ((typeof args === 'undefined' ? 'undefined' : _typeof(args)) === 'object' && args.candidate && args.candidate.indexOf('a=') === 0) { + if (_typeof(args) === 'object' && args.candidate && args.candidate.indexOf('a=') === 0) { args = JSON.parse(JSON.stringify(args)); - args.candidate = args.candidate.substr(2); + args.candidate = args.candidate.substring(2); } - if (args.candidate && args.candidate.length) { // Augment the native candidate with the parsed fields. var nativeCandidate = new NativeRTCIceCandidate(args); - var parsedCandidate = _sdp2.default.parseCandidate(args.candidate); - var augmentedCandidate = Object.assign(nativeCandidate, parsedCandidate); + var parsedCandidate = _sdp["default"].parseCandidate(args.candidate); + for (var key in parsedCandidate) { + if (!(key in nativeCandidate)) { + Object.defineProperty(nativeCandidate, key, { + value: parsedCandidate[key] + }); + } + } - // Add a serializer that does not serialize the extra attributes. - augmentedCandidate.toJSON = function toJSON() { + // Override serializer to not serialize the extra attributes. + nativeCandidate.toJSON = function toJSON() { return { - candidate: augmentedCandidate.candidate, - sdpMid: augmentedCandidate.sdpMid, - sdpMLineIndex: augmentedCandidate.sdpMLineIndex, - usernameFragment: augmentedCandidate.usernameFragment + candidate: nativeCandidate.candidate, + sdpMid: nativeCandidate.sdpMid, + sdpMLineIndex: nativeCandidate.sdpMLineIndex, + usernameFragment: nativeCandidate.usernameFragment }; }; - return augmentedCandidate; + return nativeCandidate; } return new NativeRTCIceCandidate(args); }; @@ -1269,12 +1073,33 @@ function shimRTCIceCandidate(window) { return e; }); } +function shimRTCIceCandidateRelayProtocol(window) { + if (!window.RTCIceCandidate || window.RTCIceCandidate && 'relayProtocol' in window.RTCIceCandidate.prototype) { + return; + } + // Hook up the augmented candidate in onicecandidate and + // addEventListener('icecandidate', ...) + utils.wrapPeerConnectionEvent(window, 'icecandidate', function (e) { + if (e.candidate) { + var parsedCandidate = _sdp["default"].parseCandidate(e.candidate.candidate); + if (parsedCandidate.type === 'relay') { + // This is a libwebrtc-specific mapping of local type preference + // to relayProtocol. + e.candidate.relayProtocol = { + 0: 'tls', + 1: 'tcp', + 2: 'udp' + }[parsedCandidate.priority >> 24]; + } + } + return e; + }); +} function shimMaxMessageSize(window, browserDetails) { if (!window.RTCPeerConnection) { return; } - if (!('sctp' in window.RTCPeerConnection.prototype)) { Object.defineProperty(window.RTCPeerConnection.prototype, 'sctp', { get: function get() { @@ -1282,19 +1107,17 @@ function shimMaxMessageSize(window, browserDetails) { } }); } - var sctpInDescription = function sctpInDescription(description) { if (!description || !description.sdp) { return false; } - var sections = _sdp2.default.splitSections(description.sdp); + var sections = _sdp["default"].splitSections(description.sdp); sections.shift(); return sections.some(function (mediaSection) { - var mLine = _sdp2.default.parseMLine(mediaSection); + var mLine = _sdp["default"].parseMLine(mediaSection); return mLine && mLine.kind === 'application' && mLine.protocol.indexOf('SCTP') !== -1; }); }; - var getRemoteFirefoxVersion = function getRemoteFirefoxVersion(description) { // TODO: Is there a better solution for detecting Firefox? var match = description.sdp.match(/mozilla...THIS_IS_SDPARTA-(\d+)/); @@ -1305,7 +1128,6 @@ function shimMaxMessageSize(window, browserDetails) { // Test for NaN (yes, this is ugly) return version !== version ? -1 : version; }; - var getCanSendMaxMessageSize = function getCanSendMaxMessageSize(remoteIsFirefox) { // Every implementation we know can send at least 64 KiB. // Note: Although Chrome is technically able to send up to 256 KiB, the @@ -1336,7 +1158,6 @@ function shimMaxMessageSize(window, browserDetails) { } return canSendMaxMessageSize; }; - var getMaxMessageSize = function getMaxMessageSize(description, remoteIsFirefox) { // Note: 65536 bytes is the default value from the SDP spec. Also, // every implementation we know supports receiving 65536 bytes. @@ -1348,10 +1169,9 @@ function shimMaxMessageSize(window, browserDetails) { if (browserDetails.browser === 'firefox' && browserDetails.version === 57) { maxMessageSize = 65535; } - - var match = _sdp2.default.matchPrefix(description.sdp, 'a=max-message-size:'); + var match = _sdp["default"].matchPrefix(description.sdp, 'a=max-message-size:'); if (match.length > 0) { - maxMessageSize = parseInt(match[0].substr(19), 10); + maxMessageSize = parseInt(match[0].substring(19), 10); } else if (browserDetails.browser === 'firefox' && remoteIsFirefox !== -1) { // If the maximum message size is not present in the remote SDP and // both local and remote are Firefox, the remote peer can receive @@ -1360,7 +1180,6 @@ function shimMaxMessageSize(window, browserDetails) { } return maxMessageSize; }; - var origSetRemoteDescription = window.RTCPeerConnection.prototype.setRemoteDescription; window.RTCPeerConnection.prototype.setRemoteDescription = function setRemoteDescription() { this._sctp = null; @@ -1368,21 +1187,18 @@ function shimMaxMessageSize(window, browserDetails) { // As usual, adapter.js has to do an 'ugly worakaround' // to cover up the mess. if (browserDetails.browser === 'chrome' && browserDetails.version >= 76) { - var _getConfiguration = this.getConfiguration(), - sdpSemantics = _getConfiguration.sdpSemantics; - + var _this$getConfiguratio = this.getConfiguration(), + sdpSemantics = _this$getConfiguratio.sdpSemantics; if (sdpSemantics === 'plan-b') { Object.defineProperty(this, 'sctp', { get: function get() { return typeof this._sctp === 'undefined' ? null : this._sctp; }, - enumerable: true, configurable: true }); } } - if (sctpInDescription(arguments[0])) { // Check if the remote is FF. var isFirefox = getRemoteFirefoxVersion(arguments[0]); @@ -1394,7 +1210,7 @@ function shimMaxMessageSize(window, browserDetails) { var remoteMMS = getMaxMessageSize(arguments[0], isFirefox); // Determine final maximum message size - var maxMessageSize = void 0; + var maxMessageSize; if (canSendMMS === 0 && remoteMMS === 0) { maxMessageSize = Number.POSITIVE_INFINITY; } else if (canSendMMS === 0 || remoteMMS === 0) { @@ -1413,20 +1229,24 @@ function shimMaxMessageSize(window, browserDetails) { }); this._sctp = sctp; } - return origSetRemoteDescription.apply(this, arguments); }; } - -function shimSendThrowTypeError(window) { +function shimSendThrowTypeError(window, browserDetails) { if (!(window.RTCPeerConnection && 'createDataChannel' in window.RTCPeerConnection.prototype)) { return; } + if (browserDetails.browser === 'chrome' && browserDetails.version > 149) { + // Fixed by https://issues.chromium.org/issues/490588131 + return; + } // Note: Although Firefox >= 57 has a native implementation, the maximum // message size can be reset for all data channels at a later stage. // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1426831 - + if (browserDetails.browser === 'firefox' && browserDetails.version > 60) { + return; + } function wrapDcSend(dc, pc) { var origDataChannelSend = dc.send; dc.send = function send() { @@ -1469,7 +1289,6 @@ function shimConnectionState(window) { checking: 'connecting' }[this.iceConnectionState] || this.iceConnectionState; }, - enumerable: true, configurable: true }); @@ -1486,11 +1305,9 @@ function shimConnectionState(window) { this.addEventListener('connectionstatechange', this._onconnectionstatechange = cb); } }, - enumerable: true, configurable: true }); - ['setLocalDescription', 'setRemoteDescription'].forEach(function (method) { var origMethod = proto[method]; proto[method] = function () { @@ -1510,7 +1327,6 @@ function shimConnectionState(window) { }; }); } - function removeExtmapAllowMixed(window, browserDetails) { /* remove a=extmap-allow-mixed for webrtc.org < M71 */ if (!window.RTCPeerConnection) { @@ -1519,7 +1335,7 @@ function removeExtmapAllowMixed(window, browserDetails) { if (browserDetails.browser === 'chrome' && browserDetails.version >= 71) { return; } - if (browserDetails.browser === 'safari' && browserDetails.version >= 605) { + if (browserDetails.browser === 'safari' && browserDetails._safariVersion >= 13.1) { return; } var nativeSRD = window.RTCPeerConnection.prototype.setRemoteDescription; @@ -1541,7 +1357,6 @@ function removeExtmapAllowMixed(window, browserDetails) { return nativeSRD.apply(this, arguments); }; } - function shimAddIceCandidateNullOrEmpty(window, browserDetails) { // Support for addIceCandidate(null or undefined) // as well as addIceCandidate({candidate: "", ...}) @@ -1573,7 +1388,56 @@ function shimAddIceCandidateNullOrEmpty(window, browserDetails) { }; } -},{"./utils":11,"sdp":12}],7:[function(require,module,exports){ +// Note: Make sure to call this ahead of APIs that modify +// setLocalDescription.length +function shimParameterlessSetLocalDescription(window, browserDetails) { + if (!(window.RTCPeerConnection && window.RTCPeerConnection.prototype)) { + return; + } + var nativeSetLocalDescription = window.RTCPeerConnection.prototype.setLocalDescription; + if (!nativeSetLocalDescription || nativeSetLocalDescription.length === 0) { + return; + } + window.RTCPeerConnection.prototype.setLocalDescription = function setLocalDescription() { + var _this = this; + var desc = arguments[0] || {}; + if (_typeof(desc) !== 'object' || desc.type && desc.sdp) { + return nativeSetLocalDescription.apply(this, arguments); + } + // The remaining steps should technically happen when SLD comes off the + // RTCPeerConnection's operations chain (not ahead of going on it), but + // this is too difficult to shim. Instead, this shim only covers the + // common case where the operations chain is empty. This is imperfect, but + // should cover many cases. Rationale: Even if we can't reduce the glare + // window to zero on imperfect implementations, there's value in tapping + // into the perfect negotiation pattern that several browsers support. + desc = { + type: desc.type, + sdp: desc.sdp + }; + if (!desc.type) { + switch (this.signalingState) { + case 'stable': + case 'have-local-offer': + case 'have-remote-pranswer': + desc.type = 'offer'; + break; + default: + desc.type = 'answer'; + break; + } + } + if (desc.sdp || desc.type !== 'offer' && desc.type !== 'answer') { + return nativeSetLocalDescription.apply(this, [desc]); + } + var func = desc.type === 'offer' ? this.createOffer : this.createAnswer; + return func.apply(this).then(function (d) { + return nativeSetLocalDescription.apply(_this, [d]); + }); + }; +} + +},{"./utils":10,"sdp":11}],6:[function(require,module,exports){ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -1587,65 +1451,62 @@ function shimAddIceCandidateNullOrEmpty(window, browserDetails) { Object.defineProperty(exports, "__esModule", { value: true }); -exports.shimGetDisplayMedia = exports.shimGetUserMedia = undefined; - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var _getusermedia = require('./getusermedia'); - -Object.defineProperty(exports, 'shimGetUserMedia', { +exports.shimAddTransceiver = shimAddTransceiver; +exports.shimCreateAnswer = shimCreateAnswer; +exports.shimCreateOffer = shimCreateOffer; +Object.defineProperty(exports, "shimGetDisplayMedia", { enumerable: true, get: function get() { - return _getusermedia.shimGetUserMedia; + return _getdisplaymedia.shimGetDisplayMedia; } }); - -var _getdisplaymedia = require('./getdisplaymedia'); - -Object.defineProperty(exports, 'shimGetDisplayMedia', { +exports.shimGetParameters = shimGetParameters; +exports.shimGetStats = shimGetStats; +Object.defineProperty(exports, "shimGetUserMedia", { enumerable: true, get: function get() { - return _getdisplaymedia.shimGetDisplayMedia; + return _getusermedia.shimGetUserMedia; } }); exports.shimOnTrack = shimOnTrack; exports.shimPeerConnection = shimPeerConnection; -exports.shimSenderGetStats = shimSenderGetStats; +exports.shimRTCDataChannel = shimRTCDataChannel; exports.shimReceiverGetStats = shimReceiverGetStats; exports.shimRemoveStream = shimRemoveStream; -exports.shimRTCDataChannel = shimRTCDataChannel; -exports.shimAddTransceiver = shimAddTransceiver; -exports.shimGetParameters = shimGetParameters; -exports.shimCreateOffer = shimCreateOffer; -exports.shimCreateAnswer = shimCreateAnswer; - -var _utils = require('../utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - -function _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; } - +exports.shimSenderGetStats = shimSenderGetStats; +var utils = _interopRequireWildcard(require("../utils")); +var _getusermedia = require("./getusermedia"); +var _getdisplaymedia = require("./getdisplaymedia"); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } +function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } +function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } +function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } +function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } +function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } +function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function shimOnTrack(window) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) { + if (_typeof(window) === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) { Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { get: function get() { - return { receiver: this.receiver }; + return { + receiver: this.receiver + }; } }); } } - function shimPeerConnection(window, browserDetails) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !(window.RTCPeerConnection || window.mozRTCPeerConnection)) { + if (_typeof(window) !== 'object' || !(window.RTCPeerConnection || window.mozRTCPeerConnection)) { return; // probably media.peerconnection.enabled=false in about:config } if (!window.RTCPeerConnection && window.mozRTCPeerConnection) { // very basic support for old versions. window.RTCPeerConnection = window.mozRTCPeerConnection; } - if (browserDetails.version < 53) { // shim away need for obsolete RTCIceCandidate/RTCSessionDescription. ['setLocalDescription', 'setRemoteDescription', 'addIceCandidate'].forEach(function (method) { @@ -1657,7 +1518,15 @@ function shimPeerConnection(window, browserDetails) { window.RTCPeerConnection.prototype[method] = methodObj[method]; }); } - +} +function shimGetStats(window, browserDetails) { + if (_typeof(window) !== 'object' || !(window.RTCPeerConnection || window.mozRTCPeerConnection)) { + return; // probably media.peerconnection.enabled=false in about:config + } + if (browserDetails.version >= 151) { + // https://bugzilla.mozilla.org/show_bug.cgi?id=1056433 + return; + } var modernStatsTypes = { inboundrtp: 'inbound-rtp', outboundrtp: 'outbound-rtp', @@ -1665,14 +1534,16 @@ function shimPeerConnection(window, browserDetails) { localcandidate: 'local-candidate', remotecandidate: 'remote-candidate' }; - var nativeGetStats = window.RTCPeerConnection.prototype.getStats; window.RTCPeerConnection.prototype.getStats = function getStats() { var _arguments = Array.prototype.slice.call(arguments), - selector = _arguments[0], - onSucc = _arguments[1], - onErr = _arguments[2]; - + selector = _arguments[0], + onSucc = _arguments[1], + onErr = _arguments[2]; + if (this.signalingState === 'closed') { + // No longer required in FF151+ + return Promise.resolve(new Map()); + } return nativeGetStats.apply(this, [selector || null]).then(function (stats) { if (browserDetails.version < 53 && !onSucc) { // Shim only promise getStats with spec-hyphens in type names @@ -1697,9 +1568,8 @@ function shimPeerConnection(window, browserDetails) { }).then(onSucc, onErr); }; } - function shimSenderGetStats(window) { - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) { + if (!(_typeof(window) === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) { return; } if (window.RTCRtpSender && 'getStats' in window.RTCRtpSender.prototype) { @@ -1709,7 +1579,6 @@ function shimSenderGetStats(window) { if (origGetSenders) { window.RTCPeerConnection.prototype.getSenders = function getSenders() { var _this = this; - var senders = origGetSenders.apply(this, []); senders.forEach(function (sender) { return sender._pc = _this; @@ -1717,7 +1586,6 @@ function shimSenderGetStats(window) { return senders; }; } - var origAddTrack = window.RTCPeerConnection.prototype.addTrack; if (origAddTrack) { window.RTCPeerConnection.prototype.addTrack = function addTrack() { @@ -1730,9 +1598,8 @@ function shimSenderGetStats(window) { return this.track ? this._pc.getStats(this.track) : Promise.resolve(new Map()); }; } - function shimReceiverGetStats(window) { - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) { + if (!(_typeof(window) === 'object' && window.RTCPeerConnection && window.RTCRtpSender)) { return; } if (window.RTCRtpSender && 'getStats' in window.RTCRtpReceiver.prototype) { @@ -1742,7 +1609,6 @@ function shimReceiverGetStats(window) { if (origGetReceivers) { window.RTCPeerConnection.prototype.getReceivers = function getReceivers() { var _this2 = this; - var receivers = origGetReceivers.apply(this, []); receivers.forEach(function (receiver) { return receiver._pc = _this2; @@ -1758,14 +1624,12 @@ function shimReceiverGetStats(window) { return this._pc.getStats(this.track); }; } - function shimRemoveStream(window) { if (!window.RTCPeerConnection || 'removeStream' in window.RTCPeerConnection.prototype) { return; } window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { var _this3 = this; - utils.deprecated('removeStream', 'removeTrack'); this.getSenders().forEach(function (sender) { if (sender.track && stream.getTracks().includes(sender.track)) { @@ -1774,7 +1638,6 @@ function shimRemoveStream(window) { }); }; } - function shimRTCDataChannel(window) { // rename DataChannel to RTCDataChannel (native fix in FF60): // https://bugzilla.mozilla.org/show_bug.cgi?id=1173851 @@ -1782,23 +1645,27 @@ function shimRTCDataChannel(window) { window.RTCDataChannel = window.DataChannel; } } - function shimAddTransceiver(window) { // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 // Firefox ignores the init sendEncodings options passed to addTransceiver // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection)) { + if (!(_typeof(window) === 'object' && window.RTCPeerConnection)) { return; } var origAddTransceiver = window.RTCPeerConnection.prototype.addTransceiver; if (origAddTransceiver) { window.RTCPeerConnection.prototype.addTransceiver = function addTransceiver() { this.setParametersPromises = []; - var initParameters = arguments[1]; - var shouldPerformCheck = initParameters && 'sendEncodings' in initParameters; + // WebIDL input coercion and validation + var sendEncodings = arguments[1] && arguments[1].sendEncodings; + if (sendEncodings === undefined) { + sendEncodings = []; + } + sendEncodings = _toConsumableArray(sendEncodings); + var shouldPerformCheck = sendEncodings.length > 0; if (shouldPerformCheck) { // If sendEncodings params are provided, validate grammar - initParameters.sendEncodings.forEach(function (encodingParam) { + sendEncodings.forEach(function (encodingParam) { if ('rid' in encodingParam) { var ridRegex = /^[a-z0-9]{0,16}$/i; if (!ridRegex.test(encodingParam.rid)) { @@ -1827,16 +1694,15 @@ function shimAddTransceiver(window) { // the params were asynchronously applied so we might miss the // opportunity to recreate offer. var sender = transceiver.sender; - var params = sender.getParameters(); if (!('encodings' in params) || // Avoid being fooled by patched getParameters() below. params.encodings.length === 1 && Object.keys(params.encodings[0]).length === 0) { - params.encodings = initParameters.sendEncodings; - sender.sendEncodings = initParameters.sendEncodings; + params.encodings = sendEncodings; + sender.sendEncodings = sendEncodings; this.setParametersPromises.push(sender.setParameters(params).then(function () { delete sender.sendEncodings; - }).catch(function () { + })["catch"](function () { delete sender.sendEncodings; })); } @@ -1845,9 +1711,8 @@ function shimAddTransceiver(window) { }; } } - function shimGetParameters(window) { - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCRtpSender)) { + if (!(_typeof(window) === 'object' && window.RTCRtpSender)) { return; } var origGetParameters = window.RTCRtpSender.prototype.getParameters; @@ -1861,46 +1726,42 @@ function shimGetParameters(window) { }; } } - function shimCreateOffer(window) { // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 // Firefox ignores the init sendEncodings options passed to addTransceiver // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection)) { + if (!(_typeof(window) === 'object' && window.RTCPeerConnection)) { return; } var origCreateOffer = window.RTCPeerConnection.prototype.createOffer; window.RTCPeerConnection.prototype.createOffer = function createOffer() { - var _this4 = this, - _arguments2 = arguments; - + var _arguments2 = arguments, + _this4 = this; if (this.setParametersPromises && this.setParametersPromises.length) { return Promise.all(this.setParametersPromises).then(function () { return origCreateOffer.apply(_this4, _arguments2); - }).finally(function () { + })["finally"](function () { _this4.setParametersPromises = []; }); } return origCreateOffer.apply(this, arguments); }; } - function shimCreateAnswer(window) { // https://github.com/webrtcHacks/adapter/issues/998#issuecomment-516921647 // Firefox ignores the init sendEncodings options passed to addTransceiver // https://bugzilla.mozilla.org/show_bug.cgi?id=1396918 - if (!((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCPeerConnection)) { + if (!(_typeof(window) === 'object' && window.RTCPeerConnection)) { return; } var origCreateAnswer = window.RTCPeerConnection.prototype.createAnswer; window.RTCPeerConnection.prototype.createAnswer = function createAnswer() { - var _this5 = this, - _arguments3 = arguments; - + var _arguments3 = arguments, + _this5 = this; if (this.setParametersPromises && this.setParametersPromises.length) { return Promise.all(this.setParametersPromises).then(function () { return origCreateAnswer.apply(_this5, _arguments3); - }).finally(function () { + })["finally"](function () { _this5.setParametersPromises = []; }); } @@ -1908,7 +1769,7 @@ function shimCreateAnswer(window) { }; } -},{"../utils":11,"./getdisplaymedia":8,"./getusermedia":9}],8:[function(require,module,exports){ +},{"../utils":10,"./getdisplaymedia":7,"./getusermedia":8}],7:[function(require,module,exports){ /* * Copyright (c) 2018 The adapter.js project authors. All Rights Reserved. * @@ -1939,7 +1800,9 @@ function shimGetDisplayMedia(window, preferredMediaSource) { return Promise.reject(err); } if (constraints.video === true) { - constraints.video = { mediaSource: preferredMediaSource }; + constraints.video = { + mediaSource: preferredMediaSource + }; } else { constraints.video.mediaSource = preferredMediaSource; } @@ -1947,7 +1810,7 @@ function shimGetDisplayMedia(window, preferredMediaSource) { }; } -},{}],9:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -1961,27 +1824,18 @@ function shimGetDisplayMedia(window, preferredMediaSource) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - exports.shimGetUserMedia = shimGetUserMedia; - -var _utils = require('../utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - +var utils = _interopRequireWildcard(require("../utils")); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function shimGetUserMedia(window, browserDetails) { var navigator = window && window.navigator; var MediaStreamTrack = window && window.MediaStreamTrack; - navigator.getUserMedia = function (constraints, onSuccess, onError) { // Replace Firefox 44+'s deprecation warning with unprefixed version. utils.deprecated('navigator.getUserMedia', 'navigator.mediaDevices.getUserMedia'); navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError); }; - if (!(browserDetails.version > 55 && 'autoGainControl' in navigator.mediaDevices.getSupportedConstraints())) { var remap = function remap(obj, a, b) { if (a in obj && !(b in obj)) { @@ -1989,17 +1843,15 @@ function shimGetUserMedia(window, browserDetails) { delete obj[a]; } }; - var nativeGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices); navigator.mediaDevices.getUserMedia = function (c) { - if ((typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object' && _typeof(c.audio) === 'object') { + if (_typeof(c) === 'object' && _typeof(c.audio) === 'object') { c = JSON.parse(JSON.stringify(c)); remap(c.audio, 'autoGainControl', 'mozAutoGainControl'); remap(c.audio, 'noiseSuppression', 'mozNoiseSuppression'); } return nativeGetUserMedia(c); }; - if (MediaStreamTrack && MediaStreamTrack.prototype.getSettings) { var nativeGetSettings = MediaStreamTrack.prototype.getSettings; MediaStreamTrack.prototype.getSettings = function () { @@ -2009,11 +1861,10 @@ function shimGetUserMedia(window, browserDetails) { return obj; }; } - if (MediaStreamTrack && MediaStreamTrack.prototype.applyConstraints) { var nativeApplyConstraints = MediaStreamTrack.prototype.applyConstraints; MediaStreamTrack.prototype.applyConstraints = function (c) { - if (this.kind === 'audio' && (typeof c === 'undefined' ? 'undefined' : _typeof(c)) === 'object') { + if (this.kind === 'audio' && _typeof(c) === 'object') { c = JSON.parse(JSON.stringify(c)); remap(c, 'autoGainControl', 'mozAutoGainControl'); remap(c, 'noiseSuppression', 'mozNoiseSuppression'); @@ -2024,7 +1875,7 @@ function shimGetUserMedia(window, browserDetails) { } } -},{"../utils":11}],10:[function(require,module,exports){ +},{"../utils":10}],9:[function(require,module,exports){ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -2037,27 +1888,20 @@ function shimGetUserMedia(window, browserDetails) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -exports.shimLocalStreamsAPI = shimLocalStreamsAPI; -exports.shimRemoteStreamsAPI = shimRemoteStreamsAPI; +exports.shimAudioContext = shimAudioContext; exports.shimCallbacksAPI = shimCallbacksAPI; -exports.shimGetUserMedia = shimGetUserMedia; exports.shimConstraints = shimConstraints; +exports.shimCreateOfferLegacy = shimCreateOfferLegacy; +exports.shimGetUserMedia = shimGetUserMedia; +exports.shimLocalStreamsAPI = shimLocalStreamsAPI; exports.shimRTCIceServerUrls = shimRTCIceServerUrls; +exports.shimRemoteStreamsAPI = shimRemoteStreamsAPI; exports.shimTrackEventTransceiver = shimTrackEventTransceiver; -exports.shimCreateOfferLegacy = shimCreateOfferLegacy; -exports.shimAudioContext = shimAudioContext; - -var _utils = require('../utils'); - -var utils = _interopRequireWildcard(_utils); - -function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } - +var utils = _interopRequireWildcard(require("../utils")); +function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } function shimLocalStreamsAPI(window) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !window.RTCPeerConnection) { + if (_typeof(window) !== 'object' || !window.RTCPeerConnection) { return; } if (!('getLocalStreams' in window.RTCPeerConnection.prototype)) { @@ -2072,7 +1916,6 @@ function shimLocalStreamsAPI(window) { var _addTrack = window.RTCPeerConnection.prototype.addTrack; window.RTCPeerConnection.prototype.addStream = function addStream(stream) { var _this = this; - if (!this._localStreams) { this._localStreams = []; } @@ -2088,14 +1931,11 @@ function shimLocalStreamsAPI(window) { return _addTrack.call(_this, track, stream); }); }; - window.RTCPeerConnection.prototype.addTrack = function addTrack(track) { var _this2 = this; - - for (var _len = arguments.length, streams = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + for (var _len = arguments.length, streams = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { streams[_key - 1] = arguments[_key]; } - if (streams) { streams.forEach(function (stream) { if (!_this2._localStreams) { @@ -2111,7 +1951,6 @@ function shimLocalStreamsAPI(window) { if (!('removeStream' in window.RTCPeerConnection.prototype)) { window.RTCPeerConnection.prototype.removeStream = function removeStream(stream) { var _this3 = this; - if (!this._localStreams) { this._localStreams = []; } @@ -2129,9 +1968,8 @@ function shimLocalStreamsAPI(window) { }; } } - function shimRemoteStreamsAPI(window) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !window.RTCPeerConnection) { + if (_typeof(window) !== 'object' || !window.RTCPeerConnection) { return; } if (!('getRemoteStreams' in window.RTCPeerConnection.prototype)) { @@ -2146,7 +1984,6 @@ function shimRemoteStreamsAPI(window) { }, set: function set(f) { var _this4 = this; - if (this._onaddstream) { this.removeEventListener('addstream', this._onaddstream); this.removeEventListener('track', this._onaddstreampoly); @@ -2191,9 +2028,8 @@ function shimRemoteStreamsAPI(window) { }; } } - function shimCallbacksAPI(window) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || !window.RTCPeerConnection) { + if (_typeof(window) !== 'object' || !window.RTCPeerConnection) { return; } var prototype = window.RTCPeerConnection.prototype; @@ -2202,7 +2038,6 @@ function shimCallbacksAPI(window) { var setLocalDescription = prototype.setLocalDescription; var setRemoteDescription = prototype.setRemoteDescription; var addIceCandidate = prototype.addIceCandidate; - prototype.createOffer = function createOffer(successCallback, failureCallback) { var options = arguments.length >= 2 ? arguments[2] : arguments[0]; var promise = origCreateOffer.apply(this, [options]); @@ -2212,7 +2047,6 @@ function shimCallbacksAPI(window) { promise.then(successCallback, failureCallback); return Promise.resolve(); }; - prototype.createAnswer = function createAnswer(successCallback, failureCallback) { var options = arguments.length >= 2 ? arguments[2] : arguments[0]; var promise = origCreateAnswer.apply(this, [options]); @@ -2222,7 +2056,6 @@ function shimCallbacksAPI(window) { promise.then(successCallback, failureCallback); return Promise.resolve(); }; - var withCallback = function withCallback(description, successCallback, failureCallback) { var promise = setLocalDescription.apply(this, [description]); if (!failureCallback) { @@ -2232,7 +2065,6 @@ function shimCallbacksAPI(window) { return Promise.resolve(); }; prototype.setLocalDescription = withCallback; - withCallback = function withCallback(description, successCallback, failureCallback) { var promise = setRemoteDescription.apply(this, [description]); if (!failureCallback) { @@ -2242,7 +2074,6 @@ function shimCallbacksAPI(window) { return Promise.resolve(); }; prototype.setRemoteDescription = withCallback; - withCallback = function withCallback(candidate, successCallback, failureCallback) { var promise = addIceCandidate.apply(this, [candidate]); if (!failureCallback) { @@ -2253,10 +2084,8 @@ function shimCallbacksAPI(window) { }; prototype.addIceCandidate = withCallback; } - function shimGetUserMedia(window) { var navigator = window && window.navigator; - if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { // shim not needed in Safari 12.1 var mediaDevices = navigator.mediaDevices; @@ -2265,22 +2094,20 @@ function shimGetUserMedia(window) { return _getUserMedia(shimConstraints(constraints)); }; } - if (!navigator.getUserMedia && navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.getUserMedia = function getUserMedia(constraints, cb, errcb) { navigator.mediaDevices.getUserMedia(constraints).then(cb, errcb); }.bind(navigator); } } - function shimConstraints(constraints) { if (constraints && constraints.video !== undefined) { - return Object.assign({}, constraints, { video: utils.compactObject(constraints.video) }); + return Object.assign({}, constraints, { + video: utils.compactObject(constraints.video) + }); } - return constraints; } - function shimRTCIceServerUrls(window) { if (!window.RTCPeerConnection) { return; @@ -2292,7 +2119,7 @@ function shimRTCIceServerUrls(window) { var newIceServers = []; for (var i = 0; i < pcConfig.iceServers.length; i++) { var server = pcConfig.iceServers[i]; - if (!server.hasOwnProperty('urls') && server.hasOwnProperty('url')) { + if (server.urls === undefined && server.url) { utils.deprecated('RTCIceServer.url', 'RTCIceServer.urls'); server = JSON.parse(JSON.stringify(server)); server.urls = server.url; @@ -2316,18 +2143,18 @@ function shimRTCIceServerUrls(window) { }); } } - function shimTrackEventTransceiver(window) { // Add event.transceiver member over deprecated event.receiver - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) { + if (_typeof(window) === 'object' && window.RTCTrackEvent && 'receiver' in window.RTCTrackEvent.prototype && !('transceiver' in window.RTCTrackEvent.prototype)) { Object.defineProperty(window.RTCTrackEvent.prototype, 'transceiver', { get: function get() { - return { receiver: this.receiver }; + return { + receiver: this.receiver + }; } }); } } - function shimCreateOfferLegacy(window) { var origCreateOffer = window.RTCPeerConnection.prototype.createOffer; window.RTCPeerConnection.prototype.createOffer = function createOffer(offerOptions) { @@ -2354,9 +2181,10 @@ function shimCreateOfferLegacy(window) { } } } else if (offerOptions.offerToReceiveAudio === true && !audioTransceiver) { - this.addTransceiver('audio'); + this.addTransceiver('audio', { + direction: 'recvonly' + }); } - if (typeof offerOptions.offerToReceiveVideo !== 'undefined') { // support bit values offerOptions.offerToReceiveVideo = !!offerOptions.offerToReceiveVideo; @@ -2379,21 +2207,22 @@ function shimCreateOfferLegacy(window) { } } } else if (offerOptions.offerToReceiveVideo === true && !videoTransceiver) { - this.addTransceiver('video'); + this.addTransceiver('video', { + direction: 'recvonly' + }); } } return origCreateOffer.apply(this, arguments); }; } - function shimAudioContext(window) { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) !== 'object' || window.AudioContext) { + if (_typeof(window) !== 'object' || window.AudioContext) { return; } window.AudioContext = window.webkitAudioContext; } -},{"../utils":11}],11:[function(require,module,exports){ +},{"../utils":10}],10:[function(require,module,exports){ /* * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. * @@ -2407,22 +2236,20 @@ function shimAudioContext(window) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -exports.extractVersion = extractVersion; -exports.wrapPeerConnectionEvent = wrapPeerConnectionEvent; +exports.compactObject = compactObject; +exports.deprecated = deprecated; +exports.detectBrowser = detectBrowser; exports.disableLog = disableLog; exports.disableWarnings = disableWarnings; +exports.extractVersion = extractVersion; +exports.filterStats = filterStats; exports.log = log; -exports.deprecated = deprecated; -exports.detectBrowser = detectBrowser; -exports.compactObject = compactObject; exports.walkStats = walkStats; -exports.filterStats = filterStats; - -function _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; } - +exports.wrapPeerConnectionEvent = wrapPeerConnectionEvent; +function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } +function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; } +function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } +function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); } var logDisabled_ = true; var deprecationWarnings_ = true; @@ -2436,7 +2263,7 @@ var deprecationWarnings_ = true; */ function extractVersion(uastring, expr, pos) { var match = uastring.match(expr); - return match && match.length >= pos && parseInt(match[pos], 10); + return match && match.length >= pos && parseFloat(match[pos], 10); } // Wraps the peerconnection event eventNameToWrap in a function @@ -2446,6 +2273,11 @@ function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { if (!window.RTCPeerConnection) { return; } + var addEventListener = Object.getOwnPropertyDescriptor(EventTarget.prototype, 'addEventListener'); + if (!addEventListener.writable) { + log('Unable to polyfill events'); + return; + } var proto = window.RTCPeerConnection.prototype; var nativeAddEventListener = proto.addEventListener; proto.addEventListener = function (nativeEventName, cb) { @@ -2469,7 +2301,6 @@ function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { this._eventMap[eventNameToWrap].set(cb, wrappedCallback); return nativeAddEventListener.apply(this, [nativeEventName, wrappedCallback]); }; - var nativeRemoveEventListener = proto.removeEventListener; proto.removeEventListener = function (nativeEventName, cb) { if (nativeEventName !== eventNameToWrap || !this._eventMap || !this._eventMap[eventNameToWrap]) { @@ -2479,7 +2310,7 @@ function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { return nativeRemoveEventListener.apply(this, arguments); } var unwrappedCb = this._eventMap[eventNameToWrap].get(cb); - this._eventMap[eventNameToWrap].delete(cb); + this._eventMap[eventNameToWrap]["delete"](cb); if (this._eventMap[eventNameToWrap].size === 0) { delete this._eventMap[eventNameToWrap]; } @@ -2488,7 +2319,6 @@ function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { } return nativeRemoveEventListener.apply(this, [nativeEventName, unwrappedCb]); }; - Object.defineProperty(proto, 'on' + eventNameToWrap, { get: function get() { return this['_on' + eventNameToWrap]; @@ -2502,15 +2332,13 @@ function wrapPeerConnectionEvent(window, eventNameToWrap, wrapper) { this.addEventListener(eventNameToWrap, this['_on' + eventNameToWrap] = cb); } }, - enumerable: true, configurable: true }); } - function disableLog(bool) { if (typeof bool !== 'boolean') { - return new Error('Argument type: ' + (typeof bool === 'undefined' ? 'undefined' : _typeof(bool)) + '. Please use a boolean.'); + return new Error('Argument type: ' + _typeof(bool) + '. Please use a boolean.'); } logDisabled_ = bool; return bool ? 'adapter.js logging disabled' : 'adapter.js logging enabled'; @@ -2522,14 +2350,13 @@ function disableLog(bool) { */ function disableWarnings(bool) { if (typeof bool !== 'boolean') { - return new Error('Argument type: ' + (typeof bool === 'undefined' ? 'undefined' : _typeof(bool)) + '. Please use a boolean.'); + return new Error('Argument type: ' + _typeof(bool) + '. Please use a boolean.'); } deprecationWarnings_ = !bool; return 'adapter.js deprecation warnings ' + (bool ? 'disabled' : 'enabled'); } - function log() { - if ((typeof window === 'undefined' ? 'undefined' : _typeof(window)) === 'object') { + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object') { if (logDisabled_) { return; } @@ -2557,39 +2384,53 @@ function deprecated(oldMethod, newMethod) { */ function detectBrowser(window) { // Returned result object. - var result = { browser: null, version: null }; + var result = { + browser: null, + version: null + }; // Fail early if it's not a browser - if (typeof window === 'undefined' || !window.navigator) { + if (typeof window === 'undefined' || !window.navigator || !window.navigator.userAgent) { result.browser = 'Not a browser.'; return result; } - var navigator = window.navigator; - + // Prefer navigator.userAgentData. + if (navigator.userAgentData && navigator.userAgentData.brands) { + var chromium = navigator.userAgentData.brands.find(function (brand) { + return brand.brand === 'Chromium'; + }); + if (chromium) { + return { + browser: 'chrome', + version: parseInt(chromium.version, 10) + }; + } + } if (navigator.mozGetUserMedia) { // Firefox. result.browser = 'firefox'; - result.version = extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1); - } else if (navigator.webkitGetUserMedia || window.isSecureContext === false && window.webkitRTCPeerConnection && !window.RTCIceGatherer) { + result.version = parseInt(extractVersion(navigator.userAgent, /Firefox\/(\d+)\./, 1)); + } else if (navigator.webkitGetUserMedia || window.isSecureContext === false && window.webkitRTCPeerConnection) { // Chrome, Chromium, Webview, Opera. // Version matches Chrome/WebRTC version. // Chrome 74 removed webkitGetUserMedia on http as well so we need the // more complicated fallback to webkitRTCPeerConnection. result.browser = 'chrome'; - result.version = extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2); + result.version = parseInt(extractVersion(navigator.userAgent, /Chrom(e|ium)\/(\d+)\./, 2)) || null; } else if (window.RTCPeerConnection && navigator.userAgent.match(/AppleWebKit\/(\d+)\./)) { // Safari. result.browser = 'safari'; - result.version = extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1); + result.version = parseInt(extractVersion(navigator.userAgent, /AppleWebKit\/(\d+)\./, 1)); result.supportsUnifiedPlan = window.RTCRtpTransceiver && 'currentDirection' in window.RTCRtpTransceiver.prototype; + // Only for internal usage. + result._safariVersion = extractVersion(navigator.userAgent, /Version\/(\d+(\.?\d+))/, 1); } else { // Default fallthrough: not supported. result.browser = 'Not a supported browser.'; return result; } - return result; } @@ -2612,7 +2453,6 @@ function compactObject(data) { if (!isObject(data)) { return data; } - return Object.keys(data).reduce(function (accumulator, key) { var isObj = isObject(data[key]); var value = isObj ? compactObject(data[key]) : data[key]; @@ -2664,20 +2504,18 @@ function filterStats(result, track, outbound) { return filteredResult; } -},{}],12:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ /* eslint-env node */ 'use strict'; // SDP helpers. -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; - -var SDPUtils = {}; +const SDPUtils = {}; // Generate an alphanumeric identifier for cname or mids. // TODO: use UUIDs instead? https://gist.github.com/jed/982883 SDPUtils.generateIdentifier = function () { - return Math.random().toString(36).substr(2, 10); + return Math.random().toString(36).substring(2, 12); }; // The RTCP CNAME used by all peerconnections from the same JS. @@ -2685,43 +2523,38 @@ SDPUtils.localCName = SDPUtils.generateIdentifier(); // Splits SDP into lines, dealing with both CRLF and LF. SDPUtils.splitLines = function (blob) { - return blob.trim().split('\n').map(function (line) { - return line.trim(); - }); + return blob.trim().split('\n').map(line => line.trim()); }; // Splits SDP into sessionpart and mediasections. Ensures CRLF. SDPUtils.splitSections = function (blob) { - var parts = blob.split('\nm='); - return parts.map(function (part, index) { - return (index > 0 ? 'm=' + part : part).trim() + '\r\n'; - }); + const parts = blob.split('\nm='); + return parts.map((part, index) => (index > 0 ? 'm=' + part : part).trim() + '\r\n'); }; -// returns the session description. +// Returns the session description. SDPUtils.getDescription = function (blob) { - var sections = SDPUtils.splitSections(blob); + const sections = SDPUtils.splitSections(blob); return sections && sections[0]; }; -// returns the individual media sections. +// Returns the individual media sections. SDPUtils.getMediaSections = function (blob) { - var sections = SDPUtils.splitSections(blob); + const sections = SDPUtils.splitSections(blob); sections.shift(); return sections; }; // Returns lines that start with a certain prefix. SDPUtils.matchPrefix = function (blob, prefix) { - return SDPUtils.splitLines(blob).filter(function (line) { - return line.indexOf(prefix) === 0; - }); + return SDPUtils.splitLines(blob).filter(line => line.indexOf(prefix) === 0); }; // Parses an ICE candidate line. Sample input: // candidate:702786350 2 udp 41819902 8.8.8.8 60769 typ relay raddr 8.8.8.8 // rport 55996" +// Input can be prefixed with a=. SDPUtils.parseCandidate = function (line) { - var parts = void 0; + let parts; // Parse both variants. if (line.indexOf('a=candidate:') === 0) { parts = line.substring(12).split(' '); @@ -2729,9 +2562,9 @@ SDPUtils.parseCandidate = function (line) { parts = line.substring(10).split(' '); } - var candidate = { + const candidate = { foundation: parts[0], - component: { 1: 'rtp', 2: 'rtcp' }[parts[1]], + component: { 1: 'rtp', 2: 'rtcp' }[parts[1]] || parts[1], protocol: parts[2].toLowerCase(), priority: parseInt(parts[3], 10), ip: parts[4], @@ -2741,7 +2574,7 @@ SDPUtils.parseCandidate = function (line) { type: parts[7] }; - for (var i = 8; i < parts.length; i += 2) { + for (let i = 8; i < parts.length; i += 2) { switch (parts[i]) { case 'raddr': candidate.relatedAddress = parts[i + 1]; @@ -2768,11 +2601,12 @@ SDPUtils.parseCandidate = function (line) { }; // Translates a candidate object into SDP candidate attribute. +// This does not include the a= prefix! SDPUtils.writeCandidate = function (candidate) { - var sdp = []; + const sdp = []; sdp.push(candidate.foundation); - var component = candidate.component; + const component = candidate.component; if (component === 'rtp') { sdp.push(1); } else if (component === 'rtcp') { @@ -2785,10 +2619,10 @@ SDPUtils.writeCandidate = function (candidate) { sdp.push(candidate.address || candidate.ip); sdp.push(candidate.port); - var type = candidate.type; + const type = candidate.type; sdp.push('typ'); sdp.push(type); - if (type !== 'host' && candidate.relatedAddress && candidate.relatedPort) { + if (type !== 'host' && candidate.relatedAddress && candidate.relatedPort !== undefined) { sdp.push('raddr'); sdp.push(candidate.relatedAddress); sdp.push('rport'); @@ -2806,16 +2640,17 @@ SDPUtils.writeCandidate = function (candidate) { }; // Parses an ice-options line, returns an array of option tags. +// Sample input: // a=ice-options:foo bar SDPUtils.parseIceOptions = function (line) { - return line.substr(14).split(' '); + return line.substring(14).split(' '); }; -// Parses an rtpmap line, returns RTCRtpCoddecParameters. Sample input: +// Parses a rtpmap line, returns RTCRtpCoddecParameters. Sample input: // a=rtpmap:111 opus/48000/2 SDPUtils.parseRtpMap = function (line) { - var parts = line.substr(9).split(' '); - var parsed = { + let parts = line.substring(9).split(' '); + const parsed = { payloadType: parseInt(parts.shift(), 10) // was: id }; @@ -2829,60 +2664,63 @@ SDPUtils.parseRtpMap = function (line) { return parsed; }; -// Generate an a=rtpmap line from RTCRtpCodecCapability or +// Generates a rtpmap line from RTCRtpCodecCapability or // RTCRtpCodecParameters. SDPUtils.writeRtpMap = function (codec) { - var pt = codec.payloadType; + let pt = codec.payloadType; if (codec.preferredPayloadType !== undefined) { pt = codec.preferredPayloadType; } - var channels = codec.channels || codec.numChannels || 1; + const channels = codec.channels || codec.numChannels || 1; return 'a=rtpmap:' + pt + ' ' + codec.name + '/' + codec.clockRate + (channels !== 1 ? '/' + channels : '') + '\r\n'; }; -// Parses an a=extmap line (headerextension from RFC 5285). Sample input: +// Parses a extmap line (headerextension from RFC 5285). Sample input: // a=extmap:2 urn:ietf:params:rtp-hdrext:toffset // a=extmap:2/sendonly urn:ietf:params:rtp-hdrext:toffset SDPUtils.parseExtmap = function (line) { - var parts = line.substr(9).split(' '); + const parts = line.substring(9).split(' '); return { id: parseInt(parts[0], 10), direction: parts[0].indexOf('/') > 0 ? parts[0].split('/')[1] : 'sendrecv', - uri: parts[1] + uri: parts[1], + attributes: parts.slice(2).join(' ') }; }; -// Generates a=extmap line from RTCRtpHeaderExtensionParameters or +// Generates an extmap line from RTCRtpHeaderExtensionParameters or // RTCRtpHeaderExtension. SDPUtils.writeExtmap = function (headerExtension) { - return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) + (headerExtension.direction && headerExtension.direction !== 'sendrecv' ? '/' + headerExtension.direction : '') + ' ' + headerExtension.uri + '\r\n'; + return 'a=extmap:' + (headerExtension.id || headerExtension.preferredId) + (headerExtension.direction && headerExtension.direction !== 'sendrecv' ? '/' + headerExtension.direction : '') + ' ' + headerExtension.uri + (headerExtension.attributes ? ' ' + headerExtension.attributes : '') + '\r\n'; }; -// Parses an ftmp line, returns dictionary. Sample input: +// Parses a fmtp line, returns dictionary. Sample input: // a=fmtp:96 vbr=on;cng=on // Also deals with vbr=on; cng=on +// Non-key-value such as telephone-events `0-15` get parsed as +// {`0-15`:undefined} SDPUtils.parseFmtp = function (line) { - var parsed = {}; - var kv = void 0; - var parts = line.substr(line.indexOf(' ') + 1).split(';'); - for (var j = 0; j < parts.length; j++) { + const parsed = {}; + let kv; + const parts = line.substring(line.indexOf(' ') + 1).split(';'); + for (let j = 0; j < parts.length; j++) { kv = parts[j].trim().split('='); parsed[kv[0].trim()] = kv[1]; } return parsed; }; -// Generates an a=ftmp line from RTCRtpCodecCapability or RTCRtpCodecParameters. +// Generates a fmtp line from RTCRtpCodecCapability or RTCRtpCodecParameters. SDPUtils.writeFmtp = function (codec) { - var line = ''; - var pt = codec.payloadType; + let line = ''; + let pt = codec.payloadType; if (codec.preferredPayloadType !== undefined) { pt = codec.preferredPayloadType; } if (codec.parameters && Object.keys(codec.parameters).length) { - var params = []; - Object.keys(codec.parameters).forEach(function (param) { - if (codec.parameters[param]) { + const params = []; + Object.keys(codec.parameters).forEach(param => { + if (codec.parameters[param] !== undefined) { params.push(param + '=' + codec.parameters[param]); } else { params.push(param); @@ -2893,72 +2731,74 @@ SDPUtils.writeFmtp = function (codec) { return line; }; -// Parses an rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: +// Parses a rtcp-fb line, returns RTCPRtcpFeedback object. Sample input: // a=rtcp-fb:98 nack rpsi SDPUtils.parseRtcpFb = function (line) { - var parts = line.substr(line.indexOf(' ') + 1).split(' '); + const parts = line.substring(line.indexOf(' ') + 1).split(' '); return { type: parts.shift(), parameter: parts.join(' ') }; }; + // Generate a=rtcp-fb lines from RTCRtpCodecCapability or RTCRtpCodecParameters. SDPUtils.writeRtcpFb = function (codec) { - var lines = ''; - var pt = codec.payloadType; + let lines = ''; + let pt = codec.payloadType; if (codec.preferredPayloadType !== undefined) { pt = codec.preferredPayloadType; } if (codec.rtcpFeedback && codec.rtcpFeedback.length) { // FIXME: special handling for trr-int? - codec.rtcpFeedback.forEach(function (fb) { + codec.rtcpFeedback.forEach(fb => { lines += 'a=rtcp-fb:' + pt + ' ' + fb.type + (fb.parameter && fb.parameter.length ? ' ' + fb.parameter : '') + '\r\n'; }); } return lines; }; -// Parses an RFC 5576 ssrc media attribute. Sample input: +// Parses a RFC 5576 ssrc media attribute. Sample input: // a=ssrc:3735928559 cname:something SDPUtils.parseSsrcMedia = function (line) { - var sp = line.indexOf(' '); - var parts = { - ssrc: parseInt(line.substr(7, sp - 7), 10) + const sp = line.indexOf(' '); + const parts = { + ssrc: parseInt(line.substring(7, sp), 10) }; - var colon = line.indexOf(':', sp); + const colon = line.indexOf(':', sp); if (colon > -1) { - parts.attribute = line.substr(sp + 1, colon - sp - 1); - parts.value = line.substr(colon + 1); + parts.attribute = line.substring(sp + 1, colon); + parts.value = line.substring(colon + 1); } else { - parts.attribute = line.substr(sp + 1); + parts.attribute = line.substring(sp + 1); } return parts; }; +// Parse a ssrc-group line (see RFC 5576). Sample input: +// a=ssrc-group:semantics 12 34 SDPUtils.parseSsrcGroup = function (line) { - var parts = line.substr(13).split(' '); + const parts = line.substring(13).split(' '); return { semantics: parts.shift(), - ssrcs: parts.map(function (ssrc) { - return parseInt(ssrc, 10); - }) + ssrcs: parts.map(ssrc => parseInt(ssrc, 10)) }; }; // Extracts the MID (RFC 5888) from a media section. -// returns the MID or undefined if no mid line was found. +// Returns the MID or undefined if no mid line was found. SDPUtils.getMid = function (mediaSection) { - var mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]; + const mid = SDPUtils.matchPrefix(mediaSection, 'a=mid:')[0]; if (mid) { - return mid.substr(6); + return mid.substring(6); } }; +// Parses a fingerprint line for DTLS-SRTP. SDPUtils.parseFingerprint = function (line) { - var parts = line.substr(14).split(' '); + const parts = line.substring(14).split(' '); return { algorithm: parts[0].toLowerCase(), // algorithm is case-sensitive in Edge. - value: parts[1] + value: parts[1].toUpperCase() // the definition is upper-case in RFC 4572. }; }; @@ -2966,9 +2806,8 @@ SDPUtils.parseFingerprint = function (line) { // FIXME: for consistency with other functions this should only // get the fingerprint line as input. See also getIceParameters. SDPUtils.getDtlsParameters = function (mediaSection, sessionpart) { - var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=fingerprint:'); - // Note: a=setup line is ignored since we use the 'auto' role. - // Note2: 'algorithm' is not case sensitive except in Edge. + const lines = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=fingerprint:'); + // Note: a=setup line is ignored since we use the 'auto' role in Edge. return { role: 'auto', fingerprints: lines.map(SDPUtils.parseFingerprint) @@ -2977,8 +2816,8 @@ SDPUtils.getDtlsParameters = function (mediaSection, sessionpart) { // Serializes DTLS parameters to SDP. SDPUtils.writeDtlsParameters = function (params, setupType) { - var sdp = 'a=setup:' + setupType + '\r\n'; - params.fingerprints.forEach(function (fp) { + let sdp = 'a=setup:' + setupType + '\r\n'; + params.fingerprints.forEach(fp => { sdp += 'a=fingerprint:' + fp.algorithm + ' ' + fp.value + '\r\n'; }); return sdp; @@ -2987,7 +2826,7 @@ SDPUtils.writeDtlsParameters = function (params, setupType) { // Parses a=crypto lines into // https://rawgit.com/aboba/edgertc/master/msortc-rs4.html#dictionary-rtcsrtpsdesparameters-members SDPUtils.parseCryptoLine = function (line) { - var parts = line.substr(9).split(' '); + const parts = line.substring(9).split(' '); return { tag: parseInt(parts[0], 10), cryptoSuite: parts[1], @@ -2997,7 +2836,7 @@ SDPUtils.parseCryptoLine = function (line) { }; SDPUtils.writeCryptoLine = function (parameters) { - return 'a=crypto:' + parameters.tag + ' ' + parameters.cryptoSuite + ' ' + (_typeof(parameters.keyParams) === 'object' ? SDPUtils.writeCryptoKeyParams(parameters.keyParams) : parameters.keyParams) + (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') + '\r\n'; + return 'a=crypto:' + parameters.tag + ' ' + parameters.cryptoSuite + ' ' + (typeof parameters.keyParams === 'object' ? SDPUtils.writeCryptoKeyParams(parameters.keyParams) : parameters.keyParams) + (parameters.sessionParams ? ' ' + parameters.sessionParams.join(' ') : '') + '\r\n'; }; // Parses the crypto key parameters into @@ -3006,7 +2845,7 @@ SDPUtils.parseCryptoKeyParams = function (keyParams) { if (keyParams.indexOf('inline:') !== 0) { return null; } - var parts = keyParams.substr(7).split('|'); + const parts = keyParams.substring(7).split('|'); return { keyMethod: 'inline', keySalt: parts[0], @@ -3022,7 +2861,7 @@ SDPUtils.writeCryptoKeyParams = function (keyParams) { // Extracts all SDES parameters. SDPUtils.getCryptoParameters = function (mediaSection, sessionpart) { - var lines = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=crypto:'); + const lines = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=crypto:'); return lines.map(SDPUtils.parseCryptoLine); }; @@ -3030,20 +2869,20 @@ SDPUtils.getCryptoParameters = function (mediaSection, sessionpart) { // FIXME: for consistency with other functions this should only // get the ice-ufrag and ice-pwd lines as input. SDPUtils.getIceParameters = function (mediaSection, sessionpart) { - var ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-ufrag:')[0]; - var pwd = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-pwd:')[0]; + const ufrag = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-ufrag:')[0]; + const pwd = SDPUtils.matchPrefix(mediaSection + sessionpart, 'a=ice-pwd:')[0]; if (!(ufrag && pwd)) { return null; } return { - usernameFragment: ufrag.substr(12), - password: pwd.substr(10) + usernameFragment: ufrag.substring(12), + password: pwd.substring(10) }; }; // Serializes ICE parameters to SDP. SDPUtils.writeIceParameters = function (params) { - var sdp = 'a=ice-ufrag:' + params.usernameFragment + '\r\n' + 'a=ice-pwd:' + params.password + '\r\n'; + let sdp = 'a=ice-ufrag:' + params.usernameFragment + '\r\n' + 'a=ice-pwd:' + params.password + '\r\n'; if (params.iceLite) { sdp += 'a=ice-lite\r\n'; } @@ -3052,21 +2891,22 @@ SDPUtils.writeIceParameters = function (params) { // Parses the SDP media section and returns RTCRtpParameters. SDPUtils.parseRtpParameters = function (mediaSection) { - var description = { + const description = { codecs: [], headerExtensions: [], fecMechanisms: [], rtcp: [] }; - var lines = SDPUtils.splitLines(mediaSection); - var mline = lines[0].split(' '); - for (var i = 3; i < mline.length; i++) { + const lines = SDPUtils.splitLines(mediaSection); + const mline = lines[0].split(' '); + description.profile = mline[2]; + for (let i = 3; i < mline.length; i++) { // find all codecs from mline[3..] - var pt = mline[i]; - var rtpmapline = SDPUtils.matchPrefix(mediaSection, 'a=rtpmap:' + pt + ' ')[0]; + const pt = mline[i]; + const rtpmapline = SDPUtils.matchPrefix(mediaSection, 'a=rtpmap:' + pt + ' ')[0]; if (rtpmapline) { - var codec = SDPUtils.parseRtpMap(rtpmapline); - var fmtps = SDPUtils.matchPrefix(mediaSection, 'a=fmtp:' + pt + ' '); + const codec = SDPUtils.parseRtpMap(rtpmapline); + const fmtps = SDPUtils.matchPrefix(mediaSection, 'a=fmtp:' + pt + ' '); // Only the first a=fmtp: is considered. codec.parameters = fmtps.length ? SDPUtils.parseFmtp(fmtps[0]) : {}; codec.rtcpFeedback = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-fb:' + pt + ' ').map(SDPUtils.parseRtcpFb); @@ -3083,9 +2923,20 @@ SDPUtils.parseRtpParameters = function (mediaSection) { } } } - SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(function (line) { + SDPUtils.matchPrefix(mediaSection, 'a=extmap:').forEach(line => { description.headerExtensions.push(SDPUtils.parseExtmap(line)); }); + const wildcardRtcpFb = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-fb:* ').map(SDPUtils.parseRtcpFb); + description.codecs.forEach(codec => { + wildcardRtcpFb.forEach(fb => { + const duplicate = codec.rtcpFeedback.find(existingFeedback => { + return existingFeedback.type === fb.type && existingFeedback.parameter === fb.parameter; + }); + if (!duplicate) { + codec.rtcpFeedback.push(fb); + } + }); + }); // FIXME: parse rtcp. return description; }; @@ -3093,13 +2944,13 @@ SDPUtils.parseRtpParameters = function (mediaSection) { // Generates parts of the SDP media section describing the capabilities / // parameters. SDPUtils.writeRtpDescription = function (kind, caps) { - var sdp = ''; + let sdp = ''; // Build the mline. sdp += 'm=' + kind + ' '; sdp += caps.codecs.length > 0 ? '9' : '0'; // reject if no codecs. - sdp += ' UDP/TLS/RTP/SAVPF '; - sdp += caps.codecs.map(function (codec) { + sdp += ' ' + (caps.profile || 'UDP/TLS/RTP/SAVPF') + ' '; + sdp += caps.codecs.map(codec => { if (codec.preferredPayloadType !== undefined) { return codec.preferredPayloadType; } @@ -3110,13 +2961,13 @@ SDPUtils.writeRtpDescription = function (kind, caps) { sdp += 'a=rtcp:9 IN IP4 0.0.0.0\r\n'; // Add a=rtpmap lines for each codec. Also fmtp and rtcp-fb. - caps.codecs.forEach(function (codec) { + caps.codecs.forEach(codec => { sdp += SDPUtils.writeRtpMap(codec); sdp += SDPUtils.writeFmtp(codec); sdp += SDPUtils.writeRtcpFb(codec); }); - var maxptime = 0; - caps.codecs.forEach(function (codec) { + let maxptime = 0; + caps.codecs.forEach(codec => { if (codec.maxptime > maxptime) { maxptime = codec.maxptime; } @@ -3126,7 +2977,7 @@ SDPUtils.writeRtpDescription = function (kind, caps) { } if (caps.headerExtensions) { - caps.headerExtensions.forEach(function (extension) { + caps.headerExtensions.forEach(extension => { sdp += SDPUtils.writeExtmap(extension); }); } @@ -3137,33 +2988,27 @@ SDPUtils.writeRtpDescription = function (kind, caps) { // Parses the SDP media section and returns an array of // RTCRtpEncodingParameters. SDPUtils.parseRtpEncodingParameters = function (mediaSection) { - var encodingParameters = []; - var description = SDPUtils.parseRtpParameters(mediaSection); - var hasRed = description.fecMechanisms.indexOf('RED') !== -1; - var hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1; + const encodingParameters = []; + const description = SDPUtils.parseRtpParameters(mediaSection); + const hasRed = description.fecMechanisms.indexOf('RED') !== -1; + const hasUlpfec = description.fecMechanisms.indexOf('ULPFEC') !== -1; // filter a=ssrc:... cname:, ignore PlanB-msid - var ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map(function (line) { - return SDPUtils.parseSsrcMedia(line); - }).filter(function (parts) { - return parts.attribute === 'cname'; - }); - var primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; - var secondarySsrc = void 0; + const ssrcs = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map(line => SDPUtils.parseSsrcMedia(line)).filter(parts => parts.attribute === 'cname'); + const primarySsrc = ssrcs.length > 0 && ssrcs[0].ssrc; + let secondarySsrc; - var flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID').map(function (line) { - var parts = line.substr(17).split(' '); - return parts.map(function (part) { - return parseInt(part, 10); - }); + const flows = SDPUtils.matchPrefix(mediaSection, 'a=ssrc-group:FID').map(line => { + const parts = line.substring(17).split(' '); + return parts.map(part => parseInt(part, 10)); }); if (flows.length > 0 && flows[0].length > 1 && flows[0][0] === primarySsrc) { secondarySsrc = flows[0][1]; } - description.codecs.forEach(function (codec) { + description.codecs.forEach(codec => { if (codec.name.toUpperCase() === 'RTX' && codec.parameters.apt) { - var encParam = { + let encParam = { ssrc: primarySsrc, codecPayloadType: parseInt(codec.parameters.apt, 10) }; @@ -3188,17 +3033,17 @@ SDPUtils.parseRtpEncodingParameters = function (mediaSection) { } // we support both b=AS and b=TIAS but interpret AS as TIAS. - var bandwidth = SDPUtils.matchPrefix(mediaSection, 'b='); + let bandwidth = SDPUtils.matchPrefix(mediaSection, 'b='); if (bandwidth.length) { if (bandwidth[0].indexOf('b=TIAS:') === 0) { - bandwidth = parseInt(bandwidth[0].substr(7), 10); + bandwidth = parseInt(bandwidth[0].substring(7), 10); } else if (bandwidth[0].indexOf('b=AS:') === 0) { // use formula from JSEP to convert b=AS to TIAS value. - bandwidth = parseInt(bandwidth[0].substr(5), 10) * 1000 * 0.95 - 50 * 40 * 8; + bandwidth = parseInt(bandwidth[0].substring(5), 10) * 1000 * 0.95 - 50 * 40 * 8; } else { bandwidth = undefined; } - encodingParameters.forEach(function (params) { + encodingParameters.forEach(params => { params.maxBitrate = bandwidth; }); } @@ -3207,15 +3052,11 @@ SDPUtils.parseRtpEncodingParameters = function (mediaSection) { // parses http://draft.ortc.org/#rtcrtcpparameters* SDPUtils.parseRtcpParameters = function (mediaSection) { - var rtcpParameters = {}; + const rtcpParameters = {}; // Gets the first SSRC. Note that with RTX there might be multiple // SSRCs. - var remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map(function (line) { - return SDPUtils.parseSsrcMedia(line); - }).filter(function (obj) { - return obj.attribute === 'cname'; - })[0]; + const remoteSsrc = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map(line => SDPUtils.parseSsrcMedia(line)).filter(obj => obj.attribute === 'cname')[0]; if (remoteSsrc) { rtcpParameters.cname = remoteSsrc.value; rtcpParameters.ssrc = remoteSsrc.ssrc; @@ -3223,20 +3064,20 @@ SDPUtils.parseRtcpParameters = function (mediaSection) { // Edge uses the compound attribute instead of reducedSize // compound is !reducedSize - var rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize'); + const rsize = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-rsize'); rtcpParameters.reducedSize = rsize.length > 0; rtcpParameters.compound = rsize.length === 0; // parses the rtcp-mux attrŅ–bute. // Note that Edge does not support unmuxed RTCP. - var mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux'); + const mux = SDPUtils.matchPrefix(mediaSection, 'a=rtcp-mux'); rtcpParameters.mux = mux.length > 0; return rtcpParameters; }; SDPUtils.writeRtcpParameters = function (rtcpParameters) { - var sdp = ''; + let sdp = ''; if (rtcpParameters.reducedSize) { sdp += 'a=rtcp-rsize\r\n'; } @@ -3252,17 +3093,13 @@ SDPUtils.writeRtcpParameters = function (rtcpParameters) { // parses either a=msid: or a=ssrc:... msid lines and returns // the id of the MediaStream and MediaStreamTrack. SDPUtils.parseMsid = function (mediaSection) { - var parts = void 0; - var spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:'); + let parts; + const spec = SDPUtils.matchPrefix(mediaSection, 'a=msid:'); if (spec.length === 1) { - parts = spec[0].substr(7).split(' '); + parts = spec[0].substring(7).split(' '); return { stream: parts[0], track: parts[1] }; } - var planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map(function (line) { - return SDPUtils.parseSsrcMedia(line); - }).filter(function (msidParts) { - return msidParts.attribute === 'msid'; - }); + const planB = SDPUtils.matchPrefix(mediaSection, 'a=ssrc:').map(line => SDPUtils.parseSsrcMedia(line)).filter(msidParts => msidParts.attribute === 'msid'); if (planB.length > 0) { parts = planB[0].value.split(' '); return { stream: parts[0], track: parts[1] }; @@ -3273,30 +3110,30 @@ SDPUtils.parseMsid = function (mediaSection) { // parses draft-ietf-mmusic-sctp-sdp-26 first and falls back // to draft-ietf-mmusic-sctp-sdp-05 SDPUtils.parseSctpDescription = function (mediaSection) { - var mline = SDPUtils.parseMLine(mediaSection); - var maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:'); - var maxMessageSize = void 0; + const mline = SDPUtils.parseMLine(mediaSection); + const maxSizeLine = SDPUtils.matchPrefix(mediaSection, 'a=max-message-size:'); + let maxMessageSize; if (maxSizeLine.length > 0) { - maxMessageSize = parseInt(maxSizeLine[0].substr(19), 10); + maxMessageSize = parseInt(maxSizeLine[0].substring(19), 10); } if (isNaN(maxMessageSize)) { maxMessageSize = 65536; } - var sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:'); + const sctpPort = SDPUtils.matchPrefix(mediaSection, 'a=sctp-port:'); if (sctpPort.length > 0) { return { - port: parseInt(sctpPort[0].substr(12), 10), + port: parseInt(sctpPort[0].substring(12), 10), protocol: mline.fmt, - maxMessageSize: maxMessageSize + maxMessageSize }; } - var sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:'); + const sctpMapLines = SDPUtils.matchPrefix(mediaSection, 'a=sctpmap:'); if (sctpMapLines.length > 0) { - var parts = sctpMapLines[0].substr(10).split(' '); + const parts = sctpMapLines[0].substring(10).split(' '); return { port: parseInt(parts[0], 10), protocol: parts[1], - maxMessageSize: maxMessageSize + maxMessageSize }; } }; @@ -3307,7 +3144,7 @@ SDPUtils.parseSctpDescription = function (mediaSection) { // as the draft-ietf-mmusic-sctp-sdp-05 format (indicated by the m-line // protocol of DTLS/SCTP -- without UDP/ or TCP/) SDPUtils.writeSctpDescription = function (media, sctp) { - var output = []; + let output = []; if (media.protocol !== 'DTLS/SCTP') { output = ['m=' + media.kind + ' 9 ' + media.protocol + ' ' + sctp.protocol + '\r\n', 'c=IN IP4 0.0.0.0\r\n', 'a=sctp-port:' + sctp.port + '\r\n']; } else { @@ -3324,7 +3161,7 @@ SDPUtils.writeSctpDescription = function (media, sctp) { // recommends using a cryptographically random +ve 64-bit value // but right now this should be acceptable and within the right range SDPUtils.generateSessionId = function () { - return Math.random().toString().substr(2, 21); + return Math.random().toString().substr(2, 22); }; // Write boiler plate for start of SDP @@ -3333,14 +3170,14 @@ SDPUtils.generateSessionId = function () { // sessVersion is optional and defaults to 2 // sessUser is optional and defaults to 'thisisadapterortc' SDPUtils.writeSessionBoilerplate = function (sessId, sessVer, sessUser) { - var sessionId = void 0; - var version = sessVer !== undefined ? sessVer : 2; + let sessionId; + const version = sessVer !== undefined ? sessVer : 2; if (sessId) { sessionId = sessId; } else { sessionId = SDPUtils.generateSessionId(); } - var user = sessUser || 'thisisadapterortc'; + const user = sessUser || 'thisisadapterortc'; // FIXME: sess-id should be an NTP timestamp. return 'v=0\r\n' + 'o=' + user + ' ' + sessionId + ' ' + version + ' IN IP4 127.0.0.1\r\n' + 's=-\r\n' + 't=0 0\r\n'; }; @@ -3348,14 +3185,14 @@ SDPUtils.writeSessionBoilerplate = function (sessId, sessVer, sessUser) { // Gets the direction from the mediaSection or the sessionpart. SDPUtils.getDirection = function (mediaSection, sessionpart) { // Look for sendrecv, sendonly, recvonly, inactive, default to sendrecv. - var lines = SDPUtils.splitLines(mediaSection); - for (var i = 0; i < lines.length; i++) { + const lines = SDPUtils.splitLines(mediaSection); + for (let i = 0; i < lines.length; i++) { switch (lines[i]) { case 'a=sendrecv': case 'a=sendonly': case 'a=recvonly': case 'a=inactive': - return lines[i].substr(2); + return lines[i].substring(2); default: // FIXME: What should happen here? } @@ -3367,9 +3204,9 @@ SDPUtils.getDirection = function (mediaSection, sessionpart) { }; SDPUtils.getKind = function (mediaSection) { - var lines = SDPUtils.splitLines(mediaSection); - var mline = lines[0].split(' '); - return mline[0].substr(2); + const lines = SDPUtils.splitLines(mediaSection); + const mline = lines[0].split(' '); + return mline[0].substring(2); }; SDPUtils.isRejected = function (mediaSection) { @@ -3377,8 +3214,8 @@ SDPUtils.isRejected = function (mediaSection) { }; SDPUtils.parseMLine = function (mediaSection) { - var lines = SDPUtils.splitLines(mediaSection); - var parts = lines[0].substr(2).split(' '); + const lines = SDPUtils.splitLines(mediaSection); + const parts = lines[0].substring(2).split(' '); return { kind: parts[0], port: parseInt(parts[1], 10), @@ -3388,8 +3225,8 @@ SDPUtils.parseMLine = function (mediaSection) { }; SDPUtils.parseOLine = function (mediaSection) { - var line = SDPUtils.matchPrefix(mediaSection, 'o=')[0]; - var parts = line.substr(2).split(' '); + const line = SDPUtils.matchPrefix(mediaSection, 'o=')[0]; + const parts = line.substring(2).split(' '); return { username: parts[0], sessionId: parts[1], @@ -3405,8 +3242,8 @@ SDPUtils.isValidSDP = function (blob) { if (typeof blob !== 'string' || blob.length === 0) { return false; } - var lines = SDPUtils.splitLines(blob); - for (var i = 0; i < lines.length; i++) { + const lines = SDPUtils.splitLines(blob); + for (let i = 0; i < lines.length; i++) { if (lines[i].length < 2 || lines[i].charAt(1) !== '=') { return false; } @@ -3416,7 +3253,7 @@ SDPUtils.isValidSDP = function (blob) { }; // Expose public methods. -if ((typeof module === 'undefined' ? 'undefined' : _typeof(module)) === 'object') { +if (typeof module === 'object') { module.exports = SDPUtils; } },{}]},{},[1])(1) diff --git a/resources/static/adc_camera.js b/resources/static/adc_camera.js index 1850f0d..21e54e3 100644 --- a/resources/static/adc_camera.js +++ b/resources/static/adc_camera.js @@ -1,9 +1,103 @@ +var videoRecorders = videoRecorders || {}; +var imageStreams = imageStreams || {}; + +function getVideoRecorder(instanceId) { + return videoRecorders[instanceId]; +} + +function setVideoRecorder(instanceId, recorder) { + videoRecorders[instanceId] = recorder; +} + +function getSupportedVideoMimeType() { + if (typeof MediaRecorder === "undefined" || !MediaRecorder.isTypeSupported) { + return ""; + } + + var mimeTypes = [ + "video/webm;codecs=vp9,opus", + "video/webm;codecs=vp8,opus", + "video/webm;codecs=h264,opus", + "video/webm", + "video/mp4;codecs=h264,aac", + "video/mp4" + ]; + + for (var i = 0; i < mimeTypes.length; i++) { + if (MediaRecorder.isTypeSupported(mimeTypes[i])) { + return mimeTypes[i]; + } + } + + return ""; +} + +function getVideoFileExtension(blob) { + if (!blob || !blob.type) { + return "webm"; + } + + var mimeType = blob.type.toLowerCase(); + + if (mimeType.indexOf("mp4") > -1) { + return "mp4"; + } + + if (mimeType.indexOf("webm") > -1) { + return "webm"; + } + + if (mimeType.indexOf("ogg") > -1) { + return "ogv"; + } + + return "webm"; +} + +function getVideoFileName(blob, baseName) { + return (baseName || "my_video") + "." + getVideoFileExtension(blob); +} + +function stopStreamTracks(stream) { + if (!stream || !stream.getTracks) { + return; + } + + var tracks = stream.getTracks(); + + for (var i = 0; i < tracks.length; i++) { + try { + tracks[i].stop(); + } catch (e) {} + } +} + +function clearMediaSource(mediaElement) { + if (!mediaElement) { + return; + } + + try { + mediaElement.pause(); + } catch (e) {} + + if ("srcObject" in mediaElement && mediaElement.srcObject) { + mediaElement.srcObject = null; + } + + mediaElement.removeAttribute("src"); + + try { + mediaElement.load(); + } catch (e) {} +} + function showOverlay(instanceId){ - removeClass(getElementByDynamicId("overlay_loader", instanceId),'hidden'); + removeClass(getElementByDynamicId("overlay_loader", instanceId), 'hidden'); } function hideOverlay(instanceId){ - addClass(getElementByDynamicId("overlay_loader", instanceId),'hidden'); + addClass(getElementByDynamicId("overlay_loader", instanceId), 'hidden'); } /* @@ -11,28 +105,45 @@ function hideOverlay(instanceId){ * Save the recorded video on the user's disk */ function saveVideo(instanceId){ - hideErrorMessage(instanceId); + hideErrorMessage(instanceId); hideSuccessMessage(instanceId); - var video = document.getElementById("player"); + + var video = getElementByDynamicId("player", instanceId); + var recorder = getVideoRecorder(instanceId); + if (!hasClass(video, "saved")) { - if(videoRecorder != undefined){ - if (window.navigator.msSaveOrOpenBlob) { // Edge - window.navigator.msSaveOrOpenBlob(videoRecorder.blob, "my_video.mp4"); - } else { // Others + if (recorder != undefined && recorder.blob) { + var fileName = getVideoFileName(recorder.blob, "my_video"); + + if (window.navigator.msSaveOrOpenBlob) { + window.navigator.msSaveOrOpenBlob(recorder.blob, fileName); + } else { var a = document.createElement("a"); - a.href = video.src; - a.download = "my_video.mp4"; + var objectUrl = video.src; + + if (!objectUrl) { + objectUrl = URL.createObjectURL(recorder.blob); + } + + a.href = objectUrl; + a.download = fileName; document.body.appendChild(a); a.click(); + setTimeout(function() { document.body.removeChild(a); - window.URL.revokeObjectURL(video.src); }, 0); } + addClass(video, "saved"); - getElementByDynamicId("btnSave", instanceId).disabled = true; + + var saveBtn = getElementByDynamicId("btnSave", instanceId); + if (saveBtn) { + saveBtn.disabled = true; + } + displaySuccessMessage(uploadConfig(instanceId).SuccessMsgSave, uploadConfig(instanceId).SuccessMsgColor, instanceId); - } else{ + } else { displayErrorMessage(uploadConfig(instanceId).ErrMsgSave, instanceId); } } @@ -43,26 +154,30 @@ function saveVideo(instanceId){ * Save the captured photo on the user's disk */ function saveImage(instanceId){ - hideErrorMessage(instanceId); + hideErrorMessage(instanceId); hideSuccessMessage(instanceId); - var image = document.getElementById("capturedImage"); - if(!image.hasAttribute('hidden')){ - if (window.navigator.msSaveOrOpenBlob) { // Edge - var blob = document.getElementById("canvas").msToBlob(); + + var image = getElementByDynamicId("capturedImage", instanceId); + var canvas = getElementByDynamicId("canvas", instanceId); + + if (image && !image.hasAttribute('hidden')) { + if (window.navigator.msSaveOrOpenBlob) { + var blob = canvas.msToBlob(); window.navigator.msSaveOrOpenBlob(blob, "my_image.png"); - } else { // Others + } else { var a = document.createElement("a"); a.href = image.src; a.download = "my_image.png"; document.body.appendChild(a); a.click(); + setTimeout(function() { document.body.removeChild(a); - window.URL.revokeObjectURL(image.src); }, 0); } + displaySuccessMessage(uploadConfig(instanceId).SuccessMsgSave, uploadConfig(instanceId).SuccessMsgColor, instanceId); - } else{ + } else { displayErrorMessage(uploadConfig(instanceId).ErrMsgSave, instanceId); } } @@ -72,29 +187,28 @@ function saveImage(instanceId){ * Upload the recorded video on the server */ function uploadVideo(instanceId){ - hideErrorMessage(instanceId); + hideErrorMessage(instanceId); hideSuccessMessage(instanceId); if (!uploadConfig(instanceId).apiKey || !uploadConfig(instanceId).secretKey) { - displayErrorMessage(uploadConfig(instanceId).ErrMsgInvalidApiSecretKeys, instanceId); + displayErrorMessage(uploadConfig(instanceId).ErrMsgInvalidApiSecretKeys, instanceId); return; } - if(videoRecorder != undefined){ // if a video has been recorded - var videoBlob; - videoBlob = videoRecorder.blob; + var recorder = getVideoRecorder(instanceId); + + if (recorder != undefined && recorder.blob) { + var videoBlob = recorder.blob; - if(validFileSize(instanceId, videoBlob)){ + if (validFileSize(instanceId, videoBlob)) { generateNewToken(function(token){ - uploadConfig(instanceId).token=token; + uploadConfig(instanceId).token = token; sendFileTransferCall(instanceId, videoBlob, 'video'); }, instanceId); - } - else{ + } else { displayErrorMessage(uploadConfig(instanceId).ErrMsgFileSizeExceeded, instanceId); } - } - else{ + } else { displayErrorMessage(uploadConfig(instanceId).ErrMsgSelectFile, instanceId); } } @@ -104,34 +218,37 @@ function uploadVideo(instanceId){ * Upload the captured photo on the server */ function uploadImage(instanceId){ - hideErrorMessage(instanceId); + hideErrorMessage(instanceId); hideSuccessMessage(instanceId); if (!uploadConfig(instanceId).apiKey || !uploadConfig(instanceId).secretKey) { - displayErrorMessage(uploadConfig(instanceId).ErrMsgInvalidApiSecretKeys, instanceId); + displayErrorMessage(uploadConfig(instanceId).ErrMsgInvalidApiSecretKeys, instanceId); + return; + } + + var image = getElementByDynamicId("capturedImage", instanceId); + + if (!image || image.hasAttribute("hidden") || !image.src) { + displayErrorMessage(uploadConfig(instanceId).ErrMsgSelectFile, instanceId); return; } - var image_b64 = window.atob(document.getElementById("capturedImage").src.split(",")[1]); + + var image_b64 = window.atob(image.src.split(",")[1]); var tmp = new Uint8Array(image_b64.length); + for (var i = 0; i < image_b64.length; i++) { tmp[i] = image_b64.charCodeAt(i); } + var file = new Blob([tmp], {type: "image/png"}); - var image = document.getElementById("capturedImage"); - if(!image.hasAttribute("hidden")){ // if a photo has been captured - if(validFileSize(instanceId, file)){ - generateNewToken(function(token){ - uploadConfig(instanceId).token=token; - sendFileTransferCall(instanceId, file, 'image'); - }, instanceId); - } - else{ - displayErrorMessage(uploadConfig(instanceId).ErrMsgFileSizeExceeded, instanceId); - } - } - else{ - displayErrorMessage(uploadConfig(instanceId).ErrMsgSelectFile, instanceId); + if (validFileSize(instanceId, file)) { + generateNewToken(function(token){ + uploadConfig(instanceId).token = token; + sendFileTransferCall(instanceId, file, 'image'); + }, instanceId); + } else { + displayErrorMessage(uploadConfig(instanceId).ErrMsgFileSizeExceeded, instanceId); } } @@ -143,6 +260,7 @@ function uploadImage(instanceId){ function validFileSize(instanceId, fileData){ var filesize = 0; var maxsize = uploadConfig(instanceId).maxfilesize; + if (fileData) { filesize = fileData.size / 1024; } @@ -150,6 +268,7 @@ function validFileSize(instanceId, fileData){ if (fileData && filesize > maxsize) { return false; } + return true; } @@ -159,7 +278,6 @@ function validFileSize(instanceId, fileData){ * Generates tokens for the post call */ function generateNewToken(callback, instanceId) { - var data = { ApiKey: uploadConfig(instanceId).apiKey, SecretKey: uploadConfig(instanceId).secretKey @@ -170,16 +288,17 @@ function generateNewToken(callback, instanceId) { var generateTokenSuccess = function (token) { callback(token); }; - var generateTokenError = function (error) { + + var generateTokenError = function () { hideOverlay(instanceId); displayErrorMessage(uploadConfig(instanceId).ErrMsgInvalidApiSecretKeys, instanceId); }; - var generateTokenBeforeSend=function(){ + + var generateTokenBeforeSend = function(){ showOverlay(instanceId); }; - sendAjaxPostCall(url, data, true, generateTokenSuccess, generateTokenError,generateTokenBeforeSend); - + sendAjaxPostCall(url, data, true, generateTokenSuccess, generateTokenError, generateTokenBeforeSend); } /* @@ -189,7 +308,7 @@ function generateNewToken(callback, instanceId) { * Generates right url, success and error callbacks and transfers it to sendAjaxPostCall function */ function sendFileTransferCall(instanceId, fileData, type) { - if(!uploadConfig(instanceId).token){ + if (!uploadConfig(instanceId).token) { displayErrorMessage(uploadConfig(instanceId).ErrMsgToken, instanceId); return; } @@ -200,40 +319,47 @@ function sendFileTransferCall(instanceId, fileData, type) { var guid = uploadConfig(instanceId).guidstring; var fileDataName = function () { - if (type == 'video') return 'file-name.webm'; - if (type == 'image') return 'file-name.png'; - } + if (type == 'video') return getVideoFileName(fileData, 'file-name'); + if (type == 'image') return 'file-name.png'; + return 'file-name'; + }; - // clean up guid of curly braces if (guid.charAt(0) == "{") guid = guid.substr(1); if (guid.charAt(guid.length - 1) == "}") guid = guid.substr(0, guid.length - 1); - var url=uploadConfig(instanceId).uploadUrl + "?tokenkey=" + uploadConfig(instanceId).token + "&filename=" + fileDataName() - + "&projectname=" + projectName + "&shortcut=" + shortcut + "&seed=" + seed + "&guid=" + guid; + var url = uploadConfig(instanceId).uploadUrl + + "?tokenkey=" + encodeURIComponent(uploadConfig(instanceId).token) + + "&filename=" + encodeURIComponent(fileDataName()) + + "&projectname=" + encodeURIComponent(projectName) + + "&shortcut=" + encodeURIComponent(shortcut) + + "&seed=" + encodeURIComponent(seed) + + "&guid=" + encodeURIComponent(guid); var uploadSuccessCallback = function (response) { - getElementByDynamicId("HidResult", instanceId).value=response.DestinationFileName; + getElementByDynamicId("HidResult", instanceId).value = response.DestinationFileName; displaySuccessMessage(uploadConfig(instanceId).SuccessMsgUpload, uploadConfig(instanceId).SuccessMsgColor, instanceId); hideOverlay(instanceId); + if (uploadConfig(instanceId).disabledUploadBtn == 1) { - disableUploadBtn(instanceId); + disableUploadBtn(instanceId); } + if (uploadConfig(instanceId).AutoSubmitAfterUpload == 1) { - document.getElementsByTagName("form")[0].submit(); + document.getElementsByTagName("form")[0].submit(); } else { if (uploadConfig(instanceId).EnabledNextAfterUpload == 1) { document.getElementsByName("Next")[0].hidden = false; } } }; - var uploadErrorCallback = function (error) { - getElementByDynamicId("HidResult", instanceId).value=''; + + var uploadErrorCallback = function () { + getElementByDynamicId("HidResult", instanceId).value = ''; displayErrorMessage(uploadConfig(instanceId).ErrMsgErrorAtUpload, instanceId); hideOverlay(instanceId); }; sendAjaxPostCall(url, fileData, false, uploadSuccessCallback, uploadErrorCallback); - } /* @@ -245,9 +371,10 @@ function sendFileTransferCall(instanceId, fileData, type) { * beforeSend {Function} Function to execute before sending request (optional) * Send the request and execute the callbacks */ -function sendAjaxPostCall(url, data, isJsonRequest, successCallback, errorCallback,beforeSend) { +function sendAjaxPostCall(url, data, isJsonRequest, successCallback, errorCallback, beforeSend) { var http = new XMLHttpRequest(); http.open("POST", url, true); + if (isJsonRequest) { http.setRequestHeader("Content-type", "application/json"); data = JSON.stringify(data); @@ -255,18 +382,26 @@ function sendAjaxPostCall(url, data, isJsonRequest, successCallback, errorCallba http.onreadystatechange = function () { if (http.readyState == 4) { + var response = null; + + try { + response = JSON.parse(http.responseText); + } catch (e) { + response = http.responseText; + } + if (http.status == 200) { - var response = JSON.parse(http.responseText); successCallback(response); } else { - var response = JSON.parse(http.responseText); errorCallback(response); } } - } - if(beforeSend){ + }; + + if (beforeSend) { beforeSend(); } + http.send(data); } @@ -275,8 +410,12 @@ function sendAjaxPostCall(url, data, isJsonRequest, successCallback, errorCallba * cls {String} A class * Returns a boolean depending on the element ele having the class cls or not */ -function hasClass(ele,cls) { - return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')); +function hasClass(ele, cls) { + if (!ele || !ele.className) { + return false; + } + + return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')); } /* @@ -284,10 +423,14 @@ function hasClass(ele,cls) { * cls {String} A class * Removes the class cls from element ele, if ele has the class cls */ -function removeClass(ele,cls) { - if (hasClass(ele,cls)) { - var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)'); - ele.className=ele.className.replace(reg,' '); +function removeClass(ele, cls) { + if (!ele) { + return; + } + + if (hasClass(ele, cls)) { + var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'); + ele.className = ele.className.replace(reg, ' '); } } @@ -296,9 +439,13 @@ function removeClass(ele,cls) { * cls {String} A class * Add the class cls to the element ele, if ele has not the class cls already */ -function addClass(ele,cls) { - if (!hasClass(ele,cls)) { - ele.className += ' '+ cls; +function addClass(ele, cls) { + if (!ele) { + return; + } + + if (!hasClass(ele, cls)) { + ele.className += ' ' + cls; } } @@ -309,11 +456,14 @@ function addClass(ele,cls) { */ function displayErrorMessage(message, instanceId){ hideOverlay(instanceId); + var div = getElementByDynamicId("adc-errdiv", instanceId); addClass(div, "askia-errors-summary"); div.style.marginBottom = "50px"; + var ul = getElementByDynamicId("ulErrorMessages", instanceId); ul.innerHTML = ""; + var li = document.createElement("li"); li.appendChild(document.createTextNode(message)); ul.appendChild(li); @@ -327,14 +477,16 @@ function displayErrorMessage(message, instanceId){ */ function displaySuccessMessage(message, colorcode, instanceId){ hideOverlay(instanceId); + var div = getElementByDynamicId("adc-succdiv", instanceId); - div.style.backgroundColor= 'rgb(' + colorcode + ')'; + div.style.backgroundColor = 'rgb(' + colorcode + ')'; div.style.color = 'white'; div.style.width = '100%'; div.style.paddingTop = '15px'; div.style.paddingBottom = '15px'; div.style.marginBottom = '50px'; div.style.borderRadius = '3px'; + var span = getElementByDynamicId("spanSuccessMessage", instanceId); span.innerHTML = message; } @@ -345,8 +497,13 @@ function displaySuccessMessage(message, colorcode, instanceId){ */ function disableUploadBtn(instanceId) { var btn = getElementByDynamicId("btnUpload", instanceId); + + if (!btn) { + return; + } + btn.disabled = true; - addClass(btn,"disabled"); + addClass(btn, "disabled"); btn.style.cursor = "not-allowed"; } @@ -356,8 +513,13 @@ function disableUploadBtn(instanceId) { */ function enableUploadBtn(instanceId) { var btn = getElementByDynamicId("btnUpload", instanceId); - btn.disabled = false; - removeClass(btn,"disabled"); + + if (!btn) { + return; + } + + btn.disabled = false; + removeClass(btn, "disabled"); btn.style.cursor = "pointer"; } @@ -368,6 +530,7 @@ function enableUploadBtn(instanceId) { function hideSuccessMessage(instanceId) { var div = getElementByDynamicId("adc-succdiv", instanceId); div.removeAttribute("style"); + var span = getElementByDynamicId("spanSuccessMessage", instanceId); span.innerHTML = ""; } @@ -380,6 +543,7 @@ function hideErrorMessage(instanceId){ var div = getElementByDynamicId("adc-errdiv", instanceId); removeClass(div, "askia-errors-summary"); div.removeAttribute("style"); + var ul = getElementByDynamicId("ulErrorMessages", instanceId); ul.innerHTML = ""; } @@ -397,7 +561,27 @@ function getElementByDynamicId(elementId, instanceId) { * Return the uploadConfig variable containing properties of the current adc */ function uploadConfig(instanceId) { - return eval('uploadConfig_' + instanceId); + return eval('uploadConfig_' + instanceId); +} + +/* +* instanceId {Integer} ID of the current adc +* Start image preview stream +*/ +function startImagePreview(instanceId) { + var video = getElementByDynamicId('preview', instanceId); + + if (!video) { + return; + } + + navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) { + imageStreams[instanceId] = stream; + setSrcObject(stream, video); + }).catch(function(error) { + displayErrorMessage(uploadConfig(instanceId).ErrMsgUserMediaAccess, instanceId); + console.error("Cannot access media devices: ", error); + }); } /* @@ -405,62 +589,173 @@ function uploadConfig(instanceId) { * Start the record of a video, displays the stream on screen, storing the stream in videoRecorder variable */ function startRecordingVideo(instanceId) { - var video = document.getElementById('player'); - removeClass(document.getElementsByClassName("label-start")[0], "primary"); - addClass(document.getElementsByClassName("label-stop")[0], "primary"); + hideErrorMessage(instanceId); + hideSuccessMessage(instanceId); + + var video = getElementByDynamicId('player', instanceId); + var startBtn = getElementByDynamicId('btn-start-recording', instanceId); + var stopBtn = getElementByDynamicId('btn-stop-recording', instanceId); + var saveBtn = getElementByDynamicId("btnSave", instanceId); + + if (startBtn) { + startBtn.disabled = true; + } + + if (stopBtn) { + stopBtn.disabled = true; + } + removeClass(video, "saved"); - getElementByDynamicId("btnSave",instanceId).disabled = false; + + if (saveBtn) { + saveBtn.disabled = false; + } + if (uploadConfig(instanceId).allowUploadFileChange == 1) { enableUploadBtn(instanceId); } - document.getElementById('btn-start-recording').disabled = true; + + if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { + displayErrorMessage(uploadConfig(instanceId).ErrMsgUserMediaAccess, instanceId); + + if (startBtn) { + startBtn.disabled = false; + } + + return; + } + navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(function(stream) { + clearMediaSource(video); setSrcObject(stream, video); - video.play(); video.muted = true; - videoRecorder = new RecordRTCPromisesHandler(stream, { - mimeType: 'video/mp4', + + var recorderOptions = { + type: "video", audioBitsPerSecond: 128000, - videoBitsPerSecond : 2500000, - }); - videoRecorder.startRecording().then(function() { - console.info('Recording video ...'); - }).catch(function(error) { - displayErrorMessage(uploadConfig(instanceId).ErrMsgStartRec, instanceId); - console.error('Cannot start video recording: ', error); - }); - videoRecorder.stream = stream; - document.getElementById('btn-stop-recording').disabled = false; + videoBitsPerSecond: 2500000 + }; + + var supportedMimeType = getSupportedVideoMimeType(); + + if (supportedMimeType) { + recorderOptions.mimeType = supportedMimeType; + } + + console.log("Selected video MIME type:", supportedMimeType || "browser default"); + + var recorder = new RecordRTCPromisesHandler(stream, recorderOptions); + recorder.stream = stream; + setVideoRecorder(instanceId, recorder); + + var playPromise; + + try { + playPromise = video.play(); + } catch (e) {} + + if (playPromise && typeof playPromise.catch === "function") { + playPromise.catch(function() {}); + } + + return recorder.startRecording(); + }).then(function() { + console.info('Recording video ...'); + + if (stopBtn) { + stopBtn.disabled = false; + } }).catch(function(error) { - displayErrorMessage(uploadConfig(instanceId).ErrMsgUserMediaAccess, instanceId); - console.error("Cannot access media devices: ", error); + console.error('Cannot start video recording: ', error); + displayErrorMessage(uploadConfig(instanceId).ErrMsgStartRec, instanceId); + + var recorder = getVideoRecorder(instanceId); + + if (recorder && recorder.stream) { + stopStreamTracks(recorder.stream); + } + + clearMediaSource(video); + setVideoRecorder(instanceId, undefined); + + if (startBtn) { + startBtn.disabled = false; + } + + if (stopBtn) { + stopBtn.disabled = true; + } }); } /* * instanceId {Integer} ID of the current adc -* Stop the video recording, diplays the recorded video on screen and stores the video in videoRecorder variable +* Stop the video recording, displays the recorded video on screen and stores the video in videoRecorder variable */ function stopRecordingVideo(instanceId) { - removeClass(document.getElementsByClassName("label-stop")[0], "primary"); - addClass(document.getElementsByClassName("label-start")[0], "primary"); - document.getElementById('btn-stop-recording').disabled = true; - var video = document.getElementById('player'); - videoRecorder.stopRecording().then(function() { + var startBtn = getElementByDynamicId('btn-start-recording', instanceId); + var stopBtn = getElementByDynamicId('btn-stop-recording', instanceId); + var video = getElementByDynamicId('player', instanceId); + var recorder = getVideoRecorder(instanceId); + + if (stopBtn) { + stopBtn.disabled = true; + } + + if (!recorder) { + displayErrorMessage(uploadConfig(instanceId).ErrMsgStopRec, instanceId); + + if (startBtn) { + startBtn.disabled = false; + } + + return; + } + + recorder.stopRecording().then(function() { console.info('stopRecording success'); - video.src = URL.createObjectURL(videoRecorder.blob); + clearMediaSource(video); + + if (!recorder.blob) { + throw "Empty video blob."; + } - video.play(); + video.src = URL.createObjectURL(recorder.blob); video.muted = false; - videoRecorder.stream.stop(); - document.getElementById('btn-start-recording').disabled = false; + + try { + video.load(); + } catch (e) {} + + var playPromise; + + try { + playPromise = video.play(); + } catch (e) {} + + if (playPromise && typeof playPromise.catch === "function") { + playPromise.catch(function() {}); + } + + stopStreamTracks(recorder.stream); + + if (startBtn) { + startBtn.disabled = false; + } }).catch(function(error) { displayErrorMessage(uploadConfig(instanceId).ErrMsgStopRec, instanceId); console.log("Stop recording error:", error); + + stopStreamTracks(recorder && recorder.stream ? recorder.stream : null); + clearMediaSource(video); + + if (startBtn) { + startBtn.disabled = false; + } }); } @@ -472,14 +767,22 @@ function captureImage(instanceId) { if (uploadConfig(instanceId).allowUploadFileChange == 1) { enableUploadBtn(instanceId); } - var video = document.getElementById('preview'); - var canvas = document.getElementById("canvas"); - var img = document.getElementById("capturedImage"); + + var video = getElementByDynamicId('preview', instanceId); + var canvas = getElementByDynamicId("canvas", instanceId); + var img = getElementByDynamicId("capturedImage", instanceId); + + if (!video || !canvas || !img) { + displayErrorMessage(uploadConfig(instanceId).ErrMsgSave, instanceId); + return; + } + if (img.hasAttribute("hidden")) { img.removeAttribute("hidden"); } + canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0); img.src = canvas.toDataURL('image/png'); -} +} \ No newline at end of file