public/js/browser-calls.js
/**
     * @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]
     */
@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]
@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;
        _this.availableInputDevices = new Map();
        _this.availableOutputDevices = new Map();
        _this._audioConstraints = null;
        _this._inputDevice = null;
        _this._inputStream = null;
        _this._isPollingInputVolume = false;
        _this._log = log_1.default.getInstance();
        _this._unknownDeviceIndexes = {
            audioinput: {},
            audiooutput: {},
        };
        _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;
        };
        _this._removeLostOutput = function (lostDevice) {
            var wasSpeakerLost = _this.speakerDevices.delete(lostDevice);
            var wasRingtoneLost = _this.ringtoneDevices.delete(lostDevice);
            return wasSpeakerLost || wasRingtoneLost;
        };
        _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 () {
            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;
    }
function AudioHelper ( onActiveOutputsChanged , onActiveInputChanged , getUserMedia , options ) { var _this = _super . call ( this ) || this ; _this . availableInputDevices = new Map ( ) ; _this . availableOutputDevices = new Map ( ) ; _this . _audioConstraints = null ; _this . _inputDevice = null ; _this . _inputStream = null ; _this . _isPollingInputVolume = false ; _this . _log = log_1 . default . getInstance ( ) ; _this . _unknownDeviceIndexes = { audioinput : { } , audiooutput : { } , } ; _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 ; } ; _this . _removeLostOutput = function ( lostDevice ) { var wasSpeakerLost = _this . speakerDevices . delete ( lostDevice ) ; var wasRingtoneLost = _this . ringtoneDevices . delete ( lostDevice ) ; return wasSpeakerLost || wasRingtoneLost ; } ; _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 ( ) { 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 ; }
@constructor
 @private
 @param onActiveOutputsChanged - A callback to be called when the user changes the active output devices.
@constructor @private @param onActiveOutputsChanged - A callback to be called when the user changes the active output devices .
/**
         * A Map of all audio input devices currently available to the browser by their device ID.
         */ /**
         * A Map of all audio output devices currently available to the browser by their device ID.
         */ /**
         * The currently set audio constraints set by setAudioConstraints().
         */ /**
         * The current input device.
         */ /**
         * The current input stream.
         */ /**
         * Whether the {@link AudioHelper} is currently polling the input stream's volume.
         */ /**
         * An instance of Logger to use.
         */ /**
         * A record of unknown devices (Devices without labels)
         */ /**
         * Remove an input device from inputs
         * @param lostDevice
         * @returns Whether the device was active
         */ /**
         * Remove an input device from outputs
         * @param lostDevice
         * @returns Whether the device was active
         */ /**
         * Update the available input and output devices
         */ // 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.