UNPKG

@twilio/voice-sdk

Version:
206 lines 14.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // @ts-nocheck var asyncQueue_1 = require("./asyncQueue"); var audioplayer_1 = require("./audioplayer/audioplayer"); var errors_1 = require("./errors"); /** * @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 errors_1.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_1.default.bind(audioplayer_1.default, options.audioContext) : options.AudioFactory; Object.defineProperties(this, { _Audio: { value: options.AudioPlayer }, _activeEls: { value: new Map() }, _isSinkSupported: { value: options.AudioFactory !== null && typeof options.AudioFactory.prototype.setSinkId === 'function', }, _maxDuration: { value: options.maxDuration }, _maxDurationTimeout: { value: null, writable: true, }, _operations: { value: new asyncQueue_1.AsyncQueue() }, _playPromise: { value: null, writable: true, }, _shouldLoop: { value: options.shouldLoop }, _sinkIds: { value: ['default'] }, isPlaying: { enumerable: true, get: function () { 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 errors_1.InvalidArgumentError("sinkId: \"".concat(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 _this = this; this._activeEls.forEach(function (audioEl, sinkId) { if (_this._sinkIds.includes(sinkId)) { audioEl.pause(); audioEl.currentTime = 0; } else { // Destroy the ones that are not used anymore destroyAudioElement(audioEl); _this._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 _this = this; this._operations.enqueue(function () { _this._stop(); return Promise.resolve(); }); }; /** * Add a play operation to the queue */ Sound.prototype.play = function play() { var _this = this; return this._operations.enqueue(function () { return _this._play(); }); }; exports.default = Sound; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291bmQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvdHdpbGlvL3NvdW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsY0FBYztBQUNkLDJDQUEwQztBQUMxQyx5REFBb0Q7QUFDcEQsbUNBQWdEO0FBRWhEOzs7Ozs7Ozs7R0FTRztBQUNIOzs7OztHQUtHO0FBQ0gsU0FBUyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxPQUFPO0lBQy9CLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQzdCLE9BQU8sSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLE1BQU0sSUFBSSw2QkFBb0IsQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO0lBQ3hFLENBQUM7SUFFRCxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUN0QixZQUFZLEVBQUUsT0FBTyxLQUFLLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7UUFDekQsV0FBVyxFQUFFLENBQUM7UUFDZCxVQUFVLEVBQUUsS0FBSztLQUNsQixFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBRVosT0FBTyxDQUFDLFdBQVcsR0FBRyxPQUFPLENBQUMsWUFBWTtRQUN4QyxDQUFDLENBQUMscUJBQVcsQ0FBQyxJQUFJLENBQUMscUJBQVcsRUFBRSxPQUFPLENBQUMsWUFBWSxDQUFDO1FBQ3JELENBQUMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDO0lBRXpCLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUU7UUFDNUIsTUFBTSxFQUFFLEVBQUUsS0FBSyxFQUFFLE9BQU8sQ0FBQyxXQUFXLEVBQUU7UUFDdEMsVUFBVSxFQUFFLEVBQUUsS0FBSyxF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