(self["webpackChunk"] = self["webpackChunk"] || []).push([["/js/vendor"],{

/***/ "./node_modules/twilio-client/browser/ws.js":
/*!**************************************************!*\
  !*** ./node_modules/twilio-client/browser/ws.js ***!
  \**************************************************/
/***/ ((module) => {

"use strict";

module.exports = WebSocket;


/***/ }),

/***/ "./node_modules/twilio-client/browser/xmlhttprequest.js":
/*!**************************************************************!*\
  !*** ./node_modules/twilio-client/browser/xmlhttprequest.js ***!
  \**************************************************************/
/***/ ((module) => {

"use strict";

module.exports = { XMLHttpRequest: XMLHttpRequest };


/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio.js":
/*!**************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @internalapi
 */
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var connection_1 = __webpack_require__(/*! ./twilio/connection */ "./node_modules/twilio-client/es5/twilio/connection.js");
exports.Connection = connection_1.default;
var device_1 = __webpack_require__(/*! ./twilio/device */ "./node_modules/twilio-client/es5/twilio/device.js");
exports.Device = device_1.default;
var preflight_1 = __webpack_require__(/*! ./twilio/preflight/preflight */ "./node_modules/twilio-client/es5/twilio/preflight/preflight.js");
exports.PreflightTest = preflight_1.PreflightTest;
var PStream = __webpack_require__(/*! ./twilio/pstream */ "./node_modules/twilio-client/es5/twilio/pstream.js");
exports.PStream = PStream;
var instance;
Object.defineProperty(device_1.default, 'instance', {
    get: function () { return instance; },
    set: function (_instance) {
        if (_instance === null) {
            instance = null;
        }
    },
});
device_1.default.destroy = function destroySingleton() {
    if (instance) {
        instance.destroy();
    }
    bindSingleton();
};
/**
 * Create a new Device instance and bind its functions to the Device static. This maintains
 * backwards compatibility for the Device singleton behavior and will be removed in the next
 * breaking release.
 */
function bindSingleton() {
    instance = new device_1.default();
    Object.getOwnPropertyNames(device_1.default.prototype)
        .concat(Object.getOwnPropertyNames(events_1.EventEmitter.prototype))
        .filter(function (prop) {
        return typeof device_1.default.prototype[prop] === 'function';
    })
        .filter(function (prop) { return prop !== 'destroy'; })
        .forEach(function (prop) {
        device_1.default[prop] = device_1.default.prototype[prop].bind(instance);
    });
}
bindSingleton();
Object.getOwnPropertyNames(instance)
    .filter(function (prop) { return typeof device_1.default.prototype[prop] !== 'function'; })
    .forEach(function (prop) {
    Object.defineProperty(device_1.default, prop, {
        get: function () {
            if (instance) {
                return instance[prop];
            }
        },
        set: function (_prop) {
            if (instance) {
                instance[prop] = _prop;
            }
        },
    });
});
//# sourceMappingURL=twilio.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/asyncQueue.js":
/*!*************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/asyncQueue.js ***!
  \*************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 * @internalapi
 */
var deferred_1 = __webpack_require__(/*! ./deferred */ "./node_modules/twilio-client/es5/twilio/deferred.js");
/**
 * Queue async operations and executes them synchronously.
 */
var AsyncQueue = /** @class */ (function () {
    function AsyncQueue() {
        /**
         * The list of async operations in this queue
         */
        this._operations = [];
    }
    /**
     * Adds the async operation to the queue
     * @param callback An async callback that returns a promise
     * @returns A promise that will get resolved or rejected after executing the callback
     */
    AsyncQueue.prototype.enqueue = function (callback) {
        var hasPending = !!this._operations.length;
        var deferred = new deferred_1.default();
        this._operations.push({ deferred: deferred, callback: callback });
        if (!hasPending) {
            this._processQueue();
        }
        return deferred.promise;
    };
    /**
     * Start processing the queue. This executes the first item and removes it after.
     * Then do the same for next items until the queue is emptied.
     */
    AsyncQueue.prototype._processQueue = function () {
        return __awaiter(this, void 0, void 0, function () {
            var _a, deferred, callback, result, error, hasResolved, e_1;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!this._operations.length) return [3 /*break*/, 5];
                        _a = this._operations[0], deferred = _a.deferred, callback = _a.callback;
                        result = void 0;
                        error = void 0;
                        hasResolved = void 0;
                        _b.label = 1;
                    case 1:
                        _b.trys.push([1, 3, , 4]);
                        return [4 /*yield*/, callback()];
                    case 2:
                        result = _b.sent();
                        hasResolved = true;
                        return [3 /*break*/, 4];
                    case 3:
                        e_1 = _b.sent();
                        error = e_1;
                        return [3 /*break*/, 4];
                    case 4:
                        // Remove the item
                        this._operations.shift();
                        if (hasResolved) {
                            deferred.resolve(result);
                        }
                        else {
                            deferred.reject(error);
                        }
                        return [3 /*break*/, 0];
                    case 5: return [2 /*return*/];
                }
            });
        });
    };
    return AsyncQueue;
}());
exports.AsyncQueue = AsyncQueue;
//# sourceMappingURL=asyncQueue.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/audiohelper.js":
/*!**************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/audiohelper.js ***!
  \**************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 */
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var log_1 = __webpack_require__(/*! ./log */ "./node_modules/twilio-client/es5/twilio/log.js");
var outputdevicecollection_1 = __webpack_require__(/*! ./outputdevicecollection */ "./node_modules/twilio-client/es5/twilio/outputdevicecollection.js");
var defaultMediaDevices = __webpack_require__(/*! ./shims/mediadevices */ "./node_modules/twilio-client/es5/twilio/shims/mediadevices.js");
var util_1 = __webpack_require__(/*! ./util */ "./node_modules/twilio-client/es5/twilio/util.js");
var MediaDeviceInfoShim = __webpack_require__(/*! ./shims/mediadeviceinfo */ "./node_modules/twilio-client/es5/twilio/shims/mediadeviceinfo.js");
/**
 * Aliases for audio kinds, used for labelling.
 * @private
 */
var kindAliases = {
    audioinput: 'Audio Input',
    audiooutput: 'Audio Output',
};
/**
 * Provides input and output audio-based functionality in one convenient class.
 * @publicapi
 */
var AudioHelper = /** @class */ (function (_super) {
    __extends(AudioHelper, _super);
    /**
     * @constructor
     * @private
     * @param onActiveOutputsChanged - A callback to be called when the user changes the active output devices.
     * @param onActiveInputChanged - A callback to be called when the user changes the active input device.
     * @param getUserMedia - The getUserMedia method to use.
     * @param [options]
     */
    function AudioHelper(onActiveOutputsChanged, onActiveInputChanged, getUserMedia, options) {
        var _this = _super.call(this) || this;
        /**
         * A Map of all audio input devices currently available to the browser by their device ID.
         */
        _this.availableInputDevices = new Map();
        /**
         * A Map of all audio output devices currently available to the browser by their device ID.
         */
        _this.availableOutputDevices = new Map();
        /**
         * The currently set audio constraints set by setAudioConstraints().
         */
        _this._audioConstraints = null;
        /**
         * The current input device.
         */
        _this._inputDevice = null;
        /**
         * The current input stream.
         */
        _this._inputStream = null;
        /**
         * Whether the {@link AudioHelper} is currently polling the input stream's volume.
         */
        _this._isPollingInputVolume = false;
        /**
         * An instance of Logger to use.
         */
        _this._log = log_1.default.getInstance();
        /**
         * A record of unknown devices (Devices without labels)
         */
        _this._unknownDeviceIndexes = {
            audioinput: {},
            audiooutput: {},
        };
        /**
         * Remove an input device from inputs
         * @param lostDevice
         * @returns Whether the device was active
         */
        _this._removeLostInput = function (lostDevice) {
            if (!_this.inputDevice || _this.inputDevice.deviceId !== lostDevice.deviceId) {
                return false;
            }
            _this._replaceStream(null);
            _this._inputDevice = null;
            _this._maybeStopPollingVolume();
            var defaultDevice = _this.availableInputDevices.get('default')
                || Array.from(_this.availableInputDevices.values())[0];
            if (defaultDevice) {
                _this.setInputDevice(defaultDevice.deviceId);
            }
            return true;
        };
        /**
         * Remove an input device from outputs
         * @param lostDevice
         * @returns Whether the device was active
         */
        _this._removeLostOutput = function (lostDevice) {
            var wasSpeakerLost = _this.speakerDevices.delete(lostDevice);
            var wasRingtoneLost = _this.ringtoneDevices.delete(lostDevice);
            return wasSpeakerLost || wasRingtoneLost;
        };
        /**
         * Update the available input and output devices
         */
        _this._updateAvailableDevices = function () {
            if (!_this._mediaDevices) {
                return Promise.reject('Enumeration not supported');
            }
            return _this._mediaDevices.enumerateDevices().then(function (devices) {
                _this._updateDevices(devices.filter(function (d) { return d.kind === 'audiooutput'; }), _this.availableOutputDevices, _this._removeLostOutput);
                _this._updateDevices(devices.filter(function (d) { return d.kind === 'audioinput'; }), _this.availableInputDevices, _this._removeLostInput);
                var defaultDevice = _this.availableOutputDevices.get('default')
                    || Array.from(_this.availableOutputDevices.values())[0];
                [_this.speakerDevices, _this.ringtoneDevices].forEach(function (outputDevices) {
                    if (!outputDevices.get().size && _this.availableOutputDevices.size && _this.isOutputSelectionSupported) {
                        outputDevices.set(defaultDevice.deviceId)
                            .catch(function (reason) {
                            _this._log.warn("Unable to set audio output devices. " + reason);
                        });
                    }
                });
            });
        };
        options = Object.assign({
            AudioContext: typeof AudioContext !== 'undefined' && AudioContext,
            setSinkId: typeof HTMLAudioElement !== 'undefined' && HTMLAudioElement.prototype.setSinkId,
        }, options);
        _this._getUserMedia = getUserMedia;
        _this._mediaDevices = options.mediaDevices || defaultMediaDevices;
        _this._onActiveInputChanged = onActiveInputChanged;
        var isAudioContextSupported = !!(options.AudioContext || options.audioContext);
        var isEnumerationSupported = !!(_this._mediaDevices && _this._mediaDevices.enumerateDevices);
        var isSetSinkSupported = typeof options.setSinkId === 'function';
        _this.isOutputSelectionSupported = isEnumerationSupported && isSetSinkSupported;
        _this.isVolumeSupported = isAudioContextSupported;
        if (options.enabledSounds) {
            _this._addEnabledSounds(options.enabledSounds);
        }
        if (_this.isVolumeSupported) {
            _this._audioContext = options.audioContext || options.AudioContext && new options.AudioContext();
            if (_this._audioContext) {
                _this._inputVolumeAnalyser = _this._audioContext.createAnalyser();
                _this._inputVolumeAnalyser.fftSize = 32;
                _this._inputVolumeAnalyser.smoothingTimeConstant = 0.3;
            }
        }
        _this.ringtoneDevices = new outputdevicecollection_1.default('ringtone', _this.availableOutputDevices, onActiveOutputsChanged, _this.isOutputSelectionSupported);
        _this.speakerDevices = new outputdevicecollection_1.default('speaker', _this.availableOutputDevices, onActiveOutputsChanged, _this.isOutputSelectionSupported);
        _this.addListener('newListener', function (eventName) {
            if (eventName === 'inputVolume') {
                _this._maybeStartPollingVolume();
            }
        });
        _this.addListener('removeListener', function (eventName) {
            if (eventName === 'inputVolume') {
                _this._maybeStopPollingVolume();
            }
        });
        _this.once('newListener', function () {
            // NOTE (rrowland): Ideally we would only check isEnumerationSupported here, but
            //   in at least one browser version (Tested in FF48) enumerateDevices actually
            //   returns bad data for the listed devices. Instead, we check for
            //   isOutputSelectionSupported to avoid these quirks that may negatively affect customers.
            if (!_this.isOutputSelectionSupported) {
                _this._log.warn('Warning: This browser does not support audio output selection.');
            }
            if (!_this.isVolumeSupported) {
                _this._log.warn("Warning: This browser does not support Twilio's volume indicator feature.");
            }
        });
        if (isEnumerationSupported) {
            _this._initializeEnumeration();
        }
        return _this;
    }
    Object.defineProperty(AudioHelper.prototype, "audioConstraints", {
        /**
         * The currently set audio constraints set by setAudioConstraints(). Starts as null.
         */
        get: function () { return this._audioConstraints; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(AudioHelper.prototype, "inputDevice", {
        /**
         * The active input device. Having no inputDevice specified by `setInputDevice()`
         * will disable input selection related functionality.
         */
        get: function () { return this._inputDevice; },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(AudioHelper.prototype, "inputStream", {
        /**
         * The current input stream.
         */
        get: function () { return this._inputStream; },
        enumerable: true,
        configurable: true
    });
    /**
     * Start polling volume if it's supported and there's an input stream to poll.
     * @private
     */
    AudioHelper.prototype._maybeStartPollingVolume = function () {
        var _this = this;
        if (!this.isVolumeSupported || !this._inputStream) {
            return;
        }
        this._updateVolumeSource();
        if (this._isPollingInputVolume || !this._inputVolumeAnalyser) {
            return;
        }
        var bufferLength = this._inputVolumeAnalyser.frequencyBinCount;
        var buffer = new Uint8Array(bufferLength);
        this._isPollingInputVolume = true;
        var emitVolume = function () {
            if (!_this._isPollingInputVolume) {
                return;
            }
            if (_this._inputVolumeAnalyser) {
                _this._inputVolumeAnalyser.getByteFrequencyData(buffer);
                var inputVolume = util_1.average(buffer);
                _this.emit('inputVolume', inputVolume / 255);
            }
            requestAnimationFrame(emitVolume);
        };
        requestAnimationFrame(emitVolume);
    };
    /**
     * Stop polling volume if it's currently polling and there are no listeners.
     * @private
     */
    AudioHelper.prototype._maybeStopPollingVolume = function () {
        if (!this.isVolumeSupported) {
            return;
        }
        if (!this._isPollingInputVolume || (this._inputStream && this.listenerCount('inputVolume'))) {
            return;
        }
        if (this._inputVolumeSource) {
            this._inputVolumeSource.disconnect();
            delete this._inputVolumeSource;
        }
        this._isPollingInputVolume = false;
    };
    /**
     * Unbind the listeners from mediaDevices.
     * @private
     */
    AudioHelper.prototype._unbind = function () {
        if (!this._mediaDevices) {
            throw new errors_1.NotSupportedError('Enumeration is not supported');
        }
        if (this._mediaDevices.removeEventListener) {
            this._mediaDevices.removeEventListener('devicechange', this._updateAvailableDevices);
            this._mediaDevices.removeEventListener('deviceinfochange', this._updateAvailableDevices);
        }
    };
    /**
     * Set the MediaTrackConstraints to be applied on every getUserMedia call for new input
     * device audio. Any deviceId specified here will be ignored. Instead, device IDs should
     * be specified using {@link AudioHelper#setInputDevice}. The returned Promise resolves
     * when the media is successfully reacquired, or immediately if no input device is set.
     * @param audioConstraints - The MediaTrackConstraints to apply.
     */
    AudioHelper.prototype.setAudioConstraints = function (audioConstraints) {
        this._audioConstraints = Object.assign({}, audioConstraints);
        delete this._audioConstraints.deviceId;
        return this.inputDevice
            ? this._setInputDevice(this.inputDevice.deviceId, true)
            : Promise.resolve();
    };
    /**
     * Replace the current input device with a new device by ID.
     * @param deviceId - An ID of a device to replace the existing
     *   input device with.
     */
    AudioHelper.prototype.setInputDevice = function (deviceId) {
        return !util_1.isFirefox()
            ? this._setInputDevice(deviceId, false)
            : Promise.reject(new errors_1.NotSupportedError('Firefox does not currently support opening multiple ' +
                'audio input tracks simultaneously, even across different tabs. As a result, ' +
                'Device.audio.setInputDevice is disabled on Firefox until support is added.\n' +
                'Related BugZilla thread: https://bugzilla.mozilla.org/show_bug.cgi?id=1299324'));
    };
    /**
     * Unset the MediaTrackConstraints to be applied on every getUserMedia call for new input
     * device audio. The returned Promise resolves when the media is successfully reacquired,
     * or immediately if no input device is set.
     */
    AudioHelper.prototype.unsetAudioConstraints = function () {
        this._audioConstraints = null;
        return this.inputDevice
            ? this._setInputDevice(this.inputDevice.deviceId, true)
            : Promise.resolve();
    };
    /**
     * Unset the input device, stopping the tracks. This should only be called when not in a connection, and
     *   will not allow removal of the input device during a live call.
     */
    AudioHelper.prototype.unsetInputDevice = function () {
        var _this = this;
        if (!this.inputDevice) {
            return Promise.resolve();
        }
        return this._onActiveInputChanged(null).then(function () {
            _this._replaceStream(null);
            _this._inputDevice = null;
            _this._maybeStopPollingVolume();
        });
    };
    /**
     * Merge the passed enabledSounds into {@link AudioHelper}. Currently used to merge the deprecated
     *   Device.sounds object onto the new {@link AudioHelper} interface. Mutates
     *   by reference, sharing state between {@link Device} and {@link AudioHelper}.
     * @param enabledSounds - The initial sound settings to merge.
     * @private
     */
    AudioHelper.prototype._addEnabledSounds = function (enabledSounds) {
        var _this = this;
        function setValue(key, value) {
            if (typeof value !== 'undefined') {
                enabledSounds[key] = value;
            }
            return enabledSounds[key];
        }
        Object.keys(enabledSounds).forEach(function (key) {
            _this[key] = setValue.bind(null, key);
        });
    };
    /**
     * Get the index of an un-labeled Device.
     * @param mediaDeviceInfo
     * @returns The index of the passed MediaDeviceInfo
     */
    AudioHelper.prototype._getUnknownDeviceIndex = function (mediaDeviceInfo) {
        var id = mediaDeviceInfo.deviceId;
        var kind = mediaDeviceInfo.kind;
        var index = this._unknownDeviceIndexes[kind][id];
        if (!index) {
            index = Object.keys(this._unknownDeviceIndexes[kind]).length + 1;
            this._unknownDeviceIndexes[kind][id] = index;
        }
        return index;
    };
    /**
     * Initialize output device enumeration.
     */
    AudioHelper.prototype._initializeEnumeration = function () {
        var _this = this;
        if (!this._mediaDevices) {
            throw new errors_1.NotSupportedError('Enumeration is not supported');
        }
        if (this._mediaDevices.addEventListener) {
            this._mediaDevices.addEventListener('devicechange', this._updateAvailableDevices);
            this._mediaDevices.addEventListener('deviceinfochange', this._updateAvailableDevices);
        }
        this._updateAvailableDevices().then(function () {
            if (!_this.isOutputSelectionSupported) {
                return;
            }
            Promise.all([
                _this.speakerDevices.set('default'),
                _this.ringtoneDevices.set('default'),
            ]).catch(function (reason) {
                _this._log.warn("Warning: Unable to set audio output devices. " + reason);
            });
        });
    };
    /**
     * Stop the tracks on the current input stream before replacing it with the passed stream.
     * @param stream - The new stream
     */
    AudioHelper.prototype._replaceStream = function (stream) {
        if (this._inputStream) {
            this._inputStream.getTracks().forEach(function (track) {
                track.stop();
            });
        }
        this._inputStream = stream;
    };
    /**
     * Replace the current input device with a new device by ID.
     * @param deviceId - An ID of a device to replace the existing
     *   input device with.
     * @param forceGetUserMedia - If true, getUserMedia will be called even if
     *   the specified device is already active.
     */
    AudioHelper.prototype._setInputDevice = function (deviceId, forceGetUserMedia) {
        var _this = this;
        if (typeof deviceId !== 'string') {
            return Promise.reject(new errors_1.InvalidArgumentError('Must specify the device to set'));
        }
        var device = this.availableInputDevices.get(deviceId);
        if (!device) {
            return Promise.reject(new errors_1.InvalidArgumentError("Device not found: " + deviceId));
        }
        if (this._inputDevice && this._inputDevice.deviceId === deviceId && this._inputStream) {
            if (!forceGetUserMedia) {
                return Promise.resolve();
            }
            // If the currently active track is still in readyState `live`, gUM may return the same track
            // rather than returning a fresh track.
            this._inputStream.getTracks().forEach(function (track) {
                track.stop();
            });
        }
        var constraints = { audio: Object.assign({ deviceId: { exact: deviceId } }, this.audioConstraints) };
        return this._getUserMedia(constraints).then(function (stream) {
            return _this._onActiveInputChanged(stream).then(function () {
                _this._replaceStream(stream);
                _this._inputDevice = device;
                _this._maybeStartPollingVolume();
            });
        });
    };
    /**
     * Update a set of devices.
     * @param updatedDevices - An updated list of available Devices
     * @param availableDevices - The previous list of available Devices
     * @param removeLostDevice - The method to call if a previously available Device is
     *   no longer available.
     */
    AudioHelper.prototype._updateDevices = function (updatedDevices, availableDevices, removeLostDevice) {
        var _this = this;
        var updatedDeviceIds = updatedDevices.map(function (d) { return d.deviceId; });
        var knownDeviceIds = Array.from(availableDevices.values()).map(function (d) { return d.deviceId; });
        var lostActiveDevices = [];
        // Remove lost devices
        var lostDeviceIds = util_1.difference(knownDeviceIds, updatedDeviceIds);
        lostDeviceIds.forEach(function (lostDeviceId) {
            var lostDevice = availableDevices.get(lostDeviceId);
            if (lostDevice) {
                availableDevices.delete(lostDeviceId);
                if (removeLostDevice(lostDevice)) {
                    lostActiveDevices.push(lostDevice);
                }
            }
        });
        // Add any new devices, or devices with updated labels
        var deviceChanged = false;
        updatedDevices.forEach(function (newDevice) {
            var existingDevice = availableDevices.get(newDevice.deviceId);
            var newMediaDeviceInfo = _this._wrapMediaDeviceInfo(newDevice);
            if (!existingDevice || existingDevice.label !== newMediaDeviceInfo.label) {
                availableDevices.set(newDevice.deviceId, newMediaDeviceInfo);
                deviceChanged = true;
            }
        });
        if (deviceChanged || lostDeviceIds.length) {
            // Force a new gUM in case the underlying tracks of the active stream have changed. One
            //   reason this might happen is when `default` is selected and set to a USB device,
            //   then that device is unplugged or plugged back in. We can't check for the 'ended'
            //   event or readyState because it is asynchronous and may take upwards of 5 seconds,
            //   in my testing. (rrowland)
            if (this.inputDevice !== null && this.inputDevice.deviceId === 'default') {
                this._log.warn("Calling getUserMedia after device change to ensure that the           tracks of the active device (default) have not gone stale.");
                this._setInputDevice(this.inputDevice.deviceId, true);
            }
            this.emit('deviceChange', lostActiveDevices);
        }
    };
    /**
     * Disconnect the old input volume source, and create and connect a new one with the current
     * input stream.
     */
    AudioHelper.prototype._updateVolumeSource = function () {
        if (!this._inputStream || !this._audioContext || !this._inputVolumeAnalyser) {
            return;
        }
        if (this._inputVolumeSource) {
            this._inputVolumeSource.disconnect();
        }
        this._inputVolumeSource = this._audioContext.createMediaStreamSource(this._inputStream);
        this._inputVolumeSource.connect(this._inputVolumeAnalyser);
    };
    /**
     * Convert a MediaDeviceInfo to a IMediaDeviceInfoShim.
     * @param mediaDeviceInfo - The info to convert
     * @returns The converted shim
     */
    AudioHelper.prototype._wrapMediaDeviceInfo = function (mediaDeviceInfo) {
        var options = {
            deviceId: mediaDeviceInfo.deviceId,
            groupId: mediaDeviceInfo.groupId,
            kind: mediaDeviceInfo.kind,
            label: mediaDeviceInfo.label,
        };
        if (!options.label) {
            if (options.deviceId === 'default') {
                options.label = 'Default';
            }
            else {
                var index = this._getUnknownDeviceIndex(mediaDeviceInfo);
                options.label = "Unknown " + kindAliases[options.kind] + " Device " + index;
            }
        }
        return new MediaDeviceInfoShim(options);
    };
    return AudioHelper;
}(events_1.EventEmitter));
(function (AudioHelper) {
})(AudioHelper || (AudioHelper = {}));
exports.default = AudioHelper;
//# sourceMappingURL=audiohelper.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/connection.js":
/*!*************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/connection.js ***!
  \*************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 * @publicapi
 * @internal
 */
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var device_1 = __webpack_require__(/*! ./device */ "./node_modules/twilio-client/es5/twilio/device.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var log_1 = __webpack_require__(/*! ./log */ "./node_modules/twilio-client/es5/twilio/log.js");
var icecandidate_1 = __webpack_require__(/*! ./rtc/icecandidate */ "./node_modules/twilio-client/es5/twilio/rtc/icecandidate.js");
var statsMonitor_1 = __webpack_require__(/*! ./statsMonitor */ "./node_modules/twilio-client/es5/twilio/statsMonitor.js");
var util_1 = __webpack_require__(/*! ./util */ "./node_modules/twilio-client/es5/twilio/util.js");
var Backoff = __webpack_require__(/*! backoff */ "./node_modules/backoff/index.js");
var C = __webpack_require__(/*! ./constants */ "./node_modules/twilio-client/es5/twilio/constants.js");
var PeerConnection = __webpack_require__(/*! ./rtc */ "./node_modules/twilio-client/es5/twilio/rtc/index.js").PeerConnection;
var getPreferredCodecInfo = __webpack_require__(/*! ./rtc/sdp */ "./node_modules/twilio-client/es5/twilio/rtc/sdp.js").getPreferredCodecInfo;
var BACKOFF_CONFIG = {
    factor: 1.1,
    initialDelay: 1,
    maxDelay: 30000,
    randomisationFactor: 0.5,
};
var DTMF_INTER_TONE_GAP = 70;
var DTMF_PAUSE_DURATION = 500;
var DTMF_TONE_DURATION = 160;
var METRICS_BATCH_SIZE = 10;
var METRICS_DELAY = 5000;
var MEDIA_DISCONNECT_ERROR = {
    disconnect: true,
    info: {
        code: 31003,
        message: 'Connection with Twilio was interrupted.',
        twilioError: new errors_1.MediaErrors.ConnectionError(),
    },
};
var MULTIPLE_THRESHOLD_WARNING_NAMES = {
    // The stat `packetsLostFraction` is monitored by two separate thresholds,
    // `maxAverage` and `max`. Each threshold emits a different warning name.
    packetsLostFraction: {
        max: 'packet-loss',
        maxAverage: 'packets-lost-fraction',
    },
};
var WARNING_NAMES = {
    audioInputLevel: 'audio-input-level',
    audioOutputLevel: 'audio-output-level',
    bytesReceived: 'bytes-received',
    bytesSent: 'bytes-sent',
    jitter: 'jitter',
    mos: 'mos',
    rtt: 'rtt',
};
var WARNING_PREFIXES = {
    max: 'high-',
    maxAverage: 'high-',
    maxDuration: 'constant-',
    min: 'low-',
    minStandardDeviation: 'constant-',
};
var hasBeenWarnedHandlers = false;
/**
 * A {@link Connection} represents a media and signaling connection to a TwiML application.
 * @publicapi
 */
var Connection = /** @class */ (function (_super) {
    __extends(Connection, _super);
    /**
     * @constructor
     * @private
     * @param config - Mandatory configuration options
     * @param [options] - Optional settings
     */
    function Connection(config, options) {
        var _this = _super.call(this) || this;
        /**
         * Call parameters received from Twilio for an incoming call.
         */
        _this.parameters = {};
        /**
         * The number of times input volume has been the same consecutively.
         */
        _this._inputVolumeStreak = 0;
        /**
         * Whether the call has been answered.
         */
        _this._isAnswered = false;
        /**
         * Whether the call has been cancelled.
         */
        _this._isCancelled = false;
        /**
         * The most recent public input volume value. 0 -> 1 representing -100 to -30 dB.
         */
        _this._latestInputVolume = 0;
        /**
         * The most recent public output volume value. 0 -> 1 representing -100 to -30 dB.
         */
        _this._latestOutputVolume = 0;
        /**
         * An instance of Logger to use.
         */
        _this._log = log_1.default.getInstance();
        /**
         * A batch of metrics samples to send to Insights. Gets cleared after
         * each send and appended to on each new sample.
         */
        _this._metricsSamples = [];
        /**
         * The number of times output volume has been the same consecutively.
         */
        _this._outputVolumeStreak = 0;
        /**
         * A Map of Sounds to play.
         */
        _this._soundcache = new Map();
        /**
         * State of the {@link Connection}.
         */
        _this._status = Connection.State.Pending;
        /**
         * Options passed to this {@link Connection}.
         */
        _this.options = {
            enableRingingState: false,
            mediaStreamFactory: PeerConnection,
            offerSdp: null,
            shouldPlayDisconnect: function () { return true; },
        };
        /**
         * Whether the {@link Connection} should send a hangup on disconnect.
         */
        _this.sendHangup = true;
        /**
         * String representation of {@link Connection} instance.
         * @private
         */
        _this.toString = function () { return '[Twilio.Connection instance]'; };
        _this._emitWarning = function (groupPrefix, warningName, threshold, value, wasCleared, warningData) {
            var groupSuffix = wasCleared ? '-cleared' : '-raised';
            var groupName = groupPrefix + "warning" + groupSuffix;
            // Ignore constant input if the Connection is muted (Expected)
            if (warningName === 'constant-audio-input-level' && _this.isMuted()) {
                return;
            }
            var level = wasCleared ? 'info' : 'warning';
            // Avoid throwing false positives as warnings until we refactor volume metrics
            if (warningName === 'constant-audio-output-level') {
                level = 'info';
            }
            var payloadData = { threshold: threshold };
            if (value) {
                if (value instanceof Array) {
                    payloadData.values = value.map(function (val) {
                        if (typeof val === 'number') {
                            return Math.round(val * 100) / 100;
                        }
                        return value;
                    });
                }
                else {
                    payloadData.value = value;
                }
            }
            _this._publisher.post(level, groupName, warningName, { data: payloadData }, _this);
            if (warningName !== 'constant-audio-output-level') {
                var emitName = wasCleared ? 'warning-cleared' : 'warning';
                _this.emit(emitName, warningName, warningData && !wasCleared ? warningData : null);
            }
        };
        /**
         * Called when the {@link Connection} is answered.
         * @param payload
         */
        _this._onAnswer = function (payload) {
            // answerOnBridge=false will send a 183 which we need to catch in _onRinging when
            // the enableRingingState flag is disabled. In that case, we will receive a 200 after
            // the callee accepts the call firing a second `accept` event if we don't
            // short circuit here.
            if (_this._isAnswered) {
                return;
            }
            _this._setCallSid(payload);
            _this._isAnswered = true;
            _this._maybeTransitionToOpen();
        };
        /**
         * Called when the {@link Connection} is cancelled.
         * @param payload
         */
        _this._onCancel = function (payload) {
            // (rrowland) Is this check necessary? Verify, and if so move to pstream / VSP module.
            var callsid = payload.callsid;
            if (_this.parameters.CallSid === callsid) {
                _this._isCancelled = true;
                _this._publisher.info('connection', 'cancel', null, _this);
                _this._cleanupEventListeners();
                _this.mediaStream.close();
                _this._status = Connection.State.Closed;
                _this.emit('cancel');
                _this.pstream.removeListener('cancel', _this._onCancel);
            }
        };
        /**
         * Called when the {@link Connection} is hung up.
         * @param payload
         */
        _this._onHangup = function (payload) {
            /**
             *  see if callsid passed in message matches either callsid or outbound id
             *  connection should always have either callsid or outbound id
             *  if no callsid passed hangup anyways
             */
            if (payload.callsid && (_this.parameters.CallSid || _this.outboundConnectionId)) {
                if (payload.callsid !== _this.parameters.CallSid
                    && payload.callsid !== _this.outboundConnectionId) {
                    return;
                }
            }
            else if (payload.callsid) {
                // hangup is for another connection
                return;
            }
            _this._log.info('Received HANGUP from gateway');
            if (payload.error) {
                var error = {
                    code: payload.error.code || 31000,
                    connection: _this,
                    message: payload.error.message || 'Error sent from gateway in HANGUP',
                    twilioError: new errors_1.GeneralErrors.ConnectionError(),
                };
                _this._log.error('Received an error from the gateway:', error);
                _this.emit('error', error);
            }
            _this.sendHangup = false;
            _this._publisher.info('connection', 'disconnected-by-remote', null, _this);
            _this._disconnect(null, true);
            _this._cleanupEventListeners();
        };
        /**
         * Called when there is a media failure.
         * Manages all media-related states and takes action base on the states
         * @param type - Type of media failure
         */
        _this._onMediaFailure = function (type) {
            var _a = Connection.MediaFailure, ConnectionDisconnected = _a.ConnectionDisconnected, ConnectionFailed = _a.ConnectionFailed, IceGatheringFailed = _a.IceGatheringFailed, LowBytes = _a.LowBytes;
            // These types signifies the end of a single ICE cycle
            var isEndOfIceCycle = type === ConnectionFailed || type === IceGatheringFailed;
            // Default behavior on ice failures with disabled ice restart.
            if ((!_this.options.enableIceRestart && isEndOfIceCycle)
                // All browsers except chrome doesn't update pc.iceConnectionState and pc.connectionState
                // after issuing an ICE Restart, which we use to determine if ICE Restart is complete.
                // Since we cannot detect if ICE Restart is complete, we will not retry.
                || (!util_1.isChrome(window, window.navigator) && type === ConnectionFailed)) {
                return _this.mediaStream.onerror(MEDIA_DISCONNECT_ERROR);
            }
            // Ignore any other type of media failure if ice restart is disabled
            if (!_this.options.enableIceRestart) {
                return;
            }
            // Ignore subsequent requests if ice restart is in progress
            if (_this._status === Connection.State.Reconnecting) {
                // This is a retry. Previous ICE Restart failed
                if (isEndOfIceCycle) {
                    // We already exceeded max retry time.
                    if (Date.now() - _this._mediaReconnectStartTime > BACKOFF_CONFIG.maxDelay) {
                        _this._log.info('Exceeded max ICE retries');
                        return _this.mediaStream.onerror(MEDIA_DISCONNECT_ERROR);
                    }
                    // Issue ICE restart with backoff
                    _this._mediaReconnectBackoff.backoff();
                }
                return;
            }
            var pc = _this.mediaStream.version.pc;
            var isIceDisconnected = pc && pc.iceConnectionState === 'disconnected';
            var hasLowBytesWarning = _this._monitor.hasActiveWarning('bytesSent', 'min')
                || _this._monitor.hasActiveWarning('bytesReceived', 'min');
            // Only certain conditions can trigger media reconnection
            if ((type === LowBytes && isIceDisconnected)
                || (type === ConnectionDisconnected && hasLowBytesWarning)
                || isEndOfIceCycle) {
                var mediaReconnectionError = {
                    code: 53405,
                    message: 'Media connection failed.',
                    twilioError: new errors_1.MediaErrors.ConnectionError(),
                };
                _this._log.warn('ICE Connection disconnected.');
                _this._publisher.warn('connection', 'error', mediaReconnectionError, _this);
                _this._publisher.info('connection', 'reconnecting', null, _this);
                _this._mediaReconnectStartTime = Date.now();
                _this._status = Connection.State.Reconnecting;
                _this._mediaReconnectBackoff.reset();
                _this._mediaReconnectBackoff.backoff();
                _this.emit('reconnecting', mediaReconnectionError);
            }
        };
        /**
         * Called when media connection is restored
         */
        _this._onMediaReconnected = function () {
            // Only trigger once.
            // This can trigger on pc.onIceConnectionChange and pc.onConnectionChange.
            if (_this._status !== Connection.State.Reconnecting) {
                return;
            }
            _this._log.info('ICE Connection reestablished.');
            _this._publisher.info('connection', 'reconnected', null, _this);
            _this._status = Connection.State.Open;
            _this.emit('reconnected');
        };
        /**
         * When we get a RINGING signal from PStream, update the {@link Connection} status.
         * @param payload
         */
        _this._onRinging = function (payload) {
            _this._setCallSid(payload);
            // If we're not in 'connecting' or 'ringing' state, this event was received out of order.
            if (_this._status !== Connection.State.Connecting && _this._status !== Connection.State.Ringing) {
                return;
            }
            var hasEarlyMedia = !!payload.sdp;
            if (_this.options.enableRingingState) {
                _this._status = Connection.State.Ringing;
                _this._publisher.info('connection', 'outgoing-ringing', { hasEarlyMedia: hasEarlyMedia }, _this);
                _this.emit('ringing', hasEarlyMedia);
                // answerOnBridge=false will send a 183, which we need to interpret as `answer` when
                // the enableRingingState flag is disabled in order to maintain a non-breaking API from 1.4.24
            }
            else if (hasEarlyMedia) {
                _this._onAnswer(payload);
            }
        };
        /**
         * Called each time StatsMonitor emits a sample.
         * Emits stats event and batches the call stats metrics and sends them to Insights.
         * @param sample
         */
        _this._onRTCSample = function (sample) {
            var callMetrics = __assign(__assign({}, sample), { inputVolume: _this._latestInputVolume, outputVolume: _this._latestOutputVolume });
            _this._codec = callMetrics.codecName;
            _this._metricsSamples.push(callMetrics);
            if (_this._metricsSamples.length >= METRICS_BATCH_SIZE) {
                _this._publishMetrics();
            }
            _this.emit('sample', sample);
        };
        /**
         * Called when we receive a transportClose event from pstream.
         * Re-emits the event.
         */
        _this._onTransportClose = function () {
            _this._log.error('Received transportClose from pstream');
            _this.emit('transportClose');
        };
        /**
         * Re-emit an StatsMonitor warning as a {@link Connection}.warning or .warning-cleared event.
         * @param warningData
         * @param wasCleared - Whether this is a -cleared or -raised event.
         */
        _this._reemitWarning = function (warningData, wasCleared) {
            var groupPrefix = /^audio/.test(warningData.name) ?
                'audio-level-' : 'network-quality-';
            var warningPrefix = WARNING_PREFIXES[warningData.threshold.name];
            /**
             * NOTE: There are two "packet-loss" warnings: `high-packet-loss` and
             * `high-packets-lost-fraction`, so in this case we need to use a different
             * `WARNING_NAME` mapping.
             */
            var warningName;
            if (warningData.name in MULTIPLE_THRESHOLD_WARNING_NAMES) {
                warningName = MULTIPLE_THRESHOLD_WARNING_NAMES[warningData.name][warningData.threshold.name];
            }
            else if (warningData.name in WARNING_NAMES) {
                warningName = WARNING_NAMES[warningData.name];
            }
            var warning = warningPrefix + warningName;
            _this._emitWarning(groupPrefix, warning, warningData.threshold.value, warningData.values || warningData.value, wasCleared, warningData);
        };
        /**
         * Re-emit an StatsMonitor warning-cleared as a .warning-cleared event.
         * @param warningData
         */
        _this._reemitWarningCleared = function (warningData) {
            _this._reemitWarning(warningData, true);
        };
        _this._isUnifiedPlanDefault = config.isUnifiedPlanDefault;
        _this._soundcache = config.soundcache;
        _this.message = options && options.twimlParams || {};
        _this.customParameters = new Map(Object.entries(_this.message).map(function (_a) {
            var key = _a[0], val = _a[1];
            return [key, String(val)];
        }));
        Object.assign(_this.options, options);
        if (_this.options.callParameters) {
            _this.parameters = _this.options.callParameters;
        }
        _this._direction = _this.parameters.CallSid ? Connection.CallDirection.Incoming : Connection.CallDirection.Outgoing;
        if (_this._direction === Connection.CallDirection.Incoming && _this.parameters) {
            _this.callerInfo = _this.parameters.StirStatus
                ? { isVerified: _this.parameters.StirStatus === 'TN-Validation-Passed-A' }
                : null;
        }
        else {
            _this.callerInfo = null;
        }
        _this._mediaReconnectBackoff = Backoff.exponential(BACKOFF_CONFIG);
        _this._mediaReconnectBackoff.on('ready', function () { return _this.mediaStream.iceRestart(); });
        // temporary call sid to be used for outgoing calls
        _this.outboundConnectionId = generateTempCallSid();
        var publisher = _this._publisher = config.publisher;
        if (_this._direction === Connection.CallDirection.Incoming) {
            publisher.info('connection', 'incoming', null, _this);
        }
        else {
            publisher.info('connection', 'outgoing', { preflight: _this.options.preflight }, _this);
        }
        var monitor = _this._monitor = new (_this.options.StatsMonitor || statsMonitor_1.default)();
        monitor.on('sample', _this._onRTCSample);
        // First 20 seconds or so are choppy, so let's not bother with these warnings.
        monitor.disableWarnings();
        setTimeout(function () { return monitor.enableWarnings(); }, METRICS_DELAY);
        monitor.on('warning', function (data, wasCleared) {
            if (data.name === 'bytesSent' || data.name === 'bytesReceived') {
                _this._onMediaFailure(Connection.MediaFailure.LowBytes);
            }
            _this._reemitWarning(data, wasCleared);
        });
        monitor.on('warning-cleared', function (data) {
            _this._reemitWarningCleared(data);
        });
        _this.mediaStream = new (_this.options.MediaStream || _this.options.mediaStreamFactory)(config.audioHelper, config.pstream, config.getUserMedia, {
            codecPreferences: _this.options.codecPreferences,
            dscp: _this.options.dscp,
            enableIceRestart: _this.options.enableIceRestart,
            forceAggressiveIceNomination: _this.options.forceAggressiveIceNomination,
            isUnifiedPlan: _this._isUnifiedPlanDefault,
            maxAverageBitrate: _this.options.maxAverageBitrate,
            preflight: _this.options.preflight,
        });
        _this.on('volume', function (inputVolume, outputVolume) {
            _this._inputVolumeStreak = _this._checkVolume(inputVolume, _this._inputVolumeStreak, _this._latestInputVolume, 'input');
            _this._outputVolumeStreak = _this._checkVolume(outputVolume, _this._outputVolumeStreak, _this._latestOutputVolume, 'output');
            _this._latestInputVolume = inputVolume;
            _this._latestOutputVolume = outputVolume;
        });
        _this.mediaStream.onvolume = function (inputVolume, outputVolume, internalInputVolume, internalOutputVolume) {
            // (rrowland) These values mock the 0 -> 32767 format used by legacy getStats. We should look into
            // migrating to a newer standard, either 0.0 -> linear or -127 to 0 in dB, matching the range
            // chosen below.
            monitor.addVolumes((internalInputVolume / 255) * 32767, (internalOutputVolume / 255) * 32767);
            // (rrowland) 0.0 -> 1.0 linear
            _this.emit('volume', inputVolume, outputVolume);
        };
        _this.mediaStream.ondtlstransportstatechange = function (state) {
            var level = state === 'failed' ? 'error' : 'debug';
            _this._publisher.post(level, 'dtls-transport-state', state, null, _this);
        };
        _this.mediaStream.onpcconnectionstatechange = function (state) {
            var level = 'debug';
            var dtlsTransport = _this.mediaStream.getRTCDtlsTransport();
            if (state === 'failed') {
                level = dtlsTransport && dtlsTransport.state === 'failed' ? 'error' : 'warning';
            }
            _this._publisher.post(level, 'pc-connection-state', state, null, _this);
        };
        _this.mediaStream.onicecandidate = function (candidate) {
            var payload = new icecandidate_1.IceCandidate(candidate).toPayload();
            _this._publisher.debug('ice-candidate', 'ice-candidate', payload, _this);
        };
        _this.mediaStream.onselectedcandidatepairchange = function (pair) {
            var localCandidatePayload = new icecandidate_1.IceCandidate(pair.local).toPayload();
            var remoteCandidatePayload = new icecandidate_1.IceCandidate(pair.remote, true).toPayload();
            _this._publisher.debug('ice-candidate', 'selected-ice-candidate-pair', {
                local_candidate: localCandidatePayload,
                remote_candidate: remoteCandidatePayload,
            }, _this);
        };
        _this.mediaStream.oniceconnectionstatechange = function (state) {
            var level = state === 'failed' ? 'error' : 'debug';
            _this._publisher.post(level, 'ice-connection-state', state, null, _this);
        };
        _this.mediaStream.onicegatheringfailure = function (type) {
            _this._publisher.warn('ice-gathering-state', type, null, _this);
            _this._onMediaFailure(Connection.MediaFailure.IceGatheringFailed);
        };
        _this.mediaStream.onicegatheringstatechange = function (state) {
            _this._publisher.debug('ice-gathering-state', state, null, _this);
        };
        _this.mediaStream.onsignalingstatechange = function (state) {
            _this._publisher.debug('signaling-state', state, null, _this);
        };
        _this.mediaStream.ondisconnected = function (msg) {
            _this._log.info(msg);
            _this._publisher.warn('network-quality-warning-raised', 'ice-connectivity-lost', {
                message: msg,
            }, _this);
            _this.emit('warning', 'ice-connectivity-lost');
            _this._onMediaFailure(Connection.MediaFailure.ConnectionDisconnected);
        };
        _this.mediaStream.onfailed = function (msg) {
            _this._onMediaFailure(Connection.MediaFailure.ConnectionFailed);
        };
        _this.mediaStream.onconnected = function () {
            // First time mediaStream is connected, but ICE Gathering issued an ICE restart and succeeded.
            if (_this._status === Connection.State.Reconnecting) {
                _this._onMediaReconnected();
            }
        };
        _this.mediaStream.onreconnected = function (msg) {
            _this._log.info(msg);
            _this._publisher.info('network-quality-warning-cleared', 'ice-connectivity-lost', {
                message: msg,
            }, _this);
            _this.emit('warning-cleared', 'ice-connectivity-lost');
            _this._onMediaReconnected();
        };
        _this.mediaStream.onerror = function (e) {
            if (e.disconnect === true) {
                _this._disconnect(e.info && e.info.message);
            }
            var error = {
                code: e.info.code,
                connection: _this,
                info: e.info,
                message: e.info.message || 'Error with mediastream',
                twilioError: e.info.twilioError,
            };
            _this._log.error('Received an error from MediaStream:', e);
            _this.emit('error', error);
        };
        _this.mediaStream.onopen = function () {
            // NOTE(mroberts): While this may have been happening in previous
            // versions of Chrome, since Chrome 45 we have seen the
            // PeerConnection's onsignalingstatechange handler invoked multiple
            // times in the same signalingState 'stable'. When this happens, we
            // invoke this onopen function. If we invoke it twice without checking
            // for _status 'open', we'd accidentally close the PeerConnection.
            //
            // See <https://code.google.com/p/webrtc/issues/detail?id=4996>.
            if (_this._status === Connection.State.Open || _this._status === Connection.State.Reconnecting) {
                return;
            }
            else if (_this._status === Connection.State.Ringing || _this._status === Connection.State.Connecting) {
                _this.mute(false);
                _this._maybeTransitionToOpen();
            }
            else {
                // call was probably canceled sometime before this
                _this.mediaStream.close();
            }
        };
        _this.mediaStream.onclose = function () {
            _this._status = Connection.State.Closed;
            if (_this.options.shouldPlayDisconnect && _this.options.shouldPlayDisconnect()
                // Don't play disconnect sound if this was from a cancel event. i.e. the call
                // was ignored or hung up even before it was answered.
                && !_this._isCancelled) {
                _this._soundcache.get(device_1.default.SoundName.Disconnect).play();
            }
            monitor.disable();
            _this._publishMetrics();
            if (!_this._isCancelled) {
                _this.emit('disconnect', _this);
            }
        };
        _this.pstream = config.pstream;
        _this.pstream.on('cancel', _this._onCancel);
        _this.pstream.on('ringing', _this._onRinging);
        _this.pstream.on('transportClose', _this._onTransportClose);
        _this.on('error', function (error) {
            _this._publisher.error('connection', 'error', {
                code: error.code, message: error.message,
            }, _this);
            if (_this.pstream && _this.pstream.status === 'disconnected') {
                _this._cleanupEventListeners();
            }
        });
        _this.on('disconnect', function () {
            _this._cleanupEventListeners();
        });
        return _this;
    }
    Object.defineProperty(Connection.prototype, "direction", {
        /**
         * Whether this {@link Connection} is incoming or outgoing.
         */
        get: function () {
            return this._direction;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Connection.prototype, "codec", {
        /**
         * Audio codec used for this {@link Connection}. Expecting {@link Connection.Codec} but
         * will copy whatever we get from RTC stats.
         */
        get: function () {
            return this._codec;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Get the real CallSid. Returns null if not present or is a temporary call sid.
     * @deprecated
     * @private
     */
    Connection.prototype._getRealCallSid = function () {
        this._log.warn('_getRealCallSid is deprecated and will be removed in 2.0.');
        return /^TJ/.test(this.parameters.CallSid) ? null : this.parameters.CallSid;
    };
    /**
     * Get the temporary CallSid.
     * @deprecated
     * @private
     */
    Connection.prototype._getTempCallSid = function () {
        this._log.warn('_getTempCallSid is deprecated and will be removed in 2.0. \
                    Please use outboundConnectionId instead.');
        return this.outboundConnectionId;
    };
    /**
     * Set the audio input tracks from a given stream.
     * @param stream
     * @private
     */
    Connection.prototype._setInputTracksFromStream = function (stream) {
        return this.mediaStream.setInputTracksFromStream(stream);
    };
    /**
     * Set the audio output sink IDs.
     * @param sinkIds
     * @private
     */
    Connection.prototype._setSinkIds = function (sinkIds) {
        return this.mediaStream._setSinkIds(sinkIds);
    };
    Connection.prototype.accept = function (handlerOrConstraints, rtcConfiguration) {
        var _this = this;
        if (typeof handlerOrConstraints === 'function') {
            this._addHandler('accept', handlerOrConstraints);
            return;
        }
        if (this._status !== Connection.State.Pending) {
            return;
        }
        var audioConstraints = handlerOrConstraints || this.options.audioConstraints;
        this._status = Connection.State.Connecting;
        var connect = function () {
            if (_this._status !== Connection.State.Connecting) {
                // call must have been canceled
                _this._cleanupEventListeners();
                _this.mediaStream.close();
                return;
            }
            var onAnswer = function (pc) {
                // Report that the call was answered, and directionality
                var eventName = _this._direction === Connection.CallDirection.Incoming
                    ? 'accepted-by-local'
                    : 'accepted-by-remote';
                _this._publisher.info('connection', eventName, null, _this);
                // Report the preferred codec and params as they appear in the SDP
                var _a = getPreferredCodecInfo(_this.mediaStream.version.getSDP()), codecName = _a.codecName, codecParams = _a.codecParams;
                _this._publisher.info('settings', 'codec', {
                    codec_params: codecParams,
                    selected_codec: codecName,
                }, _this);
                // Enable RTC monitoring
                _this._monitor.enable(pc);
            };
            var sinkIds = typeof _this.options.getSinkIds === 'function' && _this.options.getSinkIds();
            if (Array.isArray(sinkIds)) {
                _this.mediaStream._setSinkIds(sinkIds).catch(function () {
                    // (rrowland) We don't want this to throw to console since the customer
                    // can't control this. This will most commonly be rejected on browsers
                    // that don't support setting sink IDs.
                });
            }
            _this.pstream.addListener('hangup', _this._onHangup);
            rtcConfiguration = rtcConfiguration || _this.options.rtcConfiguration;
            if (_this._direction === Connection.CallDirection.Incoming) {
                _this._isAnswered = true;
                _this.mediaStream.answerIncomingCall(_this.parameters.CallSid, _this.options.offerSdp, _this.options.rtcConstraints, rtcConfiguration, onAnswer);
            }
            else {
                var params = Array.from(_this.customParameters.entries()).map(function (pair) {
                    return encodeURIComponent(pair[0]) + "=" + encodeURIComponent(pair[1]);
                }).join('&');
                _this.pstream.once('answer', _this._onAnswer.bind(_this));
                _this.mediaStream.makeOutgoingCall(_this.pstream.token, params, _this.outboundConnectionId, _this.options.rtcConstraints, rtcConfiguration, onAnswer);
            }
        };
        if (this.options.beforeAccept) {
            this.options.beforeAccept(this);
        }
        var inputStream = typeof this.options.getInputStream === 'function' && this.options.getInputStream();
        var promise = inputStream
            ? this.mediaStream.setInputTracksFromStream(inputStream)
            : this.mediaStream.openWithConstraints(audioConstraints);
        promise.then(function () {
            _this._publisher.info('get-user-media', 'succeeded', {
                data: { audioConstraints: audioConstraints },
            }, _this);
            connect();
        }, function (error) {
            var message;
            var code;
            if (error.code === 31208
                || ['PermissionDeniedError', 'NotAllowedError'].indexOf(error.name) !== -1) {
                code = 31208;
                message = 'User denied access to microphone, or the web browser did not allow microphone '
                    + 'access at this address.';
                _this._publisher.error('get-user-media', 'denied', {
                    data: {
                        audioConstraints: audioConstraints,
                        error: error,
                    },
                }, _this);
            }
            else {
                code = 31201;
                message = "Error occurred while accessing microphone: " + error.name + (error.message
                    ? " (" + error.message + ")"
                    : '');
                _this._publisher.error('get-user-media', 'failed', {
                    data: {
                        audioConstraints: audioConstraints,
                        error: error,
                    },
                }, _this);
            }
            _this._disconnect();
            _this.emit('error', { message: message, code: code });
        });
    };
    Connection.prototype.cancel = function (handler) {
        this._log.warn('.cancel() is deprecated. Please use .ignore() instead.');
        if (handler) {
            this.ignore(handler);
        }
        else {
            this.ignore();
        }
    };
    Connection.prototype.disconnect = function (handler) {
        if (typeof handler === 'function') {
            this._addHandler('disconnect', handler);
            return;
        }
        this._disconnect();
    };
    /**
     * @deprecated - Set a handler for the {@link errorEvent}
     */
    Connection.prototype.error = function (handler) {
        if (typeof handler === 'function') {
            this._addHandler('error', handler);
        }
    };
    /**
     * Get the local MediaStream, if set.
     */
    Connection.prototype.getLocalStream = function () {
        return this.mediaStream && this.mediaStream.stream;
    };
    /**
     * Get the remote MediaStream, if set.
     */
    Connection.prototype.getRemoteStream = function () {
        return this.mediaStream && this.mediaStream._remoteStream;
    };
    Connection.prototype.ignore = function (handler) {
        if (typeof handler === 'function') {
            this._addHandler('cancel', handler);
            return;
        }
        if (this._status !== Connection.State.Pending) {
            return;
        }
        this._status = Connection.State.Closed;
        this.emit('cancel');
        this.mediaStream.ignore(this.parameters.CallSid);
        this._publisher.info('connection', 'ignored-by-local', null, this);
    };
    /**
     * Check if connection is muted
     */
    Connection.prototype.isMuted = function () {
        return this.mediaStream.isMuted;
    };
    Connection.prototype.mute = function (shouldMute) {
        if (shouldMute === void 0) { shouldMute = true; }
        if (typeof shouldMute === 'function') {
            this._addHandler('mute', shouldMute);
            return;
        }
        var wasMuted = this.mediaStream.isMuted;
        this.mediaStream.mute(shouldMute);
        var isMuted = this.mediaStream.isMuted;
        if (wasMuted !== isMuted) {
            this._publisher.info('connection', isMuted ? 'muted' : 'unmuted', null, this);
            this.emit('mute', isMuted, this);
        }
    };
    /**
     * Post an event to Endpoint Analytics indicating that the end user
     *   has given call quality feedback. Called without a score, this
     *   will report that the customer declined to give feedback.
     * @param score - The end-user's rating of the call; an
     *   integer 1 through 5. Or undefined if the user declined to give
     *   feedback.
     * @param issue - The primary issue the end user
     *   experienced on the call. Can be: ['one-way-audio', 'choppy-audio',
     *   'dropped-call', 'audio-latency', 'noisy-call', 'echo']
     */
    Connection.prototype.postFeedback = function (score, issue) {
        if (typeof score === 'undefined' || score === null) {
            return this._postFeedbackDeclined();
        }
        if (!Object.values(Connection.FeedbackScore).includes(score)) {
            throw new errors_1.InvalidArgumentError("Feedback score must be one of: " + Object.values(Connection.FeedbackScore));
        }
        if (typeof issue !== 'undefined' && issue !== null && !Object.values(Connection.FeedbackIssue).includes(issue)) {
            throw new errors_1.InvalidArgumentError("Feedback issue must be one of: " + Object.values(Connection.FeedbackIssue));
        }
        return this._publisher.info('feedback', 'received', {
            issue_name: issue,
            quality_score: score,
        }, this, true);
    };
    Connection.prototype.reject = function (handler) {
        if (typeof handler === 'function') {
            this._addHandler('reject', handler);
            return;
        }
        if (this._status !== Connection.State.Pending) {
            return;
        }
        this.pstream.reject(this.parameters.CallSid);
        this._status = Connection.State.Closed;
        this.emit('reject');
        this.mediaStream.reject(this.parameters.CallSid);
        this._publisher.info('connection', 'rejected-by-local', null, this);
    };
    /**
     * Send a string of digits.
     * @param digits
     */
    Connection.prototype.sendDigits = function (digits) {
        if (digits.match(/[^0-9*#w]/)) {
            throw new errors_1.InvalidArgumentError('Illegal character passed into sendDigits');
        }
        var sequence = [];
        digits.split('').forEach(function (digit) {
            var dtmf = (digit !== 'w') ? "dtmf" + digit : '';
            if (dtmf === 'dtmf*') {
                dtmf = 'dtmfs';
            }
            if (dtmf === 'dtmf#') {
                dtmf = 'dtmfh';
            }
            sequence.push(dtmf);
        });
        // Binds soundCache to be used in recursion until all digits have been played.
        (function playNextDigit(soundCache, dialtonePlayer) {
            var digit = sequence.shift();
            if (digit) {
                if (dialtonePlayer) {
                    dialtonePlayer.play(digit);
                }
                else {
                    soundCache.get(digit).play();
                }
            }
            if (sequence.length) {
                setTimeout(playNextDigit.bind(null, soundCache), 200);
            }
        })(this._soundcache, this.options.dialtonePlayer);
        var dtmfSender = this.mediaStream.getOrCreateDTMFSender();
        function insertDTMF(dtmfs) {
            if (!dtmfs.length) {
                return;
            }
            var dtmf = dtmfs.shift();
            if (dtmf && dtmf.length) {
                dtmfSender.insertDTMF(dtmf, DTMF_TONE_DURATION, DTMF_INTER_TONE_GAP);
            }
            setTimeout(insertDTMF.bind(null, dtmfs), DTMF_PAUSE_DURATION);
        }
        if (dtmfSender) {
            if (!('canInsertDTMF' in dtmfSender) || dtmfSender.canInsertDTMF) {
                this._log.info('Sending digits using RTCDTMFSender');
                // NOTE(mroberts): We can't just map 'w' to ',' since
                // RTCDTMFSender's pause duration is 2 s and Twilio's is more
                // like 500 ms. Instead, we will fudge it with setTimeout.
                insertDTMF(digits.split('w'));
                return;
            }
            this._log.info('RTCDTMFSender cannot insert DTMF');
        }
        // send pstream message to send DTMF
        this._log.info('Sending digits over PStream');
        if (this.pstream !== null && this.pstream.status !== 'disconnected') {
            this.pstream.dtmf(this.parameters.CallSid, digits);
        }
        else {
            var error = {
                code: 31000,
                connection: this,
                message: 'Could not send DTMF: Signaling channel is disconnected',
            };
            this.emit('error', error);
        }
    };
    /**
     * Get the current {@link Connection} status.
     */
    Connection.prototype.status = function () {
        return this._status;
    };
    /**
     * @deprecated - Unmute the {@link Connection}.
     */
    Connection.prototype.unmute = function () {
        this._log.warn('.unmute() is deprecated. Please use .mute(false) to unmute a call instead.');
        this.mute(false);
    };
    /**
     * @deprecated - Set a handler for the {@link volumeEvent}
     * @param handler
     */
    Connection.prototype.volume = function (handler) {
        if (!window || (!window.AudioContext && !window.webkitAudioContext)) {
            this._log.warn('This browser does not support Connection.volume');
        }
        this._addHandler('volume', handler);
    };
    /**
     * Add a handler for an EventEmitter and emit a deprecation warning on first call.
     * @param eventName - Name of the event
     * @param handler - A handler to call when the event is emitted
     */
    Connection.prototype._addHandler = function (eventName, handler) {
        if (!hasBeenWarnedHandlers) {
            this._log.warn("Connection callback handlers (accept, cancel, disconnect, error, ignore, mute, reject,\n        volume) have been deprecated and will be removed in the next breaking release. Instead, the EventEmitter         interface can be used to set event listeners. Example: connection.on('" + eventName + "', handler)");
            hasBeenWarnedHandlers = true;
        }
        this.addListener(eventName, handler);
        return this;
    };
    /**
     * Check the volume passed, emitting a warning if one way audio is detected or cleared.
     * @param currentVolume - The current volume for this direction
     * @param streakFieldName - The name of the field on the {@link Connection} object that tracks how many times the
     *   current value has been repeated consecutively.
     * @param lastValueFieldName - The name of the field on the {@link Connection} object that tracks the most recent
     *   volume for this direction
     * @param direction - The directionality of this audio track, either 'input' or 'output'
     * @returns The current streak; how many times in a row the same value has been polled.
     */
    Connection.prototype._checkVolume = function (currentVolume, currentStreak, lastValue, direction) {
        var wasWarningRaised = currentStreak >= 10;
        var newStreak = 0;
        if (lastValue === currentVolume) {
            newStreak = currentStreak;
        }
        if (newStreak >= 10) {
            this._emitWarning('audio-level-', "constant-audio-" + direction + "-level", 10, newStreak, false);
        }
        else if (wasWarningRaised) {
            this._emitWarning('audio-level-', "constant-audio-" + direction + "-level", 10, newStreak, true);
        }
        return newStreak;
    };
    /**
     * Clean up event listeners.
     */
    Connection.prototype._cleanupEventListeners = function () {
        var _this = this;
        var cleanup = function () {
            if (!_this.pstream) {
                return;
            }
            _this.pstream.removeListener('answer', _this._onAnswer);
            _this.pstream.removeListener('cancel', _this._onCancel);
            _this.pstream.removeListener('hangup', _this._onHangup);
            _this.pstream.removeListener('ringing', _this._onRinging);
            _this.pstream.removeListener('transportClose', _this._onTransportClose);
        };
        // This is kind of a hack, but it lets us avoid rewriting more code.
        // Basically, there's a sequencing problem with the way PeerConnection raises
        // the
        //
        //   Cannot establish connection. Client is disconnected
        //
        // error in Connection#accept. It calls PeerConnection#onerror, which emits
        // the error event on Connection. An error handler on Connection then calls
        // cleanupEventListeners, but then control returns to Connection#accept. It's
        // at this point that we add a listener for the answer event that never gets
        // removed. setTimeout will allow us to rerun cleanup again, _after_
        // Connection#accept returns.
        cleanup();
        setTimeout(cleanup, 0);
    };
    /**
     * Create the payload wrapper for a batch of metrics to be sent to Insights.
     */
    Connection.prototype._createMetricPayload = function () {
        var payload = {
            call_sid: this.parameters.CallSid,
            dscp: !!this.options.dscp,
            sdk_version: C.RELEASE_VERSION,
            selected_region: this.options.selectedRegion,
        };
        if (this.options.gateway) {
            payload.gateway = this.options.gateway;
        }
        if (this.options.region) {
            payload.region = this.options.region;
        }
        payload.direction = this._direction;
        return payload;
    };
    /**
     * Disconnect the {@link Connection}.
     * @param message - A message explaining why the {@link Connection} is being disconnected.
     * @param wasRemote - Whether the disconnect was triggered locally or remotely.
     */
    Connection.prototype._disconnect = function (message, wasRemote) {
        message = typeof message === 'string' ? message : null;
        if (this._status !== Connection.State.Open
            && this._status !== Connection.State.Connecting
            && this._status !== Connection.State.Reconnecting
            && this._status !== Connection.State.Ringing) {
            return;
        }
        this._log.info('Disconnecting...');
        // send pstream hangup message
        if (this.pstream !== null && this.pstream.status !== 'disconnected' && this.sendHangup) {
            var callsid = this.parameters.CallSid || this.outboundConnectionId;
            if (callsid) {
                this.pstream.hangup(callsid, message);
            }
        }
        this._cleanupEventListeners();
        this.mediaStream.close();
        if (!wasRemote) {
            this._publisher.info('connection', 'disconnected-by-local', null, this);
        }
    };
    /**
     * Transition to {@link ConnectionStatus.Open} if criteria is met.
     */
    Connection.prototype._maybeTransitionToOpen = function () {
        if (this.mediaStream && this.mediaStream.status === 'open' && this._isAnswered) {
            this._status = Connection.State.Open;
            this.emit('accept', this);
        }
    };
    /**
     * Post an event to Endpoint Analytics indicating that the end user
     *   has ignored a request for feedback.
     */
    Connection.prototype._postFeedbackDeclined = function () {
        return this._publisher.info('feedback', 'received-none', null, this, true);
    };
    /**
     * Publish the current set of queued metrics samples to Insights.
     */
    Connection.prototype._publishMetrics = function () {
        var _this = this;
        if (this._metricsSamples.length === 0) {
            return;
        }
        this._publisher.postMetrics('quality-metrics-samples', 'metrics-sample', this._metricsSamples.splice(0), this._createMetricPayload(), this).catch(function (e) {
            _this._log.warn('Unable to post metrics to Insights. Received error:', e);
        });
    };
    /**
     * Set the CallSid
     * @param payload
     */
    Connection.prototype._setCallSid = function (payload) {
        var callSid = payload.callsid;
        if (!callSid) {
            return;
        }
        this.parameters.CallSid = callSid;
        this.mediaStream.callSid = callSid;
    };
    /**
     * String representation of the {@link Connection} class.
     * @private
     */
    Connection.toString = function () { return '[Twilio.Connection class]'; };
    return Connection;
}(events_1.EventEmitter));
(function (Connection) {
    /**
     * Possible states of the {@link Connection}.
     */
    var State;
    (function (State) {
        State["Closed"] = "closed";
        State["Connecting"] = "connecting";
        State["Open"] = "open";
        State["Pending"] = "pending";
        State["Reconnecting"] = "reconnecting";
        State["Ringing"] = "ringing";
    })(State = Connection.State || (Connection.State = {}));
    /**
     * Different issues that may have been experienced during a call, that can be
     * reported to Twilio Insights via {@link Connection}.postFeedback().
     */
    var FeedbackIssue;
    (function (FeedbackIssue) {
        FeedbackIssue["AudioLatency"] = "audio-latency";
        FeedbackIssue["ChoppyAudio"] = "choppy-audio";
        FeedbackIssue["DroppedCall"] = "dropped-call";
        FeedbackIssue["Echo"] = "echo";
        FeedbackIssue["NoisyCall"] = "noisy-call";
        FeedbackIssue["OneWayAudio"] = "one-way-audio";
    })(FeedbackIssue = Connection.FeedbackIssue || (Connection.FeedbackIssue = {}));
    /**
     * A rating of call quality experienced during a call, to be reported to Twilio Insights
     * via {@link Connection}.postFeedback().
     */
    var FeedbackScore;
    (function (FeedbackScore) {
        FeedbackScore[FeedbackScore["One"] = 1] = "One";
        FeedbackScore[FeedbackScore["Two"] = 2] = "Two";
        FeedbackScore[FeedbackScore["Three"] = 3] = "Three";
        FeedbackScore[FeedbackScore["Four"] = 4] = "Four";
        FeedbackScore[FeedbackScore["Five"] = 5] = "Five";
    })(FeedbackScore = Connection.FeedbackScore || (Connection.FeedbackScore = {}));
    /**
     * The directionality of the {@link Connection}, whether incoming or outgoing.
     */
    var CallDirection;
    (function (CallDirection) {
        CallDirection["Incoming"] = "INCOMING";
        CallDirection["Outgoing"] = "OUTGOING";
    })(CallDirection = Connection.CallDirection || (Connection.CallDirection = {}));
    /**
     * Valid audio codecs to use for the media connection.
     */
    var Codec;
    (function (Codec) {
        Codec["Opus"] = "opus";
        Codec["PCMU"] = "pcmu";
    })(Codec = Connection.Codec || (Connection.Codec = {}));
    /**
     * Possible ICE Gathering failures
     */
    var IceGatheringFailureReason;
    (function (IceGatheringFailureReason) {
        IceGatheringFailureReason["None"] = "none";
        IceGatheringFailureReason["Timeout"] = "timeout";
    })(IceGatheringFailureReason = Connection.IceGatheringFailureReason || (Connection.IceGatheringFailureReason = {}));
    /**
     * Possible media failures
     */
    var MediaFailure;
    (function (MediaFailure) {
        MediaFailure["ConnectionDisconnected"] = "ConnectionDisconnected";
        MediaFailure["ConnectionFailed"] = "ConnectionFailed";
        MediaFailure["IceGatheringFailed"] = "IceGatheringFailed";
        MediaFailure["LowBytes"] = "LowBytes";
    })(MediaFailure = Connection.MediaFailure || (Connection.MediaFailure = {}));
})(Connection || (Connection = {}));
function generateTempCallSid() {
    return 'TJSxxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        /* tslint:disable:no-bitwise */
        var r = Math.random() * 16 | 0;
        var v = c === 'x' ? r : (r & 0x3 | 0x8);
        /* tslint:enable:no-bitwise */
        return v.toString(16);
    });
}
exports.default = Connection;
//# sourceMappingURL=connection.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/constants.js":
/*!************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/constants.js ***!
  \************************************************************/
/***/ ((module) => {

/**
 * This file is generated on build. To make changes, see /templates/constants.js
 */
var PACKAGE_NAME = 'twilio-client';
var RELEASE_VERSION = '1.14.0';
var SOUNDS_BASE_URL = 'https://sdk.twilio.com/js/client/sounds/releases/1.0.0';
module.exports.COWBELL_AUDIO_URL = SOUNDS_BASE_URL + "/cowbell.mp3?cache=" + RELEASE_VERSION;
module.exports.ECHO_TEST_DURATION = 20000;
module.exports.PACKAGE_NAME = PACKAGE_NAME;
module.exports.RELEASE_VERSION = RELEASE_VERSION;
module.exports.SOUNDS_BASE_URL = SOUNDS_BASE_URL;
/**
 * All errors we plan to use need to be defined here.
 */
module.exports.USED_ERRORS = [
    'AuthorizationErrors.AccessTokenExpired',
    'AuthorizationErrors.AccessTokenInvalid',
    'AuthorizationErrors.AuthenticationFailed',
    'ClientErrors.BadRequest',
    'GeneralErrors.ConnectionError',
    'GeneralErrors.TransportError',
    'GeneralErrors.UnknownError',
    'MediaErrors.ClientLocalDescFailed',
    'MediaErrors.ClientRemoteDescFailed',
    'MediaErrors.ConnectionError',
    'SignalingErrors.ConnectionDisconnected',
    'SignalingErrors.ConnectionError',
];
//# sourceMappingURL=constants.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/deferred.js":
/*!***********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/deferred.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";

/**
 * @packageDocumentation
 * @module Voice
 * @internalapi
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * Deferred Promise
 */
var Deferred = /** @class */ (function () {
    /**
     * @constructor
     */
    function Deferred() {
        var _this = this;
        this._promise = new Promise(function (resolve, reject) {
            _this._resolve = resolve;
            _this._reject = reject;
        });
    }
    Object.defineProperty(Deferred.prototype, "promise", {
        /**
         * @returns The {@link Deferred} Promise
         */
        get: function () {
            return this._promise;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Rejects this promise
     */
    Deferred.prototype.reject = function (reason) {
        this._reject(reason);
    };
    /**
     * Resolves this promise
     */
    Deferred.prototype.resolve = function (value) {
        this._resolve(value);
    };
    return Deferred;
}());
exports.default = Deferred;
//# sourceMappingURL=deferred.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/device.js":
/*!*********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/device.js ***!
  \*********************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 * @preferred
 * @publicapi
 */
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var audiohelper_1 = __webpack_require__(/*! ./audiohelper */ "./node_modules/twilio-client/es5/twilio/audiohelper.js");
var connection_1 = __webpack_require__(/*! ./connection */ "./node_modules/twilio-client/es5/twilio/connection.js");
var dialtonePlayer_1 = __webpack_require__(/*! ./dialtonePlayer */ "./node_modules/twilio-client/es5/twilio/dialtonePlayer.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var log_1 = __webpack_require__(/*! ./log */ "./node_modules/twilio-client/es5/twilio/log.js");
var preflight_1 = __webpack_require__(/*! ./preflight/preflight */ "./node_modules/twilio-client/es5/twilio/preflight/preflight.js");
var regions_1 = __webpack_require__(/*! ./regions */ "./node_modules/twilio-client/es5/twilio/regions.js");
var util_1 = __webpack_require__(/*! ./util */ "./node_modules/twilio-client/es5/twilio/util.js");
var C = __webpack_require__(/*! ./constants */ "./node_modules/twilio-client/es5/twilio/constants.js");
var Publisher = __webpack_require__(/*! ./eventpublisher */ "./node_modules/twilio-client/es5/twilio/eventpublisher.js");
var PStream = __webpack_require__(/*! ./pstream */ "./node_modules/twilio-client/es5/twilio/pstream.js");
var rtc = __webpack_require__(/*! ./rtc */ "./node_modules/twilio-client/es5/twilio/rtc/index.js");
var getUserMedia = __webpack_require__(/*! ./rtc/getusermedia */ "./node_modules/twilio-client/es5/twilio/rtc/getusermedia.js");
var Sound = __webpack_require__(/*! ./sound */ "./node_modules/twilio-client/es5/twilio/sound.js");
var REGISTRATION_INTERVAL = 30000;
var RINGTONE_PLAY_TIMEOUT = 2000;
var hasBeenWarnedHandlers = false;
var hasBeenWarnedSounds = false;
/**
 * Twilio Device. Allows registration for incoming calls, and placing outgoing calls.
 * @publicapi
 */
var Device = /** @class */ (function (_super) {
    __extends(Device, _super);
    function Device(token, options) {
        var _a;
        var _this = _super.call(this) || this;
        /**
         * The AudioHelper instance associated with this {@link Device}.
         */
        _this.audio = null;
        /**
         * An array of {@link Connection}s. Though only one can be active, multiple may exist when there
         * are multiple incoming, unanswered {@link Connection}s.
         */
        _this.connections = [];
        /**
         * Whether or not {@link Device.setup} has been called.
         */
        _this.isInitialized = false;
        /**
         * Methods to enable/disable each sound. Empty if the {@link Device} has not
         * yet been set up.
         */
        _this.sounds = {};
        /**
         * The JWT string currently being used to authenticate this {@link Device}.
         */
        _this.token = null;
        /**
         * The currently active {@link Connection}, if there is one.
         */
        _this._activeConnection = null;
        /**
         * The list of chunder URIs that will be passed to PStream
         */
        _this._chunderURIs = [];
        /**
         * An audio input MediaStream to pass to new {@link Connection} instances.
         */
        _this._connectionInputStream = null;
        /**
         * An array of {@link Device} IDs to be used to play sounds through, to be passed to
         * new {@link Connection} instances.
         */
        _this._connectionSinkIds = ['default'];
        /**
         * The name of the edge the {@link Device} is connected to.
         */
        _this._edge = null;
        /**
         * Whether each sound is enabled.
         */
        _this._enabledSounds = (_a = {},
            _a[Device.SoundName.Disconnect] = true,
            _a[Device.SoundName.Incoming] = true,
            _a[Device.SoundName.Outgoing] = true,
            _a);
        /**
         * An instance of Logger to use.
         */
        _this._log = log_1.default.getInstance();
        /**
         * An Insights Event Publisher.
         */
        _this._publisher = null;
        /**
         * The region the {@link Device} is connected to.
         */
        _this._region = null;
        /**
         * The current status of the {@link Device}.
         */
        _this._status = Device.Status.Offline;
        /**
         * Value of 'audio' determines whether we should be registered for incoming calls.
         */
        _this.mediaPresence = { audio: true };
        /**
         * The options passed to {@link Device} constructor or Device.setup.
         */
        _this.options = {
            allowIncomingWhileBusy: false,
            audioConstraints: true,
            closeProtection: false,
            codecPreferences: [connection_1.default.Codec.PCMU, connection_1.default.Codec.Opus],
            connectionFactory: connection_1.default,
            debug: false,
            dscp: true,
            enableIceRestart: false,
            eventgw: 'eventgw.twilio.com',
            forceAggressiveIceNomination: false,
            iceServers: [],
            noRegister: false,
            pStreamFactory: PStream,
            preflight: false,
            rtcConstraints: {},
            soundFactory: Sound,
            sounds: {},
            warnings: true,
        };
        /**
         * A timeout ID for a setTimeout schedule to re-register the {@link Device}.
         */
        _this.regTimer = null;
        /**
         * A Map of Sounds to play.
         */
        _this.soundcache = new Map();
        /**
         * The Signaling stream.
         */
        _this.stream = null;
        /**
         * Destroy the {@link Device}, freeing references to be garbage collected.
         */
        _this.destroy = function () {
            _this._disconnectAll();
            _this._stopRegistrationTimer();
            if (_this.audio) {
                _this.audio._unbind();
            }
            if (_this.stream) {
                _this.stream.destroy();
                _this.stream = null;
            }
            if (_this._networkInformation && typeof _this._networkInformation.removeEventListener === 'function') {
                _this._networkInformation.removeEventListener('change', _this._publishNetworkChange);
            }
            if (typeof window !== 'undefined' && window.removeEventListener) {
                window.removeEventListener('beforeunload', _this._confirmClose);
                window.removeEventListener('unload', _this.destroy);
                window.removeEventListener('pagehide', _this.destroy);
            }
        };
        /**
         * Called on window's beforeunload event if closeProtection is enabled,
         * preventing users from accidentally navigating away from an active call.
         * @param event
         */
        _this._confirmClose = function (event) {
            if (!_this._activeConnection) {
                return '';
            }
            var closeProtection = _this.options.closeProtection || false;
            var confirmationMsg = typeof closeProtection !== 'string'
                ? 'A call is currently in-progress. Leaving or reloading this page will end the call.'
                : closeProtection;
            (event || window.event).returnValue = confirmationMsg;
            return confirmationMsg;
        };
        /**
         * Create the default Insights payload
         * @param [connection]
         */
        _this._createDefaultPayload = function (connection) {
            var payload = {
                aggressive_nomination: _this.options.forceAggressiveIceNomination,
                browser_extension: _this._isBrowserExtension,
                dscp: !!_this.options.dscp,
                ice_restart_enabled: _this.options.enableIceRestart,
                platform: rtc.getMediaEngine(),
                sdk_version: C.RELEASE_VERSION,
            };
            function setIfDefined(propertyName, value) {
                if (value) {
                    payload[propertyName] = value;
                }
            }
            if (connection) {
                var callSid = connection.parameters.CallSid;
                setIfDefined('call_sid', /^TJ/.test(callSid) ? undefined : callSid);
                setIfDefined('temp_call_sid', connection.outboundConnectionId);
                setIfDefined('audio_codec', connection.codec);
                payload.direction = connection.direction;
            }
            setIfDefined('gateway', _this.stream && _this.stream.gateway);
            setIfDefined('selected_region', _this.options.region);
            setIfDefined('region', _this.stream && _this.stream.region);
            return payload;
        };
        /**
         * Disconnect all {@link Connection}s.
         */
        _this._disconnectAll = function () {
            var connections = _this.connections.splice(0);
            connections.forEach(function (conn) { return conn.disconnect(); });
            if (_this._activeConnection) {
                _this._activeConnection.disconnect();
            }
        };
        /**
         * Called when a 'close' event is received from the signaling stream.
         */
        _this._onSignalingClose = function () {
            _this.stream = null;
        };
        /**
         * Called when a 'connected' event is received from the signaling stream.
         */
        _this._onSignalingConnected = function (payload) {
            var region = regions_1.getRegionShortcode(payload.region);
            _this._edge = regions_1.regionToEdge[region] || payload.region;
            _this._region = region || payload.region;
            _this._sendPresence();
        };
        /**
         * Called when an 'error' event is received from the signaling stream.
         */
        _this._onSignalingError = function (payload) {
            if (!payload.error) {
                return;
            }
            var error = __assign({}, payload.error);
            var sid = payload.callsid;
            if (sid) {
                error.connection = _this._findConnection(sid);
            }
            if (error.code === 31201) {
                error.twilioError = new errors_1.AuthorizationErrors.AuthenticationFailed();
            }
            else if (error.code === 31204) {
                error.twilioError = new errors_1.AuthorizationErrors.AccessTokenInvalid();
            }
            else if (error.code === 31205) {
                // Stop trying to register presence after token expires
                _this._stopRegistrationTimer();
                error.twilioError = new errors_1.AuthorizationErrors.AccessTokenExpired();
            }
            else if (!error.twilioError) {
                error.twilioError = new errors_1.GeneralErrors.UnknownError();
            }
            _this._log.info('Received error: ', error);
            _this.emit('error', error);
        };
        /**
         * Called when an 'invite' event is received from the signaling stream.
         */
        _this._onSignalingInvite = function (payload) {
            var wasBusy = !!_this._activeConnection;
            if (wasBusy && !_this.options.allowIncomingWhileBusy) {
                _this._log.info('Device busy; ignoring incoming invite');
                return;
            }
            if (!payload.callsid || !payload.sdp) {
                _this.emit('error', { message: 'Malformed invite from gateway', twilioError: new errors_1.ClientErrors.BadRequest() });
                return;
            }
            var callParameters = payload.parameters || {};
            callParameters.CallSid = callParameters.CallSid || payload.callsid;
            var customParameters = Object.assign({}, util_1.queryToJson(callParameters.Params));
            var connection = _this._makeConnection(customParameters, {
                callParameters: callParameters,
                offerSdp: payload.sdp,
            });
            _this.connections.push(connection);
            connection.once('accept', function () {
                _this.soundcache.get(Device.SoundName.Incoming).stop();
                _this._publishNetworkChange();
            });
            var play = (_this._enabledSounds.incoming && !wasBusy)
                ? function () { return _this.soundcache.get(Device.SoundName.Incoming).play(); }
                : function () { return Promise.resolve(); };
            _this._showIncomingConnection(connection, play);
        };
        /**
         * Called when an 'offline' event is received from the signaling stream.
         */
        _this._onSignalingOffline = function () {
            _this._log.info('Stream is offline');
            _this._status = Device.Status.Offline;
            _this._edge = null;
            _this._region = null;
            _this.emit('offline', _this);
        };
        /**
         * Called when a 'ready' event is received from the signaling stream.
         */
        _this._onSignalingReady = function () {
            _this._log.info('Stream is ready');
            _this._status = Device.Status.Ready;
            _this.emit('ready', _this);
        };
        /**
         * Publish a NetworkInformation#change event to Insights if there's an active {@link Connection}.
         */
        _this._publishNetworkChange = function () {
            if (!_this._activeConnection) {
                return;
            }
            if (_this._networkInformation) {
                _this._publisher.info('network-information', 'network-change', {
                    connection_type: _this._networkInformation.type,
                    downlink: _this._networkInformation.downlink,
                    downlinkMax: _this._networkInformation.downlinkMax,
                    effective_type: _this._networkInformation.effectiveType,
                    rtt: _this._networkInformation.rtt,
                }, _this._activeConnection);
            }
        };
        /**
         * Update the input stream being used for calls so that any current call and all future calls
         * will use the new input stream.
         * @param inputStream
         */
        _this._updateInputStream = function (inputStream) {
            var connection = _this._activeConnection;
            if (connection && !inputStream) {
                return Promise.reject(new errors_1.InvalidStateError('Cannot unset input device while a call is in progress.'));
            }
            _this._connectionInputStream = inputStream;
            return connection
                ? connection._setInputTracksFromStream(inputStream)
                : Promise.resolve();
        };
        /**
         * Update the device IDs of output devices being used to play sounds through.
         * @param type - Whether to update ringtone or speaker sounds
         * @param sinkIds - An array of device IDs
         */
        _this._updateSinkIds = function (type, sinkIds) {
            var promise = type === 'ringtone'
                ? _this._updateRingtoneSinkIds(sinkIds)
                : _this._updateSpeakerSinkIds(sinkIds);
            return promise.then(function () {
                _this._publisher.info('audio', type + "-devices-set", {
                    audio_device_ids: sinkIds,
                }, _this._activeConnection);
            }, function (error) {
                _this._publisher.error('audio', type + "-devices-set-failed", {
                    audio_device_ids: sinkIds,
                    message: error.message,
                }, _this._activeConnection);
                throw error;
            });
        };
        if (window) {
            var root = window;
            var browser = root.msBrowser || root.browser || root.chrome;
            _this._isBrowserExtension = (!!browser && !!browser.runtime && !!browser.runtime.id)
                || (!!root.safari && !!root.safari.extension);
        }
        if (_this._isBrowserExtension) {
            _this._log.info('Running as browser extension.');
        }
        if (navigator) {
            var n = navigator;
            _this._networkInformation = n.connection
                || n.mozConnection
                || n.webkitConnection;
        }
        if (token) {
            _this.setup(token, options);
        }
        else if (options) {
            throw new errors_1.InvalidArgumentError('Cannot construct a Device with options but without a token');
        }
        return _this;
    }
    Object.defineProperty(Device, "audioContext", {
        /**
         * The AudioContext to be used by {@link Device} instances.
         * @private
         */
        get: function () {
            return Device._audioContext;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Device, "extension", {
        /**
         * Which sound file extension is supported.
         * @private
         */
        get: function () {
            // NOTE(mroberts): Node workaround.
            var a = typeof document !== 'undefined'
                ? document.createElement('audio') : { canPlayType: false };
            var canPlayMp3;
            try {
                canPlayMp3 = a.canPlayType && !!a.canPlayType('audio/mpeg').replace(/no/, '');
            }
            catch (e) {
                canPlayMp3 = false;
            }
            var canPlayVorbis;
            try {
                canPlayVorbis = a.canPlayType && !!a.canPlayType('audio/ogg;codecs=\'vorbis\'').replace(/no/, '');
            }
            catch (e) {
                canPlayVorbis = false;
            }
            return (canPlayVorbis && !canPlayMp3) ? 'ogg' : 'mp3';
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Device, "isSupported", {
        /**
         * Whether or not this SDK is supported by the current browser.
         */
        get: function () { return rtc.enabled(); },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(Device, "packageName", {
        /**
         * Package name of the SDK.
         */
        get: function () { return C.PACKAGE_NAME; },
        enumerable: true,
        configurable: true
    });
    /**
     * Run some tests to identify issues, if any, prohibiting successful calling.
     * @param token - A Twilio JWT token string
     * @param options
     */
    Device.runPreflight = function (token, options) {
        return new preflight_1.PreflightTest(token, __assign({ audioContext: Device._getOrCreateAudioContext() }, options));
    };
    /**
     * String representation of {@link Device} class.
     * @private
     */
    Device.toString = function () {
        return '[Twilio.Device class]';
    };
    Object.defineProperty(Device, "version", {
        /**
         * Current SDK version.
         */
        get: function () { return C.RELEASE_VERSION; },
        enumerable: true,
        configurable: true
    });
    /**
     * Initializes the AudioContext instance shared across the Client SDK,
     * or returns the existing instance if one has already been initialized.
     */
    Device._getOrCreateAudioContext = function () {
        if (!Device._audioContext) {
            if (typeof AudioContext !== 'undefined') {
                Device._audioContext = new AudioContext();
            }
            else if (typeof webkitAudioContext !== 'undefined') {
                Device._audioContext = new webkitAudioContext();
            }
        }
        return Device._audioContext;
    };
    /**
     * Return the active {@link Connection}. Null or undefined for backward compatibility.
     */
    Device.prototype.activeConnection = function () {
        if (!this.isInitialized) {
            return null;
        }
        // @rrowland This should only return activeConnection, but customers have built around this
        // broken behavior and in order to not break their apps we are including this until
        // the next big release.
        return this._activeConnection || this.connections[0];
    };
    /**
     * @deprecated Set a handler for the cancel event.
     * @param handler
     */
    Device.prototype.cancel = function (handler) {
        return this._addHandler(Device.EventName.Cancel, handler);
    };
    Device.prototype.connect = function (paramsOrHandler, audioConstraints, rtcConfiguration) {
        if (typeof paramsOrHandler === 'function') {
            this._addHandler(Device.EventName.Connect, paramsOrHandler);
            return null;
        }
        this._throwUnlessSetup('connect');
        if (this._activeConnection) {
            throw new errors_1.InvalidStateError('A Connection is already active');
        }
        var params = paramsOrHandler || {};
        audioConstraints = audioConstraints || this.options && this.options.audioConstraints || {};
        rtcConfiguration = rtcConfiguration || this.options.rtcConfiguration;
        var connection = this._activeConnection = this._makeConnection(params, { rtcConfiguration: rtcConfiguration });
        // Make sure any incoming connections are ignored
        this.connections.splice(0).forEach(function (conn) { return conn.ignore(); });
        // Stop the incoming sound if it's playing
        this.soundcache.get(Device.SoundName.Incoming).stop();
        connection.accept(audioConstraints);
        this._publishNetworkChange();
        return connection;
    };
    /**
     * Set a handler for the disconnect event.
     * @deprecated Use {@link Device.on}.
     * @param handler
     */
    Device.prototype.disconnect = function (handler) {
        return this._addHandler(Device.EventName.Disconnect, handler);
    };
    /**
     * Disconnect all {@link Connection}s.
     */
    Device.prototype.disconnectAll = function () {
        this._throwUnlessSetup('disconnectAll');
        this._disconnectAll();
    };
    Object.defineProperty(Device.prototype, "edge", {
        /**
         * Returns the {@link Edge} value the {@link Device} is currently connected
         * to. The value will be `null` when the {@link Device} is offline.
         */
        get: function () {
            return this._edge;
        },
        enumerable: true,
        configurable: true
    });
    /**
     * Set a handler for the error event.
     * @deprecated Use {@link Device.on}.
     * @param handler
     */
    Device.prototype.error = function (handler) {
        return this._addHandler(Device.EventName.Error, handler);
    };
    /**
     * Set a handler for the incoming event.
     * @deprecated Use {@link Device.on}.
     * @param handler
     */
    Device.prototype.incoming = function (handler) {
        return this._addHandler(Device.EventName.Incoming, handler);
    };
    /**
     * Set a handler for the offline event.
     * @deprecated Use {@link Device.on}.
     * @param handler
     */
    Device.prototype.offline = function (handler) {
        return this._addHandler(Device.EventName.Offline, handler);
    };
    /**
     * Set a handler for the ready event.
     * @deprecated Use {@link Device.on}.
     * @param handler
     */
    Device.prototype.ready = function (handler) {
        return this._addHandler(Device.EventName.Ready, handler);
    };
    /**
     * Get the {@link Region} string the {@link Device} is currently connected to, or 'offline'
     * if not connected.
     */
    Device.prototype.region = function () {
        this._log.warn('`Device.region` is deprecated and will be removed in the next major ' +
            'release. Please use `Device.edge` instead.');
        this._throwUnlessSetup('region');
        return typeof this._region === 'string' ? this._region : 'offline';
    };
    /**
     * Register to receive incoming calls. Does not need to be called unless {@link Device.unregisterPresence}
     * has been called directly.
     */
    Device.prototype.registerPresence = function () {
        this._throwUnlessSetup('registerPresence');
        this.mediaPresence.audio = true;
        this._sendPresence();
        return this;
    };
    /**
     * Remove an event listener
     * @param event - The event name to stop listening for
     * @param listener - The callback to remove
     */
    Device.prototype.removeListener = function (event, listener) {
        events_1.EventEmitter.prototype.removeListener.call(this, event, listener);
        return this;
    };
    /**
     * Initialize the {@link Device}.
     * @param token - A Twilio JWT token string granting this {@link Device} access.
     * @param [options]
     */
    Device.prototype.setup = function (token, options) {
        var _this = this;
        if (options === void 0) { options = {}; }
        if (util_1.isLegacyEdge()) {
            throw new errors_1.NotSupportedError('Microsoft Edge Legacy (https://support.microsoft.com/en-us/help/4533505/what-is-microsoft-edge-legacy) ' +
                'is deprecated and will not be able to connect to Twilio to make or receive calls after September 1st, 2020. ' +
                'Please see this documentation for a list of supported browsers ' +
                'https://www.twilio.com/docs/voice/client/javascript#supported-browsers');
        }
        if (!Device.isSupported && !options.ignoreBrowserSupport) {
            if (window && window.location && window.location.protocol === 'http:') {
                throw new errors_1.NotSupportedError("twilio.js wasn't able to find WebRTC browser support.           This is most likely because this page is served over http rather than https,           which does not support WebRTC in many browsers. Please load this page over https and           try again.");
            }
            throw new errors_1.NotSupportedError("twilio.js 1.3+ SDKs require WebRTC browser support.         For more information, see <https://www.twilio.com/docs/api/client/twilio-js>.         If you have any questions about this announcement, please contact         Twilio Support at <help@twilio.com>.");
        }
        if (!token) {
            throw new errors_1.InvalidArgumentError('Token is required for Device.setup()');
        }
        Object.assign(this.options, options);
        this._log.setDefaultLevel(this.options.debug
            ? log_1.default.levels.DEBUG
            : this.options.warnings
                ? log_1.default.levels.WARN
                : log_1.default.levels.SILENT);
        this._chunderURIs = this.options.chunderw
            ? ["wss://" + this.options.chunderw + "/signal"]
            : regions_1.getChunderURIs(this.options.edge, this.options.region, this._log.warn.bind(this._log)).map(function (uri) { return "wss://" + uri + "/signal"; });
        if (typeof Device._isUnifiedPlanDefault === 'undefined') {
            Device._isUnifiedPlanDefault = typeof window !== 'undefined'
                && typeof RTCPeerConnection !== 'undefined'
                && typeof RTCRtpTransceiver !== 'undefined'
                ? util_1.isUnifiedPlanDefault(window, window.navigator, RTCPeerConnection, RTCRtpTransceiver)
                : false;
        }
        Device._getOrCreateAudioContext();
        if (Device._audioContext && options.fakeLocalDTMF) {
            if (!Device._dialtonePlayer) {
                Device._dialtonePlayer = new dialtonePlayer_1.default(Device._audioContext);
            }
        }
        else if (Device._dialtonePlayer) {
            Device._dialtonePlayer.cleanup();
            delete Device._dialtonePlayer;
        }
        if (this.isInitialized) {
            this._log.info('Found existing Device; using new token but ignoring options');
            this.updateToken(token);
            return this;
        }
        this.isInitialized = true;
        if (this.options.dscp) {
            this.options.rtcConstraints.optional = [{ googDscp: true }];
        }
        var getOrSetSound = function (key, value) {
            if (!hasBeenWarnedSounds) {
                _this._log.warn('Device.sounds is deprecated and will be removed in the next breaking ' +
                    'release. Please use the new functionality available on Device.audio.');
                hasBeenWarnedSounds = true;
            }
            if (typeof value !== 'undefined') {
                _this._enabledSounds[key] = value;
            }
            return _this._enabledSounds[key];
        };
        [Device.SoundName.Disconnect, Device.SoundName.Incoming, Device.SoundName.Outgoing]
            .forEach(function (eventName) {
            _this.sounds[eventName] = getOrSetSound.bind(null, eventName);
        });
        var defaultSounds = {
            disconnect: { filename: 'disconnect', maxDuration: 3000 },
            dtmf0: { filename: 'dtmf-0', maxDuration: 1000 },
            dtmf1: { filename: 'dtmf-1', maxDuration: 1000 },
            dtmf2: { filename: 'dtmf-2', maxDuration: 1000 },
            dtmf3: { filename: 'dtmf-3', maxDuration: 1000 },
            dtmf4: { filename: 'dtmf-4', maxDuration: 1000 },
            dtmf5: { filename: 'dtmf-5', maxDuration: 1000 },
            dtmf6: { filename: 'dtmf-6', maxDuration: 1000 },
            dtmf7: { filename: 'dtmf-7', maxDuration: 1000 },
            dtmf8: { filename: 'dtmf-8', maxDuration: 1000 },
            dtmf9: { filename: 'dtmf-9', maxDuration: 1000 },
            dtmfh: { filename: 'dtmf-hash', maxDuration: 1000 },
            dtmfs: { filename: 'dtmf-star', maxDuration: 1000 },
            incoming: { filename: 'incoming', shouldLoop: true },
            outgoing: { filename: 'outgoing', maxDuration: 3000 },
        };
        for (var _i = 0, _a = Object.keys(defaultSounds); _i < _a.length; _i++) {
            var name_1 = _a[_i];
            var soundDef = defaultSounds[name_1];
            var defaultUrl = C.SOUNDS_BASE_URL + "/" + soundDef.filename + "." + Device.extension
                + ("?cache=" + C.RELEASE_VERSION);
            var soundUrl = this.options.sounds && this.options.sounds[name_1] || defaultUrl;
            var sound = new this.options.soundFactory(name_1, soundUrl, {
                audioContext: this.options.disableAudioContextSounds ? null : Device.audioContext,
                maxDuration: soundDef.maxDuration,
                shouldLoop: soundDef.shouldLoop,
            });
            this.soundcache.set(name_1, sound);
        }
        this._publisher = (this.options.Publisher || Publisher)('twilio-js-sdk', token, {
            defaultPayload: this._createDefaultPayload,
            host: this.options.eventgw,
            metadata: {
                app_name: this.options.appName,
                app_version: this.options.appVersion,
            },
        });
        if (this.options.publishEvents === false) {
            this._publisher.disable();
        }
        else {
            this._publisher.on('error', function (error) {
                _this._log.warn('Cannot connect to insights.', error);
            });
        }
        if (this._networkInformation && typeof this._networkInformation.addEventListener === 'function') {
            this._networkInformation.addEventListener('change', this._publishNetworkChange);
        }
        this.audio = new (this.options.AudioHelper || audiohelper_1.default)(this._updateSinkIds, this._updateInputStream, getUserMedia, {
            audioContext: Device.audioContext,
            enabledSounds: this._enabledSounds,
        });
        this.audio.on('deviceChange', function (lostActiveDevices) {
            var activeConnection = _this._activeConnection;
            var deviceIds = lostActiveDevices.map(function (device) { return device.deviceId; });
            _this._publisher.info('audio', 'device-change', {
                lost_active_device_ids: deviceIds,
            }, activeConnection);
            if (activeConnection) {
                activeConnection.mediaStream._onInputDevicesChanged();
            }
        });
        this.mediaPresence.audio = !this.options.noRegister;
        this.updateToken(token);
        // Setup close protection and make sure we clean up ongoing calls on unload.
        if (typeof window !== 'undefined' && window.addEventListener) {
            window.addEventListener('unload', this.destroy);
            window.addEventListener('pagehide', this.destroy);
            if (this.options.closeProtection) {
                window.addEventListener('beforeunload', this._confirmClose);
            }
        }
        // (rrowland) This maintains backward compatibility, but we should look at
        // removing this next breaking change. Any error should be caught by the
        // customer, and anything that's not a fatal error should not be emitted
        // via error event.
        this.on(Device.EventName.Error, function () {
            if (_this.listenerCount('error') > 1) {
                return;
            }
            _this._log.info('Uncaught error event suppressed.');
        });
        return this;
    };
    /**
     * Get the status of this {@link Device} instance
     */
    Device.prototype.status = function () {
        this._throwUnlessSetup('status');
        return this._activeConnection ? Device.Status.Busy : this._status;
    };
    /**
     * String representation of {@link Device} instance.
     * @private
     */
    Device.prototype.toString = function () {
        return '[Twilio.Device instance]';
    };
    /**
     * Unregister to receiving incoming calls.
     */
    Device.prototype.unregisterPresence = function () {
        this._throwUnlessSetup('unregisterPresence');
        this.mediaPresence.audio = false;
        this._sendPresence();
        return this;
    };
    /**
     * Update the token and re-register.
     * @param token - The new token JWT string to register with.
     */
    Device.prototype.updateToken = function (token) {
        this._throwUnlessSetup('updateToken');
        this.token = token;
        this.register(token);
    };
    /**
     * Add a handler for an EventEmitter and emit a deprecation warning on first call.
     * @param eventName - Name of the event
     * @param handler - A handler to call when the event is emitted
     */
    Device.prototype._addHandler = function (eventName, handler) {
        if (!hasBeenWarnedHandlers) {
            this._log.warn("Device callback handlers (connect, error, offline, incoming, cancel, ready, disconnect)         have been deprecated and will be removed in the next breaking release. Instead, the EventEmitter         interface can be used to set event listeners. Example: device.on('" + eventName + "', handler)");
            hasBeenWarnedHandlers = true;
        }
        this.addListener(eventName, handler);
        return this;
    };
    /**
     * Calls the emit API such that it is asynchronous.
     * Only use this internal API if you don't want to break the execution after raising an event.
     * This prevents the issue where events are not dispatched to all handlers when one of the handlers throws an error.
     * For example, our connection:accept is not triggered if the handler for device:connect handler throws an error.
     * As a side effect, we are not able to perform our internal routines such as stopping incoming sounds.
     * See connection:accept inside _makeConnection where we call emit('connect'). This can throw an error.
     * See connection:accept inside _onSignalingInvite. This handler won't get called if the error above is thrown.
     * @private
     */
    Device.prototype._asyncEmit = function (event) {
        var _this = this;
        var args = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            args[_i - 1] = arguments[_i];
        }
        setTimeout(function () { return _this.emit.apply(_this, __spreadArrays([event], args)); });
    };
    /**
     * Find a {@link Connection} by its CallSid.
     * @param callSid
     */
    Device.prototype._findConnection = function (callSid) {
        return this.connections.find(function (conn) { return conn.parameters.CallSid === callSid
            || conn.outboundConnectionId === callSid; }) || null;
    };
    /**
     * Create a new {@link Connection}.
     * @param twimlParams - A flat object containing key:value pairs to be sent to the TwiML app.
     * @param [options] - Options to be used to instantiate the {@link Connection}.
     */
    Device.prototype._makeConnection = function (twimlParams, options) {
        var _this = this;
        if (typeof Device._isUnifiedPlanDefault === 'undefined') {
            throw new errors_1.InvalidStateError('Device has not been initialized.');
        }
        var config = {
            audioHelper: this.audio,
            getUserMedia: getUserMedia,
            isUnifiedPlanDefault: Device._isUnifiedPlanDefault,
            pstream: this.stream,
            publisher: this._publisher,
            soundcache: this.soundcache,
        };
        options = Object.assign({
            MediaStream: this.options.MediaStream
                || this.options.mediaStreamFactory
                || rtc.PeerConnection,
            audioConstraints: this.options.audioConstraints,
            beforeAccept: function (conn) {
                if (!_this._activeConnection || _this._activeConnection === conn) {
                    return;
                }
                _this._activeConnection.disconnect();
                _this._removeConnection(_this._activeConnection);
            },
            codecPreferences: this.options.codecPreferences,
            dialtonePlayer: Device._dialtonePlayer,
            dscp: this.options.dscp,
            enableIceRestart: this.options.enableIceRestart,
            enableRingingState: this.options.enableRingingState,
            forceAggressiveIceNomination: this.options.forceAggressiveIceNomination,
            getInputStream: function () { return _this.options.fileInputStream || _this._connectionInputStream; },
            getSinkIds: function () { return _this._connectionSinkIds; },
            maxAverageBitrate: this.options.maxAverageBitrate,
            preflight: this.options.preflight,
            rtcConfiguration: this.options.rtcConfiguration || { iceServers: this.options.iceServers },
            rtcConstraints: this.options.rtcConstraints,
            shouldPlayDisconnect: function () { return _this._enabledSounds.disconnect; },
            twimlParams: twimlParams,
        }, options);
        var connection = new this.options.connectionFactory(config, options);
        connection.once('accept', function () {
            _this._removeConnection(connection);
            _this._activeConnection = connection;
            if (_this.audio) {
                _this.audio._maybeStartPollingVolume();
            }
            if (connection.direction === connection_1.default.CallDirection.Outgoing && _this._enabledSounds.outgoing) {
                _this.soundcache.get(Device.SoundName.Outgoing).play();
            }
            var data = { edge: _this._edge || _this._region };
            var selectedEdge = _this.options.edge;
            if (selectedEdge) {
                data['selected_edge'] = Array.isArray(selectedEdge) ? selectedEdge : [selectedEdge];
            }
            _this._publisher.info('settings', 'edge', data, connection);
            _this._asyncEmit('connect', connection);
        });
        connection.addListener('error', function (error) {
            if (connection.status() === 'closed') {
                _this._removeConnection(connection);
            }
            if (_this.audio) {
                _this.audio._maybeStopPollingVolume();
            }
            _this._maybeStopIncomingSound();
            _this._asyncEmit('error', error);
        });
        connection.once('cancel', function () {
            _this._log.info("Canceled: " + connection.parameters.CallSid);
            _this._removeConnection(connection);
            if (_this.audio) {
                _this.audio._maybeStopPollingVolume();
            }
            _this._maybeStopIncomingSound();
            _this._asyncEmit('cancel', connection);
        });
        connection.once('disconnect', function () {
            if (_this.audio) {
                _this.audio._maybeStopPollingVolume();
            }
            _this._removeConnection(connection);
            _this._asyncEmit('disconnect', connection);
        });
        connection.once('reject', function () {
            _this._log.info("Rejected: " + connection.parameters.CallSid);
            if (_this.audio) {
                _this.audio._maybeStopPollingVolume();
            }
            _this._removeConnection(connection);
            _this._maybeStopIncomingSound();
        });
        connection.once('transportClose', function () {
            if (connection.status() !== connection_1.default.State.Pending) {
                return;
            }
            if (_this.audio) {
                _this.audio._maybeStopPollingVolume();
            }
            _this._removeConnection(connection);
            _this._maybeStopIncomingSound();
        });
        return connection;
    };
    /**
     * Stop the incoming sound if no {@link Connection}s remain.
     */
    Device.prototype._maybeStopIncomingSound = function () {
        if (!this.connections.length) {
            this.soundcache.get(Device.SoundName.Incoming).stop();
        }
    };
    /**
     * Remove a {@link Connection} from device.connections by reference
     * @param connection
     */
    Device.prototype._removeConnection = function (connection) {
        if (this._activeConnection === connection) {
            this._activeConnection = null;
        }
        for (var i = this.connections.length - 1; i >= 0; i--) {
            if (connection === this.connections[i]) {
                this.connections.splice(i, 1);
            }
        }
    };
    /**
     * Register with the signaling server.
     */
    Device.prototype._sendPresence = function () {
        if (!this.stream) {
            return;
        }
        this.stream.register({ audio: this.mediaPresence.audio });
        if (this.mediaPresence.audio) {
            this._startRegistrationTimer();
        }
        else {
            this._stopRegistrationTimer();
        }
    };
    /**
     * Set up the connection to the signaling server.
     * @param token
     */
    Device.prototype._setupStream = function (token) {
        this._log.info('Setting up VSP');
        this.stream = this.options.pStreamFactory(token, this._chunderURIs, {
            backoffMaxMs: this.options.backoffMaxMs,
        });
        this.stream.addListener('close', this._onSignalingClose);
        this.stream.addListener('connected', this._onSignalingConnected);
        this.stream.addListener('error', this._onSignalingError);
        this.stream.addListener('invite', this._onSignalingInvite);
        this.stream.addListener('offline', this._onSignalingOffline);
        this.stream.addListener('ready', this._onSignalingReady);
    };
    /**
     * Start playing the incoming ringtone, and subsequently emit the incoming event.
     * @param connection
     * @param play - The function to be used to play the sound. Must return a Promise.
     */
    Device.prototype._showIncomingConnection = function (connection, play) {
        var _this = this;
        var timeout;
        return Promise.race([
            play(),
            new Promise(function (resolve, reject) {
                timeout = setTimeout(function () {
                    var msg = 'Playing incoming ringtone took too long; it might not play. Continuing execution...';
                    reject(new Error(msg));
                }, RINGTONE_PLAY_TIMEOUT);
            }),
        ]).catch(function (reason) {
            _this._log.info(reason.message);
        }).then(function () {
            clearTimeout(timeout);
            _this.emit('incoming', connection);
        });
    };
    /**
     * Set a timeout to send another register message to the signaling server.
     */
    Device.prototype._startRegistrationTimer = function () {
        var _this = this;
        this._stopRegistrationTimer();
        this.regTimer = setTimeout(function () {
            _this._sendPresence();
        }, REGISTRATION_INTERVAL);
    };
    /**
     * Stop sending registration messages to the signaling server.
     */
    Device.prototype._stopRegistrationTimer = function () {
        if (this.regTimer) {
            clearTimeout(this.regTimer);
        }
    };
    /**
     * Throw an Error if Device.setup has not been called for this instance.
     * @param methodName - The name of the method being called before setup()
     */
    Device.prototype._throwUnlessSetup = function (methodName) {
        if (!this.isInitialized) {
            throw new errors_1.InvalidStateError("Call Device.setup() before " + methodName);
        }
    };
    /**
     * Update the device IDs of output devices being used to play the incoming ringtone through.
     * @param sinkIds - An array of device IDs
     */
    Device.prototype._updateRingtoneSinkIds = function (sinkIds) {
        return Promise.resolve(this.soundcache.get(Device.SoundName.Incoming).setSinkIds(sinkIds));
    };
    /**
     * Update the device IDs of output devices being used to play the non-ringtone sounds
     * and Call audio through.
     * @param sinkIds - An array of device IDs
     */
    Device.prototype._updateSpeakerSinkIds = function (sinkIds) {
        Array.from(this.soundcache.entries())
            .filter(function (entry) { return entry[0] !== Device.SoundName.Incoming; })
            .forEach(function (entry) { return entry[1].setSinkIds(sinkIds); });
        this._connectionSinkIds = sinkIds;
        var connection = this._activeConnection;
        return connection
            ? connection._setSinkIds(sinkIds)
            : Promise.resolve();
    };
    /**
     * Register the {@link Device}
     * @param token
     */
    Device.prototype.register = function (token) {
        if (this.stream) {
            this.stream.setToken(token);
            this._publisher.setToken(token);
        }
        else {
            this._setupStream(token);
        }
    };
    return Device;
}(events_1.EventEmitter));
(function (Device) {
    /**
     * All valid {@link Device} event names.
     */
    var EventName;
    (function (EventName) {
        EventName["Cancel"] = "cancel";
        EventName["Connect"] = "connect";
        EventName["Disconnect"] = "disconnect";
        EventName["Error"] = "error";
        EventName["Incoming"] = "incoming";
        EventName["Offline"] = "offline";
        EventName["Ready"] = "ready";
    })(EventName = Device.EventName || (Device.EventName = {}));
    /**
     * All possible {@link Device} statuses.
     */
    var Status;
    (function (Status) {
        Status["Busy"] = "busy";
        Status["Offline"] = "offline";
        Status["Ready"] = "ready";
    })(Status = Device.Status || (Device.Status = {}));
    /**
     * Names of all sounds handled by the {@link Device}.
     */
    var SoundName;
    (function (SoundName) {
        SoundName["Incoming"] = "incoming";
        SoundName["Outgoing"] = "outgoing";
        SoundName["Disconnect"] = "disconnect";
        SoundName["Dtmf0"] = "dtmf0";
        SoundName["Dtmf1"] = "dtmf1";
        SoundName["Dtmf2"] = "dtmf2";
        SoundName["Dtmf3"] = "dtmf3";
        SoundName["Dtmf4"] = "dtmf4";
        SoundName["Dtmf5"] = "dtmf5";
        SoundName["Dtmf6"] = "dtmf6";
        SoundName["Dtmf7"] = "dtmf7";
        SoundName["Dtmf8"] = "dtmf8";
        SoundName["Dtmf9"] = "dtmf9";
        SoundName["DtmfS"] = "dtmfs";
        SoundName["DtmfH"] = "dtmfh";
    })(SoundName = Device.SoundName || (Device.SoundName = {}));
})(Device || (Device = {}));
exports.default = Device;
//# sourceMappingURL=device.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/dialtonePlayer.js":
/*!*****************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/dialtonePlayer.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

/**
 * @packageDocumentation
 * @module Tools
 * @internalapi
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
/**
 * A Map of DTMF Sound Names to their mock frequency pairs.
 */
var bandFrequencies = {
    dtmf0: [1360, 960],
    dtmf1: [1230, 720],
    dtmf2: [1360, 720],
    dtmf3: [1480, 720],
    dtmf4: [1230, 790],
    dtmf5: [1360, 790],
    dtmf6: [1480, 790],
    dtmf7: [1230, 870],
    dtmf8: [1360, 870],
    dtmf9: [1480, 870],
    dtmfh: [1480, 960],
    dtmfs: [1230, 960],
};
var DialtonePlayer = /** @class */ (function () {
    function DialtonePlayer(_context) {
        var _this = this;
        this._context = _context;
        /**
         * Gain nodes, reducing the frequency.
         */
        this._gainNodes = [];
        this._gainNodes = [
            this._context.createGain(),
            this._context.createGain(),
        ];
        this._gainNodes.forEach(function (gainNode) {
            gainNode.connect(_this._context.destination);
            gainNode.gain.value = 0.1;
            _this._gainNodes.push(gainNode);
        });
    }
    DialtonePlayer.prototype.cleanup = function () {
        this._gainNodes.forEach(function (gainNode) {
            gainNode.disconnect();
        });
    };
    /**
     * Play the dual frequency tone for the passed DTMF name.
     * @param sound
     */
    DialtonePlayer.prototype.play = function (sound) {
        var _this = this;
        var frequencies = bandFrequencies[sound];
        if (!frequencies) {
            throw new errors_1.InvalidArgumentError('Invalid DTMF sound name');
        }
        var oscillators = [
            this._context.createOscillator(),
            this._context.createOscillator(),
        ];
        oscillators.forEach(function (oscillator, i) {
            oscillator.type = 'sine';
            oscillator.frequency.value = frequencies[i];
            oscillator.connect(_this._gainNodes[i]);
            oscillator.start();
            oscillator.stop(_this._context.currentTime + 0.1);
            oscillator.addEventListener('ended', function () { return oscillator.disconnect(); });
        });
    };
    return DialtonePlayer;
}());
exports.default = DialtonePlayer;
//# sourceMappingURL=dialtonePlayer.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/errors/generated.js":
/*!*******************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/errors/generated.js ***!
  \*******************************************************************/
/***/ (function(__unused_webpack_module, exports) {

"use strict";

/* tslint:disable max-classes-per-file max-line-length */
/**
 * @packageDocumentation
 * @module Voice
 * @publicapi
 * @internal
 */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", ({ value: true }));
// TypeScript doesn't allow extending Error so we need to run constructor logic on every one of these
// individually. Ideally this logic would be run in a constructor on a TwilioError class but
// due to this limitation TwilioError is an interface.
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes
function construct(context, messageOrError, originalError) {
    if (typeof messageOrError === 'string') {
        context.message = messageOrError;
        if (originalError instanceof Error) {
            context.originalError = originalError;
        }
    }
    else if (messageOrError instanceof Error) {
        context.originalError = messageOrError;
    }
}
var AuthorizationErrors;
(function (AuthorizationErrors) {
    var AccessTokenInvalid = /** @class */ (function (_super) {
        __extends(AccessTokenInvalid, _super);
        function AccessTokenInvalid(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 20101;
            _this.description = 'Invalid access token';
            _this.explanation = 'Twilio was unable to validate your Access Token';
            _this.solutions = [];
            Object.setPrototypeOf(_this, AuthorizationErrors.AccessTokenInvalid.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return AccessTokenInvalid;
    }(Error));
    AuthorizationErrors.AccessTokenInvalid = AccessTokenInvalid;
    var AccessTokenExpired = /** @class */ (function (_super) {
        __extends(AccessTokenExpired, _super);
        function AccessTokenExpired(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 20104;
            _this.description = 'Access token expired or expiration date invalid';
            _this.explanation = 'The Access Token provided to the Twilio API has expired, the expiration time specified in the token was invalid, or the expiration time specified was too far in the future';
            _this.solutions = [];
            Object.setPrototypeOf(_this, AuthorizationErrors.AccessTokenExpired.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return AccessTokenExpired;
    }(Error));
    AuthorizationErrors.AccessTokenExpired = AccessTokenExpired;
    var AuthenticationFailed = /** @class */ (function (_super) {
        __extends(AuthenticationFailed, _super);
        function AuthenticationFailed(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 20151;
            _this.description = 'Authentication Failed';
            _this.explanation = 'The Authentication with the provided JWT failed';
            _this.solutions = [];
            Object.setPrototypeOf(_this, AuthorizationErrors.AuthenticationFailed.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return AuthenticationFailed;
    }(Error));
    AuthorizationErrors.AuthenticationFailed = AuthenticationFailed;
})(AuthorizationErrors = exports.AuthorizationErrors || (exports.AuthorizationErrors = {}));
var ClientErrors;
(function (ClientErrors) {
    var BadRequest = /** @class */ (function (_super) {
        __extends(BadRequest, _super);
        function BadRequest(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 31400;
            _this.description = 'Bad Request (HTTP/SIP)';
            _this.explanation = 'The request could not be understood due to malformed syntax.';
            _this.solutions = [];
            Object.setPrototypeOf(_this, ClientErrors.BadRequest.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return BadRequest;
    }(Error));
    ClientErrors.BadRequest = BadRequest;
})(ClientErrors = exports.ClientErrors || (exports.ClientErrors = {}));
var GeneralErrors;
(function (GeneralErrors) {
    var UnknownError = /** @class */ (function (_super) {
        __extends(UnknownError, _super);
        function UnknownError(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 31000;
            _this.description = 'Unknown Error';
            _this.explanation = 'An unknown error has occurred. See error details for more information.';
            _this.solutions = [];
            Object.setPrototypeOf(_this, GeneralErrors.UnknownError.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return UnknownError;
    }(Error));
    GeneralErrors.UnknownError = UnknownError;
    var ConnectionError = /** @class */ (function (_super) {
        __extends(ConnectionError, _super);
        function ConnectionError(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 31005;
            _this.description = 'Connection error';
            _this.explanation = 'A connection error occurred during the call';
            _this.solutions = [];
            Object.setPrototypeOf(_this, GeneralErrors.ConnectionError.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return ConnectionError;
    }(Error));
    GeneralErrors.ConnectionError = ConnectionError;
    var TransportError = /** @class */ (function (_super) {
        __extends(TransportError, _super);
        function TransportError(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 31009;
            _this.description = 'Transport error';
            _this.explanation = 'No transport available to send or receive messages';
            _this.solutions = [];
            Object.setPrototypeOf(_this, GeneralErrors.TransportError.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return TransportError;
    }(Error));
    GeneralErrors.TransportError = TransportError;
})(GeneralErrors = exports.GeneralErrors || (exports.GeneralErrors = {}));
var SignalingErrors;
(function (SignalingErrors) {
    var ConnectionError = /** @class */ (function (_super) {
        __extends(ConnectionError, _super);
        function ConnectionError(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [];
            _this.code = 53000;
            _this.description = 'Signaling connection error';
            _this.explanation = 'Raised whenever a signaling connection error occurs that is not covered by a more specific error code.';
            _this.solutions = [];
            Object.setPrototypeOf(_this, SignalingErrors.ConnectionError.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return ConnectionError;
    }(Error));
    SignalingErrors.ConnectionError = ConnectionError;
    var ConnectionDisconnected = /** @class */ (function (_super) {
        __extends(ConnectionDisconnected, _super);
        function ConnectionDisconnected(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [
                'The device running your application lost its Internet connection.',
            ];
            _this.code = 53001;
            _this.description = 'Signaling connection disconnected';
            _this.explanation = 'Raised whenever the signaling connection is unexpectedly disconnected.';
            _this.solutions = [
                'Ensure the device running your application has access to a stable Internet connection.',
            ];
            Object.setPrototypeOf(_this, SignalingErrors.ConnectionDisconnected.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return ConnectionDisconnected;
    }(Error));
    SignalingErrors.ConnectionDisconnected = ConnectionDisconnected;
})(SignalingErrors = exports.SignalingErrors || (exports.SignalingErrors = {}));
var MediaErrors;
(function (MediaErrors) {
    var ClientLocalDescFailed = /** @class */ (function (_super) {
        __extends(ClientLocalDescFailed, _super);
        function ClientLocalDescFailed(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [
                'The Client may not be using a supported WebRTC implementation.',
                'The Client may not have the necessary resources to create or apply a new media description.',
            ];
            _this.code = 53400;
            _this.description = 'Client is unable to create or apply a local media description';
            _this.explanation = 'Raised whenever a Client is unable to create or apply a local media description.';
            _this.solutions = [
                'If you are experiencing this error using the JavaScript SDK, ensure you are running it with a supported WebRTC implementation.',
            ];
            Object.setPrototypeOf(_this, MediaErrors.ClientLocalDescFailed.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return ClientLocalDescFailed;
    }(Error));
    MediaErrors.ClientLocalDescFailed = ClientLocalDescFailed;
    var ClientRemoteDescFailed = /** @class */ (function (_super) {
        __extends(ClientRemoteDescFailed, _super);
        function ClientRemoteDescFailed(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [
                'The Client may not be using a supported WebRTC implementation.',
                'The Client may be connecting peer-to-peer with another Participant that is not using a supported WebRTC implementation.',
                'The Client may not have the necessary resources to apply a new media description.',
            ];
            _this.code = 53402;
            _this.description = 'Client is unable to apply a remote media description';
            _this.explanation = 'Raised whenever the Client receives a remote media description but is unable to apply it.';
            _this.solutions = [
                'If you are experiencing this error using the JavaScript SDK, ensure you are running it with a supported WebRTC implementation.',
            ];
            Object.setPrototypeOf(_this, MediaErrors.ClientRemoteDescFailed.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return ClientRemoteDescFailed;
    }(Error));
    MediaErrors.ClientRemoteDescFailed = ClientRemoteDescFailed;
    var ConnectionError = /** @class */ (function (_super) {
        __extends(ConnectionError, _super);
        function ConnectionError(messageOrError, originalError) {
            var _this = _super.call(this, '') || this;
            _this.causes = [
                'The Client was unable to establish a media connection.',
                'A media connection which was active failed liveliness checks.',
            ];
            _this.code = 53405;
            _this.description = 'Media connection failed';
            _this.explanation = 'Raised by the Client or Server whenever a media connection fails.';
            _this.solutions = [
                'If the problem persists, try connecting to another region.',
                'Check your Client\'s network connectivity.',
                'If you\'ve provided custom ICE Servers then ensure that the URLs and credentials are valid.',
            ];
            Object.setPrototypeOf(_this, MediaErrors.ConnectionError.prototype);
            construct(_this, messageOrError, originalError);
            return _this;
        }
        return ConnectionError;
    }(Error));
    MediaErrors.ConnectionError = ConnectionError;
})(MediaErrors = exports.MediaErrors || (exports.MediaErrors = {}));
/**
 * @private
 */
exports.errorsByCode = new Map([
    [20101, AuthorizationErrors.AccessTokenInvalid],
    [20104, AuthorizationErrors.AccessTokenExpired],
    [20151, AuthorizationErrors.AuthenticationFailed],
    [31400, ClientErrors.BadRequest],
    [31000, GeneralErrors.UnknownError],
    [31005, GeneralErrors.ConnectionError],
    [31009, GeneralErrors.TransportError],
    [53000, SignalingErrors.ConnectionError],
    [53001, SignalingErrors.ConnectionDisconnected],
    [53400, MediaErrors.ClientLocalDescFailed],
    [53402, MediaErrors.ClientRemoteDescFailed],
    [53405, MediaErrors.ConnectionError],
]);
Object.freeze(exports.errorsByCode);
//# sourceMappingURL=generated.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/errors/index.js":
/*!***************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/errors/index.js ***!
  \***************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @internalapi
 */
/* tslint:disable max-classes-per-file */
var generated_1 = __webpack_require__(/*! ./generated */ "./node_modules/twilio-client/es5/twilio/errors/generated.js");
exports.AuthorizationErrors = generated_1.AuthorizationErrors;
exports.ClientErrors = generated_1.ClientErrors;
exports.GeneralErrors = generated_1.GeneralErrors;
exports.MediaErrors = generated_1.MediaErrors;
exports.SignalingErrors = generated_1.SignalingErrors;
// Application errors that can be avoided by good app logic
var InvalidArgumentError = /** @class */ (function (_super) {
    __extends(InvalidArgumentError, _super);
    function InvalidArgumentError(message) {
        var _this = _super.call(this, message) || this;
        _this.name = 'InvalidArgumentError';
        return _this;
    }
    return InvalidArgumentError;
}(Error));
exports.InvalidArgumentError = InvalidArgumentError;
var InvalidStateError = /** @class */ (function (_super) {
    __extends(InvalidStateError, _super);
    function InvalidStateError(message) {
        var _this = _super.call(this, message) || this;
        _this.name = 'InvalidStateError';
        return _this;
    }
    return InvalidStateError;
}(Error));
exports.InvalidStateError = InvalidStateError;
var NotSupportedError = /** @class */ (function (_super) {
    __extends(NotSupportedError, _super);
    function NotSupportedError(message) {
        var _this = _super.call(this, message) || this;
        _this.name = 'NotSupportedError';
        return _this;
    }
    return NotSupportedError;
}(Error));
exports.NotSupportedError = NotSupportedError;
// This should only be used to look up error codes returned by a server
// using the same repo of error codes.
function getErrorByCode(code) {
    var error = generated_1.errorsByCode.get(code);
    if (!error) {
        throw new InvalidArgumentError("Error code " + code + " not found");
    }
    return error;
}
exports.getErrorByCode = getErrorByCode;
//# sourceMappingURL=index.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/eventpublisher.js":
/*!*****************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/eventpublisher.js ***!
  \*****************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter;
var request = __webpack_require__(/*! ./request */ "./node_modules/twilio-client/es5/twilio/request.js");
var util = __webpack_require__(/*! util */ "./node_modules/util/util.js");

/**
 * Builds Endpoint Analytics (EA) event payloads and sends them to
 *   the EA server.
 * @constructor
 * @param {String} productName - Name of the product publishing events.
 * @param {String} token - The JWT token to use to authenticate with
 *   the EA server.
 * @param {EventPublisher.Options} options
 * @property {Boolean} isEnabled - Whether or not this publisher is publishing
 *   to the server. Currently ignores the request altogether, in the future this
 *   may store them in case publishing is re-enabled later. Defaults to true.
 */ /**
    * @typedef {Object} EventPublisher.Options
    * @property {Object} [metadata=undefined] - A publisher_metadata object to send
    *   with each payload.
    * @property {String} [host='eventgw.twilio.com'] - The host address of the EA
    *   server to publish to.
    * @property {Object|Function} [defaultPayload] - A default payload to extend
    *   when creating and sending event payloads. Also takes a function that
    *   should return an object representing the default payload. This is
    *   useful for fields that should always be present when they are
    *   available, but are not always available.
    */
function EventPublisher(productName, token, options) {
  if (!(this instanceof EventPublisher)) {
    return new EventPublisher(productName, token, options);
  }

  // Apply default options
  options = Object.assign({
    defaultPayload: function defaultPayload() {
      return {};
    },

    host: 'eventgw.twilio.com'
  }, options);

  var defaultPayload = options.defaultPayload;

  if (typeof defaultPayload !== 'function') {
    defaultPayload = function defaultPayload() {
      return Object.assign({}, options.defaultPayload);
    };
  }

  var isEnabled = true;
  // eslint-disable-next-line camelcase,no-undefined
  var metadata = Object.assign({ app_name: undefined, app_version: undefined }, options.metadata);

  Object.defineProperties(this, {
    _defaultPayload: { value: defaultPayload },
    _isEnabled: {
      get: function get() {
        return isEnabled;
      },
      set: function set(_isEnabled) {
        isEnabled = _isEnabled;
      }
    },
    _host: { value: options.host },
    _request: { value: options.request || request, writable: true },
    _token: { value: token, writable: true },
    isEnabled: {
      enumerable: true,
      get: function get() {
        return isEnabled;
      }
    },
    metadata: {
      enumerable: true,
      get: function get() {
        return metadata;
      }
    },
    productName: { enumerable: true, value: productName },
    token: {
      enumerable: true,
      get: function get() {
        return this._token;
      }
    }
  });
}

util.inherits(EventPublisher, EventEmitter);

/**
 * Post to an EA server.
 * @private
 * @param {String} endpointName - Endpoint to post the event to
 * @param {String} level - ['debug', 'info', 'warning', 'error']
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {?Object} [payload=null] - The payload to pass. This will be extended
 *    onto the default payload object, if one exists.
 * @param {?Connection} [connection=null] - The {@link Connection} which is posting this payload.
 * @param {?Boolean} [force=false] - Whether or not to send this even if
 *    publishing is disabled.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype._post = function _post(endpointName, level, group, name, payload, connection, force) {
  var _this = this;

  if (!this.isEnabled && !force) {
    return Promise.resolve();
  }

  if (!connection || (!connection.parameters || !connection.parameters.CallSid) && !connection.outboundConnectionId) {
    return Promise.resolve();
  }

  var event = {
    /* eslint-disable camelcase */
    publisher: this.productName,
    group: group,
    name: name,
    timestamp: new Date().toISOString(),
    level: level.toUpperCase(),
    payload_type: 'application/json',
    private: false,
    payload: payload && payload.forEach ? payload.slice(0) : Object.assign(this._defaultPayload(connection), payload)
    /* eslint-enable camelcase */
  };

  if (this.metadata) {
    // eslint-disable-next-line camelcase
    event.publisher_metadata = this.metadata;
  }

  var requestParams = {
    url: 'https://' + this._host + '/v4/' + endpointName,
    body: event,
    headers: {
      'Content-Type': 'application/json',
      'X-Twilio-Token': this.token
    }
  };

  var self = this;
  return new Promise(function (resolve, reject) {
    self._request.post(requestParams, function (err) {
      if (err) {
        _this.emit('error', err);
        reject(err);
      } else {
        resolve();
      }
    });
  });
};

/**
 * Post an event to the EA server. Use this method when the level
 *  is dynamic. Otherwise, it's better practice to use the sugar
 *  methods named for the specific level.
 * @param {String} level - ['debug', 'info', 'warning', 'error']
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {?Object} [payload=null] - The payload to pass. This will be extended
 *    onto the default payload object, if one exists.
 * @param {?Connection} [connection=null] - The {@link Connection} which is posting this payload.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype.post = function post(level, group, name, payload, connection, force) {
  return this._post('EndpointEvents', level, group, name, payload, connection, force);
};

/**
 * Post a debug-level event to the EA server.
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {?Object} [payload=null] - The payload to pass. This will be extended
 *    onto the default payload object, if one exists.
 * @param {?Connection} [connection=null] - The {@link Connection} which is posting this payload.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype.debug = function debug(group, name, payload, connection) {
  return this.post('debug', group, name, payload, connection);
};

/**
 * Post an info-level event to the EA server.
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {?Object} [payload=null] - The payload to pass. This will be extended
 *    onto the default payload object, if one exists.
 * @param {?Connection} [connection=null] - The {@link Connection} which is posting this payload.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype.info = function info(group, name, payload, connection) {
  return this.post('info', group, name, payload, connection);
};

/**
 * Post a warning-level event to the EA server.
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {?Object} [payload=null] - The payload to pass. This will be extended
 *    onto the default payload object, if one exists.
 * @param {?Connection} [connection=null] - The {@link Connection} which is posting this payload.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype.warn = function warn(group, name, payload, connection) {
  return this.post('warning', group, name, payload, connection);
};

/**
 * Post an error-level event to the EA server.
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {?Object} [payload=null] - The payload to pass. This will be extended
 *    onto the default payload object, if one exists.
 * @param {?Connection} [connection=null] - The {@link Connection} which is posting this payload.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype.error = function error(group, name, payload, connection) {
  return this.post('error', group, name, payload, connection);
};

/**
 * Post a metrics event to the EA server.
 * @param {String} group - The name of the group the event belongs to.
 * @param {String} name - The designated event name.
 * @param {Array<Object>} metrics - The metrics to post.
 * @param {?Object} [customFields] - Custom fields to append to each payload.
 * @returns {Promise} Fulfilled if the HTTP response is 20x.
 */
EventPublisher.prototype.postMetrics = function postMetrics(group, name, metrics, customFields, connection) {
  var _this2 = this;

  return new Promise(function (resolve) {
    var samples = metrics.map(formatMetric).map(function (sample) {
      return Object.assign(sample, customFields);
    });

    resolve(_this2._post('EndpointMetrics', 'info', group, name, samples, connection));
  });
};

/**
 * Update the token to use to authenticate requests.
 * @param {string} token
 * @returns {void}
 */
EventPublisher.prototype.setToken = function setToken(token) {
  this._token = token;
};

/**
 * Enable the publishing of events.
 */
EventPublisher.prototype.enable = function enable() {
  this._isEnabled = true;
};

/**
 * Disable the publishing of events.
 */
EventPublisher.prototype.disable = function disable() {
  this._isEnabled = false;
};

function formatMetric(sample) {
  return {
    /* eslint-disable camelcase */
    timestamp: new Date(sample.timestamp).toISOString(),
    total_packets_received: sample.totals.packetsReceived,
    total_packets_lost: sample.totals.packetsLost,
    total_packets_sent: sample.totals.packetsSent,
    total_bytes_received: sample.totals.bytesReceived,
    total_bytes_sent: sample.totals.bytesSent,
    packets_received: sample.packetsReceived,
    packets_lost: sample.packetsLost,
    packets_lost_fraction: sample.packetsLostFraction && Math.round(sample.packetsLostFraction * 100) / 100,
    bytes_received: sample.bytesReceived,
    bytes_sent: sample.bytesSent,
    audio_codec: sample.codecName,
    audio_level_in: sample.audioInputLevel,
    audio_level_out: sample.audioOutputLevel,
    call_volume_input: sample.inputVolume,
    call_volume_output: sample.outputVolume,
    jitter: sample.jitter,
    rtt: sample.rtt,
    mos: sample.mos && Math.round(sample.mos * 100) / 100
    /* eslint-enable camelcase */
  };
}

module.exports = EventPublisher;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/log.js":
/*!******************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/log.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

/**
 * @packageDocumentation
 * @module Voice
 * @internalapi
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
var LogLevelModule = __webpack_require__(/*! loglevel */ "./node_modules/loglevel/lib/loglevel.js");
var constants_1 = __webpack_require__(/*! ./constants */ "./node_modules/twilio-client/es5/twilio/constants.js");
/**
 * {@link Log} provides logging features throught the sdk using loglevel module
 * See https://github.com/pimterry/loglevel for documentation
 */
var Log = /** @class */ (function () {
    /**
     * @constructor
     * @param [options] - Optional settings
     */
    function Log(options) {
        this._log = (options && options.LogLevelModule ? options.LogLevelModule : LogLevelModule).getLogger(constants_1.PACKAGE_NAME);
    }
    /**
     * Create the logger singleton instance if it doesn't exists
     * @returns The singleton {@link Log} instance
     */
    Log.getInstance = function () {
        if (!Log.instance) {
            Log.instance = new Log();
        }
        return Log.instance;
    };
    /**
     * Log a debug message
     * @param args - Any number of arguments to be passed to loglevel.debug
     */
    Log.prototype.debug = function () {
        var _a;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        (_a = this._log).debug.apply(_a, args);
    };
    /**
     * Log an error message
     * @param args - Any number of arguments to be passed to loglevel.error
     */
    Log.prototype.error = function () {
        var _a;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        (_a = this._log).error.apply(_a, args);
    };
    /**
     * Log an info message
     * @param args - Any number of arguments to be passed to loglevel.info
     */
    Log.prototype.info = function () {
        var _a;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        (_a = this._log).info.apply(_a, args);
    };
    /**
     * Set a default log level to disable all logging below the given level
     */
    Log.prototype.setDefaultLevel = function (level) {
        this._log.setDefaultLevel(level);
    };
    /**
     * Log a warning message
     * @param args - Any number of arguments to be passed to loglevel.warn
     */
    Log.prototype.warn = function () {
        var _a;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        (_a = this._log).warn.apply(_a, args);
    };
    /**
     * Log levels
     */
    Log.levels = LogLevelModule.levels;
    return Log;
}());
exports.default = Log;
//# sourceMappingURL=log.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/outputdevicecollection.js":
/*!*************************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/outputdevicecollection.js ***!
  \*************************************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 */
var constants_1 = __webpack_require__(/*! ./constants */ "./node_modules/twilio-client/es5/twilio/constants.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var DEFAULT_TEST_SOUND_URL = constants_1.SOUNDS_BASE_URL + "/outgoing.mp3";
/**
 * A smart collection containing a Set of active output devices.
 * @publicapi
 */
var OutputDeviceCollection = /** @class */ (function () {
    /**
     * @private
     */
    function OutputDeviceCollection(_name, _availableDevices, _beforeChange, _isSupported) {
        this._name = _name;
        this._availableDevices = _availableDevices;
        this._beforeChange = _beforeChange;
        this._isSupported = _isSupported;
        /**
         * The currently active output devices.
         */
        this._activeDevices = new Set();
    }
    /**
     * Delete a device from the collection. If no devices remain, the 'default'
     * device will be added as the sole device. If no `default` device exists,
     * the first available device will be used.
     * @param device - The device to delete from the collection
     * @returns whether the device was present before it was deleted
     */
    OutputDeviceCollection.prototype.delete = function (device) {
        var wasDeleted = !!(this._activeDevices.delete(device));
        var defaultDevice = this._availableDevices.get('default')
            || Array.from(this._availableDevices.values())[0];
        if (!this._activeDevices.size && defaultDevice) {
            this._activeDevices.add(defaultDevice);
        }
        // Call _beforeChange so that the implementation can react when a device is
        // removed or lost.
        var deviceIds = Array.from(this._activeDevices.values()).map(function (deviceInfo) { return deviceInfo.deviceId; });
        this._beforeChange(this._name, deviceIds);
        return !!wasDeleted;
    };
    /**
     * Get the current set of devices.
     */
    OutputDeviceCollection.prototype.get = function () {
        return this._activeDevices;
    };
    /**
     * Replace the current set of devices with a new set of devices.
     * @param deviceIdOrIds - An ID or array of IDs of devices to replace the existing devices with.
     * @returns Rejects if this feature is not supported, any of the supplied IDs are not found,
     * or no IDs are passed.
     */
    OutputDeviceCollection.prototype.set = function (deviceIdOrIds) {
        var _this = this;
        if (!this._isSupported) {
            return Promise.reject(new errors_1.NotSupportedError('This browser does not support audio output selection'));
        }
        var deviceIds = Array.isArray(deviceIdOrIds) ? deviceIdOrIds : [deviceIdOrIds];
        if (!deviceIds.length) {
            return Promise.reject(new errors_1.InvalidArgumentError('Must specify at least one device to set'));
        }
        var missingIds = [];
        var devices = deviceIds.map(function (id) {
            var device = _this._availableDevices.get(id);
            if (!device) {
                missingIds.push(id);
            }
            return device;
        });
        if (missingIds.length) {
            return Promise.reject(new errors_1.InvalidArgumentError("Devices not found: " + missingIds.join(', ')));
        }
        return new Promise(function (resolve) {
            resolve(_this._beforeChange(_this._name, deviceIds));
        }).then(function () {
            _this._activeDevices.clear();
            devices.forEach(_this._activeDevices.add, _this._activeDevices);
        });
    };
    /**
     * Test the devices by playing audio through them.
     * @param [soundUrl] - An optional URL. If none is specified, we will
     *   play a default test tone.
     * @returns Resolves with the result of the underlying HTMLAudioElements' play() calls.
     */
    OutputDeviceCollection.prototype.test = function (soundUrl) {
        if (soundUrl === void 0) { soundUrl = DEFAULT_TEST_SOUND_URL; }
        if (!this._isSupported) {
            return Promise.reject(new errors_1.NotSupportedError('This browser does not support audio output selection'));
        }
        if (!this._activeDevices.size) {
            return Promise.reject(new errors_1.InvalidStateError('No active output devices to test'));
        }
        return Promise.all(Array.from(this._activeDevices).map(function (device) {
            var el;
            // (rrowland) We need to wait for the oncanplay event because of a regression introduced
            // in Chrome M72: https://bugs.chromium.org/p/chromium/issues/detail?id=930876
            return new Promise(function (resolve) {
                el = new Audio(soundUrl);
                el.oncanplay = resolve;
            }).then(function () { return el.setSinkId(device.deviceId).then(function () { return el.play(); }); });
        }));
    };
    return OutputDeviceCollection;
}());
exports.default = OutputDeviceCollection;
//# sourceMappingURL=outputdevicecollection.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/preflight/preflight.js":
/*!**********************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/preflight/preflight.js ***!
  \**********************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __generator = (this && this.__generator) || function (thisArg, body) {
    var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
    return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
    function verb(n) { return function (v) { return step([n, v]); }; }
    function step(op) {
        if (f) throw new TypeError("Generator is already executing.");
        while (_) try {
            if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
            if (y = 0, t) op = [op[0] & 2, t.value];
            switch (op[0]) {
                case 0: case 1: t = op; break;
                case 4: _.label++; return { value: op[1], done: false };
                case 5: _.label++; y = op[1]; op = [0]; continue;
                case 7: op = _.ops.pop(); _.trys.pop(); continue;
                default:
                    if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                    if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                    if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                    if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                    if (t[2]) _.ops.pop();
                    _.trys.pop(); continue;
            }
            op = body.call(thisArg, _);
        } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
        if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
    }
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 * @preferred
 * @publicapi
 */
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var connection_1 = __webpack_require__(/*! ../connection */ "./node_modules/twilio-client/es5/twilio/connection.js");
var device_1 = __webpack_require__(/*! ../device */ "./node_modules/twilio-client/es5/twilio/device.js");
var errors_1 = __webpack_require__(/*! ../errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var stats_1 = __webpack_require__(/*! ../rtc/stats */ "./node_modules/twilio-client/es5/twilio/rtc/stats.js");
var _a = __webpack_require__(/*! ../constants */ "./node_modules/twilio-client/es5/twilio/constants.js"), COWBELL_AUDIO_URL = _a.COWBELL_AUDIO_URL, ECHO_TEST_DURATION = _a.ECHO_TEST_DURATION;
/**
 * Runs some tests to identify issues, if any, prohibiting successful calling.
 */
var PreflightTest = /** @class */ (function (_super) {
    __extends(PreflightTest, _super);
    /**
     * Construct a {@link PreflightTest} instance.
     * @constructor
     * @param token - A Twilio JWT token string.
     * @param options
     */
    function PreflightTest(token, options) {
        var _this = _super.call(this) || this;
        /**
         * Whether this test has already logged an insights-connection-warning.
         */
        _this._hasInsightsErrored = false;
        /**
         * Network related timing measurements for this test
         */
        _this._networkTiming = {};
        /**
         * The options passed to {@link PreflightTest} constructor
         */
        _this._options = {
            codecPreferences: [connection_1.default.Codec.PCMU, connection_1.default.Codec.Opus],
            debug: false,
            edge: 'roaming',
            fakeMicInput: false,
            signalingTimeoutMs: 10000,
        };
        /**
         * Current status of this test
         */
        _this._status = PreflightTest.Status.Connecting;
        Object.assign(_this._options, options);
        _this._samples = [];
        _this._warnings = [];
        _this._startTime = Date.now();
        _this._initDevice(token, __assign(__assign({}, _this._options), { fileInputStream: _this._options.fakeMicInput ?
                _this._getStreamFromFile() : undefined }));
        return _this;
    }
    /**
     * Stops the current test and raises a failed event.
     */
    PreflightTest.prototype.stop = function () {
        var _this = this;
        var error = {
            code: 31008,
            message: 'Call cancelled',
        };
        if (this._device) {
            this._device.once('offline', function () { return _this._onFailed(error); });
            this._device.destroy();
        }
        else {
            this._onFailed(error);
        }
    };
    /**
     * Emit a {PreflightTest.Warning}
     */
    PreflightTest.prototype._emitWarning = function (name, description, rtcWarning) {
        var warning = { name: name, description: description };
        if (rtcWarning) {
            warning.rtcWarning = rtcWarning;
        }
        this._warnings.push(warning);
        this.emit(PreflightTest.Events.Warning, warning);
    };
    /**
     * Returns call quality base on the RTC Stats
     */
    PreflightTest.prototype._getCallQuality = function (mos) {
        if (mos > 4.2) {
            return PreflightTest.CallQuality.Excellent;
        }
        else if (mos >= 4.1 && mos <= 4.2) {
            return PreflightTest.CallQuality.Great;
        }
        else if (mos >= 3.7 && mos <= 4) {
            return PreflightTest.CallQuality.Good;
        }
        else if (mos >= 3.1 && mos <= 3.6) {
            return PreflightTest.CallQuality.Fair;
        }
        else {
            return PreflightTest.CallQuality.Degraded;
        }
    };
    /**
     * Returns the report for this test.
     */
    PreflightTest.prototype._getReport = function () {
        var stats = this._getRTCStats();
        var testTiming = { start: this._startTime };
        if (this._endTime) {
            testTiming.end = this._endTime;
            testTiming.duration = this._endTime - this._startTime;
        }
        var report = {
            callSid: this._callSid,
            edge: this._edge,
            iceCandidateStats: this._rtcIceCandidateStatsReport.iceCandidateStats,
            networkTiming: this._networkTiming,
            samples: this._samples,
            selectedEdge: this._options.edge,
            stats: stats,
            testTiming: testTiming,
            totals: this._getRTCSampleTotals(),
            warnings: this._warnings,
        };
        var selectedIceCandidatePairStats = this._rtcIceCandidateStatsReport.selectedIceCandidatePairStats;
        if (selectedIceCandidatePairStats) {
            report.selectedIceCandidatePairStats = selectedIceCandidatePairStats;
            report.isTurnRequired = selectedIceCandidatePairStats.localCandidate.candidateType === 'relay'
                || selectedIceCandidatePairStats.remoteCandidate.candidateType === 'relay';
        }
        if (stats) {
            report.callQuality = this._getCallQuality(stats.mos.average);
        }
        return report;
    };
    /**
     * Returns RTC stats totals for this test
     */
    PreflightTest.prototype._getRTCSampleTotals = function () {
        if (!this._latestSample) {
            return;
        }
        return __assign({}, this._latestSample.totals);
    };
    /**
     * Returns RTC related stats captured during the test call
     */
    PreflightTest.prototype._getRTCStats = function () {
        var firstMosSampleIdx = this._samples.findIndex(function (sample) { return typeof sample.mos === 'number' && sample.mos > 0; });
        var samples = firstMosSampleIdx >= 0
            ? this._samples.slice(firstMosSampleIdx)
            : [];
        if (!samples || !samples.length) {
            return;
        }
        return ['jitter', 'mos', 'rtt'].reduce(function (statObj, stat) {
            var _a;
            var values = samples.map(function (s) { return s[stat]; });
            return __assign(__assign({}, statObj), (_a = {}, _a[stat] = {
                average: Number((values.reduce(function (total, value) { return total + value; }) / values.length).toPrecision(5)),
                max: Math.max.apply(Math, values),
                min: Math.min.apply(Math, values),
            }, _a));
        }, {});
    };
    /**
     * Returns a MediaStream from a media file
     */
    PreflightTest.prototype._getStreamFromFile = function () {
        var audioContext = this._options.audioContext;
        if (!audioContext) {
            throw new errors_1.NotSupportedError('Cannot fake input audio stream: AudioContext is not supported by this browser.');
        }
        var audioEl = new Audio(COWBELL_AUDIO_URL);
        audioEl.addEventListener('canplaythrough', function () { return audioEl.play(); });
        if (typeof audioEl.setAttribute === 'function') {
            audioEl.setAttribute('crossorigin', 'anonymous');
        }
        var src = audioContext.createMediaElementSource(audioEl);
        var dest = audioContext.createMediaStreamDestination();
        src.connect(dest);
        return dest.stream;
    };
    /**
     * Initialize the device
     */
    PreflightTest.prototype._initDevice = function (token, options) {
        var _this = this;
        try {
            this._device = new (options.deviceFactory || device_1.default)(token, {
                codecPreferences: options.codecPreferences,
                debug: options.debug,
                edge: options.edge,
                fileInputStream: options.fileInputStream,
                iceServers: options.iceServers,
                preflight: true,
                rtcConfiguration: options.rtcConfiguration,
            });
        }
        catch (error) {
            // We want to return before failing so the consumer can capture the event
            setTimeout(function () {
                _this._onFailed(error);
            });
            return;
        }
        this._device.once('ready', function () {
            _this._onDeviceReady();
        });
        this._device.once('error', function (error) {
            _this._onDeviceError(error);
        });
        this._signalingTimeoutTimer = setTimeout(function () {
            _this._onDeviceError({
                code: 31901,
                message: 'WebSocket - Connection Timeout',
            });
        }, options.signalingTimeoutMs);
    };
    /**
     * Called on {@link Device} error event
     * @param error
     */
    PreflightTest.prototype._onDeviceError = function (error) {
        this._device.destroy();
        this._onFailed(error);
    };
    /**
     * Called on {@link Device} ready event
     */
    PreflightTest.prototype._onDeviceReady = function () {
        var _this = this;
        clearTimeout(this._echoTimer);
        clearTimeout(this._signalingTimeoutTimer);
        this._connection = this._device.connect();
        this._networkTiming.signaling = { start: Date.now() };
        this._setupConnectionHandlers(this._connection);
        this._edge = this._device.edge || undefined;
        if (this._options.fakeMicInput) {
            this._echoTimer = setTimeout(function () { return _this._device.disconnectAll(); }, ECHO_TEST_DURATION);
            var audio = this._device.audio;
            if (audio) {
                audio.disconnect(false);
                audio.outgoing(false);
            }
        }
        this._device.once('disconnect', function () {
            _this._device.once('offline', function () { return _this._onOffline(); });
            _this._device.destroy();
        });
        var publisher = this._connection['_publisher'];
        publisher.on('error', function () {
            if (!_this._hasInsightsErrored) {
                _this._emitWarning('insights-connection-error', 'Received an error when attempting to connect to Insights gateway');
            }
            _this._hasInsightsErrored = true;
        });
    };
    /**
     * Called when there is a fatal error
     * @param error
     */
    PreflightTest.prototype._onFailed = function (error) {
        clearTimeout(this._echoTimer);
        clearTimeout(this._signalingTimeoutTimer);
        this._releaseHandlers();
        this._endTime = Date.now();
        this._status = PreflightTest.Status.Failed;
        this.emit(PreflightTest.Events.Failed, error);
    };
    /**
     * Called when the device goes offline.
     * This indicates that the test has been completed, but we won't know if it failed or not.
     * The onError event will be the indicator whether the test failed.
     */
    PreflightTest.prototype._onOffline = function () {
        var _this = this;
        // We need to make sure we always execute preflight.on('completed') last
        // as client SDK sometimes emits 'offline' event before emitting fatal errors.
        setTimeout(function () {
            if (_this._status === PreflightTest.Status.Failed) {
                return;
            }
            clearTimeout(_this._echoTimer);
            clearTimeout(_this._signalingTimeoutTimer);
            _this._releaseHandlers();
            _this._endTime = Date.now();
            _this._status = PreflightTest.Status.Completed;
            _this._report = _this._getReport();
            _this.emit(PreflightTest.Events.Completed, _this._report);
        }, 10);
    };
    /**
     * Clean up all handlers for device and connection
     */
    PreflightTest.prototype._releaseHandlers = function () {
        [this._device, this._connection].forEach(function (emitter) {
            if (emitter) {
                emitter.eventNames().forEach(function (name) { return emitter.removeAllListeners(name); });
            }
        });
    };
    /**
     * Setup the event handlers for the {@link Connection} of the test call
     * @param connection
     */
    PreflightTest.prototype._setupConnectionHandlers = function (connection) {
        var _this = this;
        if (this._options.fakeMicInput) {
            // When volume events start emitting, it means all audio outputs have been created.
            // Let's mute them if we're using fake mic input.
            connection.once('volume', function () {
                connection.mediaStream.outputs
                    .forEach(function (output) { return output.audio.muted = true; });
            });
        }
        connection.on('warning', function (name, data) {
            _this._emitWarning(name, 'Received an RTCWarning. See .rtcWarning for the RTCWarning', data);
        });
        connection.once('accept', function () {
            _this._callSid = connection.mediaStream.callSid;
            _this._status = PreflightTest.Status.Connected;
            _this.emit(PreflightTest.Events.Connected);
        });
        connection.on('sample', function (sample) { return __awaiter(_this, void 0, void 0, function () {
            var _a;
            return __generator(this, function (_b) {
                switch (_b.label) {
                    case 0:
                        if (!!this._latestSample) return [3 /*break*/, 2];
                        _a = this;
                        return [4 /*yield*/, (this._options.getRTCIceCandidateStatsReport || stats_1.getRTCIceCandidateStatsReport)(connection.mediaStream.version.pc)];
                    case 1:
                        _a._rtcIceCandidateStatsReport = _b.sent();
                        _b.label = 2;
                    case 2:
                        this._latestSample = sample;
                        this._samples.push(sample);
                        this.emit(PreflightTest.Events.Sample, sample);
                        return [2 /*return*/];
                }
            });
        }); });
        // TODO: Update the following once the SDK supports emitting these events
        // Let's shim for now
        [{
                reportLabel: 'peerConnection',
                type: 'pcconnection',
            }, {
                reportLabel: 'ice',
                type: 'iceconnection',
            }, {
                reportLabel: 'dtls',
                type: 'dtlstransport',
            }, {
                reportLabel: 'signaling',
                type: 'signaling',
            }].forEach(function (_a) {
            var type = _a.type, reportLabel = _a.reportLabel;
            var handlerName = "on" + type + "statechange";
            var originalHandler = connection.mediaStream[handlerName];
            connection.mediaStream[handlerName] = function (state) {
                var timing = _this._networkTiming[reportLabel]
                    = _this._networkTiming[reportLabel] || { start: 0 };
                if (state === 'connecting' || state === 'checking') {
                    timing.start = Date.now();
                }
                else if ((state === 'connected' || state === 'stable') && !timing.duration) {
                    timing.end = Date.now();
                    timing.duration = timing.end - timing.start;
                }
                originalHandler(state);
            };
        });
    };
    Object.defineProperty(PreflightTest.prototype, "callSid", {
        /**
         * The callsid generated for the test call.
         */
        get: function () {
            return this._callSid;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PreflightTest.prototype, "endTime", {
        /**
         * A timestamp in milliseconds of when the test ended.
         */
        get: function () {
            return this._endTime;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PreflightTest.prototype, "latestSample", {
        /**
         * The latest WebRTC sample collected.
         */
        get: function () {
            return this._latestSample;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PreflightTest.prototype, "report", {
        /**
         * The report for this test.
         */
        get: function () {
            return this._report;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PreflightTest.prototype, "startTime", {
        /**
         * A timestamp in milliseconds of when the test started.
         */
        get: function () {
            return this._startTime;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(PreflightTest.prototype, "status", {
        /**
         * The status of the test.
         */
        get: function () {
            return this._status;
        },
        enumerable: true,
        configurable: true
    });
    return PreflightTest;
}(events_1.EventEmitter));
exports.PreflightTest = PreflightTest;
(function (PreflightTest) {
    /**
     * The quality of the call determined by different mos ranges.
     * Mos is calculated base on the WebRTC stats - rtt, jitter, and packet lost.
     */
    var CallQuality;
    (function (CallQuality) {
        /**
         * If the average mos is over 4.2.
         */
        CallQuality["Excellent"] = "excellent";
        /**
         * If the average mos is between 4.1 and 4.2 both inclusive.
         */
        CallQuality["Great"] = "great";
        /**
         * If the average mos is between 3.7 and 4.0 both inclusive.
         */
        CallQuality["Good"] = "good";
        /**
         * If the average mos is between 3.1 and 3.6 both inclusive.
         */
        CallQuality["Fair"] = "fair";
        /**
         * If the average mos is 3.0 or below.
         */
        CallQuality["Degraded"] = "degraded";
    })(CallQuality = PreflightTest.CallQuality || (PreflightTest.CallQuality = {}));
    /**
     * Possible events that a [[PreflightTest]] might emit.
     */
    var Events;
    (function (Events) {
        /**
         * See [[PreflightTest.completedEvent]]
         */
        Events["Completed"] = "completed";
        /**
         * See [[PreflightTest.connectedEvent]]
         */
        Events["Connected"] = "connected";
        /**
         * See [[PreflightTest.failedEvent]]
         */
        Events["Failed"] = "failed";
        /**
         * See [[PreflightTest.sampleEvent]]
         */
        Events["Sample"] = "sample";
        /**
         * See [[PreflightTest.warningEvent]]
         */
        Events["Warning"] = "warning";
    })(Events = PreflightTest.Events || (PreflightTest.Events = {}));
    /**
     * Possible status of the test.
     */
    var Status;
    (function (Status) {
        /**
         * Connection to Twilio has initiated.
         */
        Status["Connecting"] = "connecting";
        /**
         * Connection to Twilio has been established.
         */
        Status["Connected"] = "connected";
        /**
         * The connection to Twilio has been disconnected and the test call has completed.
         */
        Status["Completed"] = "completed";
        /**
         * The test has stopped and failed.
         */
        Status["Failed"] = "failed";
    })(Status = PreflightTest.Status || (PreflightTest.Status = {}));
})(PreflightTest = exports.PreflightTest || (exports.PreflightTest = {}));
exports.PreflightTest = PreflightTest;
//# sourceMappingURL=preflight.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/pstream.js":
/*!**********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/pstream.js ***!
  \**********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

var C = __webpack_require__(/*! ./constants */ "./node_modules/twilio-client/es5/twilio/constants.js");
var EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter;
var Log = __webpack_require__(/*! ./log */ "./node_modules/twilio-client/es5/twilio/log.js").default;
var util = __webpack_require__(/*! util */ "./node_modules/util/util.js");

var WSTransport = __webpack_require__(/*! ./wstransport */ "./node_modules/twilio-client/es5/twilio/wstransport.js").default;

var _require = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js"),
    GeneralErrors = _require.GeneralErrors,
    SignalingErrors = _require.SignalingErrors;

var PSTREAM_VERSION = '1.5';

/**
 * Constructor for PStream objects.
 *
 * @exports PStream as Twilio.PStream
 * @memberOf Twilio
 * @borrows EventEmitter#addListener as #addListener
 * @borrows EventEmitter#removeListener as #removeListener
 * @borrows EventEmitter#emit as #emit
 * @borrows EventEmitter#hasListener as #hasListener
 * @constructor
 * @param {string} token The Twilio capabilities JWT
 * @param {string[]} uris An array of PStream endpoint URIs
 * @param {object} [options]
 * @config {boolean} [options.backoffMaxMs=20000] Enable debugging
 */
function PStream(token, uris, options) {
  if (!(this instanceof PStream)) {
    return new PStream(token, uris, options);
  }
  var defaults = {
    TransportFactory: WSTransport
  };
  options = options || {};
  for (var prop in defaults) {
    if (prop in options) continue;
    options[prop] = defaults[prop];
  }
  this.options = options;
  this.token = token || '';
  this.status = 'disconnected';
  this.gateway = null;
  this.region = null;
  this._messageQueue = [];
  this._uris = uris;

  this._handleTransportClose = this._handleTransportClose.bind(this);
  this._handleTransportError = this._handleTransportError.bind(this);
  this._handleTransportMessage = this._handleTransportMessage.bind(this);
  this._handleTransportOpen = this._handleTransportOpen.bind(this);

  this._log = Log.getInstance();

  // NOTE(mroberts): EventEmitter requires that we catch all errors.
  this.on('error', function () {});

  /*
   *events used by device
   *'invite',
   *'ready',
   *'error',
   *'offline',
   *
   *'cancel',
   *'presence',
   *'roster',
   *'answer',
   *'candidate',
   *'hangup'
   */

  var self = this;

  this.addListener('ready', function () {
    self.status = 'ready';
  });

  this.addListener('offline', function () {
    self.status = 'offline';
  });

  this.addListener('close', function () {
    self._log.info('Received "close" from server. Destroying PStream...');
    self._destroy();
  });

  this.transport = new this.options.TransportFactory(this._uris, {
    backoffMaxMs: this.options.backoffMaxMs
  });

  Object.defineProperties(this, {
    uri: {
      enumerable: true,
      get: function get() {
        return this.transport.uri;
      }
    }
  });

  this.transport.on('close', this._handleTransportClose);
  this.transport.on('error', this._handleTransportError);
  this.transport.on('message', this._handleTransportMessage);
  this.transport.on('open', this._handleTransportOpen);
  this.transport.open();

  return this;
}

util.inherits(PStream, EventEmitter);

PStream.prototype._handleTransportClose = function () {
  this.emit('transportClose');

  if (this.status !== 'disconnected') {
    if (this.status !== 'offline') {
      this.emit('offline', this);
    }
    this.status = 'disconnected';
  }
};

PStream.prototype._handleTransportError = function (error) {
  if (!error) {
    this.emit('error', { error: {
        code: 31000,
        message: 'Websocket closed without a provided reason',
        twilioError: new SignalingErrors.ConnectionDisconnected()
      } });
    return;
  }
  // We receive some errors without call metadata (just the error). We need to convert these
  // to be contained within the 'error' field so that these errors match the expected format.
  this.emit('error', typeof error.code !== 'undefined' ? { error: error } : error);
};

PStream.prototype._handleTransportMessage = function (msg) {
  if (!msg || !msg.data || typeof msg.data !== 'string') {
    return;
  }

  var _JSON$parse = JSON.parse(msg.data),
      type = _JSON$parse.type,
      _JSON$parse$payload = _JSON$parse.payload,
      payload = _JSON$parse$payload === undefined ? {} : _JSON$parse$payload;

  this.gateway = payload.gateway || this.gateway;
  this.region = payload.region || this.region;

  if (type === 'error' && payload.error) {
    payload.error.twilioError = new SignalingErrors.ConnectionError();
  }

  this.emit(type, payload);
};

PStream.prototype._handleTransportOpen = function () {
  var _this = this;

  this.status = 'connected';
  this.setToken(this.token);

  var messages = this._messageQueue.splice(0, this._messageQueue.length);
  messages.forEach(function (message) {
    return _this._publish.apply(_this, _toConsumableArray(message));
  });
};

/**
 * @return {string}
 */
PStream.toString = function () {
  return '[Twilio.PStream class]';
};
PStream.prototype.toString = function () {
  return '[Twilio.PStream instance]';
};

PStream.prototype.setToken = function (token) {
  this._log.info('Setting token and publishing listen');
  this.token = token;
  var payload = {
    token: token,
    browserinfo: getBrowserInfo()
  };
  this._publish('listen', payload);
};

PStream.prototype.register = function (mediaCapabilities) {
  var regPayload = {
    media: mediaCapabilities
  };
  this._publish('register', regPayload, true);
};

PStream.prototype.invite = function (sdp, callsid, preflight, params) {
  var payload = {
    callsid: callsid,
    sdp: sdp,
    preflight: !!preflight,
    twilio: params ? { params: params } : {}
  };
  this._publish('invite', payload, true);
};

PStream.prototype.answer = function (sdp, callsid) {
  this._publish('answer', { sdp: sdp, callsid: callsid }, true);
};

PStream.prototype.dtmf = function (callsid, digits) {
  this._publish('dtmf', { callsid: callsid, dtmf: digits }, true);
};

PStream.prototype.hangup = function (callsid, message) {
  var payload = message ? { callsid: callsid, message: message } : { callsid: callsid };
  this._publish('hangup', payload, true);
};

PStream.prototype.reject = function (callsid) {
  this._publish('reject', { callsid: callsid }, true);
};

PStream.prototype.reinvite = function (sdp, callsid) {
  this._publish('reinvite', { sdp: sdp, callsid: callsid }, false);
};

PStream.prototype._destroy = function () {
  this.transport.removeListener('close', this._handleTransportClose);
  this.transport.removeListener('error', this._handleTransportError);
  this.transport.removeListener('message', this._handleTransportMessage);
  this.transport.removeListener('open', this._handleTransportOpen);
  this.transport.close();

  this.emit('offline', this);
};

PStream.prototype.destroy = function () {
  this._log.info('PStream.destroy() called...');
  this._destroy();
  return this;
};

PStream.prototype.publish = function (type, payload) {
  return this._publish(type, payload, true);
};

PStream.prototype._publish = function (type, payload, shouldRetry) {
  var msg = JSON.stringify({
    type: type,
    version: PSTREAM_VERSION,
    payload: payload
  });
  var isSent = !!this.transport.send(msg);

  if (!isSent) {
    this.emit('error', { error: {
        code: 31009,
        message: 'No transport available to send or receive messages',
        twilioError: new GeneralErrors.TransportError()
      } });

    if (shouldRetry) {
      this._messageQueue.push([type, payload, true]);
    }
  }
};

function getBrowserInfo() {
  var nav = typeof navigator !== 'undefined' ? navigator : {};

  var info = {
    p: 'browser',
    v: C.RELEASE_VERSION,
    browser: {
      userAgent: nav.userAgent || 'unknown',
      platform: nav.platform || 'unknown'
    },
    plugin: 'rtc'
  };

  return info;
}

module.exports = PStream;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/regions.js":
/*!**********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/regions.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

"use strict";

var _a, _b, _c, _d;
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * @packageDocumentation
 * @module Voice
 * This module describes valid and deprecated regions.
 */
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
/**
 * Valid deprecated regions.
 * @private
 */
var DeprecatedRegion;
(function (DeprecatedRegion) {
    DeprecatedRegion["Au"] = "au";
    DeprecatedRegion["Br"] = "br";
    DeprecatedRegion["Ie"] = "ie";
    DeprecatedRegion["Jp"] = "jp";
    DeprecatedRegion["Sg"] = "sg";
    DeprecatedRegion["UsOr"] = "us-or";
    DeprecatedRegion["UsVa"] = "us-va";
})(DeprecatedRegion = exports.DeprecatedRegion || (exports.DeprecatedRegion = {}));
/**
 * Valid edges.
 * @private
 */
var Edge;
(function (Edge) {
    /**
     * Public edges
     */
    Edge["Sydney"] = "sydney";
    Edge["SaoPaulo"] = "sao-paulo";
    Edge["Dublin"] = "dublin";
    Edge["Frankfurt"] = "frankfurt";
    Edge["Tokyo"] = "tokyo";
    Edge["Singapore"] = "singapore";
    Edge["Ashburn"] = "ashburn";
    Edge["Umatilla"] = "umatilla";
    Edge["Roaming"] = "roaming";
    /**
     * Interconnect edges
     */
    Edge["AshburnIx"] = "ashburn-ix";
    Edge["SanJoseIx"] = "san-jose-ix";
    Edge["LondonIx"] = "london-ix";
    Edge["FrankfurtIx"] = "frankfurt-ix";
    Edge["SingaporeIx"] = "singapore-ix";
    Edge["SydneyIx"] = "sydney-ix";
    Edge["TokyoIx"] = "tokyo-ix";
})(Edge = exports.Edge || (exports.Edge = {}));
/**
 * Valid current regions.
 *
 * @deprecated
 *
 * CLIENT-6831
 * This is no longer used or updated for checking validity of regions in the
 * SDK. We now allow any string to be passed for region. Invalid regions won't
 * be able to connect, and won't throw an exception.
 *
 * CLIENT-7519
 * This is used again to temporarily convert edge values to regions as part of
 * Phase 1 Regional. This is still considered deprecated.
 *
 * @private
 */
var Region;
(function (Region) {
    Region["Au1"] = "au1";
    Region["Au1Ix"] = "au1-ix";
    Region["Br1"] = "br1";
    Region["De1"] = "de1";
    Region["De1Ix"] = "de1-ix";
    Region["Gll"] = "gll";
    Region["Ie1"] = "ie1";
    Region["Ie1Ix"] = "ie1-ix";
    Region["Ie1Tnx"] = "ie1-tnx";
    Region["Jp1"] = "jp1";
    Region["Jp1Ix"] = "jp1-ix";
    Region["Sg1"] = "sg1";
    Region["Sg1Ix"] = "sg1-ix";
    Region["Sg1Tnx"] = "sg1-tnx";
    Region["Us1"] = "us1";
    Region["Us1Ix"] = "us1-ix";
    Region["Us1Tnx"] = "us1-tnx";
    Region["Us2"] = "us2";
    Region["Us2Ix"] = "us2-ix";
    Region["Us2Tnx"] = "us2-tnx";
})(Region = exports.Region || (exports.Region = {}));
/**
 * Deprecated regions. Maps the deprecated region to its equivalent up-to-date region.
 * @private
 */
exports.deprecatedRegions = (_a = {},
    _a[DeprecatedRegion.Au] = Region.Au1,
    _a[DeprecatedRegion.Br] = Region.Br1,
    _a[DeprecatedRegion.Ie] = Region.Ie1,
    _a[DeprecatedRegion.Jp] = Region.Jp1,
    _a[DeprecatedRegion.Sg] = Region.Sg1,
    _a[DeprecatedRegion.UsOr] = Region.Us1,
    _a[DeprecatedRegion.UsVa] = Region.Us1,
    _a);
/**
 * Region shortcodes. Maps the full region name from AWS to the Twilio shortcode.
 * @private
 */
exports.regionShortcodes = {
    ASIAPAC_SINGAPORE: Region.Sg1,
    ASIAPAC_SYDNEY: Region.Au1,
    ASIAPAC_TOKYO: Region.Jp1,
    EU_FRANKFURT: Region.De1,
    EU_IRELAND: Region.Ie1,
    SOUTH_AMERICA_SAO_PAULO: Region.Br1,
    US_EAST_VIRGINIA: Region.Us1,
    US_WEST_OREGON: Region.Us2,
};
/**
 * Region URIs. Maps the Twilio shortcode to its Twilio endpoint URI.
 * @private
 */
var regionURIs = (_b = {},
    _b[Region.Au1] = 'chunderw-vpc-gll-au1.twilio.com',
    _b[Region.Au1Ix] = 'chunderw-vpc-gll-au1-ix.twilio.com',
    _b[Region.Br1] = 'chunderw-vpc-gll-br1.twilio.com',
    _b[Region.De1] = 'chunderw-vpc-gll-de1.twilio.com',
    _b[Region.De1Ix] = 'chunderw-vpc-gll-de1-ix.twilio.com',
    _b[Region.Gll] = 'chunderw-vpc-gll.twilio.com',
    _b[Region.Ie1] = 'chunderw-vpc-gll-ie1.twilio.com',
    _b[Region.Ie1Ix] = 'chunderw-vpc-gll-ie1-ix.twilio.com',
    _b[Region.Ie1Tnx] = 'chunderw-vpc-gll-ie1-tnx.twilio.com',
    _b[Region.Jp1] = 'chunderw-vpc-gll-jp1.twilio.com',
    _b[Region.Jp1Ix] = 'chunderw-vpc-gll-jp1-ix.twilio.com',
    _b[Region.Sg1] = 'chunderw-vpc-gll-sg1.twilio.com',
    _b[Region.Sg1Ix] = 'chunderw-vpc-gll-sg1-ix.twilio.com',
    _b[Region.Sg1Tnx] = 'chunderw-vpc-gll-sg1-tnx.twilio.com',
    _b[Region.Us1] = 'chunderw-vpc-gll-us1.twilio.com',
    _b[Region.Us1Ix] = 'chunderw-vpc-gll-us1-ix.twilio.com',
    _b[Region.Us1Tnx] = 'chunderw-vpc-gll-us1-tnx.twilio.com',
    _b[Region.Us2] = 'chunderw-vpc-gll-us2.twilio.com',
    _b[Region.Us2Ix] = 'chunderw-vpc-gll-us2-ix.twilio.com',
    _b[Region.Us2Tnx] = 'chunderw-vpc-gll-us2-tnx.twilio.com',
    _b);
/**
 * Edge to region mapping, as part of Phase 1 Regional (CLIENT-7519).
 * Temporary.
 * @private
 */
exports.edgeToRegion = (_c = {},
    _c[Edge.Sydney] = Region.Au1,
    _c[Edge.SaoPaulo] = Region.Br1,
    _c[Edge.Dublin] = Region.Ie1,
    _c[Edge.Frankfurt] = Region.De1,
    _c[Edge.Tokyo] = Region.Jp1,
    _c[Edge.Singapore] = Region.Sg1,
    _c[Edge.Ashburn] = Region.Us1,
    _c[Edge.Umatilla] = Region.Us2,
    _c[Edge.Roaming] = Region.Gll,
    /**
     * Interconnect edges
     */
    _c[Edge.AshburnIx] = Region.Us1Ix,
    _c[Edge.SanJoseIx] = Region.Us2Ix,
    _c[Edge.LondonIx] = Region.Ie1Ix,
    _c[Edge.FrankfurtIx] = Region.De1Ix,
    _c[Edge.SingaporeIx] = Region.Sg1Ix,
    _c[Edge.SydneyIx] = Region.Au1Ix,
    _c[Edge.TokyoIx] = Region.Jp1Ix,
    _c);
/**
 * Region to edge mapping, as part of Phase 1 Regional (CLIENT-7519).
 * Temporary.
 * @private
 */
exports.regionToEdge = (_d = {},
    _d[Region.Au1] = Edge.Sydney,
    _d[Region.Br1] = Edge.SaoPaulo,
    _d[Region.Ie1] = Edge.Dublin,
    _d[Region.De1] = Edge.Frankfurt,
    _d[Region.Jp1] = Edge.Tokyo,
    _d[Region.Sg1] = Edge.Singapore,
    _d[Region.Us1] = Edge.Ashburn,
    _d[Region.Us2] = Edge.Umatilla,
    _d[Region.Gll] = Edge.Roaming,
    /**
     * Interconnect edges
     */
    _d[Region.Us1Ix] = Edge.AshburnIx,
    _d[Region.Us2Ix] = Edge.SanJoseIx,
    _d[Region.Ie1Ix] = Edge.LondonIx,
    _d[Region.De1Ix] = Edge.FrankfurtIx,
    _d[Region.Sg1Ix] = Edge.SingaporeIx,
    _d[Region.Au1Ix] = Edge.SydneyIx,
    _d[Region.Jp1Ix] = Edge.TokyoIx,
    /**
     * Tnx regions
     */
    _d[Region.Us1Tnx] = Edge.AshburnIx,
    _d[Region.Us2Tnx] = Edge.AshburnIx,
    _d[Region.Ie1Tnx] = Edge.LondonIx,
    _d[Region.Sg1Tnx] = Edge.SingaporeIx,
    _d);
/**
 * The default region to connect to and create a chunder uri from if region is
 * not defined.
 * @constant
 * @private
 */
exports.defaultRegion = 'gll';
/**
 * The default edge to connect to and create a chunder uri from, if the edge
 * parameter is not specified during setup in `Device`.
 * @constant
 */
exports.defaultEdge = Edge.Roaming;
/**
 * The default chunder URI to connect to, should map to region `gll`.
 * @constant
 * @private
 */
exports.defaultChunderRegionURI = 'chunderw-vpc-gll.twilio.com';
/**
 * String template for a region chunder URI
 * @param region - The region.
 */
function createChunderRegionUri(region) {
    return region === exports.defaultRegion
        ? exports.defaultChunderRegionURI
        : "chunderw-vpc-gll-" + region + ".twilio.com";
}
/**
 * String template for an edge chunder URI
 * @param edge - The edge.
 */
function createChunderEdgeUri(edge) {
    return "voice-js." + edge + ".twilio.com";
}
/**
 * Get the URI associated with the passed region or edge. If both are passed,
 * then we want to fail `Device` setup, so we throw an error.
 * As of CLIENT-7519, Regions are deprecated in favor of edges as part of
 * Phase 1 Regional.
 *
 * @private
 * @param edge - A string or an array of edge values
 * @param region - The region shortcode.
 * @param [onDeprecated] - A callback containing the deprecation message to be
 *   warned when the passed parameters are deprecated.
 * @returns An array of chunder URIs
 */
function getChunderURIs(edge, region, onDeprecated) {
    if (!!region && typeof region !== 'string') {
        throw new errors_1.InvalidArgumentError('If `region` is provided, it must be of type `string`.');
    }
    if (!!edge && typeof edge !== 'string' && !Array.isArray(edge)) {
        throw new errors_1.InvalidArgumentError('If `edge` is provided, it must be of type `string` or an array of strings.');
    }
    var deprecatedMessages = [];
    var uris;
    if (region && edge) {
        throw new errors_1.InvalidArgumentError('You cannot specify `region` when `edge` is specified in' +
            '`Twilio.Device.Options`.');
    }
    else if (region) {
        var chunderRegion = region;
        deprecatedMessages.push('Regions are deprecated in favor of edges. Please see this page for ' +
            'documentation: https://www.twilio.com/docs/voice/client/edges.');
        var isDeprecatedRegion = Object.values(DeprecatedRegion).includes(chunderRegion);
        if (isDeprecatedRegion) {
            chunderRegion = exports.deprecatedRegions[chunderRegion];
        }
        var isKnownRegion = Object.values(Region).includes(chunderRegion);
        if (isKnownRegion) {
            var preferredEdge = exports.regionToEdge[chunderRegion];
            deprecatedMessages.push("Region \"" + chunderRegion + "\" is deprecated, please use `edge` " +
                ("\"" + preferredEdge + "\"."));
        }
        uris = [createChunderRegionUri(chunderRegion)];
    }
    else if (edge) {
        var edgeValues_1 = Object.values(Edge);
        var edgeParams = Array.isArray(edge) ? edge : [edge];
        uris = edgeParams.map(function (param) { return edgeValues_1.includes(param)
            ? createChunderRegionUri(exports.edgeToRegion[param])
            : createChunderEdgeUri(param); });
    }
    else {
        uris = [exports.defaultChunderRegionURI];
    }
    if (onDeprecated && deprecatedMessages.length) {
        setTimeout(function () { return onDeprecated(deprecatedMessages.join('\n')); });
    }
    return uris;
}
exports.getChunderURIs = getChunderURIs;
/**
 * Get the region shortcode by its full AWS region string.
 *
 * @private
 * @param region - The region's full AWS string.
 */
function getRegionShortcode(region) {
    return exports.regionShortcodes[region] || null;
}
exports.getRegionShortcode = getRegionShortcode;
//# sourceMappingURL=regions.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/request.js":
/*!**********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/request.js ***!
  \**********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var XHR = __webpack_require__(/*! xmlhttprequest */ "./node_modules/twilio-client/browser/xmlhttprequest.js").XMLHttpRequest;

function request(method, params, callback) {
  var options = {};
  options.XMLHttpRequest = options.XMLHttpRequest || XHR;
  var xhr = new options.XMLHttpRequest();

  xhr.open(method, params.url, true);
  xhr.onreadystatechange = function onreadystatechange() {
    if (xhr.readyState !== 4) {
      return;
    }

    if (200 <= xhr.status && xhr.status < 300) {
      callback(null, xhr.responseText);
      return;
    }

    callback(new Error(xhr.responseText));
  };

  for (var headerName in params.headers) {
    xhr.setRequestHeader(headerName, params.headers[headerName]);
  }

  xhr.send(JSON.stringify(params.body));
}
/**
 * Use XMLHttpRequest to get a network resource.
 * @param {String} method - HTTP Method
 * @param {Object} params - Request parameters
 * @param {String} params.url - URL of the resource
 * @param {Array}  params.headers - An array of headers to pass [{ headerName : headerBody }]
 * @param {Object} params.body - A JSON body to send to the resource
 * @returns {response}
 **/
var Request = request;

/**
 * Sugar function for request('GET', params, callback);
 * @param {Object} params - Request parameters
 * @param {Request~get} callback - The callback that handles the response.
 */
Request.get = function get(params, callback) {
  return new this('GET', params, callback);
};

/**
 * Sugar function for request('POST', params, callback);
 * @param {Object} params - Request parameters
 * @param {Request~post} callback - The callback that handles the response.
 */
Request.post = function post(params, callback) {
  return new this('POST', params, callback);
};

module.exports = Request;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/getusermedia.js":
/*!*******************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/getusermedia.js ***!
  \*******************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


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 NotSupportedError = __webpack_require__(/*! ../errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js").NotSupportedError;
var util = __webpack_require__(/*! ../util */ "./node_modules/twilio-client/es5/twilio/util.js");

function getUserMedia(constraints, options) {
  options = options || {};
  options.util = options.util || util;
  options.navigator = options.navigator || (typeof navigator !== 'undefined' ? navigator : null);

  return new Promise(function (resolve, reject) {
    if (!options.navigator) {
      throw new NotSupportedError('getUserMedia is not supported');
    }

    switch ('function') {
      case _typeof(options.navigator.mediaDevices && options.navigator.mediaDevices.getUserMedia):
        return resolve(options.navigator.mediaDevices.getUserMedia(constraints));
      case _typeof(options.navigator.webkitGetUserMedia):
        return options.navigator.webkitGetUserMedia(constraints, resolve, reject);
      case _typeof(options.navigator.mozGetUserMedia):
        return options.navigator.mozGetUserMedia(constraints, resolve, reject);
      case _typeof(options.navigator.getUserMedia):
        return options.navigator.getUserMedia(constraints, resolve, reject);
      default:
        throw new NotSupportedError('getUserMedia is not supported');
    }
  }).catch(function (e) {
    throw options.util.isFirefox() && e.name === 'NotReadableError' ? new NotSupportedError('Firefox does not currently support opening multiple audio input tracks' + 'simultaneously, even across different tabs.\n' + 'Related Bugzilla thread: https://bugzilla.mozilla.org/show_bug.cgi?id=1299324') : e;
  });
}

module.exports = getUserMedia;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/icecandidate.js":
/*!*******************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/icecandidate.js ***!
  \*******************************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";

/**
 * @packageDocumentation
 * @module Voice
 * @internalapi
 */
Object.defineProperty(exports, "__esModule", ({ value: true }));
/**
 * {@link RTCIceCandidate} parses an ICE candidate gathered by the browser
 * and returns a IceCandidate object
 */
var IceCandidate = /** @class */ (function () {
    /**
     * @constructor
     * @param iceCandidate RTCIceCandidate coming from the browser
     */
    function IceCandidate(iceCandidate, isRemote) {
        if (isRemote === void 0) { isRemote = false; }
        /**
         * Whether this is deleted from the list of candidate gathered
         */
        this.deleted = false;
        var cost;
        var parts = iceCandidate.candidate.split('network-cost ');
        if (parts[1]) {
            cost = parseInt(parts[1], 10);
        }
        this.candidateType = iceCandidate.type;
        this.ip = iceCandidate.ip || iceCandidate.address;
        this.isRemote = isRemote;
        this.networkCost = cost;
        this.port = iceCandidate.port;
        this.priority = iceCandidate.priority;
        this.protocol = iceCandidate.protocol;
        this.relatedAddress = iceCandidate.relatedAddress;
        this.relatedPort = iceCandidate.relatedPort;
        this.tcpType = iceCandidate.tcpType;
        this.transportId = iceCandidate.sdpMid;
    }
    /**
     * Get the payload object for insights
     */
    IceCandidate.prototype.toPayload = function () {
        return {
            'candidate_type': this.candidateType,
            'deleted': this.deleted,
            'ip': this.ip,
            'is_remote': this.isRemote,
            'network-cost': this.networkCost,
            'port': this.port,
            'priority': this.priority,
            'protocol': this.protocol,
            'related_address': this.relatedAddress,
            'related_port': this.relatedPort,
            'tcp_type': this.tcpType,
            'transport_id': this.transportId,
        };
    };
    return IceCandidate;
}());
exports.IceCandidate = IceCandidate;
//# sourceMappingURL=icecandidate.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/index.js":
/*!************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/index.js ***!
  \************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var PeerConnection = __webpack_require__(/*! ./peerconnection */ "./node_modules/twilio-client/es5/twilio/rtc/peerconnection.js");

var _require = __webpack_require__(/*! ./rtcpc */ "./node_modules/twilio-client/es5/twilio/rtc/rtcpc.js"),
    test = _require.test;

function enabled() {
  return test();
}

function getMediaEngine() {
  return typeof RTCIceGatherer !== 'undefined' ? 'ORTC' : 'WebRTC';
}

module.exports = {
  enabled: enabled,
  getMediaEngine: getMediaEngine,
  PeerConnection: PeerConnection
};

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/mockrtcstatsreport.js":
/*!*************************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/mockrtcstatsreport.js ***!
  \*************************************************************************/
/***/ ((module) => {

/**
 * This file was imported from another project. If making changes to this file, please don't
 * make them here. Make them on the linked repo below, then copy back:
 * https://code.hq.twilio.com/client/MockRTCStatsReport
 */
/* eslint-disable no-undefined */
// The legacy max volume, which is the positive half of a signed short integer.
var OLD_MAX_VOLUME = 32767;
var NativeRTCStatsReport = typeof window !== 'undefined'
    ? window.RTCStatsReport : undefined;
/**
 * Create a MockRTCStatsReport wrapper around a Map of RTCStats objects. If RTCStatsReport is available
 *   natively, it will be inherited so that instanceof checks pass.
 * @constructor
 * @extends RTCStatsReport
 * @param {Map<string, RTCStats>} statsMap - A Map of RTCStats objects to wrap
 *   with a MockRTCStatsReport object.
 */
function MockRTCStatsReport(statsMap) {
    if (!(this instanceof MockRTCStatsReport)) {
        return new MockRTCStatsReport(statsMap);
    }
    var self = this;
    Object.defineProperties(this, {
        size: {
            enumerable: true,
            get: function () {
                return self._map.size;
            }
        },
        _map: { value: statsMap }
    });
    this[Symbol.iterator] = statsMap[Symbol.iterator];
}
// If RTCStatsReport is available natively, inherit it. Keep our constructor.
if (NativeRTCStatsReport) {
    MockRTCStatsReport.prototype = Object.create(NativeRTCStatsReport.prototype);
    MockRTCStatsReport.prototype.constructor = MockRTCStatsReport;
}
// Map the Map-like read methods to the underlying Map
['entries', 'forEach', 'get', 'has', 'keys', 'values'].forEach(function (key) {
    MockRTCStatsReport.prototype[key] = function () {
        var _a;
        var args = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            args[_i] = arguments[_i];
        }
        return (_a = this._map)[key].apply(_a, args);
    };
});
/**
 * Convert an array of RTCStats objects into a mock RTCStatsReport object.
 * @param {Array<RTCStats>}
 * @return {MockRTCStatsReport}
 */
MockRTCStatsReport.fromArray = function fromArray(array) {
    return new MockRTCStatsReport(array.reduce(function (map, rtcStats) {
        map.set(rtcStats.id, rtcStats);
        return map;
    }, new Map()));
};
/**
 * Convert a legacy RTCStatsResponse object into a mock RTCStatsReport object.
 * @param {RTCStatsResponse} statsResponse - An RTCStatsResponse object returned by the
 *   legacy getStats(callback) method in Chrome.
 * @return {MockRTCStatsReport} A mock RTCStatsReport object.
 */
MockRTCStatsReport.fromRTCStatsResponse = function fromRTCStatsResponse(statsResponse) {
    var activeCandidatePairId;
    var transportIds = new Map();
    var statsMap = statsResponse.result().reduce(function (map, report) {
        var id = report.id;
        switch (report.type) {
            case 'googCertificate':
                map.set(id, createRTCCertificateStats(report));
                break;
            case 'datachannel':
                map.set(id, createRTCDataChannelStats(report));
                break;
            case 'googCandidatePair':
                if (getBoolean(report, 'googActiveConnection')) {
                    activeCandidatePairId = id;
                }
                map.set(id, createRTCIceCandidatePairStats(report));
                break;
            case 'localcandidate':
                map.set(id, createRTCIceCandidateStats(report, false));
                break;
            case 'remotecandidate':
                map.set(id, createRTCIceCandidateStats(report, true));
                break;
            case 'ssrc':
                if (isPresent(report, 'packetsReceived')) {
                    map.set("rtp-" + id, createRTCInboundRTPStreamStats(report));
                }
                else {
                    map.set("rtp-" + id, createRTCOutboundRTPStreamStats(report));
                }
                map.set("track-" + id, createRTCMediaStreamTrackStats(report));
                map.set("codec-" + id, createRTCCodecStats(report));
                break;
            case 'googComponent':
                var transportReport = createRTCTransportStats(report);
                transportIds.set(transportReport.selectedCandidatePairId, id);
                map.set(id, createRTCTransportStats(report));
                break;
        }
        return map;
    }, new Map());
    if (activeCandidatePairId) {
        var activeTransportId = transportIds.get(activeCandidatePairId);
        if (activeTransportId) {
            statsMap.get(activeTransportId).dtlsState = 'connected';
        }
    }
    return new MockRTCStatsReport(statsMap);
};
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCTransportStats}
 */
function createRTCTransportStats(report) {
    return {
        type: 'transport',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        bytesSent: undefined,
        bytesReceived: undefined,
        rtcpTransportStatsId: undefined,
        dtlsState: undefined,
        selectedCandidatePairId: report.stat('selectedCandidatePairId'),
        localCertificateId: report.stat('localCertificateId'),
        remoteCertificateId: report.stat('remoteCertificateId')
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCCodecStats}
 */
function createRTCCodecStats(report) {
    return {
        type: 'codec',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        payloadType: undefined,
        mimeType: report.stat('mediaType') + "/" + report.stat('googCodecName'),
        clockRate: undefined,
        channels: undefined,
        sdpFmtpLine: undefined,
        implementation: undefined
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCMediaStreamTrackStats}
 */
function createRTCMediaStreamTrackStats(report) {
    return {
        type: 'track',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        trackIdentifier: report.stat('googTrackId'),
        remoteSource: undefined,
        ended: undefined,
        kind: report.stat('mediaType'),
        detached: undefined,
        ssrcIds: undefined,
        frameWidth: isPresent(report, 'googFrameWidthReceived')
            ? getInt(report, 'googFrameWidthReceived')
            : getInt(report, 'googFrameWidthSent'),
        frameHeight: isPresent(report, 'googFrameHeightReceived')
            ? getInt(report, 'googFrameHeightReceived')
            : getInt(report, 'googFrameHeightSent'),
        framesPerSecond: undefined,
        framesSent: getInt(report, 'framesEncoded'),
        framesReceived: undefined,
        framesDecoded: getInt(report, 'framesDecoded'),
        framesDropped: undefined,
        framesCorrupted: undefined,
        partialFramesLost: undefined,
        fullFramesLost: undefined,
        audioLevel: isPresent(report, 'audioOutputLevel')
            ? getInt(report, 'audioOutputLevel') / OLD_MAX_VOLUME
            : (getInt(report, 'audioInputLevel') || 0) / OLD_MAX_VOLUME,
        echoReturnLoss: getFloat(report, 'googEchoCancellationReturnLoss'),
        echoReturnLossEnhancement: getFloat(report, 'googEchoCancellationReturnLossEnhancement')
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @param {boolean} isInbound - Whether to create an inbound stats object, or outbound.
 * @returns {RTCRTPStreamStats}
 */
function createRTCRTPStreamStats(report, isInbound) {
    return {
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        ssrc: report.stat('ssrc'),
        associateStatsId: undefined,
        isRemote: undefined,
        mediaType: report.stat('mediaType'),
        trackId: "track-" + report.id,
        transportId: report.stat('transportId'),
        codecId: "codec-" + report.id,
        firCount: isInbound
            ? getInt(report, 'googFirsSent')
            : undefined,
        pliCount: isInbound
            ? getInt(report, 'googPlisSent')
            : getInt(report, 'googPlisReceived'),
        nackCount: isInbound
            ? getInt(report, 'googNacksSent')
            : getInt(report, 'googNacksReceived'),
        sliCount: undefined,
        qpSum: getInt(report, 'qpSum')
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCInboundRTPStreamStats}
 */
function createRTCInboundRTPStreamStats(report) {
    var rtp = createRTCRTPStreamStats(report, true);
    Object.assign(rtp, {
        type: 'inbound-rtp',
        packetsReceived: getInt(report, 'packetsReceived'),
        bytesReceived: getInt(report, 'bytesReceived'),
        packetsLost: getInt(report, 'packetsLost'),
        jitter: convertMsToSeconds(report.stat('googJitterReceived')),
        fractionLost: undefined,
        roundTripTime: convertMsToSeconds(report.stat('googRtt')),
        packetsDiscarded: undefined,
        packetsRepaired: undefined,
        burstPacketsLost: undefined,
        burstPacketsDiscarded: undefined,
        burstLossCount: undefined,
        burstDiscardCount: undefined,
        burstLossRate: undefined,
        burstDiscardRate: undefined,
        gapLossRate: undefined,
        gapDiscardRate: undefined,
        framesDecoded: getInt(report, 'framesDecoded')
    });
    return rtp;
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCOutboundRTPStreamStats}
 */
function createRTCOutboundRTPStreamStats(report) {
    var rtp = createRTCRTPStreamStats(report, false);
    Object.assign(rtp, {
        type: 'outbound-rtp',
        remoteTimestamp: undefined,
        packetsSent: getInt(report, 'packetsSent'),
        bytesSent: getInt(report, 'bytesSent'),
        targetBitrate: undefined,
        framesEncoded: getInt(report, 'framesEncoded')
    });
    return rtp;
}
/**
 * @param {RTCLegacyStatsReport} report
 * @param {boolean} isRemote - Whether to create for a remote candidate, or local candidate.
 * @returns {RTCIceCandidateStats}
 */
function createRTCIceCandidateStats(report, isRemote) {
    return {
        type: isRemote
            ? 'remote-candidate'
            : 'local-candidate',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        transportId: undefined,
        isRemote: isRemote,
        ip: report.stat('ipAddress'),
        port: getInt(report, 'portNumber'),
        protocol: report.stat('transport'),
        candidateType: translateCandidateType(report.stat('candidateType')),
        priority: getFloat(report, 'priority'),
        url: undefined,
        relayProtocol: undefined,
        deleted: undefined
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCIceCandidatePairStats}
 */
function createRTCIceCandidatePairStats(report) {
    return {
        type: 'candidate-pair',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        transportId: report.stat('googChannelId'),
        localCandidateId: report.stat('localCandidateId'),
        remoteCandidateId: report.stat('remoteCandidateId'),
        state: undefined,
        priority: undefined,
        nominated: undefined,
        writable: getBoolean(report, 'googWritable'),
        readable: undefined,
        bytesSent: getInt(report, 'bytesSent'),
        bytesReceived: getInt(report, 'bytesReceived'),
        lastPacketSentTimestamp: undefined,
        lastPacketReceivedTimestamp: undefined,
        totalRoundTripTime: undefined,
        currentRoundTripTime: convertMsToSeconds(report.stat('googRtt')),
        availableOutgoingBitrate: undefined,
        availableIncomingBitrate: undefined,
        requestsReceived: getInt(report, 'requestsReceived'),
        requestsSent: getInt(report, 'requestsSent'),
        responsesReceived: getInt(report, 'responsesReceived'),
        responsesSent: getInt(report, 'responsesSent'),
        retransmissionsReceived: undefined,
        retransmissionsSent: undefined,
        consentRequestsSent: getInt(report, 'consentRequestsSent')
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCIceCertificateStats}
 */
function createRTCCertificateStats(report) {
    return {
        type: 'certificate',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        fingerprint: report.stat('googFingerprint'),
        fingerprintAlgorithm: report.stat('googFingerprintAlgorithm'),
        base64Certificate: report.stat('googDerBase64'),
        issuerCertificateId: report.stat('googIssuerId')
    };
}
/**
 * @param {RTCLegacyStatsReport} report
 * @returns {RTCDataChannelStats}
 */
function createRTCDataChannelStats(report) {
    return {
        type: 'data-channel',
        id: report.id,
        timestamp: Date.parse(report.timestamp),
        label: report.stat('label'),
        protocol: report.stat('protocol'),
        datachannelid: report.stat('datachannelid'),
        transportId: report.stat('transportId'),
        state: report.stat('state'),
        messagesSent: undefined,
        bytesSent: undefined,
        messagesReceived: undefined,
        bytesReceived: undefined
    };
}
/**
 * @param {number} inMs - A time in milliseconds
 * @returns {number} The time in seconds
 */
function convertMsToSeconds(inMs) {
    return isNaN(inMs) || inMs === ''
        ? undefined
        : parseInt(inMs, 10) / 1000;
}
/**
 * @param {string} type - A type in the legacy format
 * @returns {string} The type adjusted to new standards for known naming changes
 */
function translateCandidateType(type) {
    switch (type) {
        case 'peerreflexive':
            return 'prflx';
        case 'serverreflexive':
            return 'srflx';
        case 'host':
        case 'relay':
        default:
            return type;
    }
}
function getInt(report, statName) {
    var stat = report.stat(statName);
    return isPresent(report, statName)
        ? parseInt(stat, 10)
        : undefined;
}
function getFloat(report, statName) {
    var stat = report.stat(statName);
    return isPresent(report, statName)
        ? parseFloat(stat)
        : undefined;
}
function getBoolean(report, statName) {
    var stat = report.stat(statName);
    return isPresent(report, statName)
        ? (stat === 'true' || stat === true)
        : undefined;
}
function isPresent(report, statName) {
    var stat = report.stat(statName);
    return typeof stat !== 'undefined' && stat !== '';
}
module.exports = MockRTCStatsReport;
//# sourceMappingURL=mockrtcstatsreport.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/mos.js":
/*!**********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/mos.js ***!
  \**********************************************************/
/***/ ((module) => {

"use strict";


var rfactorConstants = {
  r0: 94.768,
  is: 1.42611
};

/**
 * Calculate the mos score of a stats object
 * @param {number} rtt
 * @param {number} jitter
 * @param {number} fractionLost - The fraction of packets that have been lost
     Calculated by packetsLost / totalPackets
 * @return {number} mos - Calculated MOS, 1.0 through roughly 4.5
 */
function calcMos(rtt, jitter, fractionLost) {
  if (!isPositiveNumber(rtt) || !isPositiveNumber(jitter) || !isPositiveNumber(fractionLost)) {
    return null;
  }

  var rFactor = calculateRFactor(rtt, jitter, fractionLost);

  var mos = 1 + 0.035 * rFactor + 0.000007 * rFactor * (rFactor - 60) * (100 - rFactor);

  // Make sure MOS is in range
  var isValid = mos >= 1.0 && mos < 4.6;
  return isValid ? mos : null;
}

function calculateRFactor(rtt, jitter, fractionLost) {
  var effectiveLatency = rtt + jitter * 2 + 10;
  var rFactor = 0;

  switch (true) {
    case effectiveLatency < 160:
      rFactor = rfactorConstants.r0 - effectiveLatency / 40;
      break;
    case effectiveLatency < 1000:
      rFactor = rfactorConstants.r0 - (effectiveLatency - 120) / 10;
      break;
    case effectiveLatency >= 1000:
      rFactor = rfactorConstants.r0 - effectiveLatency / 100;
      break;
  }

  var multiplier = .01;
  switch (true) {
    case fractionLost === -1:
      multiplier = 0;
      rFactor = 0;
      break;
    case fractionLost <= rFactor / 2.5:
      multiplier = 2.5;
      break;
    case fractionLost > rFactor / 2.5 && fractionLost < 100:
      multiplier = .25;
      break;
  }

  rFactor -= fractionLost * multiplier;
  return rFactor;
}

function isPositiveNumber(n) {
  return typeof n === 'number' && !isNaN(n) && isFinite(n) && n >= 0;
}

module.exports = {
  calculate: calcMos
};

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/peerconnection.js":
/*!*********************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/peerconnection.js ***!
  \*********************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var _require = __webpack_require__(/*! ../errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js"),
    InvalidArgumentError = _require.InvalidArgumentError,
    MediaErrors = _require.MediaErrors,
    NotSupportedError = _require.NotSupportedError,
    SignalingErrors = _require.SignalingErrors;

var Log = __webpack_require__(/*! ../log */ "./node_modules/twilio-client/es5/twilio/log.js").default;
var util = __webpack_require__(/*! ../util */ "./node_modules/twilio-client/es5/twilio/util.js");
var RTCPC = __webpack_require__(/*! ./rtcpc */ "./node_modules/twilio-client/es5/twilio/rtc/rtcpc.js");

var _require2 = __webpack_require__(/*! ./sdp */ "./node_modules/twilio-client/es5/twilio/rtc/sdp.js"),
    setIceAggressiveNomination = _require2.setIceAggressiveNomination;

var ICE_GATHERING_TIMEOUT = 15000;
var ICE_GATHERING_FAIL_NONE = 'none';
var ICE_GATHERING_FAIL_TIMEOUT = 'timeout';
var INITIAL_ICE_CONNECTION_STATE = 'new';
var VOLUME_INTERVAL_MS = 50;

/**
 * @typedef {Object} PeerConnection
 * @param audioHelper
 * @param pstream
 * @param options
 * @return {PeerConnection}
 * @constructor
 */
function PeerConnection(audioHelper, pstream, getUserMedia, options) {
  if (!audioHelper || !pstream || !getUserMedia) {
    throw new InvalidArgumentError('Audiohelper, pstream and getUserMedia are required arguments');
  }

  if (!(this instanceof PeerConnection)) {
    return new PeerConnection(audioHelper, pstream, getUserMedia, options);
  }

  function noop() {}
  this.onopen = noop;
  this.onerror = noop;
  this.onclose = noop;
  this.ondisconnected = noop;
  this.onfailed = noop;
  this.onconnected = noop;
  this.onreconnected = noop;
  this.onsignalingstatechange = noop;
  this.ondtlstransportstatechange = noop;
  this.onicegatheringfailure = noop;
  this.onicegatheringstatechange = noop;
  this.oniceconnectionstatechange = noop;
  this.onpcconnectionstatechange = noop;
  this.onicecandidate = noop;
  this.onselectedcandidatepairchange = noop;
  this.onvolume = noop;
  this.version = null;
  this.pstream = pstream;
  this.stream = null;
  this.sinkIds = new Set(['default']);
  this.outputs = new Map();
  this.status = 'connecting';
  this.callSid = null;
  this.isMuted = false;
  this.getUserMedia = getUserMedia;

  var AudioContext = typeof window !== 'undefined' && (window.AudioContext || window.webkitAudioContext);
  this._isSinkSupported = !!AudioContext && typeof HTMLAudioElement !== 'undefined' && HTMLAudioElement.prototype.setSinkId;
  // NOTE(mmalavalli): Since each Connection creates its own AudioContext,
  // after 6 instances an exception is thrown. Refer https://www.w3.org/2011/audio/track/issues/3.
  // In order to get around it, we are re-using the Device's AudioContext.
  this._audioContext = AudioContext && audioHelper._audioContext;
  this._hasIceCandidates = false;
  this._hasIceGatheringFailures = false;
  this._iceGatheringTimeoutId = null;
  this._masterAudio = null;
  this._masterAudioDeviceId = null;
  this._mediaStreamSource = null;
  this._dtmfSender = null;
  this._dtmfSenderUnsupported = false;
  this._callEvents = [];
  this._nextTimeToPublish = Date.now();
  this._onAnswerOrRinging = noop;
  this._onHangup = noop;
  this._remoteStream = null;
  this._shouldManageStream = true;
  this._iceState = INITIAL_ICE_CONNECTION_STATE;
  this._isUnifiedPlan = options.isUnifiedPlan;

  this.options = options = options || {};
  this.navigator = options.navigator || (typeof navigator !== 'undefined' ? navigator : null);
  this.util = options.util || util;
  this.codecPreferences = options.codecPreferences;

  this._log = Log.getInstance();

  return this;
}

PeerConnection.prototype.uri = function () {
  return this._uri;
};

/**
 * Open the underlying RTCPeerConnection with a MediaStream obtained by
 *   passed constraints. The resulting MediaStream is created internally
 *   and will therefore be managed and destroyed internally.
 * @param {MediaStreamConstraints} constraints
 */
PeerConnection.prototype.openWithConstraints = function (constraints) {
  return this.getUserMedia({ audio: constraints }).then(this._setInputTracksFromStream.bind(this, false));
};

/**
 * Replace the existing input audio tracks with the audio tracks from the
 *   passed input audio stream. We re-use the existing stream because
 *   the AnalyzerNode is bound to the stream.
 * @param {MediaStream} stream
 */
PeerConnection.prototype.setInputTracksFromStream = function (stream) {
  var self = this;
  return this._setInputTracksFromStream(true, stream).then(function () {
    self._shouldManageStream = false;
  });
};

PeerConnection.prototype._createAnalyser = function (audioContext, options) {
  options = Object.assign({
    fftSize: 32,
    smoothingTimeConstant: 0.3
  }, options);

  var analyser = audioContext.createAnalyser();
  for (var field in options) {
    analyser[field] = options[field];
  }

  return analyser;
};

PeerConnection.prototype._setVolumeHandler = function (handler) {
  this.onvolume = handler;
};
PeerConnection.prototype._startPollingVolume = function () {
  if (!this._audioContext || !this.stream || !this._remoteStream) {
    return;
  }

  var audioContext = this._audioContext;

  var inputAnalyser = this._inputAnalyser = this._createAnalyser(audioContext);
  var inputBufferLength = inputAnalyser.frequencyBinCount;
  var inputDataArray = new Uint8Array(inputBufferLength);
  this._inputAnalyser2 = this._createAnalyser(audioContext, {
    minDecibels: -127,
    maxDecibels: 0,
    smoothingTimeConstant: 0
  });

  var outputAnalyser = this._outputAnalyser = this._createAnalyser(audioContext);
  var outputBufferLength = outputAnalyser.frequencyBinCount;
  var outputDataArray = new Uint8Array(outputBufferLength);
  this._outputAnalyser2 = this._createAnalyser(audioContext, {
    minDecibels: -127,
    maxDecibels: 0,
    smoothingTimeConstant: 0
  });

  this._updateInputStreamSource(this.stream);
  this._updateOutputStreamSource(this._remoteStream);

  var self = this;
  setTimeout(function emitVolume() {
    if (!self._audioContext) {
      return;
    } else if (self.status === 'closed') {
      self._inputAnalyser.disconnect();
      self._outputAnalyser.disconnect();
      self._inputAnalyser2.disconnect();
      self._outputAnalyser2.disconnect();
      return;
    }

    self._inputAnalyser.getByteFrequencyData(inputDataArray);
    var inputVolume = self.util.average(inputDataArray);

    self._inputAnalyser2.getByteFrequencyData(inputDataArray);
    var inputVolume2 = self.util.average(inputDataArray);

    self._outputAnalyser.getByteFrequencyData(outputDataArray);
    var outputVolume = self.util.average(outputDataArray);

    self._outputAnalyser2.getByteFrequencyData(outputDataArray);
    var outputVolume2 = self.util.average(outputDataArray);
    self.onvolume(inputVolume / 255, outputVolume / 255, inputVolume2, outputVolume2);

    setTimeout(emitVolume, VOLUME_INTERVAL_MS);
  }, VOLUME_INTERVAL_MS);
};

PeerConnection.prototype._stopStream = function _stopStream(stream) {
  // We shouldn't stop the tracks if they were not created inside
  //   this PeerConnection.
  if (!this._shouldManageStream) {
    return;
  }

  if (typeof MediaStreamTrack.prototype.stop === 'function') {
    var audioTracks = typeof stream.getAudioTracks === 'function' ? stream.getAudioTracks() : stream.audioTracks;
    audioTracks.forEach(function (track) {
      track.stop();
    });
  }
  // NOTE(mroberts): This is just a fallback to any ancient browsers that may
  // not implement MediaStreamTrack.stop.
  else {
      stream.stop();
    }
};

/**
 * Update the stream source with the new input audio stream.
 * @param {MediaStream} stream
 * @private
 */
PeerConnection.prototype._updateInputStreamSource = function (stream) {
  if (this._inputStreamSource) {
    this._inputStreamSource.disconnect();
  }

  this._inputStreamSource = this._audioContext.createMediaStreamSource(stream);
  this._inputStreamSource.connect(this._inputAnalyser);
  this._inputStreamSource.connect(this._inputAnalyser2);
};

/**
 * Update the stream source with the new ouput audio stream.
 * @param {MediaStream} stream
 * @private
 */
PeerConnection.prototype._updateOutputStreamSource = function (stream) {
  if (this._outputStreamSource) {
    this._outputStreamSource.disconnect();
  }

  this._outputStreamSource = this._audioContext.createMediaStreamSource(stream);
  this._outputStreamSource.connect(this._outputAnalyser);
  this._outputStreamSource.connect(this._outputAnalyser2);
};

/**
 * Replace the tracks of the current stream with new tracks. We do this rather than replacing the
 *   whole stream because AnalyzerNodes are bound to a stream.
 * @param {Boolean} shouldClone - Whether the stream should be cloned if it is the first
 *   stream, or set directly. As a rule of thumb, streams that are passed in externally may have
 *   their lifecycle managed externally, and should be cloned so that we do not tear it or its tracks
 *   down when the call ends. Streams that we create internally (inside PeerConnection) should be set
 *   directly so that when the call ends it is disposed of.
 * @param {MediaStream} newStream - The new stream to copy the tracks over from.
 * @private
 */
PeerConnection.prototype._setInputTracksFromStream = function (shouldClone, newStream) {
  return this._isUnifiedPlan ? this._setInputTracksForUnifiedPlan(shouldClone, newStream) : this._setInputTracksForPlanB(shouldClone, newStream);
};

/**
 * Replace the tracks of the current stream with new tracks using the 'plan-b' method.
 * @param {Boolean} shouldClone - Whether the stream should be cloned if it is the first
 *   stream, or set directly. As a rule of thumb, streams that are passed in externally may have
 *   their lifecycle managed externally, and should be cloned so that we do not tear it or its tracks
 *   down when the call ends. Streams that we create internally (inside PeerConnection) should be set
 *   directly so that when the call ends it is disposed of.
 * @param {MediaStream} newStream - The new stream to copy the tracks over from.
 * @private
 */
PeerConnection.prototype._setInputTracksForPlanB = function (shouldClone, newStream) {
  var _this = this;

  if (!newStream) {
    return Promise.reject(new InvalidArgumentError('Can not set input stream to null while in a call'));
  }

  if (!newStream.getAudioTracks().length) {
    return Promise.reject(new InvalidArgumentError('Supplied input stream has no audio tracks'));
  }

  var localStream = this.stream;

  if (!localStream) {
    // We can't use MediaStream.clone() here because it stopped copying over tracks
    //   as of Chrome 61. https://bugs.chromium.org/p/chromium/issues/detail?id=770908
    this.stream = shouldClone ? cloneStream(newStream) : newStream;
  } else {
    this._stopStream(localStream);

    removeStream(this.version.pc, localStream);
    localStream.getAudioTracks().forEach(localStream.removeTrack, localStream);
    newStream.getAudioTracks().forEach(localStream.addTrack, localStream);
    addStream(this.version.pc, newStream);

    this._updateInputStreamSource(this.stream);
  }

  // Apply mute settings to new input track
  this.mute(this.isMuted);

  if (!this.version) {
    return Promise.resolve(this.stream);
  }

  return new Promise(function (resolve, reject) {
    _this.version.createOffer(_this.options.maxAverageBitrate, _this.codecPreferences, { audio: true }, function () {
      _this.version.processAnswer(_this.codecPreferences, _this._answerSdp, function () {
        resolve(_this.stream);
      }, reject);
    }, reject);
  });
};

/**
 * Replace the tracks of the current stream with new tracks using the 'unified-plan' method.
 * @param {Boolean} shouldClone - Whether the stream should be cloned if it is the first
 *   stream, or set directly. As a rule of thumb, streams that are passed in externally may have
 *   their lifecycle managed externally, and should be cloned so that we do not tear it or its tracks
 *   down when the call ends. Streams that we create internally (inside PeerConnection) should be set
 *   directly so that when the call ends it is disposed of.
 * @param {MediaStream} newStream - The new stream to copy the tracks over from.
 * @private
 */
PeerConnection.prototype._setInputTracksForUnifiedPlan = function (shouldClone, newStream) {
  var _this2 = this;

  if (!newStream) {
    return Promise.reject(new InvalidArgumentError('Can not set input stream to null while in a call'));
  }

  if (!newStream.getAudioTracks().length) {
    return Promise.reject(new InvalidArgumentError('Supplied input stream has no audio tracks'));
  }

  var localStream = this.stream;
  var getStreamPromise = function getStreamPromise() {
    // Apply mute settings to new input track
    _this2.mute(_this2.isMuted);
    return Promise.resolve(_this2.stream);
  };

  if (!localStream) {
    // We can't use MediaStream.clone() here because it stopped copying over tracks
    //   as of Chrome 61. https://bugs.chromium.org/p/chromium/issues/detail?id=770908
    this.stream = shouldClone ? cloneStream(newStream) : newStream;
  } else {
    // If the call was started with gUM, and we are now replacing that track with an
    // external stream's tracks, we should stop the old managed track.
    if (this._shouldManageStream) {
      this._stopStream(localStream);
    }

    if (!this._sender) {
      this._sender = this.version.pc.getSenders()[0];
    }

    return this._sender.replaceTrack(newStream.getAudioTracks()[0]).then(function () {
      _this2._updateInputStreamSource(newStream);
      return getStreamPromise();
    });
  }

  return getStreamPromise();
};

PeerConnection.prototype._onInputDevicesChanged = function () {
  if (!this.stream) {
    return;
  }

  // If all of our active tracks are ended, then our active input was lost
  var activeInputWasLost = this.stream.getAudioTracks().every(function (track) {
    return track.readyState === 'ended';
  });

  // We only want to act if we manage the stream in PeerConnection (It was created
  // here, rather than passed in.)
  if (activeInputWasLost && this._shouldManageStream) {
    this.openWithConstraints(true);
  }
};

PeerConnection.prototype._onIceGatheringFailure = function (type) {
  this._hasIceGatheringFailures = true;
  this.onicegatheringfailure(type);
};

PeerConnection.prototype._onMediaConnectionStateChange = function (newState) {
  var previousState = this._iceState;

  if (previousState === newState || newState !== 'connected' && newState !== 'disconnected' && newState !== 'failed') {
    return;
  }
  this._iceState = newState;

  var message = void 0;
  switch (newState) {
    case 'connected':
      if (previousState === 'disconnected' || previousState === 'failed') {
        message = 'ICE liveliness check succeeded. Connection with Twilio restored';
        this._log.info(message);
        this.onreconnected(message);
      } else {
        message = 'Media connection established.';
        this._log.info(message);
        this.onconnected(message);
      }
      this._stopIceGatheringTimeout();
      this._hasIceGatheringFailures = false;
      break;
    case 'disconnected':
      message = 'ICE liveliness check failed. May be having trouble connecting to Twilio';
      this._log.info(message);
      this.ondisconnected(message);
      break;
    case 'failed':
      message = 'Connection with Twilio was interrupted.';
      this._log.info(message);
      this.onfailed(message);
      break;
  }
};

PeerConnection.prototype._setSinkIds = function (sinkIds) {
  if (!this._isSinkSupported) {
    return Promise.reject(new NotSupportedError('Audio output selection is not supported by this browser'));
  }

  this.sinkIds = new Set(sinkIds.forEach ? sinkIds : [sinkIds]);
  return this.version ? this._updateAudioOutputs() : Promise.resolve();
};

/**
 * Start timeout for ICE Gathering
 */
PeerConnection.prototype._startIceGatheringTimeout = function startIceGatheringTimeout() {
  var _this3 = this;

  this._stopIceGatheringTimeout();
  this._iceGatheringTimeoutId = setTimeout(function () {
    _this3._onIceGatheringFailure(ICE_GATHERING_FAIL_TIMEOUT);
  }, ICE_GATHERING_TIMEOUT);
};

/**
 * Stop timeout for ICE Gathering
 */
PeerConnection.prototype._stopIceGatheringTimeout = function stopIceGatheringTimeout() {
  clearInterval(this._iceGatheringTimeoutId);
};

PeerConnection.prototype._updateAudioOutputs = function updateAudioOutputs() {
  var addedOutputIds = Array.from(this.sinkIds).filter(function (id) {
    return !this.outputs.has(id);
  }, this);

  var removedOutputIds = Array.from(this.outputs.keys()).filter(function (id) {
    return !this.sinkIds.has(id);
  }, this);

  var self = this;
  var createOutputPromises = addedOutputIds.map(this._createAudioOutput, this);
  return Promise.all(createOutputPromises).then(function () {
    return Promise.all(removedOutputIds.map(self._removeAudioOutput, self));
  });
};

PeerConnection.prototype._createAudio = function createAudio(arr) {
  return new Audio(arr);
};

PeerConnection.prototype._createAudioOutput = function createAudioOutput(id) {
  var dest = this._audioContext.createMediaStreamDestination();
  this._mediaStreamSource.connect(dest);

  var audio = this._createAudio();
  setAudioSource(audio, dest.stream);

  var self = this;
  return audio.setSinkId(id).then(function () {
    return audio.play();
  }).then(function () {
    self.outputs.set(id, {
      audio: audio,
      dest: dest
    });
  });
};

PeerConnection.prototype._removeAudioOutputs = function removeAudioOutputs() {
  if (this._masterAudio && typeof this._masterAudioDeviceId !== 'undefined') {
    this._disableOutput(this, this._masterAudioDeviceId);
    this.outputs.delete(this._masterAudioDeviceId);
    this._masterAudioDeviceId = null;

    // Release the audio resources before deleting the audio
    if (!this._masterAudio.paused) {
      this._masterAudio.pause();
    }
    if (typeof this._masterAudio.srcObject !== 'undefined') {
      this._masterAudio.srcObject = null;
    } else {
      this._masterAudio.src = '';
    }
    this._masterAudio = null;
  }

  return Array.from(this.outputs.keys()).map(this._removeAudioOutput, this);
};

PeerConnection.prototype._disableOutput = function disableOutput(pc, id) {
  var output = pc.outputs.get(id);
  if (!output) {
    return;
  }

  if (output.audio) {
    output.audio.pause();
    output.audio.src = '';
  }

  if (output.dest) {
    output.dest.disconnect();
  }
};

/**
 * Disable a non-master output, and update the master output to assume its state. This
 *   is called when the device ID assigned to the master output has been removed from
 *   active devices. We can not simply remove the master audio output, so we must
 *   instead reassign it.
 * @private
 * @param {PeerConnection} pc
 * @param {string} masterId - The current device ID assigned to the master audio element.
 */
PeerConnection.prototype._reassignMasterOutput = function reassignMasterOutput(pc, masterId) {
  var masterOutput = pc.outputs.get(masterId);
  pc.outputs.delete(masterId);

  var self = this;
  var idToReplace = Array.from(pc.outputs.keys())[0] || 'default';
  return masterOutput.audio.setSinkId(idToReplace).then(function () {
    self._disableOutput(pc, idToReplace);

    pc.outputs.set(idToReplace, masterOutput);
    pc._masterAudioDeviceId = idToReplace;
  }).catch(function rollback() {
    pc.outputs.set(masterId, masterOutput);
    self._log.info('Could not reassign master output. Attempted to roll back.');
  });
};

PeerConnection.prototype._removeAudioOutput = function removeAudioOutput(id) {
  if (this._masterAudioDeviceId === id) {
    return this._reassignMasterOutput(this, id);
  }

  this._disableOutput(this, id);
  this.outputs.delete(id);

  return Promise.resolve();
};

/**
 * Use an AudioContext to potentially split our audio output stream to multiple
 *   audio devices. This is only available to browsers with AudioContext and
 *   HTMLAudioElement.setSinkId() available. We save the source stream in
 *   _masterAudio, and use it for one of the active audio devices. We keep
 *   track of its ID because we must replace it if we lose its initial device.
 */
PeerConnection.prototype._onAddTrack = function onAddTrack(pc, stream) {
  var audio = pc._masterAudio = this._createAudio();
  setAudioSource(audio, stream);
  audio.play();

  // Assign the initial master audio element to a random active output device
  var deviceId = Array.from(pc.outputs.keys())[0] || 'default';
  pc._masterAudioDeviceId = deviceId;
  pc.outputs.set(deviceId, {
    audio: audio
  });

  pc._mediaStreamSource = pc._audioContext.createMediaStreamSource(stream);

  pc.pcStream = stream;
  pc._updateAudioOutputs();
};

/**
 * Use a single audio element to play the audio output stream. This does not
 *   support multiple output devices, and is a fallback for when AudioContext
 *   and/or HTMLAudioElement.setSinkId() is not available to the client.
 */
PeerConnection.prototype._fallbackOnAddTrack = function fallbackOnAddTrack(pc, stream) {
  var audio = document && document.createElement('audio');
  audio.autoplay = true;

  if (!setAudioSource(audio, stream)) {
    pc._log.info('Error attaching stream to element.');
  }

  pc.outputs.set('default', {
    audio: audio
  });
};

PeerConnection.prototype._setEncodingParameters = function (enableDscp) {
  if (!enableDscp || !this._sender || typeof this._sender.getParameters !== 'function' || typeof this._sender.setParameters !== 'function') {
    return;
  }

  var params = this._sender.getParameters();
  if (!params.priority && !(params.encodings && params.encodings.length)) {
    return;
  }

  // This is how MDN's RTPSenderParameters defines priority
  params.priority = 'high';

  // And this is how it's currently implemented in Chrome M72+
  if (params.encodings && params.encodings.length) {
    params.encodings.forEach(function (encoding) {
      encoding.priority = 'high';
      encoding.networkPriority = 'high';
    });
  }

  this._sender.setParameters(params);
};

PeerConnection.prototype._setupPeerConnection = function (rtcConstraints, rtcConfiguration) {
  var _this4 = this;

  var self = this;
  var version = new (this.options.rtcpcFactory || RTCPC)();
  version.create(rtcConstraints, rtcConfiguration);
  addStream(version.pc, this.stream);

  var eventName = 'ontrack' in version.pc ? 'ontrack' : 'onaddstream';

  version.pc[eventName] = function (event) {
    var stream = self._remoteStream = event.stream || event.streams[0];

    if (typeof version.pc.getSenders === 'function') {
      _this4._sender = version.pc.getSenders()[0];
    }

    if (self._isSinkSupported) {
      self._onAddTrack(self, stream);
    } else {
      self._fallbackOnAddTrack(self, stream);
    }

    self._startPollingVolume();
  };
  return version;
};

PeerConnection.prototype._maybeSetIceAggressiveNomination = function (sdp) {
  return this.options.forceAggressiveIceNomination ? setIceAggressiveNomination(sdp) : sdp;
};

PeerConnection.prototype._setupChannel = function () {
  var _this5 = this;

  var pc = this.version.pc;

  // Chrome 25 supports onopen
  this.version.pc.onopen = function () {
    _this5.status = 'open';
    _this5.onopen();
  };

  // Chrome 26 doesn't support onopen so must detect state change
  this.version.pc.onstatechange = function () {
    if (_this5.version.pc && _this5.version.pc.readyState === 'stable') {
      _this5.status = 'open';
      _this5.onopen();
    }
  };

  // Chrome 27 changed onstatechange to onsignalingstatechange
  this.version.pc.onsignalingstatechange = function () {
    var state = pc.signalingState;
    _this5._log.info('signalingState is "' + state + '"');

    if (_this5.version.pc && _this5.version.pc.signalingState === 'stable') {
      _this5.status = 'open';
      _this5.onopen();
    }

    _this5.onsignalingstatechange(pc.signalingState);
  };

  // Chrome 72+
  pc.onconnectionstatechange = function () {
    _this5._log.info('pc.connectionState is "' + pc.connectionState + '"');
    _this5.onpcconnectionstatechange(pc.connectionState);
    _this5._onMediaConnectionStateChange(pc.connectionState);
  };

  pc.onicecandidate = function (event) {
    var candidate = event.candidate;

    if (candidate) {
      _this5._hasIceCandidates = true;
      _this5.onicecandidate(candidate);
      _this5._setupRTCIceTransportListener();
    }

    _this5._log.info('ICE Candidate: ' + JSON.stringify(candidate));
  };

  pc.onicegatheringstatechange = function () {
    var state = pc.iceGatheringState;
    if (state === 'gathering') {
      _this5._startIceGatheringTimeout();
    } else if (state === 'complete') {
      _this5._stopIceGatheringTimeout();

      // Fail if no candidates found
      if (!_this5._hasIceCandidates) {
        _this5._onIceGatheringFailure(ICE_GATHERING_FAIL_NONE);
      }

      // There was a failure mid-gathering phase. We want to start our timer and issue
      // an ice restart if we don't get connected after our timeout
      if (_this5._hasIceCandidates && _this5._hasIceGatheringFailures) {
        _this5._startIceGatheringTimeout();
      }
    }

    _this5._log.info('pc.iceGatheringState is "' + pc.iceGatheringState + '"');
    _this5.onicegatheringstatechange(state);
  };

  pc.oniceconnectionstatechange = function () {
    _this5._log.info('pc.iceConnectionState is "' + pc.iceConnectionState + '"');
    _this5.oniceconnectionstatechange(pc.iceConnectionState);
    _this5._onMediaConnectionStateChange(pc.iceConnectionState);
  };
};
PeerConnection.prototype._initializeMediaStream = function (rtcConstraints, rtcConfiguration) {
  // if mediastream already open then do nothing
  if (this.status === 'open') {
    return false;
  }
  if (this.pstream.status === 'disconnected') {
    this.onerror({ info: {
        code: 31000,
        message: 'Cannot establish connection. Client is disconnected',
        twilioError: new SignalingErrors.ConnectionDisconnected()
      } });
    this.close();
    return false;
  }
  this.version = this._setupPeerConnection(rtcConstraints, rtcConfiguration);
  this._setupChannel();
  return true;
};

/**
 * Remove reconnection-related listeners
 * @private
 */
PeerConnection.prototype._removeReconnectionListeners = function () {
  if (this.pstream) {
    this.pstream.removeListener('answer', this._onAnswerOrRinging);
    this.pstream.removeListener('hangup', this._onHangup);
  }
};

/**
 * Setup a listener for RTCDtlsTransport to capture state changes events
 * @private
 */
PeerConnection.prototype._setupRTCDtlsTransportListener = function () {
  var _this6 = this;

  var dtlsTransport = this.getRTCDtlsTransport();

  if (!dtlsTransport || dtlsTransport.onstatechange) {
    return;
  }

  var handler = function handler() {
    _this6._log.info('dtlsTransportState is "' + dtlsTransport.state + '"');
    _this6.ondtlstransportstatechange(dtlsTransport.state);
  };

  // Publish initial state
  handler();
  dtlsTransport.onstatechange = handler;
};

/**
 * Setup a listener for RTCIceTransport to capture selected candidate pair changes
 * @private
 */
PeerConnection.prototype._setupRTCIceTransportListener = function () {
  var _this7 = this;

  var iceTransport = this._getRTCIceTransport();

  if (!iceTransport || iceTransport.onselectedcandidatepairchange) {
    return;
  }

  iceTransport.onselectedcandidatepairchange = function () {
    return _this7.onselectedcandidatepairchange(iceTransport.getSelectedCandidatePair());
  };
};

/**
 * Restarts ICE for the current connection
 * ICE Restart failures are ignored. Retries are managed in Connection
 * @private
 */
PeerConnection.prototype.iceRestart = function () {
  var _this8 = this;

  if (!this.options.enableIceRestart) {
    return;
  }
  this._log.info('Attempting to restart ICE...');
  this._hasIceCandidates = false;
  this.version.createOffer(this.options.maxAverageBitrate, this.codecPreferences, { iceRestart: true }).then(function () {
    _this8._removeReconnectionListeners();

    _this8._onAnswerOrRinging = function (payload) {
      _this8._removeReconnectionListeners();

      if (!payload.sdp || _this8.version.pc.signalingState !== 'have-local-offer') {
        var message = 'Invalid state or param during ICE Restart:' + ('hasSdp:' + !!payload.sdp + ', signalingState:' + _this8.version.pc.signalingState);
        _this8._log.info(message);
        return;
      }

      var sdp = _this8._maybeSetIceAggressiveNomination(payload.sdp);
      _this8._answerSdp = sdp;
      if (_this8.status !== 'closed') {
        _this8.version.processAnswer(_this8.codecPreferences, sdp, null, function (err) {
          var message = err && err.message ? err.message : err;
          _this8._log.info('Failed to process answer during ICE Restart. Error: ' + message);
        });
      }
    };

    _this8._onHangup = function () {
      _this8._log.info('Received hangup during ICE Restart');
      _this8._removeReconnectionListeners();
    };

    _this8.pstream.on('answer', _this8._onAnswerOrRinging);
    _this8.pstream.on('hangup', _this8._onHangup);
    _this8.pstream.reinvite(_this8.version.getSDP(), _this8.callSid);
  }).catch(function (err) {
    var message = err && err.message ? err.message : err;
    _this8._log.info('Failed to createOffer during ICE Restart. Error: ' + message);
    // CreateOffer failures doesn't transition ice state to failed
    // We need trigger it so it can be picked up by retries
    _this8.onfailed(message);
  });
};

PeerConnection.prototype.makeOutgoingCall = function (token, params, callsid, rtcConstraints, rtcConfiguration, onMediaStarted) {
  var _this9 = this;

  if (!this._initializeMediaStream(rtcConstraints, rtcConfiguration)) {
    return;
  }

  var self = this;
  this.callSid = callsid;
  function onAnswerSuccess() {
    if (self.options) {
      self._setEncodingParameters(self.options.dscp);
    }
    onMediaStarted(self.version.pc);
  }
  function onAnswerError(err) {
    var errMsg = err.message || err;
    self.onerror({ info: {
        code: 31000,
        message: 'Error processing answer: ' + errMsg,
        twilioError: new MediaErrors.ClientRemoteDescFailed()
      } });
  }
  this._onAnswerOrRinging = function (payload) {
    if (!payload.sdp) {
      return;
    }

    var sdp = _this9._maybeSetIceAggressiveNomination(payload.sdp);
    self._answerSdp = sdp;
    if (self.status !== 'closed') {
      self.version.processAnswer(_this9.codecPreferences, sdp, onAnswerSuccess, onAnswerError);
    }
    self.pstream.removeListener('answer', self._onAnswerOrRinging);
    self.pstream.removeListener('ringing', self._onAnswerOrRinging);
  };
  this.pstream.on('answer', this._onAnswerOrRinging);
  this.pstream.on('ringing', this._onAnswerOrRinging);

  function onOfferSuccess() {
    if (self.status !== 'closed') {
      self.pstream.invite(self.version.getSDP(), self.callSid, self.options.preflight, params);
      self._setupRTCDtlsTransportListener();
    }
  }

  function onOfferError(err) {
    var errMsg = err.message || err;
    self.onerror({ info: {
        code: 31000,
        message: 'Error creating the offer: ' + errMsg,
        twilioError: new MediaErrors.ClientLocalDescFailed()
      } });
  }

  this.version.createOffer(this.options.maxAverageBitrate, this.codecPreferences, { audio: true }, onOfferSuccess, onOfferError);
};
PeerConnection.prototype.answerIncomingCall = function (callSid, sdp, rtcConstraints, rtcConfiguration, onMediaStarted) {
  if (!this._initializeMediaStream(rtcConstraints, rtcConfiguration)) {
    return;
  }
  sdp = this._maybeSetIceAggressiveNomination(sdp);
  this._answerSdp = sdp.replace(/^a=setup:actpass$/gm, 'a=setup:passive');
  this.callSid = callSid;
  var self = this;
  function onAnswerSuccess() {
    if (self.status !== 'closed') {
      self.pstream.answer(self.version.getSDP(), callSid);
      if (self.options) {
        self._setEncodingParameters(self.options.dscp);
      }
      onMediaStarted(self.version.pc);
      self._setupRTCDtlsTransportListener();
    }
  }
  function onAnswerError(err) {
    var errMsg = err.message || err;
    self.onerror({ info: {
        code: 31000,
        message: 'Error creating the answer: ' + errMsg,
        twilioError: new MediaErrors.ClientRemoteDescFailed()
      } });
  }
  this.version.processSDP(this.options.maxAverageBitrate, this.codecPreferences, sdp, { audio: true }, onAnswerSuccess, onAnswerError);
};
PeerConnection.prototype.close = function () {
  if (this.version && this.version.pc) {
    if (this.version.pc.signalingState !== 'closed') {
      this.version.pc.close();
    }

    this.version.pc = null;
  }
  if (this.stream) {
    this.mute(false);
    this._stopStream(this.stream);
  }
  this.stream = null;
  this._removeReconnectionListeners();
  this._stopIceGatheringTimeout();

  Promise.all(this._removeAudioOutputs()).catch(function () {
    // We don't need to alert about failures here.
  });
  if (this._mediaStreamSource) {
    this._mediaStreamSource.disconnect();
  }
  if (this._inputAnalyser) {
    this._inputAnalyser.disconnect();
  }
  if (this._outputAnalyser) {
    this._outputAnalyser.disconnect();
  }
  if (this._inputAnalyser2) {
    this._inputAnalyser2.disconnect();
  }
  if (this._outputAnalyser2) {
    this._outputAnalyser2.disconnect();
  }
  this.status = 'closed';
  this.onclose();
};
PeerConnection.prototype.reject = function (callSid) {
  this.callSid = callSid;
};
PeerConnection.prototype.ignore = function (callSid) {
  this.callSid = callSid;
};
/**
 * Mute or unmute input audio. If the stream is not yet present, the setting
 *   is saved and applied to future streams/tracks.
 * @params {boolean} shouldMute - Whether the input audio should
 *   be muted or unmuted.
 */
PeerConnection.prototype.mute = function (shouldMute) {
  this.isMuted = shouldMute;
  if (!this.stream) {
    return;
  }

  if (this._sender && this._sender.track) {
    this._sender.track.enabled = !shouldMute;
  } else {
    var audioTracks = typeof this.stream.getAudioTracks === 'function' ? this.stream.getAudioTracks() : this.stream.audioTracks;

    audioTracks.forEach(function (track) {
      track.enabled = !shouldMute;
    });
  }
};
/**
 * Get or create an RTCDTMFSender for the first local audio MediaStreamTrack
 * we can get from the RTCPeerConnection. Return null if unsupported.
 * @instance
 * @returns ?RTCDTMFSender
 */
PeerConnection.prototype.getOrCreateDTMFSender = function getOrCreateDTMFSender() {
  if (this._dtmfSender || this._dtmfSenderUnsupported) {
    return this._dtmfSender || null;
  }

  var self = this;
  var pc = this.version.pc;
  if (!pc) {
    this._log.info('No RTCPeerConnection available to call createDTMFSender on');
    return null;
  }

  if (typeof pc.getSenders === 'function' && (typeof RTCDTMFSender === 'function' || typeof RTCDtmfSender === 'function')) {
    var chosenSender = pc.getSenders().find(function (sender) {
      return sender.dtmf;
    });
    if (chosenSender) {
      this._log.info('Using RTCRtpSender#dtmf');
      this._dtmfSender = chosenSender.dtmf;
      return this._dtmfSender;
    }
  }

  if (typeof pc.createDTMFSender === 'function' && typeof pc.getLocalStreams === 'function') {
    var track = pc.getLocalStreams().map(function (stream) {
      var tracks = self._getAudioTracks(stream);
      return tracks && tracks[0];
    })[0];

    if (!track) {
      this._log.info('No local audio MediaStreamTrack available on the RTCPeerConnection to pass to createDTMFSender');
      return null;
    }

    this._log.info('Creating RTCDTMFSender');
    this._dtmfSender = pc.createDTMFSender(track);
    return this._dtmfSender;
  }

  this._log.info('RTCPeerConnection does not support RTCDTMFSender');
  this._dtmfSenderUnsupported = true;
  return null;
};

/**
 * Get the RTCDtlTransport object from the PeerConnection
 * @returns RTCDtlTransport
 */
PeerConnection.prototype.getRTCDtlsTransport = function getRTCDtlsTransport() {
  var sender = this.version && this.version.pc && typeof this.version.pc.getSenders === 'function' && this.version.pc.getSenders()[0];
  return sender && sender.transport || null;
};

PeerConnection.prototype._canStopMediaStreamTrack = function () {
  return typeof MediaStreamTrack.prototype.stop === 'function';
};

PeerConnection.prototype._getAudioTracks = function (stream) {
  return typeof stream.getAudioTracks === 'function' ? stream.getAudioTracks() : stream.audioTracks;
};

/**
 * Get the RTCIceTransport object from the PeerConnection
 * @returns RTCIceTransport
 */
PeerConnection.prototype._getRTCIceTransport = function _getRTCIceTransport() {
  var dtlsTransport = this.getRTCDtlsTransport();
  return dtlsTransport && dtlsTransport.iceTransport || null;
};

// Is PeerConnection.protocol used outside of our SDK? We should remove this if not.
PeerConnection.protocol = function () {
  return RTCPC.test() ? new RTCPC() : null;
}();

function addStream(pc, stream) {
  if (typeof pc.addTrack === 'function') {
    stream.getAudioTracks().forEach(function (track) {
      // The second parameters, stream, should not be necessary per the latest editor's
      //   draft, but FF requires it. https://bugzilla.mozilla.org/show_bug.cgi?id=1231414
      pc.addTrack(track, stream);
    });
  } else {
    pc.addStream(stream);
  }
}

function cloneStream(oldStream) {
  var newStream = typeof MediaStream !== 'undefined' ? new MediaStream()
  // eslint-disable-next-line
  : new webkitMediaStream();

  oldStream.getAudioTracks().forEach(newStream.addTrack, newStream);
  return newStream;
}

function removeStream(pc, stream) {
  if (typeof pc.removeTrack === 'function') {
    pc.getSenders().forEach(function (sender) {
      pc.removeTrack(sender);
    });
  } else {
    pc.removeStream(stream);
  }
}

/**
 * Set the source of an HTMLAudioElement to the specified MediaStream
 * @param {HTMLAudioElement} audio
 * @param {MediaStream} stream
 * @returns {boolean} Whether the audio source was set successfully
 */
function setAudioSource(audio, stream) {
  if (typeof audio.srcObject !== 'undefined') {
    audio.srcObject = stream;
  } else if (typeof audio.mozSrcObject !== 'undefined') {
    audio.mozSrcObject = stream;
  } else if (typeof audio.src !== 'undefined') {
    var _window = audio.options.window || window;
    audio.src = (_window.URL || _window.webkitURL).createObjectURL(stream);
  } else {
    return false;
  }

  return true;
}

PeerConnection.enabled = RTCPC.test();

module.exports = PeerConnection;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/rtcpc.js":
/*!************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/rtcpc.js ***!
  \************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


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; };

/* global webkitRTCPeerConnection, mozRTCPeerConnection, mozRTCSessionDescription, mozRTCIceCandidate */
var RTCPeerConnectionShim = __webpack_require__(/*! rtcpeerconnection-shim */ "./node_modules/rtcpeerconnection-shim/rtcpeerconnection.js");
var Log = __webpack_require__(/*! ../log */ "./node_modules/twilio-client/es5/twilio/log.js").default;

var _require = __webpack_require__(/*! ./sdp */ "./node_modules/twilio-client/es5/twilio/rtc/sdp.js"),
    setCodecPreferences = _require.setCodecPreferences,
    setMaxAverageBitrate = _require.setMaxAverageBitrate;

var util = __webpack_require__(/*! ../util */ "./node_modules/twilio-client/es5/twilio/util.js");

function RTCPC() {
  if (typeof window === 'undefined') {
    this.log.info('No RTCPeerConnection implementation available. The window object was not found.');
    return;
  }

  if (util.isLegacyEdge()) {
    this.RTCPeerConnection = new RTCPeerConnectionShim(typeof window !== 'undefined' ? window : __webpack_require__.g);
  } else if (typeof window.RTCPeerConnection === 'function') {
    this.RTCPeerConnection = window.RTCPeerConnection;
  } else if (typeof window.webkitRTCPeerConnection === 'function') {
    this.RTCPeerConnection = webkitRTCPeerConnection;
  } else if (typeof window.mozRTCPeerConnection === 'function') {
    this.RTCPeerConnection = mozRTCPeerConnection;
    window.RTCSessionDescription = mozRTCSessionDescription;
    window.RTCIceCandidate = mozRTCIceCandidate;
  } else {
    this.log.info('No RTCPeerConnection implementation available');
  }
}

RTCPC.prototype.create = function (rtcConstraints, rtcConfiguration) {
  this.log = Log.getInstance();
  this.pc = new this.RTCPeerConnection(rtcConfiguration, rtcConstraints);
};
RTCPC.prototype.createModernConstraints = function (c) {
  // createOffer differs between Chrome 23 and Chrome 24+.
  // See https://groups.google.com/forum/?fromgroups=#!topic/discuss-webrtc/JBDZtrMumyU
  // Unfortunately I haven't figured out a way to detect which format
  // is required ahead of time, so we'll first try the old way, and
  // if we get an exception, then we'll try the new way.
  if (typeof c === 'undefined') {
    return null;
  }
  // NOTE(mroberts): As of Chrome 38, Chrome still appears to expect
  // constraints under the 'mandatory' key, and with the first letter of each
  // constraint capitalized. Firefox, on the other hand, has deprecated the
  // 'mandatory' key and does not expect the first letter of each constraint
  // capitalized.
  var nc = Object.assign({}, c);
  if (typeof webkitRTCPeerConnection !== 'undefined' && !util.isLegacyEdge()) {
    nc.mandatory = {};
    if (typeof c.audio !== 'undefined') {
      nc.mandatory.OfferToReceiveAudio = c.audio;
    }
    if (typeof c.video !== 'undefined') {
      nc.mandatory.OfferToReceiveVideo = c.video;
    }
  } else {
    if (typeof c.audio !== 'undefined') {
      nc.offerToReceiveAudio = c.audio;
    }
    if (typeof c.video !== 'undefined') {
      nc.offerToReceiveVideo = c.video;
    }
  }

  delete nc.audio;
  delete nc.video;

  return nc;
};
RTCPC.prototype.createOffer = function (maxAverageBitrate, codecPreferences, constraints, onSuccess, onError) {
  var _this = this;

  constraints = this.createModernConstraints(constraints);
  return promisifyCreate(this.pc.createOffer, this.pc)(constraints).then(function (offer) {
    if (!_this.pc) {
      return Promise.resolve();
    }

    var sdp = setMaxAverageBitrate(offer.sdp, maxAverageBitrate);

    return promisifySet(_this.pc.setLocalDescription, _this.pc)(new RTCSessionDescription({
      type: 'offer',
      sdp: setCodecPreferences(sdp, codecPreferences)
    }));
  }).then(onSuccess, onError);
};
RTCPC.prototype.createAnswer = function (maxAverageBitrate, codecPreferences, constraints, onSuccess, onError) {
  var _this2 = this;

  constraints = this.createModernConstraints(constraints);
  return promisifyCreate(this.pc.createAnswer, this.pc)(constraints).then(function (answer) {
    if (!_this2.pc) {
      return Promise.resolve();
    }
    var sdp = setMaxAverageBitrate(answer.sdp, maxAverageBitrate);

    return promisifySet(_this2.pc.setLocalDescription, _this2.pc)(new RTCSessionDescription({
      type: 'answer',
      sdp: setCodecPreferences(sdp, codecPreferences)
    }));
  }).then(onSuccess, onError);
};
RTCPC.prototype.processSDP = function (maxAverageBitrate, codecPreferences, sdp, constraints, onSuccess, onError) {
  var _this3 = this;

  sdp = setCodecPreferences(sdp, codecPreferences);
  var desc = new RTCSessionDescription({ sdp: sdp, type: 'offer' });
  return promisifySet(this.pc.setRemoteDescription, this.pc)(desc).then(function () {
    _this3.createAnswer(maxAverageBitrate, codecPreferences, constraints, onSuccess, onError);
  });
};
RTCPC.prototype.getSDP = function () {
  return this.pc.localDescription.sdp;
};
RTCPC.prototype.processAnswer = function (codecPreferences, sdp, onSuccess, onError) {
  if (!this.pc) {
    return Promise.resolve();
  }
  sdp = setCodecPreferences(sdp, codecPreferences);

  return promisifySet(this.pc.setRemoteDescription, this.pc)(new RTCSessionDescription({ sdp: sdp, type: 'answer' })).then(onSuccess, onError);
};
/* NOTE(mroberts): Firefox 18 through 21 include a `mozRTCPeerConnection`
   object, but attempting to instantiate it will throw the error

       Error: PeerConnection not enabled (did you set the pref?)

   unless the `media.peerconnection.enabled` pref is enabled. So we need to test
   if we can actually instantiate `mozRTCPeerConnection`; however, if the user
   *has* enabled `media.peerconnection.enabled`, we need to perform the same
   test that we use to detect Firefox 24 and above, namely:

       typeof (new mozRTCPeerConnection()).getLocalStreams === 'function'


    NOTE(rrowland): We no longer support Legacy Edge as of Sep 1, 2020.
*/
RTCPC.test = function () {
  if ((typeof navigator === 'undefined' ? 'undefined' : _typeof(navigator)) === 'object') {
    var getUserMedia = navigator.mediaDevices && navigator.mediaDevices.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.getUserMedia;

    if (util.isLegacyEdge(navigator)) {
      return false;
    }

    if (getUserMedia && typeof window.RTCPeerConnection === 'function') {
      return true;
    } else if (getUserMedia && typeof window.webkitRTCPeerConnection === 'function') {
      return true;
    } else if (getUserMedia && typeof window.mozRTCPeerConnection === 'function') {
      try {
        // eslint-disable-next-line babel/new-cap
        var test = new window.mozRTCPeerConnection();
        if (typeof test.getLocalStreams !== 'function') return false;
      } catch (e) {
        return false;
      }
      return true;
    } else if (typeof RTCIceGatherer !== 'undefined') {
      return true;
    }
  }

  return false;
};

function promisify(fn, ctx, areCallbacksFirst) {
  return function () {
    var args = Array.prototype.slice.call(arguments);

    return new Promise(function (resolve) {
      resolve(fn.apply(ctx, args));
    }).catch(function () {
      return new Promise(function (resolve, reject) {
        fn.apply(ctx, areCallbacksFirst ? [resolve, reject].concat(args) : args.concat([resolve, reject]));
      });
    });
  };
}

function promisifyCreate(fn, ctx) {
  return promisify(fn, ctx, true);
}

function promisifySet(fn, ctx) {
  return promisify(fn, ctx, false);
}

module.exports = RTCPC;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/sdp.js":
/*!**********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/sdp.js ***!
  \**********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var util = __webpack_require__(/*! ../util */ "./node_modules/twilio-client/es5/twilio/util.js");

var ptToFixedBitrateAudioCodecName = {
  0: 'PCMU',
  8: 'PCMA'
};

var defaultOpusId = 111;
var BITRATE_MAX = 510000;
var BITRATE_MIN = 6000;

function getPreferredCodecInfo(sdp) {
  var _ref = /a=rtpmap:(\d+) (\S+)/m.exec(sdp) || [null, '', ''],
      _ref2 = _slicedToArray(_ref, 3),
      codecId = _ref2[1],
      codecName = _ref2[2];

  var regex = new RegExp('a=fmtp:' + codecId + ' (\\S+)', 'm');

  var _ref3 = regex.exec(sdp) || [null, ''],
      _ref4 = _slicedToArray(_ref3, 2),
      codecParams = _ref4[1];

  return { codecName: codecName, codecParams: codecParams };
}

function setIceAggressiveNomination(sdp) {
  // This only works on Chrome. We don't want any side effects on other browsers
  // https://bugs.chromium.org/p/chromium/issues/detail?id=1024096
  // https://issues.corp.twilio.com/browse/CLIENT-6911
  if (!util.isChrome(window, window.navigator)) {
    return sdp;
  }

  return sdp.split('\n').filter(function (line) {
    return line.indexOf('a=ice-lite') === -1;
  }).join('\n');
}

function setMaxAverageBitrate(sdp, maxAverageBitrate) {
  if (typeof maxAverageBitrate !== 'number' || maxAverageBitrate < BITRATE_MIN || maxAverageBitrate > BITRATE_MAX) {
    return sdp;
  }

  var matches = /a=rtpmap:(\d+) opus/m.exec(sdp);
  var opusId = matches && matches.length ? matches[1] : defaultOpusId;
  var regex = new RegExp('a=fmtp:' + opusId);
  var lines = sdp.split('\n').map(function (line) {
    return regex.test(line) ? line + (';maxaveragebitrate=' + maxAverageBitrate) : line;
  });

  return lines.join('\n');
}

/**
 * Return a new SDP string with the re-ordered codec preferences.
 * @param {string} sdp
 * @param {Array<AudioCodec>} preferredCodecs - If empty, the existing order
 *   of audio codecs is preserved
 * @returns {string} Updated SDP string
 */
function setCodecPreferences(sdp, preferredCodecs) {
  var mediaSections = getMediaSections(sdp);
  var session = sdp.split('\r\nm=')[0];
  return [session].concat(mediaSections.map(function (section) {
    // Codec preferences should not be applied to m=application sections.
    if (!/^m=(audio|video)/.test(section)) {
      return section;
    }
    var kind = section.match(/^m=(audio|video)/)[1];
    var codecMap = createCodecMapForMediaSection(section);
    var payloadTypes = getReorderedPayloadTypes(codecMap, preferredCodecs);
    var newSection = setPayloadTypesInMediaSection(payloadTypes, section);

    var pcmaPayloadTypes = codecMap.get('pcma') || [];
    var pcmuPayloadTypes = codecMap.get('pcmu') || [];
    var fixedBitratePayloadTypes = kind === 'audio' ? new Set(pcmaPayloadTypes.concat(pcmuPayloadTypes)) : new Set();

    return fixedBitratePayloadTypes.has(payloadTypes[0]) ? newSection.replace(/\r\nb=(AS|TIAS):([0-9]+)/g, '') : newSection;
  })).join('\r\n');
}

/**
 * Get the m= sections of a particular kind and direction from an sdp.
 * @param {string} sdp - SDP string
 * @param {string} [kind] - Pattern for matching kind
 * @param {string} [direction] - Pattern for matching direction
 * @returns {Array<string>} mediaSections
 */
function getMediaSections(sdp, kind, direction) {
  return sdp.replace(/\r\n\r\n$/, '\r\n').split('\r\nm=').slice(1).map(function (mediaSection) {
    return 'm=' + mediaSection;
  }).filter(function (mediaSection) {
    var kindPattern = new RegExp('m=' + (kind || '.*'), 'gm');
    var directionPattern = new RegExp('a=' + (direction || '.*'), 'gm');
    return kindPattern.test(mediaSection) && directionPattern.test(mediaSection);
  });
}

/**
 * Create a Codec Map for the given m= section.
 * @param {string} section - The given m= section
 * @returns {Map<Codec, Array<PT>>}
 */
function createCodecMapForMediaSection(section) {
  return Array.from(createPtToCodecName(section)).reduce(function (codecMap, pair) {
    var pt = pair[0];
    var codecName = pair[1];
    var pts = codecMap.get(codecName) || [];
    return codecMap.set(codecName, pts.concat(pt));
  }, new Map());
}

/**
 * Create the reordered Codec Payload Types based on the preferred Codec Names.
 * @param {Map<Codec, Array<PT>>} codecMap - Codec Map
 * @param {Array<Codec>} preferredCodecs - Preferred Codec Names
 * @returns {Array<PT>} Reordered Payload Types
 */
function getReorderedPayloadTypes(codecMap, preferredCodecs) {
  preferredCodecs = preferredCodecs.map(function (codecName) {
    return codecName.toLowerCase();
  });

  var preferredPayloadTypes = util.flatMap(preferredCodecs, function (codecName) {
    return codecMap.get(codecName) || [];
  });

  var remainingCodecs = util.difference(Array.from(codecMap.keys()), preferredCodecs);
  var remainingPayloadTypes = util.flatMap(remainingCodecs, function (codecName) {
    return codecMap.get(codecName);
  });

  return preferredPayloadTypes.concat(remainingPayloadTypes);
}

/**
 * Set the given Codec Payload Types in the first line of the given m= section.
 * @param {Array<PT>} payloadTypes - Payload Types
 * @param {string} section - Given m= section
 * @returns {string} - Updated m= section
 */
function setPayloadTypesInMediaSection(payloadTypes, section) {
  var lines = section.split('\r\n');
  var mLine = lines[0];
  var otherLines = lines.slice(1);
  mLine = mLine.replace(/([0-9]+\s?)+$/, payloadTypes.join(' '));
  return [mLine].concat(otherLines).join('\r\n');
}

/**
 * Create a Map from PTs to codec names for the given m= section.
 * @param {string} mediaSection - The given m= section.
 * @returns {Map<PT, Codec>} ptToCodecName
 */
function createPtToCodecName(mediaSection) {
  return getPayloadTypesInMediaSection(mediaSection).reduce(function (ptToCodecName, pt) {
    var rtpmapPattern = new RegExp('a=rtpmap:' + pt + ' ([^/]+)');
    var matches = mediaSection.match(rtpmapPattern);
    var codecName = matches ? matches[1].toLowerCase() : ptToFixedBitrateAudioCodecName[pt] ? ptToFixedBitrateAudioCodecName[pt].toLowerCase() : '';
    return ptToCodecName.set(pt, codecName);
  }, new Map());
}

/**
 * Get the Codec Payload Types present in the first line of the given m= section
 * @param {string} section - The m= section
 * @returns {Array<PT>} Payload Types
 */
function getPayloadTypesInMediaSection(section) {
  var mLine = section.split('\r\n')[0];

  // In "m=<kind> <port> <proto> <payload_type_1> <payload_type_2> ... <payload_type_n>",
  // the regex matches <port> and the PayloadTypes.
  var matches = mLine.match(/([0-9]+)/g);

  // This should not happen, but in case there are no PayloadTypes in
  // the m= line, return an empty array.
  if (!matches) {
    return [];
  }

  // Since only the PayloadTypes are needed, we discard the <port>.
  return matches.slice(1).map(function (match) {
    return parseInt(match, 10);
  });
}

module.exports = {
  getPreferredCodecInfo: getPreferredCodecInfo,
  setCodecPreferences: setCodecPreferences,
  setIceAggressiveNomination: setIceAggressiveNomination,
  setMaxAverageBitrate: setMaxAverageBitrate
};

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/rtc/stats.js":
/*!************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/rtc/stats.js ***!
  \************************************************************/
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

var __spreadArrays = (this && this.__spreadArrays) || function () {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
};
/* eslint-disable no-fallthrough */
var _a = __webpack_require__(/*! ../errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js"), NotSupportedError = _a.NotSupportedError, InvalidArgumentError = _a.InvalidArgumentError;
var MockRTCStatsReport = __webpack_require__(/*! ./mockrtcstatsreport */ "./node_modules/twilio-client/es5/twilio/rtc/mockrtcstatsreport.js");
var ERROR_PEER_CONNECTION_NULL = 'PeerConnection is null';
var ERROR_WEB_RTC_UNSUPPORTED = 'WebRTC statistics are unsupported';
/**
 * Generate WebRTC statistics report for the given {@link PeerConnection}
 * @param {PeerConnection} peerConnection - Target connection.
 * @return {Promise<RTCStatsReport>} WebRTC RTCStatsReport object
 */
function getRTCStatsReport(peerConnection) {
    if (!peerConnection) {
        return Promise.reject(new InvalidArgumentError(ERROR_PEER_CONNECTION_NULL));
    }
    if (typeof peerConnection.getStats !== 'function') {
        return Promise.reject(new NotSupportedError(ERROR_WEB_RTC_UNSUPPORTED));
    }
    var promise;
    try {
        promise = peerConnection.getStats();
    }
    catch (e) {
        promise = new Promise(function (resolve) { return peerConnection.getStats(resolve); }).then(MockRTCStatsReport.fromRTCStatsResponse);
    }
    return promise;
}
/**
 * @typedef {Object} StatsOptions
 * Used for testing to inject and extract methods.
 * @property {function} [createRTCSample] - Method for parsing an RTCStatsReport
 */
/**
 * Collects any WebRTC statistics for the given {@link PeerConnection}
 * @param {PeerConnection} peerConnection - Target connection.
 * @param {StatsOptions} options - List of custom options.
 * @return {Promise<RTCSample>} Universally-formatted version of RTC stats.
 */
function getRTCStats(peerConnection, options) {
    options = Object.assign({
        createRTCSample: createRTCSample
    }, options);
    return getRTCStatsReport(peerConnection).then(options.createRTCSample);
}
/**
 * Generate WebRTC stats report containing relevant information about ICE candidates for the given {@link PeerConnection}
 * @param {PeerConnection} peerConnection - Target connection.
 * @return {Promise<RTCIceCandidateStatsReport>} RTCIceCandidateStatsReport object
 */
function getRTCIceCandidateStatsReport(peerConnection) {
    return getRTCStatsReport(peerConnection).then(function (report) {
        // Find the relevant information needed to determine selected candidates later
        var _a = Array.from(report.values()).reduce(function (rval, stat) {
            ['candidatePairs', 'localCandidates', 'remoteCandidates'].forEach(function (prop) {
                if (!rval[prop]) {
                    rval[prop] = [];
                }
            });
            switch (stat.type) {
                case 'candidate-pair':
                    rval.candidatePairs.push(stat);
                    break;
                case 'local-candidate':
                    rval.localCandidates.push(stat);
                    break;
                case 'remote-candidate':
                    rval.remoteCandidates.push(stat);
                    break;
                case 'transport':
                    // This transport is the one being used if selectedCandidatePairId is populated
                    if (stat.selectedCandidatePairId) {
                        rval.transport = stat;
                    }
                    break;
            }
            return rval;
        }, {}), candidatePairs = _a.candidatePairs, localCandidates = _a.localCandidates, remoteCandidates = _a.remoteCandidates, transport = _a.transport;
        // This is a report containing information about the selected candidates, such as IDs
        // This is coming from WebRTC stats directly and doesn't contain the actual ICE Candidates info
        var selectedCandidatePairReport = candidatePairs.find(function (pair) {
            // Firefox
            return pair.selected ||
                // Spec-compliant way
                (transport && pair.id === transport.selectedCandidatePairId);
        });
        var selectedIceCandidatePairStats;
        if (selectedCandidatePairReport) {
            selectedIceCandidatePairStats = {
                localCandidate: localCandidates.find(function (candidate) { return candidate.id === selectedCandidatePairReport.localCandidateId; }),
                remoteCandidate: remoteCandidates.find(function (candidate) { return candidate.id === selectedCandidatePairReport.remoteCandidateId; }),
            };
        }
        // Build the return object
        return {
            iceCandidateStats: __spreadArrays(localCandidates, remoteCandidates),
            selectedIceCandidatePairStats: selectedIceCandidatePairStats,
        };
    });
}
/**
 * @typedef {Object} RTCSample - A sample containing relevant WebRTC stats information.
 * @property {Number} [timestamp]
 * @property {String} [codecName] - MimeType name of the codec being used by the outbound audio stream
 * @property {Number} [rtt] - Round trip time
 * @property {Number} [jitter]
 * @property {Number} [packetsSent]
 * @property {Number} [packetsLost]
 * @property {Number} [packetsReceived]
 * @property {Number} [bytesReceived]
 * @property {Number} [bytesSent]
 * @property {Number} [localAddress]
 * @property {Number} [remoteAddress]
 */
function RTCSample() { }
/**
 * Create an RTCSample object from an RTCStatsReport
 * @private
 * @param {RTCStatsReport} statsReport
 * @returns {RTCSample}
 */
function createRTCSample(statsReport) {
    var activeTransportId = null;
    var sample = new RTCSample();
    var fallbackTimestamp;
    Array.from(statsReport.values()).forEach(function (stats) {
        // Skip isRemote tracks which will be phased out completely and break in FF66.
        if (stats.isRemote) {
            return;
        }
        // Firefox hack -- Older firefox doesn't have dashes in type names
        var type = stats.type.replace('-', '');
        fallbackTimestamp = fallbackTimestamp || stats.timestamp;
        // (rrowland) As I understand it, this is supposed to come in on remote-inbound-rtp but it's
        // currently coming in on remote-outbound-rtp, so I'm leaving this outside the switch until
        // the appropriate place to look is cleared up.
        if (stats.remoteId) {
            var remote = statsReport.get(stats.remoteId);
            if (remote && remote.roundTripTime) {
                sample.rtt = remote.roundTripTime * 1000;
            }
        }
        switch (type) {
            case 'inboundrtp':
                sample.timestamp = sample.timestamp || stats.timestamp;
                sample.jitter = stats.jitter * 1000;
                sample.packetsLost = stats.packetsLost;
                sample.packetsReceived = stats.packetsReceived;
                sample.bytesReceived = stats.bytesReceived;
                break;
            case 'outboundrtp':
                sample.timestamp = stats.timestamp;
                sample.packetsSent = stats.packetsSent;
                sample.bytesSent = stats.bytesSent;
                if (stats.codecId) {
                    var codec = statsReport.get(stats.codecId);
                    sample.codecName = codec
                        ? codec.mimeType && codec.mimeType.match(/(.*\/)?(.*)/)[2]
                        : stats.codecId;
                }
                break;
            case 'transport':
                activeTransportId = stats.id;
                break;
        }
    });
    if (!sample.timestamp) {
        sample.timestamp = fallbackTimestamp;
    }
    var activeTransport = statsReport.get(activeTransportId);
    if (!activeTransport) {
        return sample;
    }
    var selectedCandidatePair = statsReport.get(activeTransport.selectedCandidatePairId);
    if (!selectedCandidatePair) {
        return sample;
    }
    var localCandidate = statsReport.get(selectedCandidatePair.localCandidateId);
    var remoteCandidate = statsReport.get(selectedCandidatePair.remoteCandidateId);
    if (!sample.rtt) {
        sample.rtt = selectedCandidatePair &&
            (selectedCandidatePair.currentRoundTripTime * 1000);
    }
    Object.assign(sample, {
        localAddress: localCandidate && localCandidate.ip,
        remoteAddress: remoteCandidate && remoteCandidate.ip,
    });
    return sample;
}
module.exports = {
    getRTCStats: getRTCStats,
    getRTCIceCandidateStatsReport: getRTCIceCandidateStatsReport,
};
//# sourceMappingURL=stats.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/shims/eventtarget.js":
/*!********************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/shims/eventtarget.js ***!
  \********************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var EventEmitter = __webpack_require__(/*! events */ "./node_modules/events/events.js").EventEmitter;
function EventTarget() {
    Object.defineProperties(this, {
        _eventEmitter: {
            value: new EventEmitter()
        },
        _handlers: {
            value: {}
        },
    });
}
EventTarget.prototype.dispatchEvent = function dispatchEvent(event) {
    return this._eventEmitter.emit(event.type, event);
};
EventTarget.prototype.addEventListener = function addEventListener() {
    var _a;
    return (_a = this._eventEmitter).addListener.apply(_a, arguments);
};
EventTarget.prototype.removeEventListener = function removeEventListener() {
    var _a;
    return (_a = this._eventEmitter).removeListener.apply(_a, arguments);
};
EventTarget.prototype._defineEventHandler = function _defineEventHandler(eventName) {
    var self = this;
    Object.defineProperty(this, "on" + eventName, {
        get: function () {
            return self._handlers[eventName];
        },
        set: function (newHandler) {
            var oldHandler = self._handlers[eventName];
            if (oldHandler
                && (typeof newHandler === 'function'
                    || typeof newHandler === 'undefined'
                    || newHandler === null)) {
                self._handlers[eventName] = null;
                self.removeEventListener(eventName, oldHandler);
            }
            if (typeof newHandler === 'function') {
                self._handlers[eventName] = newHandler;
                self.addEventListener(eventName, newHandler);
            }
        }
    });
};
module.exports = EventTarget;
//# sourceMappingURL=eventtarget.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/shims/mediadeviceinfo.js":
/*!************************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/shims/mediadeviceinfo.js ***!
  \************************************************************************/
/***/ ((module) => {

"use strict";


function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var MediaDeviceInfoShim = function MediaDeviceInfoShim(options) {
  _classCallCheck(this, MediaDeviceInfoShim);

  Object.defineProperties(this, {
    deviceId: {
      get: function get() {
        return options.deviceId;
      }
    },
    groupId: {
      get: function get() {
        return options.groupId;
      }
    },
    kind: {
      get: function get() {
        return options.kind;
      }
    },
    label: {
      get: function get() {
        return options.label;
      }
    }
  });
};

module.exports = MediaDeviceInfoShim;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/shims/mediadevices.js":
/*!*********************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/shims/mediadevices.js ***!
  \*********************************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

var EventTarget = __webpack_require__(/*! ./eventtarget */ "./node_modules/twilio-client/es5/twilio/shims/eventtarget.js");
var inherits = __webpack_require__(/*! util */ "./node_modules/util/util.js").inherits;
var POLL_INTERVAL_MS = 500;
var nativeMediaDevices = typeof navigator !== 'undefined' && navigator.mediaDevices;
/**
 * Make a custom MediaDevices object, and proxy through existing functionality. If
 *   devicechange is present, we simply reemit the event. If not, we will do the
 *   detection ourselves and fire the event when necessary. The same logic exists
 *   for deviceinfochange for consistency, however deviceinfochange is our own event
 *   so it is unlikely that it will ever be native. The w3c spec for devicechange
 *   is unclear as to whether MediaDeviceInfo changes (such as label) will
 *   trigger the devicechange event. We have an open question on this here:
 *   https://bugs.chromium.org/p/chromium/issues/detail?id=585096
 */
function MediaDevicesShim() {
    EventTarget.call(this);
    this._defineEventHandler('devicechange');
    this._defineEventHandler('deviceinfochange');
    var knownDevices = [];
    Object.defineProperties(this, {
        _deviceChangeIsNative: {
            value: reemitNativeEvent(this, 'devicechange')
        },
        _deviceInfoChangeIsNative: {
            value: reemitNativeEvent(this, 'deviceinfochange')
        },
        _knownDevices: {
            value: knownDevices
        },
        _pollInterval: {
            value: null,
            writable: true
        }
    });
    if (typeof nativeMediaDevices.enumerateDevices === 'function') {
        nativeMediaDevices.enumerateDevices().then(function (devices) {
            devices.sort(sortDevicesById).forEach([].push, knownDevices);
        });
    }
    this._eventEmitter.on('newListener', function maybeStartPolling(eventName) {
        if (eventName !== 'devicechange' && eventName !== 'deviceinfochange') {
            return;
        }
        this._pollInterval = this._pollInterval
            || setInterval(sampleDevices.bind(null, this), POLL_INTERVAL_MS);
    }.bind(this));
    this._eventEmitter.on('removeListener', function maybeStopPolling() {
        if (this._pollInterval && !hasChangeListeners(this)) {
            clearInterval(this._pollInterval);
            this._pollInterval = null;
        }
    }.bind(this));
}
inherits(MediaDevicesShim, EventTarget);
if (nativeMediaDevices && typeof nativeMediaDevices.enumerateDevices === 'function') {
    MediaDevicesShim.prototype.enumerateDevices = function enumerateDevices() {
        return nativeMediaDevices.enumerateDevices.apply(nativeMediaDevices, arguments);
    };
}
MediaDevicesShim.prototype.getUserMedia = function getUserMedia() {
    return nativeMediaDevices.getUserMedia.apply(nativeMediaDevices, arguments);
};
function deviceInfosHaveChanged(newDevices, oldDevices) {
    var oldLabels = oldDevices.reduce(function (map, device) { return map.set(device.deviceId, device.label || null); }, new Map());
    return newDevices.some(function (newDevice) {
        var oldLabel = oldLabels.get(newDevice.deviceId);
        return typeof oldLabel !== 'undefined' && oldLabel !== newDevice.label;
    });
}
function devicesHaveChanged(newDevices, oldDevices) {
    return newDevices.length !== oldDevices.length
        || propertyHasChanged('deviceId', newDevices, oldDevices);
}
function hasChangeListeners(mediaDevices) {
    return ['devicechange', 'deviceinfochange'].reduce(function (count, event) { return count + mediaDevices._eventEmitter.listenerCount(event); }, 0) > 0;
}
/**
 * Sample the current set of devices and emit devicechange event if a device has been
 *   added or removed, and deviceinfochange if a device's label has changed.
 * @param {MediaDevicesShim} mediaDevices
 * @private
 */
function sampleDevices(mediaDevices) {
    nativeMediaDevices.enumerateDevices().then(function (newDevices) {
        var knownDevices = mediaDevices._knownDevices;
        var oldDevices = knownDevices.slice();
        // Replace known devices in-place
        [].splice.apply(knownDevices, [0, knownDevices.length]
            .concat(newDevices.sort(sortDevicesById)));
        if (!mediaDevices._deviceChangeIsNative
            && devicesHaveChanged(knownDevices, oldDevices)) {
            mediaDevices.dispatchEvent(new Event('devicechange'));
        }
        if (!mediaDevices._deviceInfoChangeIsNative
            && deviceInfosHaveChanged(knownDevices, oldDevices)) {
            mediaDevices.dispatchEvent(new Event('deviceinfochange'));
        }
    });
}
/**
 * Accepts two sorted arrays and the name of a property to compare on objects from each.
 *   Arrays should also be of the same length.
 * @param {string} propertyName - Name of the property to compare on each object
 * @param {Array<Object>} as - The left-side array of objects to compare.
 * @param {Array<Object>} bs - The right-side array of objects to compare.
 * @private
 * @returns {boolean} True if the property of any object in array A is different than
 *   the same property of its corresponding object in array B.
 */
function propertyHasChanged(propertyName, as, bs) {
    return as.some(function (a, i) { return a[propertyName] !== bs[i][propertyName]; });
}
/**
 * Re-emit the native event, if the native mediaDevices has the corresponding property.
 * @param {MediaDevicesShim} mediaDevices
 * @param {string} eventName - Name of the event
 * @private
 * @returns {boolean} Whether the native mediaDevice had the corresponding property
 */
function reemitNativeEvent(mediaDevices, eventName) {
    var methodName = "on" + eventName;
    function dispatchEvent(event) {
        mediaDevices.dispatchEvent(event);
    }
    if (methodName in nativeMediaDevices) {
        // Use addEventListener if it's available so we don't stomp on any other listeners
        // for this event. Currently, navigator.mediaDevices.addEventListener does not exist in Safari.
        if ('addEventListener' in nativeMediaDevices) {
            nativeMediaDevices.addEventListener(eventName, dispatchEvent);
        }
        else {
            nativeMediaDevices[methodName] = dispatchEvent;
        }
        return true;
    }
    return false;
}
function sortDevicesById(a, b) {
    return a.deviceId < b.deviceId;
}
module.exports = (function shimMediaDevices() {
    return nativeMediaDevices ? new MediaDevicesShim() : null;
})();
//# sourceMappingURL=mediadevices.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/sound.js":
/*!********************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/sound.js ***!
  \********************************************************/
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {

"use strict";


var AsyncQueue = __webpack_require__(/*! ./asyncQueue */ "./node_modules/twilio-client/es5/twilio/asyncQueue.js").AsyncQueue;
var AudioPlayer = __webpack_require__(/*! @twilio/audioplayer */ "./node_modules/@twilio/audioplayer/es5/index.js");
var InvalidArgumentError = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js").InvalidArgumentError;

/**
 * @class
 * @param {string} name - Name of the sound
 * @param {string} url - URL of the sound
 * @param {Sound#ConstructorOptions} options
 * @property {boolean} isPlaying - Whether the Sound is currently playing audio.
 * @property {string} name - Name of the sound
 * @property {string} url - URL of the sound
 * @property {AudioContext} audioContext - The AudioContext to use if available for AudioPlayer.
 */ /**
    * @typedef {Object} Sound#ConstructorOptions
    * @property {number} [maxDuration=0] - The maximum length of time to play the sound
    *   before stopping it.
    * @property {Boolean} [shouldLoop=false] - Whether the sound should be looped.
    */
function Sound(name, url, options) {
  if (!(this instanceof Sound)) {
    return new Sound(name, url, options);
  }

  if (!name || !url) {
    throw new InvalidArgumentError('name and url are required arguments');
  }

  options = Object.assign({
    AudioFactory: typeof Audio !== 'undefined' ? Audio : null,
    maxDuration: 0,
    shouldLoop: false
  }, options);

  options.AudioPlayer = options.audioContext ? AudioPlayer.bind(AudioPlayer, options.audioContext) : options.AudioFactory;

  Object.defineProperties(this, {
    _activeEls: {
      value: new Map()
    },
    _Audio: {
      value: options.AudioPlayer
    },
    _isSinkSupported: {
      value: options.AudioFactory !== null && typeof options.AudioFactory.prototype.setSinkId === 'function'
    },
    _maxDuration: {
      value: options.maxDuration
    },
    _maxDurationTimeout: {
      value: null,
      writable: true
    },
    _operations: {
      value: new AsyncQueue()
    },
    _playPromise: {
      value: null,
      writable: true
    },
    _shouldLoop: {
      value: options.shouldLoop
    },
    _sinkIds: {
      value: ['default']
    },
    isPlaying: {
      enumerable: true,
      get: function get() {
        return !!this._playPromise;
      }
    },
    name: {
      enumerable: true,
      value: name
    },
    url: {
      enumerable: true,
      value: url
    }
  });

  if (this._Audio) {
    // Play it (muted and should not loop) as soon as possible so that it does not get incorrectly caught by Chrome's
    // "gesture requirement for media playback" feature.
    // https://plus.google.com/+FrancoisBeaufort/posts/6PiJQqJzGqX
    this._play(true, false);
  }
}

function destroyAudioElement(audioElement) {
  if (audioElement) {
    audioElement.pause();
    audioElement.src = '';
    audioElement.srcObject = null;
    audioElement.load();
  }
}

/**
 * Plays the audio element that was initialized using the speficied sinkId
 */
Sound.prototype._playAudioElement = function _playAudioElement(sinkId, isMuted, shouldLoop) {
  var _this = this;

  var audioElement = this._activeEls.get(sinkId);

  if (!audioElement) {
    throw new InvalidArgumentError('sinkId: "' + sinkId + '" doesn\'t have an audio element');
  }

  audioElement.muted = !!isMuted;
  audioElement.loop = !!shouldLoop;

  return audioElement.play().then(function () {
    return audioElement;
  }).catch(function (reason) {
    destroyAudioElement(audioElement);
    _this._activeEls.delete(sinkId);
    throw reason;
  });
};

/**
 * Start playing the sound. Will stop the currently playing sound first.
 * If it exists, the audio element that was initialized for the sinkId will be used
 */
Sound.prototype._play = function _play(forceIsMuted, forceShouldLoop) {
  if (this.isPlaying) {
    this._stop();
  }

  if (this._maxDuration > 0) {
    this._maxDurationTimeout = setTimeout(this._stop.bind(this), this._maxDuration);
  }

  forceShouldLoop = typeof forceShouldLoop === 'boolean' ? forceShouldLoop : this._shouldLoop;
  var self = this;
  var playPromise = this._playPromise = Promise.all(this._sinkIds.map(function createAudioElement(sinkId) {
    if (!self._Audio) {
      return Promise.resolve();
    }

    var audioElement = self._activeEls.get(sinkId);
    if (audioElement) {
      return self._playAudioElement(sinkId, forceIsMuted, forceShouldLoop);
    }

    audioElement = new self._Audio(self.url);

    // Make sure the browser always retrieves the resource using CORS.
    // By default when using media tags, origin header is not sent to server
    // which causes the server to not return CORS headers. When this caches
    // on the CDN or browser, it causes issues to future requests that needs CORS,
    // which is true when using AudioContext. Please note that we won't have to do this
    // once we migrate to CloudFront.
    if (typeof audioElement.setAttribute === 'function') {
      audioElement.setAttribute('crossorigin', 'anonymous');
    }

    /**
     * (rrowland) Bug in Chrome 53 & 54 prevents us from calling Audio.setSinkId without
     *   crashing the tab. https://bugs.chromium.org/p/chromium/issues/detail?id=655342
     */
    return new Promise(function (resolve) {
      audioElement.addEventListener('canplaythrough', resolve);
    }).then(function () {
      return (self._isSinkSupported ? audioElement.setSinkId(sinkId) : Promise.resolve()).then(function setSinkIdSuccess() {
        self._activeEls.set(sinkId, audioElement);

        // Stop has been called, bail out
        if (!self._playPromise) {
          return Promise.resolve();
        }
        return self._playAudioElement(sinkId, forceIsMuted, forceShouldLoop);
      });
    });
  }));

  return playPromise;
};

/**
 * Stop playing the sound.
 */
Sound.prototype._stop = function _stop() {
  var _this2 = this;

  this._activeEls.forEach(function (audioEl, sinkId) {
    if (_this2._sinkIds.includes(sinkId)) {
      audioEl.pause();
      audioEl.currentTime = 0;
    } else {
      // Destroy the ones that are not used anymore
      destroyAudioElement(audioEl);
      _this2._activeEls.delete(sinkId);
    }
  });

  clearTimeout(this._maxDurationTimeout);

  this._playPromise = null;
  this._maxDurationTimeout = null;
};

/**
 * Update the sinkIds of the audio output devices this sound should play through.
 */
Sound.prototype.setSinkIds = function setSinkIds(ids) {
  if (!this._isSinkSupported) {
    return;
  }

  ids = ids.forEach ? ids : [ids];
  [].splice.apply(this._sinkIds, [0, this._sinkIds.length].concat(ids));
};

/**
 * Add a stop operation to the queue
 */
Sound.prototype.stop = function stop() {
  var _this3 = this;

  this._operations.enqueue(function () {
    _this3._stop();
    return Promise.resolve();
  });
};

/**
 * Add a play operation to the queue
 */
Sound.prototype.play = function play() {
  var _this4 = this;

  return this._operations.enqueue(function () {
    return _this4._play();
  });
};

module.exports = Sound;

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/statsMonitor.js":
/*!***************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/statsMonitor.js ***!
  \***************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

/**
 * @packageDocumentation
 * @module Voice
 * @internalapi
 */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || function () {
    __assign = Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    return __assign.apply(this, arguments);
};
var __spreadArrays = (this && this.__spreadArrays) || function () {
    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
    for (var r = Array(s), k = 0, i = 0; i < il; i++)
        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
            r[k] = a[j];
    return r;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var util_1 = __webpack_require__(/*! ./util */ "./node_modules/twilio-client/es5/twilio/util.js");
var getRTCStats = __webpack_require__(/*! ./rtc/stats */ "./node_modules/twilio-client/es5/twilio/rtc/stats.js").getRTCStats;
var Mos = __webpack_require__(/*! ./rtc/mos */ "./node_modules/twilio-client/es5/twilio/rtc/mos.js");
// How many samples we use when testing metric thresholds
var SAMPLE_COUNT_METRICS = 5;
// How many samples that need to cross the threshold to
// raise or clear a warning.
var SAMPLE_COUNT_CLEAR = 0;
var SAMPLE_COUNT_RAISE = 3;
var SAMPLE_INTERVAL = 1000;
var WARNING_TIMEOUT = 5 * 1000;
var DEFAULT_THRESHOLDS = {
    audioInputLevel: { minStandardDeviation: 327.67, sampleCount: 10 },
    audioOutputLevel: { minStandardDeviation: 327.67, sampleCount: 10 },
    bytesReceived: { clearCount: 2, min: 1, raiseCount: 3, sampleCount: 3 },
    bytesSent: { clearCount: 2, min: 1, raiseCount: 3, sampleCount: 3 },
    jitter: { max: 30 },
    mos: { min: 3 },
    packetsLostFraction: [{
            max: 1,
        }, {
            clearValue: 1,
            maxAverage: 3,
            sampleCount: 7,
        }],
    rtt: { max: 400 },
};
/**
 * Count the number of values that cross the max threshold.
 * @private
 * @param max - The max allowable value.
 * @param values - The values to iterate over.
 * @returns The amount of values in which the stat crossed the threshold.
 */
function countHigh(max, values) {
    return values.reduce(function (highCount, value) { return highCount += (value > max) ? 1 : 0; }, 0);
}
/**
 * Count the number of values that cross the min threshold.
 * @private
 * @param min - The minimum allowable value.
 * @param values - The values to iterate over.
 * @returns The amount of values in which the stat crossed the threshold.
 */
function countLow(min, values) {
    return values.reduce(function (lowCount, value) { return lowCount += (value < min) ? 1 : 0; }, 0);
}
/**
 * Calculate the standard deviation from a list of numbers.
 * @private
 * @param values The list of numbers to calculate the standard deviation from.
 * @returns The standard deviation of a list of numbers.
 */
function calculateStandardDeviation(values) {
    if (values.length <= 0) {
        return null;
    }
    var valueAverage = values.reduce(function (partialSum, value) { return partialSum + value; }, 0) / values.length;
    var diffSquared = values.map(function (value) { return Math.pow(value - valueAverage, 2); });
    var stdDev = Math.sqrt(diffSquared.reduce(function (partialSum, value) { return partialSum + value; }, 0) / diffSquared.length);
    return stdDev;
}
/**
 * Flatten a set of numerical sample sets into a single array of samples.
 * @param sampleSets
 */
function flattenSamples(sampleSets) {
    return sampleSets.reduce(function (flat, current) { return __spreadArrays(flat, current); }, []);
}
/**
 * {@link StatsMonitor} polls a peerConnection via PeerConnection.getStats
 * and emits warnings when stats cross the specified threshold values.
 */
var StatsMonitor = /** @class */ (function (_super) {
    __extends(StatsMonitor, _super);
    /**
     * @constructor
     * @param [options] - Optional settings
     */
    function StatsMonitor(options) {
        var _this = _super.call(this) || this;
        /**
         * A map of warnings with their raised time
         */
        _this._activeWarnings = new Map();
        /**
         * A map of stats with the number of exceeded thresholds
         */
        _this._currentStreaks = new Map();
        /**
         * Keeps track of input volumes in the last second
         */
        _this._inputVolumes = [];
        /**
         * Keeps track of output volumes in the last second
         */
        _this._outputVolumes = [];
        /**
         * Sample buffer. Saves most recent samples
         */
        _this._sampleBuffer = [];
        /**
         * Keeps track of supplemental sample values.
         *
         * Currently used for constant audio detection. Contains an array of volume
         * samples for each sample interval.
         */
        _this._supplementalSampleBuffers = {
            audioInputLevel: [],
            audioOutputLevel: [],
        };
        /**
         * Whether warnings should be enabled
         */
        _this._warningsEnabled = true;
        options = options || {};
        _this._getRTCStats = options.getRTCStats || getRTCStats;
        _this._mos = options.Mos || Mos;
        _this._peerConnection = options.peerConnection;
        _this._thresholds = __assign(__assign({}, DEFAULT_THRESHOLDS), options.thresholds);
        var thresholdSampleCounts = Object.values(_this._thresholds)
            .map(function (threshold) { return threshold.sampleCount; })
            .filter(function (sampleCount) { return !!sampleCount; });
        _this._maxSampleCount = Math.max.apply(Math, __spreadArrays([SAMPLE_COUNT_METRICS], thresholdSampleCounts));
        if (_this._peerConnection) {
            _this.enable(_this._peerConnection);
        }
        return _this;
    }
    /**
     * Called when a volume sample is available
     * @param inputVolume - Input volume level from 0 to 32767
     * @param outputVolume - Output volume level from 0 to 32767
     */
    StatsMonitor.prototype.addVolumes = function (inputVolume, outputVolume) {
        this._inputVolumes.push(inputVolume);
        this._outputVolumes.push(outputVolume);
    };
    /**
     * Stop sampling RTC statistics for this {@link StatsMonitor}.
     * @returns The current {@link StatsMonitor}.
     */
    StatsMonitor.prototype.disable = function () {
        clearInterval(this._sampleInterval);
        delete this._sampleInterval;
        return this;
    };
    /**
     * Disable warnings for this {@link StatsMonitor}.
     * @returns The current {@link StatsMonitor}.
     */
    StatsMonitor.prototype.disableWarnings = function () {
        if (this._warningsEnabled) {
            this._activeWarnings.clear();
        }
        this._warningsEnabled = false;
        return this;
    };
    /**
     * Start sampling RTC statistics for this {@link StatsMonitor}.
     * @param peerConnection - A PeerConnection to monitor.
     * @returns The current {@link StatsMonitor}.
     */
    StatsMonitor.prototype.enable = function (peerConnection) {
        if (peerConnection) {
            if (this._peerConnection && peerConnection !== this._peerConnection) {
                throw new errors_1.InvalidArgumentError('Attempted to replace an existing PeerConnection in StatsMonitor.enable');
            }
            this._peerConnection = peerConnection;
        }
        if (!this._peerConnection) {
            throw new errors_1.InvalidArgumentError('Can not enable StatsMonitor without a PeerConnection');
        }
        this._sampleInterval = this._sampleInterval ||
            setInterval(this._fetchSample.bind(this), SAMPLE_INTERVAL);
        return this;
    };
    /**
     * Enable warnings for this {@link StatsMonitor}.
     * @returns The current {@link StatsMonitor}.
     */
    StatsMonitor.prototype.enableWarnings = function () {
        this._warningsEnabled = true;
        return this;
    };
    /**
     * Check if there is an active warning for a specific stat and threshold
     * @param statName - The name of the stat to check
     * @param thresholdName - The name of the threshold to check
     * @returns Whether there is an active warning for a specific stat and threshold
     */
    StatsMonitor.prototype.hasActiveWarning = function (statName, thresholdName) {
        var warningId = statName + ":" + thresholdName;
        return !!this._activeWarnings.get(warningId);
    };
    /**
     * Add a sample to our sample buffer and remove the oldest if we are over the limit.
     * @param sample - Sample to add
     */
    StatsMonitor.prototype._addSample = function (sample) {
        var samples = this._sampleBuffer;
        samples.push(sample);
        // We store 1 extra sample so that we always have (current, previous)
        // available for all {sampleBufferSize} threshold validations.
        if (samples.length > this._maxSampleCount) {
            samples.splice(0, samples.length - this._maxSampleCount);
        }
    };
    /**
     * Clear an active warning.
     * @param statName - The name of the stat to clear.
     * @param thresholdName - The name of the threshold to clear
     * @param [data] - Any relevant sample data.
     */
    StatsMonitor.prototype._clearWarning = function (statName, thresholdName, data) {
        var warningId = statName + ":" + thresholdName;
        var activeWarning = this._activeWarnings.get(warningId);
        if (!activeWarning || Date.now() - activeWarning.timeRaised < WARNING_TIMEOUT) {
            return;
        }
        this._activeWarnings.delete(warningId);
        this.emit('warning-cleared', __assign(__assign({}, data), { name: statName, threshold: {
                name: thresholdName,
                value: this._thresholds[statName][thresholdName],
            } }));
    };
    /**
     * Create a sample object from a stats object using the previous sample, if available.
     * @param stats - Stats retrieved from getStatistics
     * @param [previousSample=null] - The previous sample to use to calculate deltas.
     * @returns A universally-formatted version of RTC stats.
     */
    StatsMonitor.prototype._createSample = function (stats, previousSample) {
        var previousBytesSent = previousSample && previousSample.totals.bytesSent || 0;
        var previousBytesReceived = previousSample && previousSample.totals.bytesReceived || 0;
        var previousPacketsSent = previousSample && previousSample.totals.packetsSent || 0;
        var previousPacketsReceived = previousSample && previousSample.totals.packetsReceived || 0;
        var previousPacketsLost = previousSample && previousSample.totals.packetsLost || 0;
        var currentBytesSent = stats.bytesSent - previousBytesSent;
        var currentBytesReceived = stats.bytesReceived - previousBytesReceived;
        var currentPacketsSent = stats.packetsSent - previousPacketsSent;
        var currentPacketsReceived = stats.packetsReceived - previousPacketsReceived;
        var currentPacketsLost = stats.packetsLost - previousPacketsLost;
        var currentInboundPackets = currentPacketsReceived + currentPacketsLost;
        var currentPacketsLostFraction = (currentInboundPackets > 0) ?
            (currentPacketsLost / currentInboundPackets) * 100 : 0;
        var totalInboundPackets = stats.packetsReceived + stats.packetsLost;
        var totalPacketsLostFraction = (totalInboundPackets > 0) ?
            (stats.packetsLost / totalInboundPackets) * 100 : 100;
        var rttValue = (typeof stats.rtt === 'number' || !previousSample) ? stats.rtt : previousSample.rtt;
        var audioInputLevelValues = this._inputVolumes.splice(0);
        this._supplementalSampleBuffers.audioInputLevel.push(audioInputLevelValues);
        var audioOutputLevelValues = this._outputVolumes.splice(0);
        this._supplementalSampleBuffers.audioOutputLevel.push(audioOutputLevelValues);
        return {
            audioInputLevel: Math.round(util_1.average(audioInputLevelValues)),
            audioOutputLevel: Math.round(util_1.average(audioOutputLevelValues)),
            bytesReceived: currentBytesReceived,
            bytesSent: currentBytesSent,
            codecName: stats.codecName,
            jitter: stats.jitter,
            mos: this._mos.calculate(rttValue, stats.jitter, previousSample && currentPacketsLostFraction),
            packetsLost: currentPacketsLost,
            packetsLostFraction: currentPacketsLostFraction,
            packetsReceived: currentPacketsReceived,
            packetsSent: currentPacketsSent,
            rtt: rttValue,
            timestamp: stats.timestamp,
            totals: {
                bytesReceived: stats.bytesReceived,
                bytesSent: stats.bytesSent,
                packetsLost: stats.packetsLost,
                packetsLostFraction: totalPacketsLostFraction,
                packetsReceived: stats.packetsReceived,
                packetsSent: stats.packetsSent,
            },
        };
    };
    /**
     * Get stats from the PeerConnection and add it to our list of samples.
     */
    StatsMonitor.prototype._fetchSample = function () {
        var _this = this;
        this._getSample().then(function (sample) {
            _this._addSample(sample);
            _this._raiseWarnings();
            _this.emit('sample', sample);
        }).catch(function (error) {
            _this.disable();
            // We only bubble up any errors coming from pc.getStats()
            // No need to attach a twilioError
            _this.emit('error', error);
        });
    };
    /**
     * Get stats from the PeerConnection.
     * @returns A universally-formatted version of RTC stats.
     */
    StatsMonitor.prototype._getSample = function () {
        var _this = this;
        return this._getRTCStats(this._peerConnection).then(function (stats) {
            var previousSample = null;
            if (_this._sampleBuffer.length) {
                previousSample = _this._sampleBuffer[_this._sampleBuffer.length - 1];
            }
            return _this._createSample(stats, previousSample);
        });
    };
    /**
     * Raise a warning and log its raised time.
     * @param statName - The name of the stat to raise.
     * @param thresholdName - The name of the threshold to raise
     * @param [data] - Any relevant sample data.
     */
    StatsMonitor.prototype._raiseWarning = function (statName, thresholdName, data) {
        var warningId = statName + ":" + thresholdName;
        if (this._activeWarnings.has(warningId)) {
            return;
        }
        this._activeWarnings.set(warningId, { timeRaised: Date.now() });
        var thresholds = this._thresholds[statName];
        var thresholdValue;
        if (Array.isArray(thresholds)) {
            var foundThreshold = thresholds.find(function (threshold) { return thresholdName in threshold; });
            if (foundThreshold) {
                thresholdValue = foundThreshold[thresholdName];
            }
        }
        else {
            thresholdValue = this._thresholds[statName][thresholdName];
        }
        this.emit('warning', __assign(__assign({}, data), { name: statName, threshold: {
                name: thresholdName,
                value: thresholdValue,
            } }));
    };
    /**
     * Apply our thresholds to our array of RTCStat samples.
     */
    StatsMonitor.prototype._raiseWarnings = function () {
        var _this = this;
        if (!this._warningsEnabled) {
            return;
        }
        Object.keys(this._thresholds).forEach(function (name) { return _this._raiseWarningsForStat(name); });
    };
    /**
     * Apply thresholds for a given stat name to our array of
     * RTCStat samples and raise or clear any associated warnings.
     * @param statName - Name of the stat to compare.
     */
    StatsMonitor.prototype._raiseWarningsForStat = function (statName) {
        var _this = this;
        var limits = Array.isArray(this._thresholds[statName])
            ? this._thresholds[statName]
            : [this._thresholds[statName]];
        limits.forEach(function (limit) {
            var samples = _this._sampleBuffer;
            var clearCount = limit.clearCount || SAMPLE_COUNT_CLEAR;
            var raiseCount = limit.raiseCount || SAMPLE_COUNT_RAISE;
            var sampleCount = limit.sampleCount || _this._maxSampleCount;
            var relevantSamples = samples.slice(-sampleCount);
            var values = relevantSamples.map(function (sample) { return sample[statName]; });
            // (rrowland) If we have a bad or missing value in the set, we don't
            // have enough information to throw or clear a warning. Bail out.
            var containsNull = values.some(function (value) { return typeof value === 'undefined' || value === null; });
            if (containsNull) {
                return;
            }
            var count;
            if (typeof limit.max === 'number') {
                count = countHigh(limit.max, values);
                if (count >= raiseCount) {
                    _this._raiseWarning(statName, 'max', { values: values, samples: relevantSamples });
                }
                else if (count <= clearCount) {
                    _this._clearWarning(statName, 'max', { values: values, samples: relevantSamples });
                }
            }
            if (typeof limit.min === 'number') {
                count = countLow(limit.min, values);
                if (count >= raiseCount) {
                    _this._raiseWarning(statName, 'min', { values: values, samples: relevantSamples });
                }
                else if (count <= clearCount) {
                    _this._clearWarning(statName, 'min', { values: values, samples: relevantSamples });
                }
            }
            if (typeof limit.maxDuration === 'number' && samples.length > 1) {
                relevantSamples = samples.slice(-2);
                var prevValue = relevantSamples[0][statName];
                var curValue = relevantSamples[1][statName];
                var prevStreak = _this._currentStreaks.get(statName) || 0;
                var streak = (prevValue === curValue) ? prevStreak + 1 : 0;
                _this._currentStreaks.set(statName, streak);
                if (streak >= limit.maxDuration) {
                    _this._raiseWarning(statName, 'maxDuration', { value: streak });
                }
                else if (streak === 0) {
                    _this._clearWarning(statName, 'maxDuration', { value: prevStreak });
                }
            }
            if (typeof limit.minStandardDeviation === 'number') {
                var sampleSets = _this._supplementalSampleBuffers[statName];
                if (!sampleSets || sampleSets.length < limit.sampleCount) {
                    return;
                }
                if (sampleSets.length > limit.sampleCount) {
                    sampleSets.splice(0, sampleSets.length - limit.sampleCount);
                }
                var flatSamples = flattenSamples(sampleSets.slice(-sampleCount));
                var stdDev = calculateStandardDeviation(flatSamples);
                if (typeof stdDev !== 'number') {
                    return;
                }
                if (stdDev < limit.minStandardDeviation) {
                    _this._raiseWarning(statName, 'minStandardDeviation', { value: stdDev });
                }
                else {
                    _this._clearWarning(statName, 'minStandardDeviation', { value: stdDev });
                }
            }
            [
                ['maxAverage', function (x, y) { return x > y; }],
                ['minAverage', function (x, y) { return x < y; }],
            ].forEach(function (_a) {
                var thresholdName = _a[0], comparator = _a[1];
                if (typeof limit[thresholdName] === 'number' && values.length >= sampleCount) {
                    var avg = util_1.average(values);
                    if (comparator(avg, limit[thresholdName])) {
                        _this._raiseWarning(statName, thresholdName, { values: values, samples: relevantSamples });
                    }
                    else if (!comparator(avg, limit.clearValue || limit[thresholdName])) {
                        _this._clearWarning(statName, thresholdName, { values: values, samples: relevantSamples });
                    }
                }
            });
        });
    };
    return StatsMonitor;
}(events_1.EventEmitter));
exports.default = StatsMonitor;
//# sourceMappingURL=statsMonitor.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/util.js":
/*!*******************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/util.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {

/**
 * Exception class.
 * @class
 * @name Exception
 * @exports Exception as Twilio.Exception
 * @memberOf Twilio
 * @param {string} message The exception message
 */
function TwilioException(message) {
    if (!(this instanceof TwilioException)) {
        return new TwilioException(message);
    }
    this.message = message;
}
/**
 * Returns the exception message.
 *
 * @return {string} The exception message.
 */
TwilioException.prototype.toString = function () {
    return "Twilio.Exception: " + this.message;
};
function average(values) {
    return values && values.length ? values.reduce(function (t, v) { return t + v; }) / values.length : 0;
}
function difference(lefts, rights, getKey) {
    getKey = getKey || (function (a) { return a; });
    var rightKeys = new Set(rights.map(getKey));
    return lefts.filter(function (left) { return !rightKeys.has(getKey(left)); });
}
function isElectron(navigator) {
    return !!navigator.userAgent.match('Electron');
}
function isChrome(window, navigator) {
    var isCriOS = !!navigator.userAgent.match('CriOS');
    var isHeadlessChrome = !!navigator.userAgent.match('HeadlessChrome');
    var isGoogle = typeof window.chrome !== 'undefined'
        && navigator.vendor === 'Google Inc.'
        && navigator.userAgent.indexOf('OPR') === -1
        && navigator.userAgent.indexOf('Edge') === -1;
    return isCriOS || isElectron(navigator) || isGoogle || isHeadlessChrome;
}
function isFirefox(navigator) {
    navigator = navigator || (typeof window === 'undefined'
        ? __webpack_require__.g.navigator : window.navigator);
    return !!(navigator) && typeof navigator.userAgent === 'string'
        && /firefox|fxios/i.test(navigator.userAgent);
}
function isLegacyEdge(navigator) {
    navigator = navigator || (typeof window === 'undefined'
        ? __webpack_require__.g.navigator : window.navigator);
    return !!(navigator) && typeof navigator.userAgent === 'string'
        && /edge\/\d+/i.test(navigator.userAgent);
}
function isSafari(navigator) {
    return !!(navigator.vendor) && navigator.vendor.indexOf('Apple') !== -1
        && navigator.userAgent
        && navigator.userAgent.indexOf('CriOS') === -1
        && navigator.userAgent.indexOf('FxiOS') === -1;
}
function isUnifiedPlanDefault(window, navigator, PeerConnection, RtpTransceiver) {
    if (typeof window === 'undefined'
        || typeof navigator === 'undefined'
        || typeof PeerConnection === 'undefined'
        || typeof RtpTransceiver === 'undefined'
        || typeof PeerConnection.prototype === 'undefined'
        || typeof RtpTransceiver.prototype === 'undefined') {
        return false;
    }
    if (isChrome(window, navigator) && PeerConnection.prototype.addTransceiver) {
        var pc = new PeerConnection();
        var isUnifiedPlan = true;
        try {
            pc.addTransceiver('audio');
        }
        catch (e) {
            isUnifiedPlan = false;
        }
        pc.close();
        return isUnifiedPlan;
    }
    else if (isFirefox(navigator)) {
        return true;
    }
    else if (isSafari(navigator)) {
        return 'currentDirection' in RtpTransceiver.prototype;
    }
    // Edge currently does not support unified plan.
    // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/17733189/
    // https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/34451998-sdp-unified-plan
    return false;
}
function queryToJson(params) {
    if (!params) {
        return '';
    }
    return params.split('&').reduce(function (output, pair) {
        var parts = pair.split('=');
        var key = parts[0];
        var value = decodeURIComponent((parts[1] || '').replace(/\+/g, '%20'));
        if (key) {
            output[key] = value;
        }
        return output;
    }, {});
}
/**
 * Map a list to an array of arrays, and return the flattened result.
 * @param {Array<*>|Set<*>|Map<*>} list
 * @param {function(*): Array<*>} [mapFn]
 * @returns Array<*>
 */
function flatMap(list, mapFn) {
    var listArray = list instanceof Map || list instanceof Set
        ? Array.from(list.values())
        : list;
    mapFn = mapFn || (function (item) { return item; });
    return listArray.reduce(function (flattened, item) {
        var mapped = mapFn(item);
        return flattened.concat(mapped);
    }, []);
}
exports.Exception = TwilioException;
exports.average = average;
exports.difference = difference;
exports.isElectron = isElectron;
exports.isChrome = isChrome;
exports.isFirefox = isFirefox;
exports.isLegacyEdge = isLegacyEdge;
exports.isSafari = isSafari;
exports.isUnifiedPlanDefault = isUnifiedPlanDefault;
exports.queryToJson = queryToJson;
exports.flatMap = flatMap;
//# sourceMappingURL=util.js.map

/***/ }),

/***/ "./node_modules/twilio-client/es5/twilio/wstransport.js":
/*!**************************************************************!*\
  !*** ./node_modules/twilio-client/es5/twilio/wstransport.js ***!
  \**************************************************************/
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {

"use strict";

/**
 * @packageDocumentation
 * @module Tools
 * @internalapi
 */
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
Object.defineProperty(exports, "__esModule", ({ value: true }));
var events_1 = __webpack_require__(/*! events */ "./node_modules/events/events.js");
var WebSocket = __webpack_require__(/*! ws */ "./node_modules/twilio-client/browser/ws.js");
var errors_1 = __webpack_require__(/*! ./errors */ "./node_modules/twilio-client/es5/twilio/errors/index.js");
var log_1 = __webpack_require__(/*! ./log */ "./node_modules/twilio-client/es5/twilio/log.js");
// tslint:disable-next-line
var Backoff = __webpack_require__(/*! backoff */ "./node_modules/backoff/index.js");
var CONNECT_SUCCESS_TIMEOUT = 10000;
var CONNECT_TIMEOUT = 5000;
var HEARTBEAT_TIMEOUT = 15000;
/**
 * All possible states of WSTransport.
 */
var WSTransportState;
(function (WSTransportState) {
    /**
     * The WebSocket is not open but is trying to connect.
     */
    WSTransportState["Connecting"] = "connecting";
    /**
     * The WebSocket is not open and is not trying to connect.
     */
    WSTransportState["Closed"] = "closed";
    /**
     * The underlying WebSocket is open and active.
     */
    WSTransportState["Open"] = "open";
})(WSTransportState = exports.WSTransportState || (exports.WSTransportState = {}));
/**
 * WebSocket Transport
 */
var WSTransport = /** @class */ (function (_super) {
    __extends(WSTransport, _super);
    /**
     * @constructor
     * @param uris - List of URI of the endpoints to connect to.
     * @param [options] - Constructor options.
     */
    function WSTransport(uris, options) {
        if (options === void 0) { options = {}; }
        var _this = _super.call(this) || this;
        /**
         * The current state of the WSTransport.
         */
        _this.state = WSTransportState.Closed;
        /**
         * An instance of Logger to use.
         */
        _this._log = log_1.default.getInstance();
        /**
         * Whether we should attempt to fallback if we receive an applicable error
         * when trying to connect to a signaling endpoint.
         */
        _this._shouldFallback = false;
        /**
         * The current uri index that the transport is connected to.
         */
        _this._uriIndex = 0;
        /**
         * Move the uri index to the next index
         * If the index is at the end, the index goes back to the first one.
         */
        _this._moveUriIndex = function () {
            _this._uriIndex++;
            if (_this._uriIndex >= _this._uris.length) {
                _this._uriIndex = 0;
            }
        };
        /**
         * Called in response to WebSocket#close event.
         */
        _this._onSocketClose = function (event) {
            _this._log.info("Received websocket close event code: " + event.code + ". Reason: " + event.reason);
            // 1006: Abnormal close. When the server is unreacheable
            // 1015: TLS Handshake error
            if (event.code === 1006 || event.code === 1015) {
                _this.emit('error', {
                    code: 31005,
                    message: event.reason ||
                        'Websocket connection to Twilio\'s signaling servers were ' +
                            'unexpectedly ended. If this is happening consistently, there may ' +
                            'be an issue resolving the hostname provided. If a region or an ' +
                            'edge is being specified in Device setup, ensure it is valid.',
                    twilioError: new errors_1.SignalingErrors.ConnectionError(),
                });
                var wasConnected = (
                // Only in Safari and certain Firefox versions, on network interruption, websocket drops right away with 1006
                // Let's check current state if it's open, meaning we should not fallback
                // because we're coming from a previously connected session
                _this.state === WSTransportState.Open ||
                    // But on other browsers, websocket doesn't drop
                    // but our heartbeat catches it, setting the internal state to "Connecting".
                    // With this, we should check the previous state instead.
                    _this._previousState === WSTransportState.Open);
                // Only fallback if this is not the first error
                // and if we were not connected previously
                if (_this._shouldFallback || !wasConnected) {
                    _this._moveUriIndex();
                }
                _this._shouldFallback = true;
            }
            _this._closeSocket();
        };
        /**
         * Called in response to WebSocket#error event.
         */
        _this._onSocketError = function (err) {
            _this._log.info("WebSocket received error: " + err.message);
            _this.emit('error', {
                code: 31000,
                message: err.message || 'WSTransport socket error',
                twilioError: new errors_1.SignalingErrors.ConnectionDisconnected(),
            });
        };
        /**
         * Called in response to WebSocket#message event.
         */
        _this._onSocketMessage = function (message) {
            // Clear heartbeat timeout on any incoming message, as they
            // all indicate an active connection.
            _this._setHeartbeatTimeout();
            // Filter and respond to heartbeats
            if (_this._socket && message.data === '\n') {
                _this._socket.send('\n');
                return;
            }
            _this.emit('message', message);
        };
        /**
         * Called in response to WebSocket#open event.
         */
        _this._onSocketOpen = function () {
            _this._log.info('WebSocket opened successfully.');
            _this._timeOpened = Date.now();
            _this._shouldFallback = false;
            _this._setState(WSTransportState.Open);
            clearTimeout(_this._connectTimeout);
            _this._setHeartbeatTimeout();
            _this.emit('open');
        };
        _this._connectTimeoutMs = options.connectTimeoutMs || CONNECT_TIMEOUT;
        var initialDelay = 100;
        if (uris && uris.length > 1) {
            // We only want a random initial delay if there are any fallback edges
            // Initial delay between 1s and 5s both inclusive
            initialDelay = Math.floor(Math.random() * (5000 - 1000 + 1)) + 1000;
        }
        var backoffConfig = {
            factor: 2.0,
            initialDelay: initialDelay,
            maxDelay: typeof options.backoffMaxMs === 'number'
                ? Math.max(options.backoffMaxMs, 3000)
                : 20000,
            randomisationFactor: 0.40,
        };
        _this._log.info('Initializing transport backoff using config: ', backoffConfig);
        _this._backoff = Backoff.exponential(backoffConfig);
        _this._uris = uris;
        _this._WebSocket = options.WebSocket || WebSocket;
        // Called when a backoff timer is started.
        _this._backoff.on('backoff', function (_, delay) {
            if (_this.state === WSTransportState.Closed) {
                return;
            }
            _this._log.info("Will attempt to reconnect WebSocket in " + delay + "ms");
        });
        // Called when a backoff timer ends. We want to try to reconnect
        // the WebSocket at this point.
        _this._backoff.on('ready', function (attempt) {
            if (_this.state === WSTransportState.Closed) {
                return;
            }
            _this._connect(attempt + 1);
        });
        return _this;
    }
    /**
     * Close the WebSocket, and don't try to reconnect.
     */
    WSTransport.prototype.close = function () {
        this._log.info('WSTransport.close() called...');
        this._close();
    };
    /**
     * Attempt to open a WebSocket connection.
     */
    WSTransport.prototype.open = function () {
        this._log.info('WSTransport.open() called...');
        if (this._socket &&
            (this._socket.readyState === WebSocket.CONNECTING ||
                this._socket.readyState === WebSocket.OPEN)) {
            this._log.info('WebSocket already open.');
            return;
        }
        this._connect();
    };
    /**
     * Send a message through the WebSocket connection.
     * @param message - A message to send to the endpoint.
     * @returns Whether the message was sent.
     */
    WSTransport.prototype.send = function (message) {
        // We can't send the message if the WebSocket isn't open
        if (!this._socket || this._socket.readyState !== WebSocket.OPEN) {
            return false;
        }
        try {
            this._socket.send(message);
        }
        catch (e) {
            // Some unknown error occurred. Reset the socket to get a fresh session.
            this._log.info('Error while sending message:', e.message);
            this._closeSocket();
            return false;
        }
        return true;
    };
    /**
     * Close the WebSocket, and don't try to reconnect.
     */
    WSTransport.prototype._close = function () {
        this._setState(WSTransportState.Closed);
        this._closeSocket();
    };
    /**
     * Close the WebSocket and remove all event listeners.
     */
    WSTransport.prototype._closeSocket = function () {
        clearTimeout(this._connectTimeout);
        clearTimeout(this._heartbeatTimeout);
        this._log.info('Closing and cleaning up WebSocket...');
        if (!this._socket) {
            this._log.info('No WebSocket to clean up.');
            return;
        }
        this._socket.removeEventListener('close', this._onSocketClose);
        this._socket.removeEventListener('error', this._onSocketError);
        this._socket.removeEventListener('message', this._onSocketMessage);
        this._socket.removeEventListener('open', this._onSocketOpen);
        if (this._socket.readyState === WebSocket.CONNECTING ||
            this._socket.readyState === WebSocket.OPEN) {
            this._socket.close();
        }
        // Reset backoff counter if connection was open for long enough to be considered successful
        if (this._timeOpened && Date.now() - this._timeOpened > CONNECT_SUCCESS_TIMEOUT) {
            this._backoff.reset();
        }
        this._backoff.backoff();
        delete this._socket;
        this.emit('close');
    };
    /**
     * Attempt to connect to the endpoint via WebSocket.
     * @param [retryCount] - Retry number, if this is a retry. Undefined if
     *   first attempt, 1+ if a retry.
     */
    WSTransport.prototype._connect = function (retryCount) {
        var _this = this;
        if (retryCount) {
            this._log.info("Attempting to reconnect (retry #" + retryCount + ")...");
        }
        else {
            this._log.info('Attempting to connect...');
        }
        this._closeSocket();
        this._setState(WSTransportState.Connecting);
        var socket = null;
        try {
            socket = new this._WebSocket(this._uris[this._uriIndex]);
        }
        catch (e) {
            this._log.info('Could not connect to endpoint:', e.message);
            this._close();
            this.emit('error', {
                code: 31000,
                message: e.message || "Could not connect to " + this._uris[this._uriIndex],
                twilioError: new errors_1.SignalingErrors.ConnectionDisconnected(),
            });
            return;
        }
        delete this._timeOpened;
        this._connectTimeout = setTimeout(function () {
            _this._log.info('WebSocket connection attempt timed out.');
            _this._moveUriIndex();
            _this._closeSocket();
        }, this._connectTimeoutMs);
        socket.addEventListener('close', this._onSocketClose);
        socket.addEventListener('error', this._onSocketError);
        socket.addEventListener('message', this._onSocketMessage);
        socket.addEventListener('open', this._onSocketOpen);
        this._socket = socket;
    };
    /**
     * Set a timeout to reconnect after HEARTBEAT_TIMEOUT milliseconds
     *   have passed without receiving a message over the WebSocket.
     */
    WSTransport.prototype._setHeartbeatTimeout = function () {
        var _this = this;
        clearTimeout(this._heartbeatTimeout);
        this._heartbeatTimeout = setTimeout(function () {
            _this._log.info("No messages received in " + HEARTBEAT_TIMEOUT / 1000 + " seconds. Reconnecting...");
            _this._shouldFallback = true;
            _this._closeSocket();
        }, HEARTBEAT_TIMEOUT);
    };
    /**
     * Set the current and previous state
     */
    WSTransport.prototype._setState = function (state) {
        this._previousState = this.state;
        this.state = state;
    };
    Object.defineProperty(WSTransport.prototype, "uri", {
        /**
         * The uri the transport is currently connected to
         */
        get: function () {
            return this._uris[this._uriIndex];
        },
        enumerable: true,
        configurable: true
    });
    return WSTransport;
}(events_1.EventEmitter));
exports.default = WSTransport;
//# sourceMappingURL=wstransport.js.map

/***/ })

}]);