{"version":3,"sources":["webpack:///./node_modules/videojs-contrib-quality-levels/dist/videojs-contrib-quality-levels.js","webpack:///./node_modules/@silvermine/videojs-chromecast/dist/images/ic_cast_black_24dp.png","webpack:///./node_modules/feed-media-audio-player/lib/index.js","webpack:///./node_modules/tiny-cookie/es/util.js","webpack:///./node_modules/tiny-cookie/es/index.js"],"names":["factory","i","props","length","descriptor","enumerable","configurable","writable","Object","defineProperty","target","key","_setPrototypeOf","o","p","setPrototypeOf","__proto__","_createSuper","Derived","hasNativeReflectConstruct","Reflect","construct","sham","Proxy","Boolean","prototype","valueOf","call","e","_isNativeReflectConstruct","result","Super","_getPrototypeOf","NewTarget","this","constructor","arguments","apply","_possibleConstructorReturn","self","_typeof","_assertThisInitialized","ReferenceError","getPrototypeOf","_classCallCheck","instance","Constructor","TypeError","obj","Symbol","iterator","videojs","_interopDefaultLegacy","videojs__default","QualityLevel","representation","level","id","label","width","height","bitrate","bandwidth","frameRate","enabled_","enabled","get","set","enable","QualityLevelList","_videojs__default$def","subClass","superClass","create","value","_inherits","protoProps","staticProps","_super","_this","list","levels_","selectedIndex_","qualityLevel","getQualityLevelById","index","push","trigger","type","removed","l","splice","_defineProperties","EventTarget","event","allowedEvents_","change","addqualitylevel","removequalitylevel","version","registerPlugin","plugin","qualityLevels","options","player","mergeOptions","originalPluginFn","qualityLevelList","on","disposeHandler","dispose","off","VERSION","exports","module","tinyCookie","log","historyEntry","args","Array","slice","Date","now","console","JSON","stringify","ts","message","history","shift","reset","oldHistory","idCounter","uniqueId","prefix","nativeIndexOf","indexOf","uniq","array","isSorted","context","initial","map","results","seen","forEach","some","intersection","alpha","tests","retests","test","RegExp","filter","item","find","other","repeatAfter","delay","max","cb","setTimeout","baseUrl","getBaseUrl","setBaseUrl","url","secure","window","location","protocol","substr","addProtocol","clientPromise","cookieName","noDocument","document","noDocumentClientId","_getStoredCid","getCookie","_setStoredCid","setCookie","expires","path","_requestClientId","onSuccess","clientId","fetch","method","then","response","json","success","client_id","newDelay","catch","status","fullResponse","parse","responseText","getClientId","localClientPromise","Promise","resolve","getStoredClientId","setStoredClientId","_createClass","_slicedToArray","arr","isArray","_arrayWithHoles","_arr","_n","_d","_e","undefined","_s","_i","next","done","err","_iterableToArrayLimit","_unsupportedIterableToArray","_nonIterableRest","_toConsumableArray","_arrayLikeToArray","_arrayWithoutHoles","iter","from","_iterableToArray","_nonIterableSpread","minLen","n","toString","name","len","arr2","_createForOfIteratorHelper","F","s","_e2","f","it","normalCompletion","didErr","step","_e3","return","Events","callback","eventsApi","_events","ctx","once","func","memo","ran","once$1","_callback","retain","ev","events","names","j","k","keys","allEvents","all","triggerEvents","stopListening","listeners","_listeners","deleteListener","_listenerId","eventSplitter","action","rest","concat","split","a1","a2","a3","listenMethods","listenTo","listenToOnce","_loop","_Object$keys","implementation","Listener","uuid","assign","_uuid","_state","_timeout","clearTimeout","onTimeout","previousState","_activePlay","_this2","body","headers","becameIdle","state","previousPlay","play","seconds_since_start","duration_in_seconds","error","code","FEED_STATE_KEY","FEED_ELAPSED_TIME_KEY","supports_html5_storage","store","localStorage","setItem","remove","removeItem","getItem","Session","token","secret","config","remoteLogging","formats","maxBitrate","timeOffset","current","pendingRequest","pendingPlay","setCredentials","_submitLogHistory","setStationId","stationId","advance","secondsOfCrossfade","stations","stringStationId","changed","station","_assignCurrentPlay","_requestNextPlay","setFormats","isTuned","tune","setMaxBitrate","Error","_getDefaultPlacementInformation","placementId","placement","_signedAjax","session","_getClientId","_receiveDefaultPlacementInformation","bind","_failedDefaultPlacementInformation","placementInformation","warn","getActivePlacement","getActivePlay","hasActivePlayStarted","started","reportPlayStarted","_startPlay","reportPlayElapsed","seconds","reportPlayCompleted","pendingComplete","finally","_receivePlayCompleted","reportPlayStopped","requestSkip","canSkip","_receiveSkip","_failSkip","requestInvalidate","audio_file","_sendInvalidate","_receiveInvalidate","_failInvalidate","_this3","retryCount","_receiveStartPlay","can_skip","_failStartPlay","_this4","waitingIfEmpty","currentPlay","_ajax","ajax","_receiveNextPlay","_failedNextPlay","data","max_bitrate","placement_id","station_id","at","crossfade","start_at","_this5","Math","min","canSkipInStation","maybeCanSkip","canLike","can_like","likePlay","playId","liked","unlikePlay","dislikePlay","cookieName$1","_deleteStoredCid","removeCookie","_sign","request","authorization","btoa","Authorization","extraHeaders","header","hasOwnProperty","ok","statusText","count","parameters","_submitEvent","_this6","blobSupport","binary","bin","buf","ArrayBuffer","Uint8Array","charCodeAt","fixBinary","atob","png","Blob","URL","createObjectURL","objectUrl","exec","img","Image","onload","revokeObjectURL","onerror","src","hasBlobSupport","IOS","includes","navigator","platform","userAgent","brokenWebkit","SILENCE","TIMEUPDATE_PERIOD","requestAnimationFrame","Sound","speaker","loaded","startPosition","endPosition","fadeInSeconds","fadeInStart","fadeInEnd","fadeOutSeconds","fadeOutStart","fadeOutEnd","gain","d","audio","currentTime","paused","duration","readyState","_playSound","pause","_pauseSound","resume","position","_position","_duration","destroy","fadeOut","_destroySound","gainAdjustedVolume","volume","pow","Speaker","maxRetries","revoke","supports_html5_storage$1","vol","outstandingSounds","audioContext","active","fading","preparing","responses","preloaded","prepareWhenReady","initializeAudio","AudioCtor","AudioContext","webkitAudioContext","sampleRate","buffer","createBuffer","dummy","createBufferSource","connect","destination","start","disconnect","close","createAudioContext","_createAudio","pwr","_prepare","getSupportedFormats","createElement","canPlayType","_createAudioGainNode","source","createMediaElementSource","gainNode","createGain","Audio","crossOrigin","loop","preload","_addEventListeners","sound","canplaythrough","addEventListener","_onAudioPauseEvent","_onAudioEndedEvent","_onAudioErroredEvent","_onAudioTimeUpdateEvent","_onAudioCanPlay","currentTarget","_setVolume","awaitingPlayResponse","endPositionSeconds","prepare","audioGroup","currentVolume","calculatedVolume","_debugAudioObject","object","optionsAndCallbacks","_preload","ranges","buffered","range","end","activeUrl","logState","group","groupEnd","blobUrl","_fetch","attempt","retry","res","text","entries","blob","properMimeTypeBlob","playing","finishedSound","me","pauseAfterPlay","stack","flush","floor","isNaN","round","setVolume","getVolume","Player","simulcast","debug","trimming","normalizeVolume","resumable","crossfadeIn","serverAssignedCrossfade","_stationsPromise","reject","_stationsResolve","_stationsReject","brokenWebkitFormats","reqFormatList","suppFormatList","reqAndSuppFormatList","reqAndSuppFormats","join","_reqFormatList","_suppFormatList","_reqAndSuppFormatList","_reqAndSuppFormats","_restore","_onPlayActive","_onPlayStarted","_onPlayCompleted","_onPlaysExhausted","_onPrepareSound","_onPlacement","_onStations","_onStationChanged","setMuted","isMuted","_persist","playerState","shallowCopy","activePlay","sessionConfig","_ref","persisted","elapsed","sessionCurrent","_station","_stations","_placement","crossfade_seconds","fadeOutOrAdvance","fadeOnDestroy","_onSoundPlay","_onSoundPause","finish","_onSoundFinish","elapse","_onSoundElapse","replaygain_track_gain","pre_gain","extra","trim_start","trim_end","startReportedToServer","soundCompleted","playStarted","previousPosition","playerWasResumed","timestamp","asString","stringTimestamp","stateTimestamp","encodingTime","storageTime","persistState","withError","play_id","soundCompletedWithError","stop","previousCount","currentCount","updateSimulcast","preparedUrl","isPaused","ap","val","like","unlike","dislike","skip","getCurrentState","getPosition","getDuration","mutedKey","getStations","_this7","NodeList","thisArg","PlayerView","alertId","durationId","startedPlayback","$el","Element","getElementById","_onPlayPaused","_onPlayResumed","_onPlayStopped","_onPlayLiked","_onPlayUnliked","_onPlayDisliked","_onSkipDenied","_onSuspend","_enableButtonsBasedOnState","displayText","originalDisplayText","querySelector","innerHTML","renderStatus","querySelectorAll","_onStatusClick","button","_onPlayButtonClick","_onPauseButtonClick","_onSkipButtonClick","_onLikeButtonClick","_onDislikeButtonClick","formatTime","millis","asSeconds","secondsPart","classList","contains","$","arg","formatPlacement","formatPlay","_setLikeStatus","_enablePositionTracker","playerView","setInterval","renderPosition","likes","dislikes","element","add","_disablePositionTracker","clearInterval","renderAlert","track","title","artist","release","dur","progress","style","alertText","toEnable","toDisable","_step","_iterator","disabled","_step2","_iterator2","_item","classes","SimulcastPlayer","_speaker","_activeSound","_metadataTimeout","_tryingToPlay","_retries","_setState","baseApiUrl","_streamUrl","hostname","_requestStream","_lastElapsedAt","_elapsed","_scheduleMetadataTimeout","ms","_cancelMetadataTimeout","_onMetadataTimeout","oldElapsed","toObject","_logEvents","newState","metadataTimeoutIsNull","tryingToPlay","retries","resetClientId","maxAge","encoded","parseFloat","retrieveStateAndElapsed","hasOwn","computeExpires","str","lastCh","charAt","parseInt","setFullYear","getFullYear","setMonth","getMonth","setDate","getDate","setHours","getHours","setMinutes","getMinutes","setSeconds","getSeconds","_extends","isEnabled","re","cookie","decoder","decodeURIComponent","match","replace","getAll","reKey","cookies","lastIndex","encoder","encodeURIComponent","attrsStr","opts","toUTCString","convert","newCookie","getRaw","setRaw"],"mappings":"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","file":"js/vendors~admin-billboard-show~admin-live-instructor-show~admin-live-show~admin-redemption~plan-entry-~14f1148a-c4c8d60ae0ce72b06c98.chunk.js","sourcesContent":["function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }\nfunction _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function\"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }\nfunction _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }\nfunction _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }\nfunction _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === \"object\" || typeof call === \"function\")) { return call; } return _assertThisInitialized(self); }\nfunction _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return self; }\nfunction _isNativeReflectConstruct() { if (typeof Reflect === \"undefined\" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === \"function\") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }\nfunction _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\nfunction _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\n/*! @name videojs-contrib-quality-levels @version 3.0.0 @license Apache-2.0 */\n(function (global, factory) {\n (typeof exports === \"undefined\" ? \"undefined\" : _typeof(exports)) === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('video.js')) : typeof define === 'function' && define.amd ? define(['video.js'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.videojsContribQualityLevels = factory(global.videojs));\n})(this, function (videojs) {\n 'use strict';\n\n function _interopDefaultLegacy(e) {\n return e && _typeof(e) === 'object' && 'default' in e ? e : {\n 'default': e\n };\n }\n var videojs__default = /*#__PURE__*/_interopDefaultLegacy(videojs);\n\n /**\n * A single QualityLevel.\n *\n * interface QualityLevel {\n * readonly attribute DOMString id;\n * attribute DOMString label;\n * readonly attribute long width;\n * readonly attribute long height;\n * readonly attribute long bitrate;\n * attribute boolean enabled;\n * };\n *\n * @class QualityLevel\n */\n var QualityLevel =\n /**\n * Creates a QualityLevel\n *\n * @param {Representation|Object} representation The representation of the quality level\n * @param {string} representation.id Unique id of the QualityLevel\n * @param {number=} representation.width Resolution width of the QualityLevel\n * @param {number=} representation.height Resolution height of the QualityLevel\n * @param {number} representation.bandwidth Bitrate of the QualityLevel\n * @param {number=} representation.frameRate Frame-rate of the QualityLevel\n * @param {Function} representation.enabled Callback to enable/disable QualityLevel\n */\n function QualityLevel(representation) {\n _classCallCheck(this, QualityLevel);\n var level = this; // eslint-disable-line\n\n level.id = representation.id;\n level.label = level.id;\n level.width = representation.width;\n level.height = representation.height;\n level.bitrate = representation.bandwidth;\n level.frameRate = representation.frameRate;\n level.enabled_ = representation.enabled;\n Object.defineProperty(level, 'enabled', {\n /**\n * Get whether the QualityLevel is enabled.\n *\n * @return {boolean} True if the QualityLevel is enabled.\n */\n get: function get() {\n return level.enabled_();\n },\n /**\n * Enable or disable the QualityLevel.\n *\n * @param {boolean} enable true to enable QualityLevel, false to disable.\n */\n set: function set(enable) {\n level.enabled_(enable);\n }\n });\n return level;\n };\n /**\n * A list of QualityLevels.\n *\n * interface QualityLevelList : EventTarget {\n * getter QualityLevel (unsigned long index);\n * readonly attribute unsigned long length;\n * readonly attribute long selectedIndex;\n *\n * void addQualityLevel(QualityLevel qualityLevel)\n * void removeQualityLevel(QualityLevel remove)\n * QualityLevel? getQualityLevelById(DOMString id);\n *\n * attribute EventHandler onchange;\n * attribute EventHandler onaddqualitylevel;\n * attribute EventHandler onremovequalitylevel;\n * };\n *\n * @extends videojs.EventTarget\n * @class QualityLevelList\n */\n var QualityLevelList = /*#__PURE__*/function (_videojs__default$def) {\n _inherits(QualityLevelList, _videojs__default$def);\n var _super = _createSuper(QualityLevelList);\n function QualityLevelList() {\n var _this;\n _classCallCheck(this, QualityLevelList);\n _this = _super.call(this);\n var list = _assertThisInitialized(_this); // eslint-disable-line\n\n list.levels_ = [];\n list.selectedIndex_ = -1;\n /**\n * Get the index of the currently selected QualityLevel.\n *\n * @returns {number} The index of the selected QualityLevel. -1 if none selected.\n * @readonly\n */\n\n Object.defineProperty(list, 'selectedIndex', {\n get: function get() {\n return list.selectedIndex_;\n }\n });\n /**\n * Get the length of the list of QualityLevels.\n *\n * @returns {number} The length of the list.\n * @readonly\n */\n\n Object.defineProperty(list, 'length', {\n get: function get() {\n return list.levels_.length;\n }\n });\n return _possibleConstructorReturn(_this, list);\n }\n /**\n * Adds a quality level to the list.\n *\n * @param {Representation|Object} representation The representation of the quality level\n * @param {string} representation.id Unique id of the QualityLevel\n * @param {number=} representation.width Resolution width of the QualityLevel\n * @param {number=} representation.height Resolution height of the QualityLevel\n * @param {number} representation.bandwidth Bitrate of the QualityLevel\n * @param {number=} representation.frameRate Frame-rate of the QualityLevel\n * @param {Function} representation.enabled Callback to enable/disable QualityLevel\n * @return {QualityLevel} the QualityLevel added to the list\n * @method addQualityLevel\n */\n _createClass(QualityLevelList, [{\n key: \"addQualityLevel\",\n value: function addQualityLevel(representation) {\n var qualityLevel = this.getQualityLevelById(representation.id); // Do not add duplicate quality levels\n\n if (qualityLevel) {\n return qualityLevel;\n }\n var index = this.levels_.length;\n qualityLevel = new QualityLevel(representation);\n if (!('' + index in this)) {\n Object.defineProperty(this, index, {\n get: function get() {\n return this.levels_[index];\n }\n });\n }\n this.levels_.push(qualityLevel);\n this.trigger({\n qualityLevel: qualityLevel,\n type: 'addqualitylevel'\n });\n return qualityLevel;\n }\n /**\n * Removes a quality level from the list.\n *\n * @param {QualityLevel} remove QualityLevel to remove to the list.\n * @return {QualityLevel|null} the QualityLevel removed or null if nothing removed\n * @method removeQualityLevel\n */\n }, {\n key: \"removeQualityLevel\",\n value: function removeQualityLevel(qualityLevel) {\n var removed = null;\n for (var i = 0, l = this.length; i < l; i++) {\n if (this[i] === qualityLevel) {\n removed = this.levels_.splice(i, 1)[0];\n if (this.selectedIndex_ === i) {\n this.selectedIndex_ = -1;\n } else if (this.selectedIndex_ > i) {\n this.selectedIndex_--;\n }\n break;\n }\n }\n if (removed) {\n this.trigger({\n qualityLevel: qualityLevel,\n type: 'removequalitylevel'\n });\n }\n return removed;\n }\n /**\n * Searches for a QualityLevel with the given id.\n *\n * @param {string} id The id of the QualityLevel to find.\n * @return {QualityLevel|null} The QualityLevel with id, or null if not found.\n * @method getQualityLevelById\n */\n }, {\n key: \"getQualityLevelById\",\n value: function getQualityLevelById(id) {\n for (var i = 0, l = this.length; i < l; i++) {\n var level = this[i];\n if (level.id === id) {\n return level;\n }\n }\n return null;\n }\n /**\n * Resets the list of QualityLevels to empty\n *\n * @method dispose\n */\n }, {\n key: \"dispose\",\n value: function dispose() {\n this.selectedIndex_ = -1;\n this.levels_.length = 0;\n }\n }]);\n return QualityLevelList;\n }(videojs__default['default'].EventTarget);\n /**\n * change - The selected QualityLevel has changed.\n * addqualitylevel - A QualityLevel has been added to the QualityLevelList.\n * removequalitylevel - A QualityLevel has been removed from the QualityLevelList.\n */\n QualityLevelList.prototype.allowedEvents_ = {\n change: 'change',\n addqualitylevel: 'addqualitylevel',\n removequalitylevel: 'removequalitylevel'\n }; // emulate attribute EventHandler support to allow for feature detection\n\n for (var event in QualityLevelList.prototype.allowedEvents_) {\n QualityLevelList.prototype['on' + event] = null;\n }\n var version = \"3.0.0\";\n var registerPlugin = videojs__default['default'].registerPlugin || videojs__default['default'].plugin;\n /**\n * Initialization function for the qualityLevels plugin. Sets up the QualityLevelList and\n * event handlers.\n *\n * @param {Player} player Player object.\n * @param {Object} options Plugin options object.\n * @function initPlugin\n */\n\n var initPlugin = function initPlugin(player, options) {\n var originalPluginFn = player.qualityLevels;\n var qualityLevelList = new QualityLevelList();\n var disposeHandler = function disposeHandler() {\n qualityLevelList.dispose();\n player.qualityLevels = originalPluginFn;\n player.off('dispose', disposeHandler);\n };\n player.on('dispose', disposeHandler);\n player.qualityLevels = function () {\n return qualityLevelList;\n };\n player.qualityLevels.VERSION = version;\n return qualityLevelList;\n };\n /**\n * A video.js plugin.\n *\n * In the plugin function, the value of `this` is a video.js `Player`\n * instance. You cannot rely on the player being in a \"ready\" state here,\n * depending on how the plugin is invoked. This may or may not be important\n * to you; if not, remove the wait for \"ready\"!\n *\n * @param {Object} options Plugin options object\n * @function qualityLevels\n */\n\n var qualityLevels = function qualityLevels(options) {\n return initPlugin(this, videojs__default['default'].mergeOptions({}, options));\n }; // Register the plugin with video.js.\n\n registerPlugin('qualityLevels', qualityLevels); // Include the version number.\n\n qualityLevels.VERSION = version;\n return qualityLevels;\n});","module.exports = __webpack_public_path__ + \"media/images/ic_cast_black_24dp-3457484d.png\";","'use strict';\n\nvar tinyCookie = require('tiny-cookie');\n\n/* eslint-disable no-console */\nvar enabled = false;\nvar log = function log() {\n var args = Array.prototype.slice.call(arguments);\n args[0] = Date.now() + ' feed.fm: ' + args[0];\n if (enabled) {\n console.log.apply(console, args);\n }\n var historyEntry;\n try {\n historyEntry = JSON.stringify({\n ts: new Date(),\n message: args[0],\n args: args.slice(1)\n });\n } catch (e) {\n historyEntry = JSON.stringify({\n ts: new Date(),\n message: args[0],\n args: 'truncated'\n });\n }\n log.history.push(historyEntry);\n if (history.length > 500) {\n log.history.shift();\n }\n};\nlog.history = [];\nlog.enable = function () {\n enabled = true;\n};\nlog.reset = function () {\n var oldHistory = log.history;\n log.history = [];\n return oldHistory;\n};\nfunction addProtocol(url, secure) {\n // handle '//somewhere.com/' url's\n if (url.slice(0, 2) === '//') {\n if (secure === true) {\n url = 'https:' + url;\n } else if (secure === false) {\n url = 'http:' + url;\n } else if (window.location.protocol.substr(0, 4) === 'http') {\n url = window.location.protocol + url;\n } else {\n url = 'http';\n }\n }\n return url;\n}\n/**\n * The below are adapted from the Underscore library:\n * Underscore.js 1.5.2\n * http://underscorejs.org\n * (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n * Underscore may be freely distributed under the MIT license.\n */\n\nvar idCounter = 0;\nfunction uniqueId(prefix) {\n var id = ++idCounter;\n return prefix + id;\n}\nvar nativeIndexOf = Array.prototype.indexOf;\nfunction contains(obj, target) {\n if (obj === null) return false;\n if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;\n return obj.some(function (value) {\n return value === target;\n });\n}\nfunction uniq(array, isSorted, iterator, context) {\n if (typeof isSorted === 'function') {\n context = iterator;\n iterator = isSorted;\n isSorted = false;\n }\n var initial = iterator ? array.map(iterator, context) : array;\n var results = [];\n var seen = [];\n initial.forEach(function (value, index) {\n if (isSorted ? !index || seen[seen.length - 1] !== value : !contains(seen, value)) {\n seen.push(value);\n results.push(array[index]);\n }\n });\n return results;\n}\nfunction intersection(alpha, tests) {\n var retests = tests.map(function (test) {\n return new RegExp(test);\n });\n return uniq(alpha).filter(function (item) {\n return retests.find(function (other) {\n return other.test(item);\n });\n });\n}\nfunction once(func) {\n var ran = false,\n memo;\n return function () {\n if (ran) return memo;\n ran = true;\n memo = func.apply(this, arguments);\n func = null;\n return memo;\n };\n}\nfunction repeatAfter(delay, max, cb) {\n delay = delay ? 2 * delay : 200;\n if (delay > max) {\n delay = max;\n }\n setTimeout(function () {\n cb(delay);\n }, delay);\n}\nvar baseUrl = 'https://feed.fm';\nfunction getBaseUrl() {\n return baseUrl;\n}\nfunction setBaseUrl(url) {\n baseUrl = addProtocol(url);\n}\nvar cookieName = 'cid';\nvar clientPromise;\nvar noDocument = typeof document === 'undefined';\nvar noDocumentClientId = null;\nfunction _getStoredCid() {\n if (noDocument) {\n return noDocumentClientId;\n } else {\n return tinyCookie.getCookie(cookieName);\n }\n}\nfunction _setStoredCid(value) {\n if (noDocument) {\n noDocumentClientId = value;\n } else {\n tinyCookie.setCookie(cookieName, value, {\n expires: 3650,\n path: '/'\n });\n }\n}\nfunction _deleteStoredCid() {\n if (noDocument) {\n noDocumentClientId = null;\n } else {\n tinyCookie.removeCookie(cookieName);\n }\n} // hit the server up for a client id and return it to the callback\n\nfunction _requestClientId(onSuccess, delay) {\n // see if we've got a cookie\n var clientId = _getStoredCid();\n if (clientId) {\n return onSuccess(clientId);\n } else {\n fetch(getBaseUrl() + '/api/v2/client', {\n method: 'POST'\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.success) {\n onSuccess(response.client_id);\n } else {\n repeatAfter(delay, 2000, function (newDelay) {\n // retry until the end of time\n _requestClientId(onSuccess, newDelay);\n });\n }\n }).catch(function (response) {\n if (response.status === 403) {\n try {\n var fullResponse = JSON.parse(response.responseText);\n log('error trying to get client id:', fullResponse);\n } catch (e) {\n // some other response - fall through and try again\n log('unknown response for client id request', e.message);\n }\n } else {\n log('unknown client id response status', response.status);\n }\n repeatAfter(delay, 2000, function (newDelay) {\n // retry until the end of time\n _requestClientId(onSuccess, newDelay);\n });\n });\n }\n}\nfunction getClientId() {\n if (!clientPromise) {\n var localClientPromise = clientPromise = new Promise(function (resolve) {\n _requestClientId(function (clientId) {\n if (clientPromise === localClientPromise) {\n // success!\n _setStoredCid(clientId);\n resolve(clientId);\n } else if (clientPromise) {\n // end user updated the client id while we were waiting for a new one\n clientPromise.then(function (clientId) {\n resolve(clientId);\n });\n } else {\n // end user deleted the client id while we were waiting for a new one\n getClientId().then(function (clientId) {\n resolve(clientId);\n });\n }\n });\n });\n }\n return clientPromise;\n}\nvar getStoredClientId = _getStoredCid;\nvar setStoredClientId = _setStoredCid;\nfunction deleteClientId() {\n _deleteStoredCid();\n clientPromise = null;\n}\nfunction _typeof(obj) {\n \"@babel/helpers - typeof\";\n\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function _typeof(obj) {\n return typeof obj;\n };\n } else {\n _typeof = function _typeof(obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n return _typeof(obj);\n}\nfunction _classCallCheck(instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n}\nfunction _defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n}\nfunction _createClass(Constructor, protoProps, staticProps) {\n if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n if (staticProps) _defineProperties(Constructor, staticProps);\n return Constructor;\n}\nfunction _slicedToArray(arr, i) {\n return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest();\n}\nfunction _toConsumableArray(arr) {\n return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();\n}\nfunction _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) return _arrayLikeToArray(arr);\n}\nfunction _arrayWithHoles(arr) {\n if (Array.isArray(arr)) return arr;\n}\nfunction _iterableToArray(iter) {\n if (typeof Symbol !== \"undefined\" && Symbol.iterator in Object(iter)) return Array.from(iter);\n}\nfunction _iterableToArrayLimit(arr, i) {\n if (typeof Symbol === \"undefined\" || !(Symbol.iterator in Object(arr))) return;\n var _arr = [];\n var _n = true;\n var _d = false;\n var _e = undefined;\n try {\n for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {\n _arr.push(_s.value);\n if (i && _arr.length === i) break;\n }\n } catch (err) {\n _d = true;\n _e = err;\n } finally {\n try {\n if (!_n && _i[\"return\"] != null) _i[\"return\"]();\n } finally {\n if (_d) throw _e;\n }\n }\n return _arr;\n}\nfunction _unsupportedIterableToArray(o, minLen) {\n if (!o) return;\n if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);\n var n = Object.prototype.toString.call(o).slice(8, -1);\n if (n === \"Object\" && o.constructor) n = o.constructor.name;\n if (n === \"Map\" || n === \"Set\") return Array.from(n);\n if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);\n}\nfunction _arrayLikeToArray(arr, len) {\n if (len == null || len > arr.length) len = arr.length;\n for (var i = 0, arr2 = new Array(len); i < len; i++) {\n arr2[i] = arr[i];\n }\n return arr2;\n}\nfunction _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nfunction _nonIterableRest() {\n throw new TypeError(\"Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\nfunction _createForOfIteratorHelper(o) {\n if (typeof Symbol === \"undefined\" || o[Symbol.iterator] == null) {\n if (Array.isArray(o) || (o = _unsupportedIterableToArray(o))) {\n var i = 0;\n var F = function F() {};\n return {\n s: F,\n n: function n() {\n if (i >= o.length) return {\n done: true\n };\n return {\n done: false,\n value: o[i++]\n };\n },\n e: function e(_e2) {\n throw _e2;\n },\n f: F\n };\n }\n throw new TypeError(\"Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n }\n var it,\n normalCompletion = true,\n didErr = false,\n err;\n return {\n s: function s() {\n it = o[Symbol.iterator]();\n },\n n: function n() {\n var step = it.next();\n normalCompletion = step.done;\n return step;\n },\n e: function e(_e3) {\n didErr = true;\n err = _e3;\n },\n f: function f() {\n try {\n if (!normalCompletion && it.return != null) it.return();\n } finally {\n if (didErr) throw err;\n }\n }\n };\n}\nvar slice = Array.prototype.slice;\nvar Events = {\n // Bind an event to a `callback` function. Passing `\"all\"` will bind\n // the callback to all events fired.\n on: function on(name, callback, context) {\n if (!eventsApi(this, 'on', name, [callback, context]) || !callback) {\n return this;\n }\n if (!this._events) {\n this._events = {};\n }\n var events = this._events[name] || (this._events[name] = []);\n events.push({\n callback: callback,\n context: context,\n ctx: context || this\n });\n return this;\n },\n // Bind an event to only be triggered a single time. After the first time\n // the callback is invoked, it will be removed.\n once: function once$1(name, callback, context) {\n if (!eventsApi(this, 'once', name, [callback, context]) || !callback) {\n return this;\n }\n var self = this;\n var once$1 = once(function () {\n self.off(name, once$1);\n callback.apply(this, arguments);\n });\n once$1._callback = callback;\n return this.on(name, once$1, context);\n },\n // Remove one or many callbacks. If `context` is null, removes all\n // callbacks with that function. If `callback` is null, removes all\n // callbacks for the event. If `name` is null, removes all bound\n // callbacks for all events.\n off: function off(name, callback, context) {\n var retain, ev, events, names, i, l, j, k;\n if (!this._events || !eventsApi(this, 'off', name, [callback, context])) {\n return this;\n }\n if (!name && !callback && !context) {\n this._events = {};\n return this;\n }\n names = name ? [name] : Object.keys(this._events);\n for (i = 0, l = names.length; i < l; i++) {\n name = names[i];\n if (events = this._events[name]) {\n // eslint-disable-line no-cond-assign\n this._events[name] = retain = [];\n if (callback || context) {\n for (j = 0, k = events.length; j < k; j++) {\n ev = events[j];\n if (callback && callback !== ev.callback && callback !== ev.callback._callback || context && context !== ev.context) {\n retain.push(ev);\n }\n }\n }\n if (!retain.length) {\n delete this._events[name];\n }\n }\n }\n return this;\n },\n // Trigger one or many events, firing all bound callbacks. Callbacks are\n // passed the same arguments as `trigger` is, apart from the event name\n // (unless you're listening on `\"all\"`, which will cause your callback to\n // receive the true name of the event as the first argument).\n trigger: function trigger(name) {\n if (!this._events) {\n return this;\n }\n var args = slice.call(arguments, 1);\n if (!eventsApi(this, 'trigger', name, args)) {\n return this;\n }\n var events = this._events[name];\n var allEvents = this._events.all;\n if (events) {\n triggerEvents(events, args);\n }\n if (allEvents) {\n triggerEvents(allEvents, arguments);\n }\n return this;\n },\n // Tell this object to stop listening to either specific events ... or\n // to every object it's currently listening to.\n stopListening: function stopListening(obj, name, callback) {\n var listeners = this._listeners;\n if (!listeners) {\n return this;\n }\n var deleteListener = !name && !callback;\n if (_typeof(name) === 'object') {\n callback = this;\n }\n if (obj) {\n (listeners = {})[obj._listenerId] = obj;\n }\n /*jshint forin:false */\n\n for (var id in listeners) {\n listeners[id].off(name, callback, this);\n if (deleteListener) {\n delete this._listeners[id];\n }\n }\n return this;\n }\n}; // Regular expression used to split event strings.\n\nvar eventSplitter = /\\s+/; // Implement fancy features of the Events API such as multiple event\n// names `\"change blur\"` and jQuery-style event maps `{change: action}`\n// in terms of the existing API.\n\nvar eventsApi = function eventsApi(obj, action, name, rest) {\n if (!name) {\n return true;\n } // Handle event maps.\n\n if (_typeof(name) === 'object') {\n /*jshint forin:false */\n for (var key in name) {\n obj[action].apply(obj, [key, name[key]].concat(rest));\n }\n return false;\n } // Handle space separated event names.\n\n if (eventSplitter.test(name)) {\n var names = name.split(eventSplitter);\n for (var i = 0, l = names.length; i < l; i++) {\n obj[action].apply(obj, [names[i]].concat(rest));\n }\n return false;\n }\n return true;\n}; // A difficult-to-believe, but optimized internal dispatch function for\n// triggering events. Tries to keep the usual cases speedy (most internal\n// Backbone events have 3 arguments).\n\nvar triggerEvents = function triggerEvents(events, args) {\n var ev,\n i = -1,\n l = events.length,\n a1 = args[0],\n a2 = args[1],\n a3 = args[2];\n switch (args.length) {\n case 0:\n while (++i < l) {\n (ev = events[i]).callback.call(ev.ctx);\n }\n return;\n case 1:\n while (++i < l) {\n (ev = events[i]).callback.call(ev.ctx, a1);\n }\n return;\n case 2:\n while (++i < l) {\n (ev = events[i]).callback.call(ev.ctx, a1, a2);\n }\n return;\n case 3:\n while (++i < l) {\n (ev = events[i]).callback.call(ev.ctx, a1, a2, a3);\n }\n return;\n default:\n while (++i < l) {\n (ev = events[i]).callback.apply(ev.ctx, args);\n }\n }\n};\nvar listenMethods = {\n listenTo: 'on',\n listenToOnce: 'once'\n}; // Inversion-of-control versions of `on` and `once`. Tell *this* object to\n// listen to an event in another object ... keeping track of what it's\n// listening to.\n\nvar _loop = function _loop() {\n var method = _Object$keys[_i];\n var implementation = listenMethods[method];\n Events[method] = function (obj, name, callback) {\n var listeners = this._listeners || (this._listeners = {});\n var id = obj._listenerId || (obj._listenerId = uniqueId('l'));\n listeners[id] = obj;\n if (_typeof(name) === 'object') {\n callback = this;\n }\n obj[implementation](name, callback, this);\n return this;\n };\n};\nfor (var _i = 0, _Object$keys = Object.keys(listenMethods); _i < _Object$keys.length; _i++) {\n _loop();\n}\n\n/**\n * This class connects to a specific simulcast stream and\n * sends out events to indicate when new songs are starting\n * or when music has stopped playing. This listener has a\n * 'state' that is one of \n * \n * 'idle' - no music is playing\n * 'playing' - a song is actively playing\n * 'paused' - the current song is paused\n * 'music-unavailable' - no music is available for this client\n * \n * events:\n * play-started - indicates a new song has begun playback, or we've\n * dropped in on an already playing song\n * music-unavailable - indicates the listener may not listen to music\n * music-stopped - indicates that music has stopped streaming. This maps\n * up to the end of a broadcast, and not a 'pause' in music.\n * state-changed - indicates the state of the player changed\n * \n * demo: https://jsbin.com/biwogiyewu/edit?html,js,output\n */\n\nvar Listener = /*#__PURE__*/function () {\n function Listener(uuid) {\n _classCallCheck(this, Listener);\n Object.assign(this, Events);\n this._uuid = uuid;\n this._state = 'idle'; //this._activePlay = null;\n }\n _createClass(Listener, [{\n key: \"listen\",\n value: function listen() {\n var _this = this;\n if (this._timeout) {\n clearTimeout(this._timeout);\n delete this._timeout;\n }\n getClientId().then(function (clientId) {\n _this.onTimeout(clientId);\n });\n }\n }, {\n key: \"stop\",\n value: function stop() {\n if (this._timeout) {\n clearTimeout(this._timeout);\n delete this._timeout;\n }\n var previousState = this._state;\n this._state = 'idle';\n delete this._activePlay;\n if (previousState !== 'idle') {\n try {\n this.trigger('state-changed', this._state, previousState);\n } catch (e) {\n /* ignore */\n }\n }\n }\n }, {\n key: \"onTimeout\",\n value: function onTimeout(clientId) {\n var _this2 = this;\n fetch(getBaseUrl() + \"/api/v2/simulcast/\".concat(this._uuid, \"/listen\"), {\n method: 'POST',\n body: JSON.stringify({\n client_id: clientId\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n var delay = 5000;\n if (response.success) {\n var becameIdle = response.state === 'idle' && _this2._state !== 'idle';\n var previousPlay = _this2._activePlay;\n var previousState = _this2._state;\n var state = _this2._state = response.state;\n if (state === 'idle') {\n delete _this2._activePlay;\n } else {\n _this2._activePlay = response.play;\n }\n if (previousState !== state) {\n try {\n _this2.trigger('state-changed', state, previousState);\n } catch (e) {\n /* ignore */\n }\n }\n if (state === 'idle') {\n if (becameIdle) {\n try {\n _this2.trigger('music-stopped');\n } catch (e) {\n /* ignore */\n }\n }\n } else {\n if (!previousPlay || previousPlay.id !== _this2._activePlay.id) {\n try {\n _this2.trigger('play-started', _this2._activePlay);\n } catch (e) {\n /* ignore */\n }\n }\n if (response.seconds_since_start > 20 && response.play.duration_in_seconds - response.seconds_since_start > 20) {\n delay = 15000;\n }\n }\n } else {\n if (response.error && response.error.code === 19) {\n _this2._state = 'music-unavailable';\n _this2.trigger('music-unavailable'); // don't schedule another update\n\n return;\n }\n }\n _this2._timeout = setTimeout(function () {\n _this2.onTimeout(clientId);\n }, delay);\n }).catch(function (response) {\n if (response.status === 403) {\n try {\n var fullResponse = JSON.parse(response.responseText);\n if (fullResponse.error && fullResponse.error.code === 19) {\n try {\n _this2._state = 'music-unavailable';\n _this2.trigger('music-unavailable');\n } catch (e) {\n /* ignore */\n }\n return;\n }\n console.log('unexpected error:', fullResponse);\n } catch (e) {\n // some other response - fall through and try again\n console.log('bad response', e.message);\n }\n } else {\n console.log('odd response', response);\n }\n _this2._timeout = setTimeout(function () {\n _this2.onTimeout(clientId);\n }, 15000);\n });\n }\n }, {\n key: \"getCurrentState\",\n value: function getCurrentState() {\n return this._state;\n }\n }, {\n key: \"getCurrentPlay\",\n value: function getCurrentPlay() {\n return this._activePlay;\n }\n }]);\n return Listener;\n}();\nvar FEED_STATE_KEY = 'feedfm:active';\nvar FEED_ELAPSED_TIME_KEY = 'feedfm:elapsed_time';\nfunction supports_html5_storage() {\n try {\n return 'localStorage' in window && window['localStorage'] !== null;\n } catch (e) {\n return false;\n }\n}\nfunction store(key, value) {\n if (supports_html5_storage()) {\n localStorage.setItem(key, value);\n }\n}\nfunction remove(key) {\n if (supports_html5_storage()) {\n localStorage.removeItem(key);\n }\n}\nfunction get(key) {\n if (supports_html5_storage()) {\n return localStorage.getItem(key);\n } else {\n return null;\n }\n}\nfunction persistState(state) {\n var timestamp = Date.now();\n var asString = JSON.stringify({\n state: state,\n timestamp: timestamp\n });\n var stringTimestamp = Date.now(); // update timestamp and store in local storage\n\n store(FEED_STATE_KEY, asString);\n var stateTimestamp = Date.now();\n store(FEED_ELAPSED_TIME_KEY, '0');\n log('persisted state', {\n timestamp: timestamp,\n encodingTime: stringTimestamp - timestamp,\n storageTime: stateTimestamp - stringTimestamp,\n state: state\n });\n}\nfunction persistElapsed(milliseconds) {\n // save elapsed seconds in current song\n store(FEED_ELAPSED_TIME_KEY, milliseconds.toString());\n}\nfunction retrieveStateAndElapsed(maxAge) {\n // pull things out of state, if they're less than maxAge milliseconds old, or null\n var encoded = get(FEED_STATE_KEY);\n if (encoded) {\n var persisted = JSON.parse(encoded);\n if (persisted.timestamp + maxAge > Date.now()) {\n var elapsed = parseFloat(get(FEED_ELAPSED_TIME_KEY), 10);\n return [persisted.state, elapsed];\n }\n }\n return [];\n}\nfunction clearPersistance() {\n // nuke any stored state\n remove(FEED_STATE_KEY);\n remove(FEED_ELAPSED_TIME_KEY);\n}\nvar version = \"1.103.6\";\n\n/*\n * Feed Media Session API\n *\n * This manages all communication with the server and is the single point\n * of truth for a client to manage what is actively being played. It\n * should be created with:\n *\n * var session = new Feed.Session(token, secret[, options]);\n *\n * Then you attach event listeners to the session:\n *\n * session.on('play-active', someHandler);\n *\n * Then you can optionally set a station:\n *\n * session.setStationId(stationId);\n *\n * If any of the above calls are made while we're actively tuning (we've\n * got an active song or a pending song), then any currently active song\n * will be marked as 'completed' and a new song will be requested from\n * the server.\n *\n * Then you tell the session to start maintaining a queue of \n * music to play:\n *\n * session.tune();\n *\n * The session will now emit the following events:\n *\n * music-unavailable: if the current user may not listen to music\n * This check is made every time we try to retrieve a song, and also\n * on the 'tune()' call. Once \n * you get this event, you should assume nothing further will work.\n * invalid-credentials: the token and secret passed to this function\n * are not valid.\n * placement: after we tune in to a placement or station,\n * this passes on information about the placement we\n * tuned in to.\n * stations: after tuning to a specific placement, the server returns a\n * list of available stations. This is that list.\n * station-changed: emitted after a 'setStation' call, and passed the\n * ID of the station and the station object\n * play-active: when the session has a play ready for playback\n * play-started: when the active play has started playback (as\n * a result of a call to reportPlayStarted)\n * play-completed: when the session has successfully told the server\n * that the current play has completed, been skipped (after a \n * call to reportPlayCompleted), or been invalidated\n * skip-denied: when the session has been told by the server that the\n * skip cannot be performed (after a call to requestSkip)\n * plays-exhausted: when the server can find no more music in the\n * current station that satisfies DMCA constraints (this will\n * be either the first event after a 'tune' call, or after a\n * play-completed event). The client must make another call to\n * tune() to begin pulling in more music.\n * prepare-sound: this holds a URL of a sound that might be played\n * next. Clients can start loading the sound in preparation.\n * forbidden: if an unsatisfiable request is made (such as to advance\n * in a non-first play station)\n *\n * Clients that use the session object should tell the session about\n * the status of the current play as it progresses:\n *\n * session.reportPlayStarted(): tell the server we have begun playback of the\n * current song to the end user.\n * session.reportPlayElapsed(seconds): tell the server how many elapsed seconds\n * of the song have been played since it started.\n * session.reportPlayCompleted(): tell the server that we have completed \n * playing the current song. This will cause the session object\n * to emit a 'play-completed' event followed by a 'play-active' when\n * the next song is ready for playback\n *\n * session.requestSkip(): ask the server if we can skip playback of the current\n * song. If the skip is denied, a 'skip-denied' event will be triggered,\n * otherwise a 'play-completed' will be triggered.\n * session.requestInvalidate(): tell the server that we're unable to play the\n * current song for some reason, and the server should stop playback\n * of the song (if started) and give us a new song. The session will\n * trigger a 'play-completed' event after this call.\n *\n * Data held by the session can be retrieved with:\n *\n * session.getActivePlay(): returns the currently active play, if any, or null\n * session.isTuned(): true if the session has active plays available or is awaiting\n * plays from the server\n * session.hasActivePlayStarted(): returns true if the active play is playing now\n * session.canSkip(): returns true if there is a song being played now and \n * we believe we can skip it.\n *\n * Other misc calls:\n * \n * session.likePlay(), session.unlikePlay(), session.dislikePlay(): like handling\n * session.setFormats(formats): comma separated list of audio formats to \n * request, i.e.: 'mp3', 'aac', 'aac,mp3'. Defaults to\n * 'mp3,aac'\n *\n * The optional 'options' argument passed to the constructor can have the following\n * attributes:\n * baseUrl: defines the base host that responds to API calls - defaults\n * to '//feed.fm'. Really only used with local testing.\n * simulcast: id of simulcast to broad\n */\n\nvar Session = function Session(token, secret, options) {\n Object.assign(this, Events); // No token/secret implies we're restoring from a saved state. It would\n // be best if this class could suspend/restore itself, but things are \n // so poorly encapsulated now that it isn't worth putting the suspend/restore\n // in multiple places.\n\n if (!token || !secret) {\n return;\n }\n options = options || {};\n if (options.baseUrl) {\n setBaseUrl(options.baseUrl);\n }\n this.config = {\n remoteLogging: !!options.remoteLogging,\n // token\n // secret\n // placementId\n // placement\n // stationId\n // stations\n // station\n formats: 'mp3,aac',\n maxBitrate: 128,\n timeOffset: 0,\n // Represent the active 'play' or null if there is no active play. This should\n // only be null before the first tune() call or after the server tells us there\n // is no more music available.\n current: null,\n /* {\n play: play object we're currently playing\n started: defaults to false\n canSkip: defaults to false\n retryCount: number of times we've tried to tell server we started this\n }, */\n // Details of any 'POST /play' request we're awaiting a response for. If this\n // is null, then we're not waiting for the server to give us a play\n pendingRequest: null,\n /* {\n url: url being posted to\n ajax: form data we sent to request a play, copied\n here so we can retry it if it fails\n retryCount: number of times we've retried \n }, */\n // Once a play has been created and then started, the server will let us\n // create a new play. This holds a reference to the next play that will\n // be active on completion of the current play\n pendingPlay: null // play object we'll start upon completion of current\n // sound \n };\n if (token && secret) {\n this.setCredentials(token, secret);\n }\n if (options.remoteLogging) {\n log('remote logging enabled', this.config);\n this._submitLogHistory();\n }\n};\nSession.prototype.setCredentials = function (token, secret) {\n this.config.token = token;\n this.config.secret = secret;\n};\nSession.prototype.setStationId = function (stationId, advance, secondsOfCrossfade) {\n // if we haven't received stations, we can't select one\n if (!this.config.stations) {\n return;\n }\n var stringStationId = '' + stationId;\n var changed = '' + this.config.stationId !== stringStationId;\n if (changed || advance) {\n var station = this.config.stations.find(function (station) {\n return '' + station.id === stringStationId;\n });\n if (station) {\n this.config.stationId = stationId;\n this.config.station = station;\n if (changed) {\n this.trigger('station-changed', stationId, station);\n } // abort any pending requests or plays\n\n this.config.pendingRequest = null;\n this.config.pendingPlay = null; // stop playback of any current song, and set\n // the status to waiting\n\n this._assignCurrentPlay(null, true); // request the next play\n\n this._requestNextPlay(0, advance, secondsOfCrossfade);\n }\n }\n};\nSession.prototype.setFormats = function (formats) {\n this.config.formats = formats; // re-retrieve the next song, since we changed formats\n\n if (this.isTuned()) {\n this.tune();\n }\n};\nSession.prototype.setMaxBitrate = function (maxBitrate) {\n this.config.maxBitrate = maxBitrate;\n}; // tune\n\nSession.prototype.tune = function () {\n if (!this.config.token) {\n throw new Error('no token set with setCredentials()');\n }\n if (!this.config.secret) {\n throw new Error('no secret set with setCredentials()');\n } // abort any pending requests or plays\n\n this.config.pendingRequest = null;\n this.config.pendingPlay = null; // stop playback of any current song, and set\n // the status to waiting\n\n this._assignCurrentPlay(null, true); // pull information in about the placement, followed by\n // a request for the next play\n\n this._getDefaultPlacementInformation();\n}; // _getDefaultPlacementInformation\n\nSession.prototype._getDefaultPlacementInformation = function (delay) {\n var self = this;\n if (this.config.placementId && this.config.placement && this.config.placement.id === this.config.placementId) {\n // already have placement info, so kick off request for next play\n this._requestNextPlay();\n return;\n } // request placement info from server\n\n log('requesting default placement information from server');\n self._signedAjax(getBaseUrl() + '/api/v2/session', {\n method: 'POST',\n body: JSON.stringify({\n client_id: getStoredClientId()\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(function (response) {\n return response.json();\n }).then(function (response) {\n if (response.session && response.session.client_id) {\n setStoredClientId(response.session.client_id);\n } // client id creation now tied to session, so this next call is superfluous,\n // and only exists for testing\n\n return self._getClientId().then(function () {\n return response;\n });\n }).then(self._receiveDefaultPlacementInformation.bind(self)).catch(self._failedDefaultPlacementInformation.bind(self, delay));\n};\nSession.prototype._receiveDefaultPlacementInformation = function (placementInformation) {\n if (placementInformation && placementInformation.success && placementInformation.placement) {\n this.config.placement = placementInformation.placement;\n this.config.stations = placementInformation.stations;\n this.config.placementId = placementInformation.placement.id;\n this.trigger('placement', this.config.placement);\n if (this.config.stations.length > 0) {\n this.config.stationId = this.config.stations[0].id;\n this.config.station = this.config.stations[0];\n this.trigger('station-changed', this.config.stationId, this.config.station);\n }\n this.trigger('stations', this.config.stations); // kick off request for next play\n\n this._requestNextPlay();\n } else {\n // music is not available to this user for some reason.\n this.trigger('music-unavailable');\n }\n};\nSession.prototype._failedDefaultPlacementInformation = function (delay, response) {\n var _this = this;\n if (response.status === 401) {\n try {\n var fullResponse = JSON.parse(response.responseText);\n if (fullResponse.error && fullResponse.error.code === 5) {\n this.trigger('invalid-credentials');\n return;\n }\n } catch (e) {// ignore\n }\n } else {\n // eslint-disable-next-line no-console\n console.warn('error from placement request', response);\n } // otherwise, try again in a bit\n\n delay = delay ? delay * 2 : 500;\n setTimeout(function () {\n _this._getDefaultPlacementInformation(delay);\n }, delay);\n};\nSession.prototype.getActivePlacement = function () {\n if (this.config.placement) {\n return this.config.placement;\n } else {\n return null;\n }\n};\nSession.prototype.getActivePlay = function () {\n if (this.config.current) {\n return this.config.current.play;\n } else {\n return null;\n }\n};\nSession.prototype.isTuned = function () {\n return this.config.current || this.config.pendingRequest;\n};\nSession.prototype.hasActivePlayStarted = function () {\n return this.config.current && this.config.current.started;\n};\nSession.prototype.reportPlayStarted = function () {\n if (!this.config.current) {\n throw new Error('attempt to report a play started, but there is no active play');\n }\n this._startPlay(this.config.current.play);\n};\nSession.prototype.reportPlayElapsed = function (seconds) {\n if (!this.config.current) {\n throw new Error('attempt to report elapsed play time, but the play hasn\\'t started');\n }\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + this.config.current.play.id + '/elapse', {\n method: 'POST',\n body: JSON.stringify({\n seconds: seconds\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).catch(function (e) {\n return log('server returned error on elapse call. ignoring', e);\n });\n};\nSession.prototype.reportPlayCompleted = function () {\n if (this.config.current && this.config.current.started) {\n this.pendingComplete = this._signedAjax(getBaseUrl() + '/api/v2/play/' + this.config.current.play.id + '/complete', {\n method: 'POST'\n }).catch(function (err) {\n log('play completed returned error - ignoring', err);\n }).finally(function () {\n log('play completed response sent');\n }); // queue up the next song \n\n if (!this.config.pendingRequest) {\n log('song finished, and no outstanding request, so playing pendingPlay'); // if we're not waiting for an incoming request, then we must\n // have the next play queued up, so play it:\n\n var pendingPlay = this.config.pendingPlay;\n this.config.pendingPlay = null;\n this._assignCurrentPlay(pendingPlay);\n } else {\n log('song finished, but we\\'re still waiting for next one to return'); // we're waiting for a request to come in, so kill the current\n // song and announce that we're waiting\n\n this._assignCurrentPlay(null, true);\n }\n } else {\n log('finish on non-active or playing song');\n throw new Error('no active or playing song');\n }\n};\nSession.prototype._receivePlayCompleted = function () {\n if (!this.config.pendingRequest) {\n log('song finished, and no outstanding request, so playing pendingPlay'); // if we're not waiting for an incoming request, then we must\n // have the next play queued up, so play it:\n\n var pendingPlay = this.config.pendingPlay;\n this.config.pendingPlay = null;\n this._assignCurrentPlay(pendingPlay);\n } else {\n log('song finished, but we\\'re still waiting for next one to return'); // we're waiting for a request to come in, so kill the current\n // song and announce that we're waiting\n\n this._assignCurrentPlay(null, true);\n }\n};\nSession.prototype.reportPlayStopped = function (seconds) {\n if (this.config.current && this.config.current.started) {\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + this.config.current.play.id + '/elapse', {\n method: 'POST',\n body: JSON.stringify({\n seconds: seconds\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(function (response) {\n return response.json();\n }).catch(function (e) {\n return log('server returned error on elapse call. ignoring', e);\n });\n } // dump any future plays queued up\n\n this.config.pendingRequest = null;\n this.config.pendingPlay = null; // we're not playing anything now, baby!\n\n this._assignCurrentPlay(null, true);\n};\nSession.prototype.requestSkip = function () {\n var _this2 = this;\n if (!this.hasActivePlayStarted()) {\n throw new Error('No song playing or started');\n }\n if (!this.config.current.canSkip) {\n setTimeout(function () {\n _this2.trigger('skip-denied');\n }, 1);\n return;\n }\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + this.config.current.play.id + '/skip', {\n method: 'POST'\n }).then(function (response) {\n return response.json();\n }).then(this._receiveSkip.bind(this, this.config.current.play)).catch(this._failSkip.bind(this, this.config.current.play));\n};\nSession.prototype.requestInvalidate = function (url) {\n if (!url) {\n if (!this.config.current) {\n throw new Error('No active song to invalidate!');\n }\n this._sendInvalidate(this.config.current.play);\n } else if (this.config.current && this.config.current.play.audio_file.url === url) {\n this._sendInvalidate(this.config.current.play);\n } else if (this.config.pendingPlay && this.config.pendingPlay.audio_file.url === url) {\n this._sendInvalidate(this.config.pendingPlay);\n }\n};\nSession.prototype._sendInvalidate = function (play, delay) {\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + play.id + '/invalidate', {\n method: 'POST'\n }).then(function (response) {\n return response.json();\n }).then(this._receiveInvalidate.bind(this, play)).catch(this._failInvalidate.bind(this, delay, play));\n};\nSession.prototype._failInvalidate = function (delay, play, response) {\n var self = this;\n delay = delay ? delay * 2 : 200;\n if (delay < 3000) {\n setTimeout(function () {\n self._sendInvalidate(play, delay);\n }, delay);\n } else {\n log('gave up trying to invalidate play', response);\n }\n};\nSession.prototype._receiveInvalidate = function (play, response) {\n var self = this;\n log('invalidate response');\n this._submitLogHistory();\n setTimeout(function () {\n log('5 second follow up after invalidate');\n self._submitLogHistory();\n }, 5000);\n if (!response.success) {\n log('failed invalidate! - technically this is impossible');\n return;\n }\n if (!this.config.current || this.config.current.play !== play) {\n if (play === this.config.pendingPlay) {\n log('invalidated pending play, queueing up new pending play');\n this.config.pendingPlay = null;\n this._requestNextPlay();\n }\n return;\n }\n if (this.config.pendingPlay) {\n log('invalidating to song already queued up'); // skip to play already queued up\n\n var pendingPlay = this.config.pendingPlay;\n this.config.pendingPlay = null;\n this._assignCurrentPlay(pendingPlay);\n } else {\n log('invalidating current song');\n this._assignCurrentPlay(null, true);\n if (!this.config.pendingRequest) {\n log('queueing up new song');\n this._requestNextPlay();\n }\n }\n};\nSession.prototype._failSkip = function (play) {\n if (!this.config.current || this.config.current.play !== play) {\n // not playing this song any more - just ignore it\n return;\n } // technically the skip wasn't denied - we just couldn't confirm wether\n // it was ok, but this is the best we can return at the moment\n\n this.trigger('skip-denied');\n};\nSession.prototype._receiveSkip = function (play, response) {\n if (!this.config.current || this.config.current.play !== play) {\n // not playing this song any more - just ignore it\n return;\n }\n if (!response.success) {\n log('failed skip!');\n this.trigger('skip-denied');\n return;\n }\n if (this.config.pendingPlay) {\n log('skipping to song already queued up'); // skip to play already queued up\n\n var pendingPlay = this.config.pendingPlay;\n this.config.pendingPlay = null;\n this._assignCurrentPlay(pendingPlay);\n } else if (this.config.pendingRequest) {\n log('skipping to what is queued up'); // we're waiting for a request - so just wait for that to show up\n\n this._assignCurrentPlay(null, true);\n } else {\n log('skipping to what is queued up'); // nothing queued up and nothing being requested - we're outta music!\n\n this._assignCurrentPlay(null);\n }\n};\nSession.prototype._startPlay = function (play) {\n var _this3 = this;\n if (this.config.current.retryCount > 2) {\n // fuck it - let the user hear the song\n this._receiveStartPlay(play, {\n success: true,\n can_skip: true\n });\n } else {\n log('telling server we\\'re starting the play', play);\n var request;\n if (this.pendingComplete) {\n request = this.pendingComplete.then(function () {\n return _this3._signedAjax(getBaseUrl() + '/api/v2/play/' + play.id + '/start', {\n method: 'POST' // TODO: add timeout!\n });\n });\n } else {\n // tell the server that we're going to start this song\n request = this._signedAjax(getBaseUrl() + '/api/v2/play/' + play.id + '/start', {\n method: 'POST' // TODO: add timeout!\n });\n }\n request.then(function (response) {\n return response.json();\n }).then(this._receiveStartPlay.bind(this, play)).catch(this._failStartPlay.bind(this, play));\n }\n};\nSession.prototype._receiveStartPlay = function (play, response) {\n if (response.success) {\n if (this.config.current && this.config.current.play === play) {\n this.config.current.canSkip = response.can_skip;\n this.config.current.started = true; // since we're ok to start this song, we can start looking for the\n // next song\n\n this._requestNextPlay();\n this.trigger('play-started', play);\n } else {\n log('received start play, but not waiting any more');\n }\n } else {\n log('received failed start success');\n }\n};\nSession.prototype._failStartPlay = function (play, response) {\n var _this4 = this;\n var self = this;\n log('start failed', response);\n this._submitLogHistory();\n setTimeout(function () {\n log('5 second follow up after start failure');\n self._submitLogHistory();\n }, 5000); // only process if we're still actually waiting for this\n\n if (this.config.current && this.config.current.play === play) {\n if (response && response.status === 403) {\n try {\n var fullResponse = JSON.parse(response.responseText);\n if (fullResponse.error && fullResponse.error.code === 20) {\n // we seem to have missed the response to the original start, so\n // let's assume the start was good and the song is skippable\n return this._receiveStartPlay(play, {\n success: true,\n can_skip: true\n });\n }\n } catch (e) {\n // ignore\n log('unable to parse start play response', e.message);\n }\n }\n log('request failed - trying again in 1 second', response);\n this.config.current.retryCount++; // wait a second and try again\n\n setTimeout(function () {\n _this4._startPlay(play);\n });\n } else {\n log('startPlay failed, but we don\\'t care any more');\n }\n}; // start playing the given song\n\nSession.prototype._assignCurrentPlay = function (play, waitingIfEmpty) {\n // remove any existing play\n if (this.config.current) {\n var currentPlay = this.config.current.play;\n this.config.current = null;\n this.trigger('play-completed', currentPlay);\n }\n if (play === null) {\n // nothing to play right now\n if (waitingIfEmpty) {\n //this.config.status = 'waiting';\n log('nothing to play... waiting');\n } else {\n //this.config.status = 'idle';\n log('nothing to play from the current station');\n this.trigger('plays-exhausted');\n }\n } else {\n // we're starting this song, so note that\n this.config.current = {\n play: play,\n canSkip: false,\n started: false,\n retryCount: 0\n }; //this.config.status = 'active';\n\n log('activated new song');\n this.trigger('play-active', play);\n }\n};\nSession.prototype._requestNextPlay = function (delay, advance, secondsOfCrossfade) {\n var self = this;\n self._getClientId().then(function (clientId) {\n if (self.config.pendingRequest) {\n if (!delay) {\n log('already waiting for a request to finish');\n return;\n } else if (delay > 60000) {\n log('giving up on retrieving next play'); // we already retried this - let's give up\n\n self.config.pendingRequest = null;\n if (self.config.current === null) {\n // we're not playing anything, so we're waiting. \n // set assign play to null again to trigger empty/idle\n self._assignCurrentPlay(null);\n }\n return;\n } else {\n log('retrying pending request'); // retry the request\n\n self.config.pendingRequest.retryCount++;\n var _ajax = self.config.pendingRequest.ajax;\n self._signedAjax(self.config.pendingRequest.url, _ajax).then(function (response) {\n return response.json();\n }).then(self._receiveNextPlay.bind(self, _ajax)).catch(self._failedNextPlay.bind(self, delay, _ajax));\n return;\n }\n } else {\n // create a new request\n var data = {\n formats: self.config.formats,\n client_id: clientId,\n max_bitrate: self.config.maxBitrate,\n secure: true\n };\n if (self.config.placementId) {\n data.placement_id = self.config.placementId;\n }\n if (self.config.stationId) {\n data.station_id = self.config.stationId;\n }\n if (advance) {\n data.at = advance;\n if (secondsOfCrossfade) {\n data.crossfade = secondsOfCrossfade;\n }\n }\n var ajax = {\n method: 'POST',\n body: JSON.stringify(data),\n headers: {\n 'Content-Type': 'application/json'\n }\n };\n self.config.pendingRequest = {\n url: getBaseUrl() + '/api/v2/play',\n ajax: ajax,\n retryCount: 0\n }; // request new play from server\n\n log('requesting new play from server', ajax);\n self._signedAjax(getBaseUrl() + '/api/v2/play', ajax).then(function (response) {\n return response.json();\n }).then(self._receiveNextPlay.bind(self, ajax)).catch(self._failedNextPlay.bind(self, delay, ajax));\n }\n });\n}; // we received a song to play from the server\n\nSession.prototype._receiveNextPlay = function (ajax, response) {\n // only process if we're still actually waiting for this\n if (this.config.pendingRequest && this.config.pendingRequest.ajax === ajax) {\n // this isn't pending any more\n this.config.pendingRequest = null;\n if (response.success) {\n this.trigger('prepare-sound', response.play.audio_file.url, response.play.start_at, response.play.id);\n if (this.config.current) {\n log('received play, but we\\'re already playing, so queueing up', response.play); // play this when the current song is complete\n\n this.config.pendingPlay = response.play;\n } else {\n log('received play and no current song, making active now', response.play); // start playing this right now, since nothing else is playing\n\n this._assignCurrentPlay(response.play);\n }\n } else if (response.error && response.error.code === 9) {\n if (this.config.current) {\n log('ran out of music to play, but we\\'re already playing');\n this.config.pendingPlay = null;\n } else {\n log('ran out of music, and nothing playing now');\n this.trigger('plays-exhausted');\n }\n } else if (response.error && response.error.code === 6) {\n this.trigger('forbidden', response.error.message);\n } else {\n log('unsuccessful response', response);\n }\n } else {\n log('nextPlay succeeded, but we don\\'t care');\n }\n}; // server returned an error when we requested the next song\n\nSession.prototype._failedNextPlay = function (delay, ajax, response) {\n var _this5 = this;\n log('next play failed', response);\n this._submitLogHistory();\n setTimeout(function () {\n log('5 second follow up after next play failure');\n _this5._submitLogHistory();\n }, 5000); // only process if we're still actually waiting for this\n\n if (this.config.pendingRequest && this.config.pendingRequest.ajax === ajax) {\n if (response && response.status === 403) {\n try {\n var fullResponse = JSON.parse(response.responseText);\n if (fullResponse.error && fullResponse.error.code === 19) {\n // user isn't in the US any more, so let the call fail\n this.trigger('music-unavailable', fullResponse.error.message); // legacy:\n\n this.trigger('not-in-us', fullResponse.error.message);\n return;\n }\n } catch (e) {\n // some other response - fall through and try again\n log('problem parsing 403 response', e.message);\n }\n }\n delay = Math.min(delay ? delay * 2 : 500, 2000);\n log('request failed - trying again after ' + delay + 'ms');\n setTimeout(function () {\n _this5._requestNextPlay(delay);\n }, delay);\n } else {\n log('nextPlay failed, but we don\\'t care');\n }\n};\nSession.prototype.canSkipInStation = function () {\n return !(this.config.station && this.config.station.can_skip === false);\n};\n/**\n * @returns {boolean} true if the user can skip the current song\n */\n\nSession.prototype.maybeCanSkip = function () {\n return this.canSkip();\n};\n/**\n * @returns {boolean} true if the user can skip the current song\n */\n\nSession.prototype.canSkip = function () {\n // you can probably skip unless we've explicitly disallowed it at the station or current song level\n var can = this.canSkipInStation() && this.config.current && this.config.current.started && this.config.current.canSkip;\n return !!can;\n};\n/**\n * @returns {boolean} true if the user can like the current song\n */\n\nSession.prototype.canLike = function () {\n var response = !(this.config.station && this.config.station.can_like === false);\n return response;\n};\nSession.prototype.likePlay = function (playId) {\n if (!this.canLike()) {\n // technically, this play could be from a different station, but we're not tracking\n // that right now... so let's just assume it is in the current station.\n return;\n }\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + playId + '/like', {\n method: 'POST'\n }).then(function (response) {\n return response.json();\n }).catch(function (e) {\n return log('server returned error on like call. ignoring', e);\n });\n if (this.config.current && this.config.current.play.id === playId) {\n this.config.current.play.liked = true;\n }\n};\nSession.prototype.unlikePlay = function (playId) {\n if (!this.canLike()) {\n // technically, this play could be from a different station, but we're not tracking\n // that right now... so let's just assume it is in the current station.\n return;\n }\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + playId + '/like', {\n method: 'DELETE'\n }).then(function (response) {\n return response.json();\n }).catch(function (e) {\n return log('server returned error on unlike call. ignoring', e);\n });\n if (this.config.current && this.config.current.play.id === playId) {\n delete this.config.current.play['liked'];\n }\n};\nSession.prototype.dislikePlay = function (playId) {\n if (!this.canLike()) {\n // technically, this play could be from a different station, but we're not tracking\n // that right now... so let's just assume it is in the current station.\n return;\n }\n this._signedAjax(getBaseUrl() + '/api/v2/play/' + playId + '/dislike', {\n method: 'POST'\n }).then(function (response) {\n return response.json();\n }).catch(function (e) {\n return log('server returned error on invalidate call. ignoring', e);\n });\n if (this.config.current && this.config.current.play.id === playId) {\n this.config.current.play.liked = false;\n }\n};\nvar cookieName$1 = 'cid';\nSession.prototype._getStoredCid = function () {\n return tinyCookie.getCookie(cookieName$1);\n};\nSession.prototype._setStoredCid = function (value) {\n tinyCookie.setCookie(cookieName$1, value, {\n expires: 3650,\n path: '/'\n });\n};\nSession.prototype._deleteStoredCid = function () {\n tinyCookie.removeCookie(cookieName$1);\n};\nSession.prototype._sign = function (request) {\n var authorization;\n if (!request) {\n request = {};\n } // use Basic auth for HTTPS\n\n authorization = 'Basic ' + btoa(this.config.token + ':' + this.config.secret);\n if (request.headers) {\n request.headers['Authorization'] = authorization;\n } else {\n request.headers = {\n Authorization: authorization\n };\n }\n request.headers['X-Feed-SDK'] = version + ' js';\n if (this.extraHeaders) {\n for (var header in this.extraHeaders) {\n // eslint-disable-next-line\n if (this.extraHeaders.hasOwnProperty(header)) {\n request.headers[header] = this.extraHeaders[header];\n }\n }\n }\n return request;\n};\nSession.prototype._signedAjax = function (url, request) {\n var self = this;\n return self._ajax(url, self._sign(request)).then(function (response) {\n if (!response.ok) {\n throw new Error('server returned error ' + response.status + ': ' + response.statusText);\n }\n return response;\n });\n};\nSession.prototype._ajax = function (url, request) {\n return fetch(url, request);\n};\nSession.prototype._submitLogHistory = function () {\n var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;\n var session = this;\n var history = log.history;\n log.history = [];\n if (!this.config.remoteLogging) {\n return;\n }\n return this._signedAjax(getBaseUrl() + '/api/v2/session/event', {\n method: 'POST',\n body: JSON.stringify({\n event: 'playerHistory',\n parameters: history\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).then(function (response) {\n return response.json();\n }).catch(function () {\n if (count < 2) {\n setTimeout(function () {\n log.history = history.concat(['failed log report attempt, try #' + count], log.history);\n session._submitLogHistory(count + 1);\n }, 5000);\n }\n });\n};\nSession.prototype._submitLogHistory = function () {\n var count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;\n var session = this;\n var history = log.history;\n log.history = [];\n if (!this.config.remoteLogging) {\n return;\n }\n return this._signedAjax(getBaseUrl() + '/api/v2/session/event', {\n method: 'POST',\n body: JSON.stringify({\n event: 'playerHistory',\n parameters: history\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n }).catch(function () {\n if (count < 2) {\n setTimeout(function () {\n log.history = history.concat(['failed log report attempt, try #' + count], log.history);\n session._submitLogHistory(count + 1);\n }, 5000);\n }\n });\n};\nSession.prototype._submitEvent = function (name, parameters) {\n var _this6 = this;\n var count = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;\n var session = this;\n return this._getClientId().then(function (clientId) {\n return _this6._signedAjax(getBaseUrl() + '/api/v2/session/event', {\n method: 'POST',\n body: JSON.stringify({\n event: name,\n client_id: clientId,\n parameters: JSON.stringify(parameters)\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n }).catch(function () {\n if (count < 2) {\n setTimeout(function () {\n log.history = history.concat(['failed event submission, try #' + count], log.history);\n session._submitLogHistory(count + 1);\n }, 5000);\n }\n });\n};\nSession.prototype._getClientId = function () {\n return getClientId();\n};\n\n/**\n * Test to see if browser supports blob URLs\n * \n * adapted from https://github.com/ssorallen/blob-feature-check/blob/master/blob-feature-check.js\n **/\nvar blobSupport = false;\nfunction fixBinary(bin) {\n var length = bin.length;\n var buf = new ArrayBuffer(length);\n var arr = new Uint8Array(buf);\n for (var i = 0; i < length; i++) {\n arr[i] = bin.charCodeAt(i);\n }\n return buf;\n}\nvar binary = fixBinary(atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGP6DwABBQECz6AuzQAAAABJRU5ErkJggg=='));\nvar png = new Blob([binary], {\n type: 'image/png'\n});\ntry {\n if (URL && URL.createObjectURL) {\n var objectUrl = URL.createObjectURL(png);\n if (/^blob:/.exec(objectUrl) !== null) {\n var img = new Image();\n img.onload = function () {\n blobSupport = true;\n URL.revokeObjectURL(objectUrl);\n };\n img.onerror = function () {\n blobSupport = false;\n };\n img.src = objectUrl;\n }\n }\n} catch (e) {\n /* ignore - no blob support */\n}\nvar hasBlobSupport = function hasBlobSupport() {\n return blobSupport;\n};\nvar DEFAULT_VOLUME = 1.0;\nvar IOS = ['iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone', 'iPod'].includes(navigator.platform) // iPad on iOS 13 detection\n|| navigator.userAgent.includes('Mac') && 'ontouchend' in document;\nvar brokenWebkit = IOS && /OS 13_[543210]/i.test(navigator.userAgent);\nvar SILENCE = IOS ? 'https://dgase5ckewowv.cloudfront.net/feedfm-audio/250-milliseconds-of-silence.mp3' : 'data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA'; //const SILENCE = 'https://dgase5ckewowv.cloudfront.net/feedfm-audio/1573592316-88123.m4a';\n\nvar TIMEUPDATE_PERIOD = window.requestAnimationFrame ? 1.0 : 0;\nvar Sound = function Sound(speaker, options, id, url) {\n var obj = Object.assign(this, Events);\n obj.id = id; //url = url.replace('u9e9h7z5.map2.ssl.hwcdn.net', 's3.amazonaws.com');\n\n obj.url = url;\n obj.speaker = speaker;\n obj.loaded = false;\n if (options) {\n this.startPosition = +options.startPosition;\n this.endPosition = +options.endPosition;\n this.fadeInSeconds = +options.fadeInSeconds;\n if (this.fadeInSeconds) {\n this.fadeInStart = this.startPosition ? this.startPosition / 1000 : 0;\n this.fadeInEnd = this.fadeInStart + this.fadeInSeconds;\n } else {\n this.fadeInStart = 0;\n this.fadeInEnd = 0;\n }\n this.fadeOutSeconds = +options.fadeOutSeconds;\n if (this.fadeOutSeconds) {\n if (this.endPosition) {\n this.fadeOutStart = this.endPosition / 1000 - this.fadeOutSeconds;\n this.fadeOutEnd = this.endPosition / 1000;\n } else {\n this.fadeOutStart = 0;\n this.fadeOutEnd = 0;\n }\n }\n for (var _i = 0, _arr = ['play', 'pause', 'finish', 'elapse']; _i < _arr.length; _i++) {\n var ev = _arr[_i];\n if (ev in options) {\n obj.on(ev, options[ev]);\n }\n }\n this.gain = options.gain || 0;\n } else {\n this.gain = 0;\n }\n return obj;\n};\nfunction d(audio) {\n return ' src = ' + audio.src + ', time = ' + audio.currentTime + ', paused = ' + audio.paused + ', duration = ' + audio.duration + ', readyState = ' + audio.readyState;\n}\nSound.prototype = {\n play: function play() {\n log('sound ' + this.id + ' play');\n return this.speaker._playSound(this);\n },\n // pause playback of the current sound clip\n pause: function pause() {\n log('sound ' + this.id + ' pause');\n return this.speaker._pauseSound(this);\n },\n // resume playback of the current sound clip\n resume: function resume() {\n log('sound ' + this.id + ' resume');\n return this.speaker._playSound(this);\n },\n // elapsed number of milliseconds played\n position: function position() {\n //log(this.id + ' sound position');\n return this.speaker._position(this);\n },\n // duration in milliseconds of the song\n // (this may change until the song is full loaded)\n duration: function duration() {\n //log(this.id + ' sound duration');\n return this.speaker._duration(this);\n },\n // stop playing the given sound clip, unload it, and disable events\n // note that no further events will be sent from this sound\n // (so no 'finish' event, in particular)\n destroy: function destroy(fadeOut) {\n log('sound ' + this.id + ' destroy' + (fadeOut ? ' (with fade)' : ''));\n this.speaker._destroySound(this, fadeOut);\n },\n gainAdjustedVolume: function gainAdjustedVolume(volume) {\n if (!this.gain) {\n return volume / 100;\n }\n var adjusted = Math.max(Math.min(volume / 100 * (50 * Math.pow(10, this.gain / 20)), 100), 0) / 100; //log('gain adjustment is ' + this.gain + ', and final adjusted volume is ' + adjusted);\n\n return adjusted;\n }\n};\n/**\n * Create new speaker object. Add event handling to it.\n * \n * @returns Speaker\n */\n\nvar Speaker = function Speaker(options) {\n if (options && options.maxRetries) {\n this.maxRetries = options.maxRetries;\n }\n return Object.assign(this, Events);\n}; // exports with this version of Javacript isn't working, so...\n\nSpeaker.IOS = IOS;\nSpeaker.brokenWebkit = brokenWebkit;\nfunction createAudioContext() {\n var AudioCtor = window.AudioContext || window.webkitAudioContext;\n var desiredSampleRate = 44100;\n var context = new AudioCtor(); // Check if hack is necessary. Only occurs in iOS6+ devices\n // and only when you first boot the iPhone, or play a audio/video\n // with a different sample rate\n\n if (context.sampleRate !== desiredSampleRate) {\n var buffer = context.createBuffer(1, 1, desiredSampleRate);\n var dummy = context.createBufferSource();\n dummy.buffer = buffer;\n dummy.connect(context.destination);\n dummy.start(0);\n dummy.disconnect();\n context.close(); // dispose old context\n\n context = new AudioCtor();\n } // despite being in the moz docs, this doesn't work:\n // if (context.state !== 'running') {\n // throw new Error('Initial playback was not started in response to a user interaction!', context.state);\n // }\n\n return context;\n}\nSpeaker.prototype = {\n vol: 100,\n // 0..100\n outstandingSounds: {},\n // Sound instances that have not yet been destroyed\n audioContext: null,\n // for mobile safari volume adjustment\n active: null,\n // active audio element, sound, and gain node\n fading: null,\n // fading audio element, sound, and gain node\n preparing: null,\n // preparing audio element, sound, and gain node\n responses: null,\n // array of response headers from preloading\n maxRetries: 10,\n // max number of times to retry preloading a song\n // each of the above look like:\n // {\n // audio: an HTML Audio element (created during initializeAudio() and reused)\n // sound: refers to Sound object whose URL has been assigned to 'audio.src' and\n // audio.play() has successfully returned.\n // gain: AudioGainNode for apple\n // volume: relative volume of this sound (0..1),\n // canplaythrough: boolean indicating if the 'canplaythrough' event has been\n // triggered for this URL\n // }\n //\n // note that when audio.src is not SILENCE, and sound is null, we're waiting for\n // a return from audio.play(). If the audio.src is changed, or audio.pause() is called\n // before audio.play() returns, chrome will throw an error!\n //\n // When a sound is started, it is thrown into preparing.audio.src, then 'preparing' and\n // 'active' are swapped, then active.audio.play() is called.\n //\n // When a sound has completed playback or been destroyed, the sound property is set\n // to null, the audio is paused, and audio.src is set to SILENCE.\n // If the browser supports URL.objectToURL(), we try to load audio with fetch and\n // then pass the blob URL to the audio element.\n preloaded: null,\n /*\n { \n url, // url we are trying to load manually (will not be null)\n blobUrl: null // blob url for URL above, or null if not loaded yet\n },\n */\n // Fallback for preloading if the browser does not support URL.objectToURL()\n prepareWhenReady: null,\n // { url, start }\n initializeAudio: function initializeAudio() {\n // On mobile devices, we need to kick off playback of a sound in\n // response to a user event. This does that.\n if (this.active === null) {\n log('initializing for mobile');\n try {\n throw new Error('initialize check');\n } catch (e) {\n log('initialize audio called from', e);\n }\n this.audioContext = createAudioContext();\n this.active = this._createAudio(SILENCE);\n this.fading = this._createAudio(SILENCE);\n var pwr = this.prepareWhenReady;\n if (pwr) {\n this.preparing = this._createAudio(pwr.url);\n this._prepare(pwr.url, pwr.startPosition);\n } else {\n this.preparing = this._createAudio(SILENCE);\n }\n } else {\n log('mobile already initialized');\n }\n },\n getSupportedFormats: function getSupportedFormats() {\n if (document.createElement('audio').canPlayType('audio/aac')) {\n return 'mp3,aac';\n } else {\n return 'mp3';\n }\n },\n _createAudioGainNode: function _createAudioGainNode(audio) {\n var source = this.audioContext.createMediaElementSource(audio);\n var gainNode = this.audioContext.createGain();\n gainNode.gain.value = DEFAULT_VOLUME;\n source.connect(gainNode);\n gainNode.connect(this.audioContext.destination);\n return gainNode.gain;\n },\n _createAudio: function _createAudio(url) {\n var DEFAULT_VOLUME = 1.0;\n var audio = new Audio(url);\n audio.crossOrigin = 'anonymous';\n audio.loop = false;\n audio.preload = 'auto';\n audio.volume = DEFAULT_VOLUME;\n this._addEventListeners(audio); // apple volume adjustment\n\n var gain = null;\n if (Speaker.IOS && !brokenWebkit) {\n gain = this._createAudioGainNode(audio);\n }\n return {\n audio: audio,\n sound: null,\n gain: gain,\n volume: DEFAULT_VOLUME,\n canplaythrough: false\n };\n },\n _addEventListeners: function _addEventListeners(audio) {\n audio.addEventListener('pause', this._onAudioPauseEvent.bind(this));\n audio.addEventListener('ended', this._onAudioEndedEvent.bind(this));\n audio.addEventListener('error', this._onAudioErroredEvent.bind(this));\n audio.addEventListener('timeupdate', this._onAudioTimeUpdateEvent.bind(this));\n audio.addEventListener('canplaythrough', this._onAudioCanPlay.bind(this));\n audio.addEventListener('canplay', function (event) {\n log('can play!', event.currentTarget.src);\n }); //this._debugAudioObject(audio);\n },\n _onAudioCanPlay: function _onAudioCanPlay(event) {\n var audio = event.currentTarget;\n if (audio.src === SILENCE) {\n return;\n }\n log('can play through!', audio.src);\n if (audio === this.preparing.audio) {\n log('preparing file can play through', audio.src);\n this.preparing.canplaythrough = true;\n this.trigger('prepared', audio.src, true);\n }\n },\n _onAudioPauseEvent: function _onAudioPauseEvent(event) {\n var audio = event.currentTarget;\n if (audio.src === SILENCE) {\n return;\n }\n if (audio !== this.active.audio || audio.currentTime === audio.duration) {\n return;\n }\n if (!this.active.sound) {\n log('active audio pause, but no matching sound');\n return;\n }\n this.active.sound.trigger('pause');\n },\n _onAudioEndedEvent: function _onAudioEndedEvent(event) {\n var audio = event.currentTarget;\n if (audio.src === SILENCE) {\n return;\n }\n if (audio === this.fading.audio) {\n revoke(audio);\n audio.src = SILENCE;\n this.fading.sound = null;\n return;\n }\n if (audio !== this.active.audio) {\n return;\n }\n if (!this.active.sound) {\n log('active audio ended, but no matching sound', audio.src);\n return;\n }\n log('active audio ended');\n var sound = this.active.sound;\n this.active.sound = null;\n sound.trigger('finish');\n },\n _onAudioErroredEvent: function _onAudioErroredEvent(event) {\n var audio = event.currentTarget;\n if (audio.src === SILENCE) {\n return;\n }\n if (audio === this.fading.audio) {\n revoke(audio);\n audio.src = SILENCE;\n this.fading.sound = null;\n return;\n }\n if (audio !== this.active.audio) {\n return;\n }\n if (!this.active.sound) {\n log('active audio errored, but no matching sound', audio.src);\n return;\n }\n log('active audio errored', event.error);\n var sound = this.active.sound;\n this.active.sound = null;\n sound.trigger('finish', event.error);\n },\n _onAudioTimeUpdateEvent: function _onAudioTimeUpdateEvent(event) {\n var _this = this;\n var audio = event.currentTarget;\n if (audio.src === SILENCE) {\n return;\n }\n if (audio === this.fading.audio && this.fading.sound) {\n if (this.fading.sound.endPosition && audio.currentTime >= this.fading.sound.endPosition / 1000) {\n this.fading.sound = null;\n revoke(this.fading.audio);\n this.fading.audio.src = SILENCE;\n } else {\n this._setVolume(this.fading);\n }\n return;\n }\n if (audio !== this.active.audio) {\n return;\n }\n if (!this.active.sound || this.active.sound.awaitingPlayResponse) {\n // got an elapse event before the play() succeeded\n return;\n }\n var currentTime = audio.currentTime;\n var endPositionSeconds = this.active.sound.endPosition / 1000;\n if (this.active.sound.endPosition && currentTime >= endPositionSeconds - TIMEUPDATE_PERIOD) {\n if (currentTime < endPositionSeconds && !this.active.audio.paused) {\n // we're not quite there yet - use requestAnimationFrame to get as close as possible\n window.requestAnimationFrame(function () {\n return _this._onAudioTimeUpdateEvent({\n currentTarget: audio\n });\n });\n return;\n } // song reached end of play\n\n var sound = this.active.sound;\n this.active.sound = null;\n revoke(this.active.audio);\n this.active.audio.src = SILENCE;\n sound.trigger('finish');\n } else if (this.active.sound.fadeOutEnd && currentTime >= this.active.sound.fadeOutStart - TIMEUPDATE_PERIOD) {\n if (currentTime < this.active.sound.fadeOutStart && !this.active.audio.paused) {\n // we're not quite there yet - use requestAnimationFrame to get as close as possible\n window.requestAnimationFrame(function () {\n return _this._onAudioTimeUpdateEvent({\n currentTarget: audio\n });\n });\n return;\n } // song hit start of fade out\n\n this._setVolume(this.active); // active becomes fading, and fading becomes active\n\n var fading = this.fading;\n this.fading = this.active;\n this.active = fading;\n this.active.sound = null; // not used any more\n // pretend the song finished\n\n this.fading.sound.trigger('finish');\n } else {\n this._setVolume(this.active);\n this.active.sound.trigger('elapse');\n }\n if (this.prepareWhenReady) {\n // we've got something we want to load. check if we've loaded \n // enough of the current song that we can start loading next song.\n this.prepare(this.prepareWhenReady.url, this.prepareWhenReady.startPosition);\n }\n },\n _setVolume: function _setVolume(audioGroup, sound) {\n if (!sound) {\n sound = audioGroup.sound;\n }\n var currentTime = audioGroup.audio.currentTime;\n var currentVolume = audioGroup.volume;\n var calculatedVolume = sound.gainAdjustedVolume(this.vol);\n if (sound.fadeInStart !== sound.fadeInEnd && currentTime < sound.fadeInStart) {\n calculatedVolume = 0;\n log('pre-fade-in volume is 0');\n } else if (sound.fadeInStart !== sound.fadeInEnd && currentTime >= sound.fadeInStart && currentTime <= sound.fadeInEnd) {\n // ramp up from 0 - 100%\n calculatedVolume = (currentTime - sound.fadeInStart) / (sound.fadeInEnd - sound.fadeInStart) * calculatedVolume;\n log('ramping â–² volume', {\n currentTime: currentTime,\n currentVolume: currentVolume,\n calculatedVolume: calculatedVolume,\n sound: sound\n });\n } else if (sound.fadeOutStart !== sound.fadeOutEnd && currentTime > sound.fadeOutEnd) {\n calculatedVolume = 0;\n log('post-fade-out volume is 0');\n } else if (sound.fadeOutStart !== sound.fadeOutEnd && currentTime >= sound.fadeOutStart && currentTime <= sound.fadeOutEnd) {\n // ramp down from 100% to 0\n calculatedVolume = (1 - (currentTime - sound.fadeOutStart) / (sound.fadeOutEnd - sound.fadeOutStart)) * calculatedVolume;\n log('ramping â–¼ volume', {\n currentTime: currentTime,\n currentVolume: currentVolume,\n calculatedVolume: calculatedVolume,\n sound: sound\n });\n }\n if (currentVolume !== calculatedVolume) {\n if (Speaker.IOS) {\n if (!brokenWebkit) {\n audioGroup.gain.value = calculatedVolume;\n }\n } else {\n audioGroup.audio.volume = calculatedVolume;\n }\n audioGroup.volume = calculatedVolume;\n }\n },\n _debugAudioObject: function _debugAudioObject(object) {\n var events = ['abort', 'load', 'loadend', 'loadstart', 'loadeddata', 'loadedmetadata', 'canplay', 'canplaythrough', 'seeked', 'seeking', 'stalled', 'timeupdate', 'volumechange', 'waiting', 'durationchange', 'progress', 'emptied', 'ended', 'play', 'pause', 'error'];\n var speaker = this;\n for (var i = 0; i < events.length; i++) {\n object.addEventListener(events[i], function (event) {\n var audio = event.currentTarget;\n var name = audio === speaker.active.audio ? 'active' : audio === speaker.preparing.audio ? 'preparing' : 'fading';\n log(name + ': ' + event.type);\n log(' active: ' + d(speaker.active.audio));\n log(' preparing: ' + d(speaker.preparing.audio));\n log(' fading: ' + d(speaker.fading.audio));\n if (audio.src === SILENCE) {\n return;\n }\n });\n }\n },\n // Create and return new sound object. This throws the song into\n // the preparing audio instance.\n create: function create(url, optionsAndCallbacks) {\n var id = uniqueId('feed-play-');\n var sound = new Sound(this, optionsAndCallbacks, id, url);\n log('created play ' + id + ' (' + url + ')', optionsAndCallbacks);\n this.outstandingSounds[sound.id] = sound; // start loading sound, if we can\n //this.prepare(url, optionsAndCallbacks.startPosition);\n\n return sound;\n },\n /**\n * This function checks to see if we can prepare the given audio. \n * If it believes we can, it calls _prepare to put the audio in the\n * prepared audio element and actually prepare it. If it doesn't \n * believe we can, it makes a note of what we want prepared.\n * \n * @param {string} url \n * @param {number} startPosition?\n * @returns true if the song is already loaded up and ready to play\n */\n prepare: function prepare(url) {\n var startPosition = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n if (!this.active || !this.active.audio) {\n if (hasBlobSupport()) {\n log('pre-loading audio', {\n url: url\n });\n return this._preload(url);\n } else {\n log('saving url to prepare when audio is initialized', {\n url: url,\n startPosition: startPosition\n });\n this.prepareWhenReady = {\n url: url,\n startPosition: startPosition\n };\n return false;\n }\n }\n var ranges = this.active.audio.buffered;\n var range = ranges.length > 0 && ranges.end(ranges.length - 1);\n if (range >= this.active.audio.duration) {\n log('active song has loaded enough, so preparing', url);\n if (hasBlobSupport()) {\n return this._preload(url);\n } else {\n return this._prepare(url, startPosition);\n }\n } else if (this.active.audio.src === SILENCE) {\n log('preparing over silence');\n if (hasBlobSupport()) {\n return this._preload(url);\n } else {\n return this._prepare(url, startPosition);\n }\n } // still loading primary audio - so hold off for now\n\n log('still loading primary, so waiting to do active prepare', {\n activeUrl: this.active.audio.src,\n range: range\n });\n this.prepareWhenReady = {\n url: url,\n startPosition: startPosition\n };\n return false;\n },\n /* eslint-disable no-console */\n logState: function logState(label) {\n // local testing:\n console.group('speaker: ' + (label || ''));\n if (!this.active) {\n console.group('active');\n console.log('uninitialized');\n console.groupEnd();\n console.group('preparing');\n console.log('uninitialized');\n console.groupEnd();\n console.group('fading');\n console.log('uninitialized');\n console.groupEnd();\n } else {\n console.group('active');\n console.log(\"audio.src: \".concat(this.active.audio.src));\n console.log(\"audio.paused: \".concat(this.active.audio.paused));\n console.log(\"sound: \".concat(this.active.sound ? this.active.sound.id : 'NULL'));\n console.log(\"volume: \".concat(this.active.volume));\n console.groupEnd();\n console.group('preparing');\n console.log(\"audio.src: \".concat(this.preparing.audio.src));\n console.log(\"audio.paused: \".concat(this.preparing.audio.paused));\n console.log(\"sound: \".concat(this.preparing.sound ? this.preparing.sound.id : 'NULL'));\n console.log(\"volume: \".concat(this.preparing.volume));\n console.groupEnd();\n console.group('fading');\n console.log(\"audio.src: \".concat(this.fading.audio.src));\n console.log(\"audio.paused: \".concat(this.fading.audio.paused));\n console.log(\"sound: \".concat(this.fading.sound ? this.fading.sound.id : 'NULL'));\n console.log(\"volume: \".concat(this.fading.volume));\n console.groupEnd();\n }\n console.group('outstanding sounds');\n for (var id in this.outstandingSounds) {\n var play = this.outstandingSounds[id];\n console.log(play.id + ': ' + play.url);\n }\n console.groupEnd();\n console.groupEnd();\n },\n /** \n * This function tries to fetch the given URL and convert it\n * into a blob url. If the URL is already loaded up, this\n * returns true.\n * \n * @param {string} url url to load into memory\n * @returns true if the url is already loaded up\n **/\n _preload: function _preload(url) {\n log('preloading!');\n this.prepareWhenReady = null;\n if (this.preloaded) {\n if (this.preloaded.url === url) {\n // true when already loaded up\n var preloaded = !!this.preloaded.blobUrl;\n log('preloading', {\n url: url,\n preloaded: preloaded\n });\n return preloaded;\n }\n if (this.preloaded.blobUrl) {\n log('revoking previously loaded url', {\n url: this.preloaded.url\n }); // unload previous blob\n\n URL.revokeObjectURL(this.preloaded.blobUrl);\n this.preloaded = null;\n }\n }\n this.preloaded = {\n url: url,\n blobUrl: null,\n responses: []\n };\n this._fetch(url, this.preloaded.responses);\n return false;\n },\n _fetch: function _fetch(url, responses) {\n var _this2 = this;\n var attempt = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;\n log(\"preload attempt #\".concat(attempt), {\n url: url\n });\n var response = {\n start: new Date().toString()\n };\n responses.push(response);\n var retry = function retry() {\n if (!_this2.preloaded || _this2.preloaded.url !== url) {\n log('preload abandoning retry because we have moved on', {\n url: url\n });\n return;\n }\n if (attempt > _this2.maxRetries) {\n log('preload failed to fetch', {\n url: url,\n responses: responses\n });\n _this2.preloaded = null;\n _this2.trigger('prepared', url, false, responses);\n return;\n }\n setTimeout(function () {\n return _this2._fetch(url, responses, attempt + 1);\n }, Math.min(Math.pow(10, attempt), 10000));\n };\n log('preloading', {\n url: url,\n responses: responses\n }); // stress test:\n // const extra = (Math.random() < 0.7) ? '-extrajunkj' : '';\n\n fetch(url\n /* + extra */).then(function (res) {\n log('preload got response');\n response.end = new Date().toString();\n response.status = res.status;\n response.text = res.statusText;\n response.headers = _toConsumableArray(res.headers.entries()); // if res.type == 'opaque', could cause problems\n\n if (res.type === 'opaque') {\n log('preload opaque response, so retrying');\n response.name = 'OpaqueResponse';\n response.message = 'Browser returned oaque response';\n retry();\n return;\n }\n if (!res.ok) {\n log('preload fetch error - retrying');\n retry();\n return;\n }\n res.blob().then(function (blob) {\n log('preload got blob');\n if (_this2.preloaded && _this2.preloaded.url === url) {\n log('preloaded', {\n url: url\n });\n var properMimeTypeBlob = new Blob([blob], {\n type: 'audio/mpeg'\n });\n _this2.preloaded.blobUrl = URL.createObjectURL(properMimeTypeBlob);\n _this2.trigger('prepared', url, true, responses);\n } else {\n // finished retrieving file, but nobody cares any more\n log('preload retrieved url, but nobody cares any more');\n }\n }).catch(function (err) {\n log('preload error blobbing', err, err.name, err.message);\n response.name = err.name;\n response.message = err.message;\n retry();\n });\n }).catch(function (err) {\n log('preload error', err, err.name, err.message); // connectivity error \n\n response.end = new Date().toString();\n response.name = err.name;\n response.message = err.message;\n retry();\n });\n },\n /**\n * This function puts the given URL into the prepared audio element and tells\n * the browser to advance to the given start position.\n * \n * @param {*} url \n * @param {*} startPosition \n * @returns true if the song is already loaded up and ready to play\n */\n _prepare: function _prepare(url, startPosition) {\n // empty out any pending request\n this.prepareWhenReady = null;\n if (!url) {\n return false;\n }\n if (this.preparing && this.preparing.audio.src === url && this.preparing.canplaythrough) {\n log('play already prepared!'); // song is already prepared!\n\n return true;\n }\n if (this.preparing.audio.src !== url) {\n log('preparing', url);\n if (this.preparing.audio.playing) {\n this.preparing.audio.pause();\n }\n this.preparing.canplaythrough = false;\n revoke(this.preparing.audio);\n this.preparing.audio.src = url;\n }\n if (startPosition && this.preparing.audio.currentTime !== startPosition) {\n log('advancing preparing audio to', startPosition / 1000);\n this.preparing.audio.currentTime = startPosition / 1000;\n }\n return false;\n },\n /*\n * Kick off playback of the requested sound.\n */\n _playSound: function _playSound(sound) {\n var _this3 = this;\n var speaker = this;\n if (!this.active || !this.active.audio) {\n // eslint-disable-next-line\n console.error('**** player.initializeAudio() *** not called before playback!');\n return;\n }\n if (this.active.sound === sound) {\n if (this.active.audio.paused) {\n log(sound.id + ' was paused, so resuming'); // resume playback\n\n this.active.audio.play().then(function () {\n log('resumed playback');\n sound.trigger('play');\n }).catch(function (e) {\n log('error resuming playback', e.name, e.message, e.stack, sound.id);\n speaker.active.sound = null;\n sound.trigger('finish');\n });\n if (this.fading.sound) {\n this.fading.audio.play().then(function () {\n log('resumed fading playback');\n }).catch(function (e) {\n log('error resuming fading playback', e.name, e.message, e.stack, sound.id);\n speaker.fading.sound = null;\n revoke(speaker.fading.audio);\n speaker.fading.audio.src = SILENCE;\n });\n }\n } else {\n log(sound.id + ' is already playing');\n }\n return;\n }\n if (this.preloaded && this.preloaded.url === sound.url && this.preloaded.blobUrl) {\n log(sound.id + ' using preloaded audio', this.preloaded);\n if (this.preparing.audio.playing) {\n this.preparing.audio.pause();\n }\n sound.responses = this.preloaded.responses;\n revoke(this.preparing.audio);\n this.preparing.audio.src = this.preloaded.blobUrl;\n this.preparing.canplaythrough = true;\n this.preloaded = null;\n } else if (this.preparing.audio.src !== sound.url) {\n // hopefully, by this time, any sound that was destroyed before its\n // play() call completed has actually completed its play call. Otherwise\n // this will trigger an exception in the play preparation.\n this._prepare(sound.url, sound.startPosition);\n } // swap prepared -> active\n\n var active = this.active;\n this.active = this.preparing;\n this.preparing = active;\n this.preparing.canplaythrough = false;\n revoke(this.preparing.audio);\n this.preparing.audio.src = SILENCE; // don't throw sound object in active until playback starts (below)\n\n this.active.sound = null;\n this._setVolume(this.active, sound); // notify clients that whatever was previously playing has finished\n\n if (this.preparing.sound) {\n var finishedSound = this.preparing.sound;\n this.preparing.sound = null;\n finishedSound.trigger('finish');\n }\n sound.awaitingPlayResponse = true;\n this.active.sound = sound;\n var me = this.active;\n var attempt = 1;\n var play = function play() {\n log(sound.id + ' initiating play()', {\n attempt: attempt\n });\n _this3.active.audio.play().then(function () {\n delete sound.awaitingPlayResponse;\n if (!speaker.outstandingSounds[sound.id]) {\n log(sound.id + ' play() succeeded, but sound has been destroyed'); // this sound was killed before playback began - make sure to stop it\n\n if (me.audio && me.audio.src === sound.url) {\n log(sound.id + ' being paused and unloaded');\n me.audio.pause();\n revoke(me.audio);\n me.audio.src = SILENCE;\n }\n return;\n }\n log(sound.id + ' play() succeeded'); // configure fade-out now that metadata is loaded\n\n if (sound.fadeOutSeconds && sound.fadeOutEnd === 0) {\n sound.fadeOutStart = me.audio.duration - sound.fadeOutSeconds;\n sound.fadeOutEnd = me.audio.duration;\n }\n if (sound.startPosition) {\n log('updating start position');\n me.audio.currentTime = sound.startPosition / 1000;\n log('updated');\n }\n var paused = me.audio.paused;\n sound.trigger('play');\n if (me.pauseAfterPlay) {\n me.audio.pause();\n } else if (paused) {\n sound.trigger('pause');\n }\n }).catch(function (error) {\n log('error starting playback with sound ' + sound.id, {\n name: error.name,\n message: error.message,\n attempt: attempt\n });\n if (attempt < 4) {\n attempt++;\n setTimeout(play, 10);\n } else {\n sound.trigger('finish', error);\n }\n });\n };\n play();\n },\n _destroySound: function _destroySound(sound) {\n var fadeOut = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n sound.off();\n if (this.active && this.active.sound === sound) {\n if (!fadeOut || !sound.fadeOutSeconds) {\n log('destroy triggered for current sound (no fadeout)', sound.id);\n this.active.audio.pause();\n revoke(this.active.audio);\n this.active.audio.src = SILENCE;\n } else {\n log('destroy triggered for current sound (with fadeout)', sound.id);\n var audio = this.active.audio;\n sound.fadeOutStart = audio.currentTime;\n if (sound.endPosition) {\n sound.fadeOutEnd = Math.min(audio.currentTime + sound.fadeOutSeconds, sound.endPosition / 1000);\n sound.endPosition = Math.min(sound.fadeOutEnd * 1000, sound.endPosition);\n } else {\n sound.fadeOutEnd = audio.currentTime + sound.fadeOutSeconds;\n sound.endPosition = sound.fadeOutEnd * 1000;\n } // song hit start of fade out\n\n this._setVolume(this.active); // active becomes fading, and fading becomes active\n\n var fading = this.fading;\n this.fading = this.active;\n this.active = fading;\n this.active.sound = null; // not used any more \n }\n } else {\n log('destroy triggered for inactive sound', sound.id); // if (this.active && (this.active.audio.sound === sound)) {\n // We're destroying the active sound, but it hasn't completed its play()\n // yet (indicated by this.active.sound === sound), so we can't pause it\n // here. When the play does complete, it will notice it isn't in the \n // outstandingSounds map and it will pause itself\n // }\n }\n delete this.outstandingSounds[sound.id];\n },\n flush: function flush() {\n // destroy all outstanding sound objects\n for (var id in this.outstandingSounds) {\n this.outstandingSounds[id].destroy();\n }\n },\n _pauseSound: function _pauseSound(sound) {\n if (this.active && sound === this.active.sound) {\n if (sound.awaitingPlayResponse) {\n // wait for the play() call to complete before pausing, otherwise\n // we'll get an exception\n this.active.pauseAfterPlay = true;\n } else {\n this.active.audio.pause();\n }\n }\n if (this.fading && this.fading.audio) {\n this.fading.audio.pause();\n }\n },\n _position: function _position(sound) {\n if (this.active && sound === this.active.sound) {\n return Math.floor(this.active.audio.currentTime * 1000);\n } else {\n return 0;\n }\n },\n _duration: function _duration(sound) {\n if (sound === this.active.sound) {\n var durationRounded = isNaN(this.active.audio.duration) ? 0 : Math.round(this.active.audio.duration);\n return durationRounded * 1000;\n } else {\n return 0;\n }\n },\n // set the volume (0-100)\n setVolume: function setVolume(value) {\n if (typeof value !== 'undefined') {\n this.vol = value;\n if (this.active && this.active.sound) {\n this._setVolume(this.active);\n }\n this.trigger('volume', value);\n }\n return this.vol;\n },\n getVolume: function getVolume() {\n return this.vol;\n }\n};\nfunction revoke(audio) {\n if (audio.src.slice(0, 4) === 'blob') {\n log('revoking', {\n url: audio.src\n });\n URL.revokeObjectURL(audio.src);\n }\n} // add events to speaker class\n\nObject.assign(Speaker.prototype, Events);\n\n/*\n * Feed Media Player\n *\n * This class requests and plays audio files from the feed servers. It\n * makes use of the Session class to communicate with the server. There\n * should technically only ever be one instance of this class in a page.\n * This class does no UI - that should be handled by Feed.PlayerView \n * or similar.\n *\n * Create this with:\n * player = new Feed.Player(token, secret[, options])\n *\n * options can be:\n * debug: false, // when true, display console logging statements\n * remoteLogging: false // when true, failed play starts or errors will cause the\n * // last 500 log entries from the player to be sent to\n * // feed.fm to assist with debugging.\n * trimming: true, // when true, song start/end trims will be honored\n * crossfadeIn: false, // when true, songs do not fade in - they start at full volume\n * normalizeVolume: true, // automatically adjust volume of songs in station to be at same approx loudness\n * secondsOfCrossfade: 0 // number of seconds to crossfade songs during song transitions (note: this might be\n * // overidden by the server)\n * simulcast: 'uuid' // id to announce music playback on, for simulcast listeners\n * maxRetries: 6 // max number of times to retry retrieving a song before giving up\n * resumable: true // when true, playback can be resumed after a page refresh with Feed.resumable();\n *\n * In response to a user-interaction event, and before you begin any\n * music playback, be sure to call:\n *\n * player.initializeAudio();\n *\n * That will ensure the library has permission from the browser to play\n * audio.\n * \n * To retrieve a list of available stations, register for the 'stations' event,\n * and then call `player.tune()`:\n * \n * player.on('stations', function(stations) {\n * console.log('available stations', stations);\n * });\n * player.tune();\n * \n * or use the promise returned from `player.tune()`:\n *\n * let stations = await player.tune();\n *\n * Then control playback with:\n *\n * play() - start playing the current placement/station or resume the current song\n * pause() - pause playback of the current song, if any\n * like() - tell the server we like this song\n * unlike() - tell the server to remove the 'like' for this song\n * dislike() - tell the server we dislike this song, and skip to the next one\n * skip() - request to skip the current song\n * setStationId(id [, fade]) - switch to a different station. Optionally set 'fade' to true to\n * crossfade playback to the new station. This has a side effect of triggering\n * a 'station-changed' event.\n * setStationId(id, advanceTo) - switch to station with id `id`, and begin playback of that\n * station at `advanceTo` seconds from the start of the station. This only works for first play\n * or single play stations, and will trigger an error for other stations.\n * setVolume(xxx) - adjust music volume (0-100)\n * getVolume() - retrieve music volume (0-100)\n *\n * player has a current state that can be queried with 'getCurrentState()':\n * uninitialized - player is still trying to initialize\n * unavailable - no music is available\n * idle - ready for playback, not playing anything\n * playing - if session.hasActivePlayStarted() and we're not paused\n * paused - if session.hasActivePlayStarted() and we're paused\n * \n * events emitted by the player:\n * station-changed - the current station from which music is pulled has changed.\n * this is triggered in response to a \n * stations - this is triggered after a call to `tune()`, and passes the event handler an\n * array of all stations available for playback. Alterntively, the\n * `getStations()` method returns a promise that resolves to the same\n * value.\n * music-unavailable - user isn't located in the US and can't play music\n * play-started - this play has begun playback. The event handler is passed a \n * 'play' object with song metadata. If the event was triggered\n * via a `Feed.resumable().tune()` call, then a second argument\n * of `true` will be passed to the event handler.\n * play-paused - the currently playing song has been paused. The event handler\n * is passed a 'play' object with song metadata. if the event\n * was triggered via a `Feed.resumable().tune()` call, then a\n * second argument of `true` will be passed to the event handler.\n * play-stopped - player.stop() has been called\n * skip-denied - the given song could not be skipped due to DMCA rules\n * skip-failed - the request to skip a song was denied\n * forbidden - an unsatisfiable request for music was made (currently only\n * triggered when trying to start playback in the middle of a non-first\n * play station with the `advanceTo` argument to `setStationId`)\n *\n * Some misc methods:\n *\n * setMuted(muted)\n * canLike() - returns true if the current song may be liked/unliked/disliked\n * canSkip() - returns true if the current song may be skipped (some stations have\n * skip frequency limits or disable skipping entirely)\n *\n */\n\nfunction supports_html5_storage$1() {\n try {\n return 'localStorage' in window && window['localStorage'] !== null && (window.localStorage['feed-test'] = true);\n } catch (e) {\n return false;\n }\n}\nvar Player = function Player(token, secret, options) {\n var _this = this;\n if (!secret) {\n // restore from saved state\n this._restore(token);\n } else {\n options = options || {};\n options.maxRetries = options.maxRetries || 10;\n this.options = options;\n this.state = {\n paused: true,\n // activePlay\n simulcast: options.simulcast\n };\n if (options.debug) {\n log.enable();\n } // this._station = current station\n // this._stations = list of available stations\n // this._placement = current placement\n\n this.trimming = options.trimming === false ? false : true;\n this.normalizeVolume = 'normalizeVolume' in options ? options.normalizeVolume : true;\n this.resumable = 'resumable' in options ? options.resumable : true;\n this.secondsOfCrossfade = options.secondsOfCrossfade || 0;\n this.crossfadeIn = !!options.crossfadeIn;\n this.serverAssignedCrossfade = false;\n this._stationsPromise = new Promise(function (resolve, reject) {\n _this._stationsResolve = resolve;\n _this._stationsReject = reject;\n });\n var speaker = this.speaker = new Speaker({\n maxRetries: options.maxRetries\n });\n var session = this.session = new Session(token, secret, options);\n if (options.brokenWebkitFormats && Speaker.brokenWebkit) {\n var reqFormatList = options.brokenWebkitFormats.split(','),\n suppFormatList = speaker.getSupportedFormats().split(','),\n reqAndSuppFormatList = intersection(reqFormatList, suppFormatList),\n reqAndSuppFormats = reqAndSuppFormatList.join(',');\n log('input format list is', reqFormatList, suppFormatList);\n log('final support list is', reqAndSuppFormats);\n if (reqAndSuppFormatList.length === 0) {\n reqAndSuppFormats = speaker.getSupportedFormats();\n }\n session.setFormats(reqAndSuppFormats);\n } else if (options.formats) {\n var _reqFormatList = options.formats.split(','),\n _suppFormatList = speaker.getSupportedFormats().split(','),\n _reqAndSuppFormatList = intersection(_reqFormatList, _suppFormatList),\n _reqAndSuppFormats = _reqAndSuppFormatList.join(',');\n if (_reqAndSuppFormatList.length === 0) {\n _reqAndSuppFormats = speaker.getSupportedFormats();\n }\n log('input format list is', _reqFormatList, _suppFormatList);\n log('final support list is', _reqAndSuppFormats);\n session.setFormats(_reqAndSuppFormats);\n } else {\n session.setFormats(speaker.getSupportedFormats());\n }\n }\n Object.assign(this, Events);\n this.session.on('play-active', this._onPlayActive, this);\n this.session.on('play-started', this._onPlayStarted, this);\n this.session.on('play-completed', this._onPlayCompleted, this);\n this.session.on('plays-exhausted', this._onPlaysExhausted, this);\n this.session.on('prepare-sound', this._onPrepareSound, this);\n this.session.on('placement', this._onPlacement, this);\n this.session.on('stations', this._onStations, this);\n this.session.on('station-changed', this._onStationChanged, this);\n var player = this;\n var _loop = function _loop() {\n var event = _arr[_i];\n _this.session.on(event, function () {\n player.trigger.apply(player, [event].concat(Array.prototype.slice.call(arguments, 0)));\n });\n };\n for (var _i = 0, _arr = ['music-unavailable', 'not-in-us', 'invalid-credentials', 'skip-denied', 'play-active', 'forbidden']; _i < _arr.length; _i++) {\n _loop();\n }\n this.setMuted(this.isMuted());\n};\nPlayer.prototype._persist = function () {\n var playerState = shallowCopy(this.state);\n if (playerState.activePlay) {\n // remove the 'sound' object\n playerState.activePlay = shallowCopy(playerState.activePlay);\n delete playerState.activePlay.sound;\n }\n var persisted = {\n state: playerState,\n options: this.options,\n trimming: this.trimming,\n normalizeVolume: this.normalizeVolume,\n secondsOfCrossfade: this.secondsOfCrossfade,\n serverAssignedCrossfade: this.serverAssignedCrossfade,\n crossfadeIn: this.crossfadeIn,\n sessionConfig: this.session.config\n };\n return persisted;\n};\nPlayer.prototype._restore = function (_ref) {\n var _this2 = this;\n var persisted = _ref.persisted,\n elapsed = _ref.elapsed;\n if (persisted.options.debug) {\n log.enable();\n }\n log('restoring!'); // session will be initialized with no current play\n\n var sessionConfig = persisted.sessionConfig;\n var sessionCurrent = sessionConfig.current;\n sessionConfig.current = null;\n sessionConfig.pendingRequest = null;\n sessionConfig.pendingPlay = null;\n this.session = new Session();\n this.session.config = sessionConfig;\n this.options = persisted.options;\n this.speaker = new Speaker({\n maxRetries: this.options.maxRetries\n }); // start off in paused state\n\n this.state = {\n paused: true,\n simulcast: this.options.simulcast\n };\n this.trimming = persisted.trimming;\n this.normalizeVolume = persisted.normalizeVolume;\n this.resumable = true;\n this.secondsOfCrossfade = persisted.secondsOfCrossfade;\n this.serverAssignedCrossfade = persisted.serverAssignedCrossfade;\n this.crossfadeIn = persisted.crossfadeIn;\n this._stationsPromise = new Promise(function (resolve, reject) {\n _this2._stationsResolve = resolve;\n _this2._stationsReject = reject;\n }); // at this point, we're in a state similar to a newly initialized player,\n // but the session object has placement/station info\n // swap out the default tune\n\n this.tune = function () {\n var _this3 = this;\n\n // on the next tick, throw out events to simulate a normal tune() call\n return Promise.resolve(true).then(function () {\n _this3._station = persisted.sessionConfig.station;\n _this3._stations = persisted.sessionConfig.stations;\n _this3._placement = persisted.sessionConfig.placement;\n _this3._stationsResolve(persisted._stations);\n _this3.trigger('placement', _this3._placement);\n _this3.trigger('station-changed', _this3._station);\n _this3.trigger('stations', _this3._stations); // stick the previously active song into the session\n\n _this3.session.config.current = sessionCurrent;\n _this3.session.config.current.started = false;\n var play = _this3.session.config.current.play; // get the player to create a sound object with the audio advanced to the\n // old elapsed position\n\n play.start_at = elapsed / 1000;\n _this3.session.trigger('play-active', play);\n _this3.session.config.current.started = true; // pretend the song was started\n\n _this3.state.paused = false;\n _this3.session.trigger('play-started', play, true); // announce that the song is paused\n\n _this3.state.paused = true;\n _this3.trigger('play-paused', play, true); // now we're in the same spot we'd be if we played and paused.\n }).then(function () {\n return _this3._stationsPromise;\n });\n };\n};\nPlayer.prototype.initializeAudio = function () {\n log('INTIALIZE AUDIO');\n this.speaker.initializeAudio();\n};\nPlayer.prototype._onPlacement = function (placement) {\n this._placement = placement;\n if (placement.options && placement.options.crossfade_seconds) {\n this.secondsOfCrossfade = placement.options.crossfade_seconds;\n this.serverAssignedCrossfade = true;\n }\n this.trigger('placement', placement);\n};\nPlayer.prototype._onStations = function (stations) {\n this._stations = stations;\n this._stationsResolve(stations);\n this.trigger('stations', stations);\n};\nPlayer.prototype._onStationChanged = function (stationId, station) {\n this._station = station;\n if (this.serverAssignedCrossfade && station.options && 'crossfade_seconds' in station.options) {\n // apply station level crossfade, if available\n this.secondsOfCrossfade = station.options.crossfade_seconds;\n } else if (this.serverAssignedCrossfade && this._placement.options && 'crossfade_seconds' in this._placement.options) {\n // revert to placement level crossfade, if available\n this.secondsOfCrossfade = this._placement.options.crossfade_seconds;\n }\n this.trigger('station-changed', stationId, station);\n};\nPlayer.prototype.setStationId = function (stationId, fadeOutOrAdvance) {\n var advance;\n var fadeOut = false;\n if (fadeOutOrAdvance === true) {\n fadeOut = fadeOutOrAdvance;\n log('SET STATION ID (WITH FADE)', stationId);\n } else if (fadeOutOrAdvance) {\n advance = fadeOutOrAdvance;\n log('SET STATION ID (WITH ADVANCE)', stationId, advance);\n } else {\n log('SET STATION ID', stationId);\n }\n if (fadeOut && this.state.activePlay) {\n // when we destroy the sound, have it fade out\n this.state.activePlay.fadeOnDestroy = true;\n }\n this.session.setStationId(stationId, advance, this.crossfadeIn);\n};\nPlayer.prototype._onPlayActive = function (play) {\n // create a new sound object\n var options = {\n play: this._onSoundPlay.bind(this, play.id),\n pause: this._onSoundPause.bind(this, play.id),\n finish: this._onSoundFinish.bind(this, play.id),\n elapse: this._onSoundElapse.bind(this, play.id)\n };\n if (this.normalizeVolume) {\n options.gain = (play.audio_file.replaygain_track_gain || 0) + (play.station.pre_gain || 0);\n }\n if (play.start_at) {\n // when offsetting into a station, ignore the trim and honor the start_at\n options.startPosition = play.start_at * 1000;\n } else {\n if (this.trimming && play.audio_file.extra && play.audio_file.extra.trim_start) {\n options.startPosition = play.audio_file.extra.trim_start * 1000;\n }\n }\n if (this.trimming && play.audio_file.extra && play.audio_file.extra.trim_end && play.audio_file.duration_in_seconds) {\n options.endPosition = (play.audio_file.duration_in_seconds - play.audio_file.extra.trim_end) * 1000;\n }\n if (this.secondsOfCrossfade) {\n if (this.crossfadeIn) {\n options.fadeInSeconds = this.secondsOfCrossfade;\n }\n options.fadeOutSeconds = this.secondsOfCrossfade;\n }\n var sound = this.speaker.create(play.audio_file.url, options);\n this.state.activePlay = {\n id: play.id,\n sound: sound,\n startReportedToServer: false,\n // whether we got a 'play-started' event from session\n soundCompleted: false,\n // whether the sound object told us it finished playback\n playStarted: false,\n // whether playback started on the sound object yet\n fadeOnDestroy: false,\n // when true, apply a fade out when destroying the sound\n previousPosition: 0 // last time we got an 'elapse' callback\n }; // if we're not paused, then start it\n\n if (!this.state.paused) {\n var s = this.state.activePlay.sound;\n s.play();\n }\n};\nPlayer.prototype._onSoundPlay = function (playId) {\n // sound started playing\n if (!this.state.activePlay || this.state.activePlay.id !== playId) {\n log('received sound play, but active play does not match', this.state.activePlay, playId);\n return;\n }\n this.state.paused = false;\n var playerWasResumed = this.state.activePlay.playStarted;\n this.state.activePlay.playStarted = true; // on the first play, tell the server we're good to go\n\n if (!this.state.activePlay.startReportedToServer) {\n // save the state so we can restore\n if (this.resumable) {\n persistState(this._persist());\n }\n return this.session.reportPlayStarted();\n } else if (playerWasResumed) {\n // subsequent plays are considered 'resumed' events\n this.trigger('play-resumed', this.session.getActivePlay());\n }\n};\nPlayer.prototype.getActivePlay = function () {\n return this.session.getActivePlay();\n};\nPlayer.prototype.hasActivePlayStarted = function () {\n return this.session.hasActivePlayStarted();\n};\nPlayer.prototype.getActivePlacement = function () {\n return this.session.getActivePlacement();\n};\nPlayer.prototype._onSoundPause = function (playId) {\n // sound paused playback\n if (!this.state.activePlay || this.state.activePlay.id !== playId) {\n log('received sound pause, but active play does not match', this.state.activePlay, playId);\n return;\n }\n this.state.paused = true;\n this.trigger('play-paused', this.session.getActivePlay());\n};\nPlayer.prototype._onSoundFinish = function (playId, withError) {\n if (!this.state.activePlay || this.state.activePlay.id !== playId) {\n log('received sound finish, but active play does not match', this.state.activePlay, playId);\n return;\n }\n var sound = this.state.activePlay.sound;\n this.state.activePlay.soundCompleted = true;\n if (withError) {\n this.session._submitEvent('playback-error', {\n url: sound.url,\n responses: sound.responses,\n error: withError,\n play_id: playId\n });\n this.state.activePlay.soundCompletedWithError = true;\n if (withError.name === 'NotAllowedError') {\n // eslint-disable-next-line no-console\n console.error('Feed.fm: first call to \"initializeAudio()\" or \"play()\" must be made in user-initiated event handler');\n this.stop();\n return;\n }\n }\n if (!this.state.activePlay.playStarted) {\n // never reported this as started... mark it as invalidated so\n // we can advance.\n this.trigger('invalidated', playId);\n this.session.requestInvalidate();\n return;\n }\n if (!this.state.activePlay.startReportedToServer) {\n // if the song failed before we recieved start response, wait\n // until word from the server that we started before we say\n // that we completed the song\n return;\n }\n if (withError) {\n log('song completed with error - marking as invalid', withError);\n this.trigger('invalidated', playId);\n this.session.requestInvalidate();\n } else {\n this.session.reportPlayCompleted();\n }\n};\nPlayer.prototype._onSoundElapse = function (playId) {\n if (!this.state.activePlay || this.state.activePlay.id !== playId) {\n log('received sound elapse, but active play does not match', this.state.activePlay, playId);\n return;\n }\n var sound = this.state.activePlay.sound,\n position = sound.position(),\n interval = 30 * 1000,\n // ping server every 30 seconds\n previousCount = Math.floor(this.state.activePlay.previousPosition / interval),\n currentCount = Math.floor(position / interval);\n if (this.resumable) {\n persistElapsed(position);\n }\n this.state.activePlay.previousPosition = position;\n if (currentCount !== previousCount) {\n this.session.reportPlayElapsed(Math.floor(position / 1000));\n }\n};\nPlayer.prototype._onPlayStarted = function (play) {\n var _this4 = this;\n var session = this.session;\n if (!this.state.activePlay || this.state.activePlay.id !== play.id) {\n log('received play started, but it does not match active play', play, this.state.activePlay);\n return;\n }\n this.state.activePlay.startReportedToServer = true;\n if (this.state.activePlay.soundCompleted) {\n // the audio completed playback before the session announced the play started\n log('sound completed before we finished reporting start', this.state.activePlay); // In the normal case we'd just quit here, but since the audio completed playback\n // already, we've got to make sure a 'session.reportPlayCompleted()' gets kicked\n // off to record the completion of this song.\n // Defer the reporting so other 'play-started' handlers can complete as normal\n // before a 'play-completed' gets triggered\n\n if (this.state.activePlay.soundCompletedWithError) {\n setTimeout(function () {\n _this4.trigger('invalidated', play.id);\n session.requestInvalidate();\n }, 1);\n } else {\n setTimeout(function () {\n return session.reportPlayCompleted();\n }, 1);\n }\n }\n this.updateSimulcast();\n this.trigger('play-started', play);\n};\nPlayer.prototype._onPlayCompleted = function (play) {\n if (!this.state.activePlay || this.state.activePlay.id !== play.id) {\n log('received play completed, but it does not match active play', play, this.state.activePlay);\n return;\n }\n this.state.activePlay.sound.destroy(this.state.activePlay.fadeOnDestroy);\n var started = this.state.activePlay.playStarted;\n delete this.state.activePlay;\n if (started) {\n this.trigger('play-completed', play);\n } // skip to complete the current song.\n //this.state.paused = false;\n};\nPlayer.prototype._onPlaysExhausted = function () {\n if (this.state.paused) {\n return;\n }\n this.state.paused = false;\n this.updateSimulcast();\n this.trigger('plays-exhausted');\n};\nPlayer.prototype._onPrepareSound = function (url, startPosition, playId) {\n var _this5 = this;\n log('preparing sound', url, startPosition);\n this.speaker.prepare(url, startPosition * 1000);\n this.speaker.once('prepared', function (preparedUrl, success, headers) {\n if (url !== preparedUrl) {\n return;\n }\n if (headers && headers.length > 1) {\n _this5.session._submitEvent('preload-error', {\n url: url,\n play_id: playId,\n responses: headers\n });\n }\n var activePlay = _this5.session.getActivePlay();\n if (!success && (!activePlay || activePlay.id !== playId)) {\n _this5.session.requestInvalidate(url);\n }\n });\n};\nPlayer.prototype.isPaused = function () {\n return this.session.isTuned() && this.state.paused;\n};\nPlayer.prototype.tune = function () {\n log('TUNE');\n if (!this.session.isTuned()) {\n this.session.tune();\n }\n return this._stationsPromise;\n};\n/**\n * This call triggers the SDK to load the next song into memory and\n * returns a promise that resolves when the next song is fully loaded\n * and ready for immediate playback via play().\n * \n * Additionally, this method triggers a 'prepared' event on the player\n * object when the next song is fully loaded and ready for immediate\n * playback.\n * \n * Note: a song cannot be fully loaded into memory until initializeAudio()\n * has been called. The promise returned by this method will not resolve\n * unless initializeAudio() is successfully called before or after this\n * method.\n * \n * @returns Promise that resolves when a song is in memory and ready for immediate playback\n */\n\nPlayer.prototype.prepare = function () {\n log('PREPARE');\n this.speaker.initializeAudio();\n return this._prepare();\n};\nPlayer.prototype._prepare = function () {\n var _this6 = this;\n var ap = this.state.activePlay;\n if (ap) {\n var url = ap.sound.url;\n var prepared = this.speaker.prepare(url, ap.sound.startPosition);\n if (prepared) {\n return Promise.resolve(true).then(function () {\n log('already prepared');\n _this6.trigger('prepared');\n });\n } else {\n return new Promise(function (resolve) {\n log('waiting for un/prepared event');\n _this6.speaker.once('prepared', function (preparedUrl, success, headers) {\n if (headers && headers.length > 1) {\n _this6.session._submitEvent('preload-error', {\n url: preparedUrl,\n play_id: ap.id,\n responses: headers\n });\n }\n if (preparedUrl !== url) {\n return;\n }\n if (success) {\n _this6.trigger('prepared');\n resolve(true);\n } else {\n // invalidate the play, and request a new one\n _this6.session.requestInvalidate();\n _this6.session.once('play-active', function () {\n _this6._prepare().then(function (val) {\n return resolve(val);\n });\n });\n }\n });\n });\n }\n } else {\n return new Promise(function (resolve) {\n _this6.session.once('play-active', function () /* play */\n {\n _this6._prepare().then(function (val) {\n return resolve(val);\n });\n });\n if (!_this6.session.isTuned()) {\n log('tuning');\n _this6.session.tune();\n }\n });\n }\n};\nPlayer.prototype.play = function () {\n log('PLAY');\n var session = this.session;\n var state = this.state;\n this.speaker.initializeAudio();\n if (!session.isTuned()) {\n // not currently playing music\n state.paused = false;\n return session.tune();\n }\n if (session.getActivePlay() && state.activePlay && state.paused) {\n // resume playback of song\n if (state.activePlay.playStarted) {\n state.activePlay.sound.resume();\n } else {\n state.activePlay.sound.play();\n }\n } // 'start' event from sound will definitely be asynchronous, so prevent repeated calls\n\n state.paused = false;\n this.updateSimulcast();\n};\nPlayer.prototype.pause = function () {\n log('PAUSE');\n if (!this.session.hasActivePlayStarted() || !this.state.activePlay || this.state.paused) {\n return;\n } // pause current song\n\n this.state.activePlay.sound.pause(); // 'pause' event from sound might be asynchronous, so prevent repeated calls\n\n this.state.paused = true;\n this.updateSimulcast();\n};\n/**\n * Some regions disallow 'like'ing of songs (e.g. Canada). Check this after\n * changing the active station or when a new song starts to know if the current\n * song may be liked/disliked/unliked.\n * \n * @returns {boolean} true if we can 'like' songs in the currently active station\n */\n\nPlayer.prototype.canLike = function () {\n return this.session.canLike();\n};\nPlayer.prototype.like = function () {\n log('LIKE');\n if (!this.session.hasActivePlayStarted()) {\n return;\n }\n if (!this.session.canLike()) {\n return;\n }\n this.session.likePlay(this.state.activePlay.id);\n this.trigger('play-liked');\n};\nPlayer.prototype.unlike = function () {\n log('UNLIKE');\n if (!this.session.hasActivePlayStarted()) {\n return;\n }\n if (!this.session.canLike()) {\n return;\n }\n this.session.unlikePlay(this.state.activePlay.id);\n this.trigger('play-unliked');\n};\nPlayer.prototype.dislike = function () {\n log('DISLIKE');\n if (!this.session.hasActivePlayStarted()) {\n return;\n }\n if (!this.session.canLike()) {\n return;\n }\n this.session.dislikePlay(this.state.activePlay.id);\n this.trigger('play-disliked'); // start playback if we're paused and try to advance to next song\n\n this.state.paused = false;\n this.skip();\n};\nPlayer.prototype.skip = function () {\n log('SKIP');\n if (!this.session.hasActivePlayStarted()) {\n // can't skip non-playing song\n return;\n } // cannot skip in station with skipping disabled\n\n if (!this.session.canSkipInStation()) {\n return;\n }\n this.state.paused = false;\n this.session.requestSkip();\n};\nPlayer.prototype.stop = function () {\n log('STOP');\n clearPersistance();\n this.state.paused = true;\n var activePlay = this.state.activePlay;\n if (activePlay && activePlay.sound) {\n log('stopping active play', activePlay);\n if (activePlay.startReportedToServer) {\n // report where we played to\n var position = activePlay.sound.position();\n this.session.reportPlayStopped(Math.floor(position / 1000));\n } // stop any playback\n\n activePlay.sound.pause();\n activePlay.sound.destroy();\n } else {\n log('no active play');\n }\n delete this.state.activePlay; // flush out any prepared sounds\n\n this.speaker.flush();\n this.trigger('play-stopped');\n this.updateSimulcast();\n};\nPlayer.prototype.destroy = function () {\n this.session = null;\n if (this.state.activePlay && this.state.activePlay.sound) {\n this.state.activePlay.sound.destroy();\n }\n};\nPlayer.prototype.getCurrentState = function () {\n if (!this.session.hasActivePlayStarted()) {\n // nothing started, so we're idle\n return 'idle';\n } else {\n if (this.state.paused) {\n return 'paused';\n } else {\n return 'playing';\n }\n }\n};\nPlayer.prototype.getPosition = function () {\n if (this.state.activePlay && this.state.activePlay.sound) {\n return this.state.activePlay.sound.position();\n } else {\n return 0;\n }\n};\nPlayer.prototype.getDuration = function () {\n if (this.state.activePlay && this.state.activePlay.sound) {\n return this.state.activePlay.sound.duration();\n } else {\n return 0;\n }\n};\n/**\n * Return true if the user may skip the current song.\n * \n * @returns {boolean}\n */\n\nPlayer.prototype.canSkip = function () {\n return this.session.canSkip();\n};\n/**\n * Technically, you might not be able to skip a song at the time it starts, but\n * eventually enough time might pass that you can skip the song. Hence, we\n * had 'maybeCanSkip'. However, nobody is repeatedly checking for skippability\n * while playing a song, so this method is deprecated.\n */\n\nPlayer.prototype.maybeCanSkip = function () {\n return this.canSkip();\n};\nvar mutedKey = 'muted';\nPlayer.prototype.isMuted = function () {\n if (supports_html5_storage$1()) {\n if (mutedKey in localStorage) {\n return localStorage[mutedKey] === 'true';\n }\n }\n return false;\n};\nPlayer.prototype.setMuted = function (isMuted) {\n if (isMuted) {\n this.speaker.setVolume(0);\n if (supports_html5_storage$1()) {\n localStorage[mutedKey] = true;\n }\n this.trigger('muted');\n } else {\n this.speaker.setVolume(100);\n if (supports_html5_storage$1()) {\n localStorage[mutedKey] = false;\n }\n this.trigger('unmuted');\n }\n};\nPlayer.prototype.getVolume = function () {\n return this.speaker.getVolume();\n};\nPlayer.prototype.setVolume = function (vol) {\n this.speaker.setVolume(vol);\n};\nPlayer.prototype.getStations = function () {\n return this._stationsPromise;\n};\nPlayer.prototype.updateSimulcast = function () {\n var _this7 = this;\n if (!this.state.simulcast) {\n return;\n }\n var state = this.getCurrentState();\n getClientId().then(function (clientId) {\n _this7.session._signedAjax(getBaseUrl() + \"/api/v2/simulcast/\".concat(_this7.state.simulcast, \"/in-progress\"), {\n method: 'POST',\n body: JSON.stringify({\n state: state,\n client_id: clientId\n }),\n headers: {\n 'Content-Type': 'application/json'\n }\n });\n });\n};\nfunction shallowCopy(obj) {\n if (obj === null) {\n return null;\n }\n return Object.assign({}, obj);\n}\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}\nvar PlayerView = function PlayerView(id, player) {\n var _this = this;\n this.alertId = null;\n this.durationId = null;\n this.startedPlayback = false;\n this.$el = id instanceof Element ? id : document.getElementById(id);\n this.player = player;\n this.player.on('placement', this._onPlacement, this);\n this.player.on('play-started', this._onPlayStarted, this);\n this.player.on('play-paused', this._onPlayPaused, this);\n this.player.on('play-resumed', this._onPlayResumed, this);\n this.player.on('play-completed', this._onPlayCompleted, this);\n this.player.on('play-stopped', this._onPlayStopped, this);\n this.player.on('play-liked', this._onPlayLiked, this);\n this.player.on('play-unliked', this._onPlayUnliked, this);\n this.player.on('play-disliked', this._onPlayDisliked, this);\n this.player.on('station-changed', this._onStationChanged, this);\n this.player.on('plays-exhausted', this._onPlaysExhausted, this);\n this.player.on('skip-denied', this._onSkipDenied, this);\n this.player.on('suspend', this._onSuspend, this);\n this._enableButtonsBasedOnState();\n this.displayText = this.originalDisplayText = this.$el.querySelector('.status').innerHTML;\n this.renderStatus();\n this.$el.querySelectorAll('.status').forEach(function (status) {\n status.addEventListener('click', _this._onStatusClick.bind(_this));\n });\n this.$el.querySelectorAll('.play-button, .start-button, .resume-button').forEach(function (button) {\n button.addEventListener('click', _this._onPlayButtonClick.bind(_this));\n });\n this.$el.querySelectorAll('.pause-button').forEach(function (pause) {\n pause.addEventListener('click', _this._onPauseButtonClick.bind(_this));\n });\n this.$el.querySelectorAll('.skip-button').forEach(function (skip) {\n skip.addEventListener('click', _this._onSkipButtonClick.bind(_this));\n });\n this.$el.querySelectorAll('.like-button').forEach(function (like) {\n like.addEventListener('click', _this._onLikeButtonClick.bind(_this));\n });\n this.$el.querySelectorAll('.dislike-button').forEach(function (dislike) {\n dislike.addEventListener('click', _this._onDislikeButtonClick.bind(_this));\n });\n};\nPlayerView.prototype._onStatusClick = function () {\n var state = this.player.getCurrentState();\n if (state === 'playing') {\n this._onPauseButtonClick();\n } else {\n this._onPlayButtonClick();\n }\n};\nPlayerView.prototype._onPlayButtonClick = function () {\n this.player.initializeAudio();\n this.player.play();\n};\nPlayerView.prototype._onPauseButtonClick = function () {\n this.player.pause();\n};\nPlayerView.prototype._onSkipButtonClick = function () {\n this.player.skip();\n};\nPlayerView.prototype._onLikeButtonClick = function (event) {\n log('like button clicked!', event.target, this);\n if (event.target.classList.contains('liked')) {\n this.player.unlike();\n } else {\n this.player.like();\n }\n};\nPlayerView.prototype._onDislikeButtonClick = function () {\n this.player.dislike();\n};\nPlayerView.prototype.$ = function (arg) {\n return this.$el.find(arg);\n};\nPlayerView.prototype._onPlacement = function (placement) {\n if (!this.originalDisplayText) {\n this.originalDisplayText = this.formatPlacement(placement);\n this.renderStatus(this.originalDisplayText);\n }\n};\nPlayerView.prototype.formatPlacement = function () {\n return 'Tune in!';\n};\nPlayerView.prototype._onPlayStarted = function (play) {\n this.startedPlayback = true;\n this.renderStatus(this.formatPlay(play));\n this._enableButtonsBasedOnState();\n this._setLikeStatus(play.liked);\n this._enablePositionTracker();\n};\nPlayerView.prototype._onStationChanged = function () {\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._enablePositionTracker = function () {\n var playerView = this;\n if (!this.durationId) {\n this.durationId = window.setInterval(function () {\n playerView.renderPosition(playerView.player.getPosition(), playerView.player.getDuration());\n }, 500);\n }\n};\nPlayerView.prototype._setLikeStatus = function (liked) {\n var likes = this.$el.querySelectorAll('.like-button');\n var dislikes = this.$el.querySelectorAll('.dislike-button');\n if (liked === true) {\n // highlight the like button\n likes.forEach(function (element) {\n element.classList.add('liked');\n });\n dislikes.forEach(function (element) {\n element.classList.remove('disliked');\n });\n } else if (liked === false) {\n // highlight the dislike button\n likes.forEach(function (element) {\n element.classList.remove('liked');\n });\n dislikes.forEach(function (element) {\n element.classList.add('disliked');\n });\n } else {\n // nobody gets highlighted\n likes.forEach(function (element) {\n element.classList.remove('liked');\n });\n dislikes.forEach(function (element) {\n element.classList.remove('disliked');\n });\n }\n};\nPlayerView.prototype._disablePositionTracker = function () {\n if (this.durationId) {\n window.clearInterval(this.durationId);\n this.durationId = null;\n }\n};\nPlayerView.prototype._onPlayResumed = function () {\n this._enablePositionTracker();\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._onPlayPaused = function () {\n this._disablePositionTracker();\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._onPlayCompleted = function () {\n this.renderPosition(0, 0);\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._onPlayStopped = function () {\n this.renderStatus(this.originalDisplayText);\n this.renderPosition(0, 0);\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._onPlaysExhausted = function () {\n this.renderStatus(this.originalDisplayText);\n this.renderAlert('There is no more music to play in this station!');\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._onPlayLiked = function () {\n this._setLikeStatus(true);\n};\nPlayerView.prototype._onPlayDisliked = function () {\n this._setLikeStatus(false);\n};\nPlayerView.prototype._onPlayUnliked = function () {\n this._setLikeStatus();\n};\nPlayerView.prototype._onSkipDenied = function () {\n this.renderAlert('Sorry you\\'ve temporarily run out of skips!');\n};\nPlayerView.prototype.formatPlay = function (play) {\n return '' + play.audio_file.track.title + ' by ' + play.audio_file.artist.name + ' on ' + play.audio_file.release.title + '';\n};\nPlayerView.prototype.renderStatus = function (displayText) {\n var _this2 = this;\n if (displayText !== undefined) {\n this.displayText = displayText;\n }\n if (!this.alertId) {\n this.$el.querySelectorAll('.status').forEach(function (status) {\n status.innerHTML = _this2.displayText;\n status.classList.remove('alert');\n });\n }\n};\nPlayerView.prototype.renderPosition = function (position, duration) {\n this.$el.querySelectorAll('.elapsed').forEach(function (elapsed) {\n elapsed.innerHTML = formatTime(position);\n });\n this.$el.querySelectorAll('.duration').forEach(function (dur) {\n dur.innerHTML = formatTime(duration);\n });\n if (duration === 0) {\n this.$el.querySelectorAll('.progress').forEach(function (progress) {\n progress.style.width = '0';\n });\n } else {\n var elapsed = Math.round((position + 1000) / duration * 100);\n elapsed = elapsed > 100 ? 100 : elapsed;\n this.$el.querySelectorAll('.progress').forEach(function (progress) {\n progress.style.width = elapsed + '%';\n });\n }\n};\nfunction formatTime(millis) {\n var asSeconds = Math.floor(millis / 1000),\n secondsPart = asSeconds % 60,\n minutesPart = Math.floor(asSeconds / 60);\n if (secondsPart < 10) {\n secondsPart = '0' + secondsPart;\n }\n return minutesPart + ':' + secondsPart;\n}\nPlayerView.prototype.renderAlert = function (alertText) {\n if (this.alertId) {\n window.clearTimeout(this.alertId);\n }\n this.$el.querySelectorAll('.status').forEach(function (status) {\n status.innerHTML = alertText;\n status.classList.add('alert');\n });\n var playerView = this;\n this.alertId = window.setTimeout(function () {\n playerView.alertId = null;\n playerView.renderStatus();\n }, 3000);\n};\nPlayerView.prototype._onSuspend = function () {\n this._enableButtonsBasedOnState();\n};\nPlayerView.prototype._enableButtonsBasedOnState = function () {\n var state = this.player.getCurrentState(),\n toEnable,\n toDisable;\n switch (state) {\n case 'playing':\n toEnable = ['.pause-button'];\n toDisable = ['.play-button', '.start-button', '.resume-button'];\n if (this.player.canLike()) {\n toEnable.push('.dislike-button', '.like-button');\n } else {\n toDisable.push('.dislike-button', '.like-button');\n }\n if (this.player.canSkip()) {\n toEnable.push('.skip-button');\n } else {\n toDisable.push('.skip-button');\n }\n break;\n case 'paused':\n toEnable = ['.play-button', '.resume-button'];\n toDisable = ['.pause-button', '.start-button'];\n if (this.player.canLike()) {\n toEnable.push('.dislike-button', '.like-button');\n } else {\n toDisable.push('.dislike-button', '.like-button');\n }\n if (this.player.canSkip()) {\n toEnable.push('.skip-button');\n } else {\n toDisable.push('.skip-button');\n }\n break;\n\n /* case 'idle': */\n\n default:\n toEnable = ['.play-button', '.start-button'];\n toDisable = ['.resume-button', '.pause-button', '.like-button', '.dislike-button', '.skip-button'];\n break;\n }\n var _iterator = _createForOfIteratorHelper(toDisable),\n _step;\n try {\n for (_iterator.s(); !(_step = _iterator.n()).done;) {\n var item = _step.value;\n this.$el.querySelectorAll(item).forEach(function (element) {\n element.classList.remove('button-enabled');\n element.classList.add('button-disabled');\n element.disabled = true;\n });\n }\n } catch (err) {\n _iterator.e(err);\n } finally {\n _iterator.f();\n }\n var _iterator2 = _createForOfIteratorHelper(toEnable),\n _step2;\n try {\n for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {\n var _item = _step2.value;\n this.$el.querySelectorAll(_item).forEach(function (element) {\n element.classList.remove('button-disabled');\n element.classList.add('button-enabled');\n element.disabled = false;\n });\n }\n } catch (err) {\n _iterator2.e(err);\n } finally {\n _iterator2.f();\n }\n var classes = this.$el.classList;\n classes.remove('state-playing');\n classes.remove('state-paused');\n classes.remove('state-idle');\n classes.add('state-' + state);\n};\nvar METADATA_TIMEOUT = 10000;\nvar ADVANCE_TIMEOUT = 8000;\n/**\n * This class connects to a specific simulcast stream and\n * sends out events to indicate when new songs are starting\n * or when music has stopped playing. This class exposes \n * 'connect' and 'disconnect' methods to turn on the audio or stop\n * the audio.\n * \n * initializeAudio\n * connect\n * disconnect\n * getVolume\n * setVolume\n * \n * The player has a state, returned from getCurrentState():\n * \n * 'idle' - class hasn't attempted to connect to the stream, or we've\n * disconnected from a stream.\n * 'connecting' - we're conneting to the stream (this is set when a\n * call to 'connect()' is made)\n * 'connected' - we have connected to the stream and are playing music (or silence)\n * 'music-unavailable' - no music is available for this client for this stream\n * \n * The audio volume can be adjusted with setVolume() and retrieved with\n * getVolume().\n * \n * The player triggers the following events:\n * play-started - indicates a new song has begun playback, or we've\n * dropped in on an already playing song. The 'play' that represents\n * the song is passed as an argument. The 'play' value may be null, \n * which indicates silence is playing right now.\n * music-unavailable - indicates the listener may not listen to music\n * state-changed - indicates the state of the player changed\n * \n * Upon a call to 'connect', the client can expect either a 'play-started'\n * event or a 'music-unavailable' event.\n */\n\nvar SimulcastPlayer = /*#__PURE__*/function () {\n // var _uuid; // uuid of stream\n // var _speaker; // Speaker instance\n // var _streamUrl; // stream we're connecting to\n // var _activePlay; // currently playing song, or null\n // var _activeSound; // if we're playing, this holds the sound\n // var _metadataTimeout; // timeout for retrieving updated metadata\n // var _tryingToPlay = false; // true if we want to play/hear music\n // var _retries; // number of times we've retried playing music\n function SimulcastPlayer(uuid) {\n _classCallCheck(this, SimulcastPlayer);\n Object.assign(this, Events);\n this._speaker = new Speaker();\n this._uuid = uuid;\n this._state = 'idle';\n this._activePlay = null;\n this._activeSound = null;\n this._metadataTimeout = null;\n this._tryingToPlay = false;\n this._retries = 0;\n }\n _createClass(SimulcastPlayer, [{\n key: \"initializeAudio\",\n value: function initializeAudio() {\n log('INTIALIZE AUDIO');\n this._speaker.initializeAudio();\n }\n }, {\n key: \"connect\",\n value: function connect() {\n log(\"CONNECT to \".concat(this._uuid));\n if (this._tryingToPlay) {\n log(\"ignoring pointless connect to \".concat(this._uuid));\n return;\n }\n if (this._state !== 'idle') {\n log('ignoring connect() since we\\'re already connected');\n return;\n }\n this._tryingToPlay = true; // initialize speaker,\n\n this._speaker.initializeAudio();\n this._setState('connecting'); // this should ask the API server for a URL, really\n\n var baseApiUrl = new URL(getBaseUrl());\n this._streamUrl = 'https://cast.' + baseApiUrl.hostname + '/' + this._uuid;\n this._requestStream();\n }\n }, {\n key: \"_onSoundPlay\",\n value: function _onSoundPlay() {\n var _this = this;\n\n // we've just connected to the stream.\n log('sound play!'); // reset retry count\n\n this._retries = 0; // starting point to watch for stalls\n\n this._lastElapsedAt = Date.now();\n if (this._state === 'connecting') {\n this._setState('connected'); // get details about the play\n\n fetch(this._streamUrl + '/play?elapsed=' + this._elapsed).then(function (res) {\n return res.json();\n }).then(function (res) {\n if (res.success) {\n _this._activePlay = res.play;\n _this.trigger('play-started', _this._activePlay);\n _this._scheduleMetadataTimeout();\n } else {\n // try again in 3 seconds\n _this._scheduleMetadataTimeout(3000);\n }\n }).catch(function () {\n // try again in 2 seconds\n _this._scheduleMetadataTimeout(2000);\n });\n } else if (!this._metadataTimeout) {\n this._scheduleMetadataTimeout();\n }\n }\n }, {\n key: \"_scheduleMetadataTimeout\",\n value: function _scheduleMetadataTimeout() {\n var _this2 = this;\n var ms = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : METADATA_TIMEOUT;\n this._cancelMetadataTimeout();\n this._metadataTimeout = setTimeout(function () {\n _this2._onMetadataTimeout();\n }, ms);\n }\n }, {\n key: \"_cancelMetadataTimeout\",\n value: function _cancelMetadataTimeout() {\n if (this._metadataTimeout) {\n clearTimeout(this._metadataTimeout);\n }\n this._metadataTimeout = null;\n }\n }, {\n key: \"_onSoundElapse\",\n value: function _onSoundElapse() {\n if (this._activeSound) {\n var oldElapsed = this._elapsed;\n var newlyElapsed = this._elapsed = this._activeSound.position();\n if (newlyElapsed - oldElapsed > 0) {\n this._lastElapsedAt = Date.now();\n }\n }\n }\n }, {\n key: \"_requestStream\",\n value: function _requestStream() {\n log('requesting stream');\n if (!this._tryingToPlay) {\n return;\n }\n if (this._activeSound) {\n this._activeSound.destroy();\n this._activeSound = null;\n } // don't query for metadata while we are trying to stream again\n\n this._cancelMetadataTimeout();\n this._activePlay = null; // keep retrying until we reconnect (but increase space between retries)\n\n this._activeSound = this._speaker.create(this._streamUrl, {\n play: this._onSoundPlay.bind(this),\n finish: this._onSoundFinish.bind(this),\n elapse: this._onSoundElapse.bind(this)\n });\n this._activeSound.play();\n this._elapsed = 0;\n this._lastElapsedAt = Date.now();\n }\n }, {\n key: \"_onMetadataTimeout\",\n value: function _onMetadataTimeout() {\n var _this3 = this;\n this._cancelMetadataTimeout(); // check for update of current song\n\n fetch(this._streamUrl + '/play?elapsed=' + this._elapsed).then(function (res) {\n return res.json();\n }).then(function (res) {\n if (res.success) {\n if (res.play === null && _this3._activePlay !== null || res.play !== null && _this3._activePlay === null || res.play !== null && _this3._activePlay !== null && res.play.audio_file.id !== _this3._activePlay.audio_file.id) {\n _this3._activePlay = res.play;\n log('current play updated', _this3._activePlay);\n _this3.trigger('play-started', _this3._activePlay);\n }\n }\n _this3._scheduleMetadataTimeout();\n var elapsed = Date.now() - _this3._lastElapsedAt;\n if (elapsed > ADVANCE_TIMEOUT) {\n log(\"stream has not advanced for \".concat(elapsed, \" ms, so reconnecting\"), _this3.toObject()); // reconnect if we've been down for a while\n\n _this3._requestStream();\n }\n }).catch(function () {\n var elapsed = Date.now() - _this3._lastElapsedAt;\n if (elapsed > ADVANCE_TIMEOUT) {\n log(\"stream has not advanced for \".concat(elapsed, \" ms, so reconnecting\"), _this3.toObject()); // reconnect if we've been down for a while\n\n _this3._requestStream();\n } else {\n _this3._scheduleMetadataTimeout();\n }\n });\n }\n }, {\n key: \"_onSoundFinish\",\n value: function _onSoundFinish(error) {\n var _this4 = this;\n log('sound finished', this.toObject());\n if (this._state === 'connecting' && error) {\n // we weren't granted access to stream\n this._tryingToPlay = false;\n this._setState('music-unavailable');\n this.trigger('music-unavailable');\n } else {\n log('reconnecting after stream ended', error); // we must have lost the stream during playback. try\n // reconnecting. \n\n if (this._activeSound) {\n this._activeSound.destroy();\n this._activeSound = null;\n } // don't query for metadata while we are trying to stream again\n\n this._cancelMetadataTimeout();\n this._activePlay = null; // keep retrying until we reconnect (but increase space between retries)\n\n this._retries += 1;\n setTimeout(function () {\n if (_this4._tryingToPlay) {\n log('retrying connection after stream ended');\n _this4._requestStream();\n }\n }, Math.pow(2, this._retries));\n } // help us narrow down streaming issues\n\n this._logEvents();\n }\n }, {\n key: \"disconnect\",\n value: function disconnect() {\n log('DISCONNECT', this.toObject());\n if (!this._tryingToPlay) {\n return;\n }\n this._tryingToPlay = false;\n this._activePlay = null;\n this._elapsed = 0;\n this._cancelMetadataTimeout(); // stop and destroy our sound object\n\n if (this._activeSound) {\n this._activeSound.destroy();\n this._activeSound = null;\n }\n this._setState('idle');\n this._logEvents();\n }\n }, {\n key: \"getVolume\",\n value: function getVolume() {\n return this._speaker.getVolume();\n }\n }, {\n key: \"setVolume\",\n value: function setVolume(vol) {\n this._speaker.setVolume(vol);\n }\n }, {\n key: \"_setState\",\n value: function _setState(newState) {\n if (this._state !== newState) {\n log(\"state transition \".concat(this._state, \" -> \").concat(newState));\n this._state = newState;\n this.trigger('state-changed', this._state);\n }\n }\n }, {\n key: \"getCurrentState\",\n value: function getCurrentState() {\n return this._state;\n }\n }, {\n key: \"getCurrentPlay\",\n value: function getCurrentPlay() {\n return this._activePlay;\n }\n }, {\n key: \"_logEvents\",\n value: function _logEvents() {\n var history = log.reset();\n return fetch(getBaseUrl() + '/api/v2/session/event', {\n method: 'POST',\n body: JSON.stringify({\n event: 'playerHistory',\n parameters: history\n }),\n headers: {\n 'Content-Type': 'application/json',\n 'X-Feed-SDK': version + ' js'\n }\n });\n }\n }, {\n key: \"toObject\",\n value: function toObject() {\n return {\n state: this._state,\n activePlay: this._activePlay,\n uuid: this._uuid,\n metadataTimeoutIsNull: this._metadataTimeout === null,\n tryingToPlay: this._tryingToPlay,\n elapsed: this._elapsed,\n retries: this._retries\n };\n }\n }, {\n key: \"toString\",\n value: function toString() {\n return JSON.stringify(this.toString());\n }\n }]);\n return SimulcastPlayer;\n}();\n\n/**\n * This method checks local storage to see if a Player instance was playing\n * music within the given number of milliseconds. If not, null is returned.\n * If so, a new Player instance is created and returned, but the `tune()`\n * method is swapped out so that, after calling `tune()` the player will \n * transition into a `paused` state. When `play()` is called, the player\n * will begin playback from the last position of the song the player\n * was previously playing.\n **/\n\nfunction resumable() {\n var maxMilliseconds = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 4000;\n var state = retrieveStateAndElapsed(maxMilliseconds);\n if (state.length === 2) {\n var _state = _slicedToArray(state, 2),\n persisted = _state[0],\n elapsed = _state[1];\n var player = new Player({\n persisted: persisted,\n elapsed: elapsed\n });\n return player;\n }\n return null;\n}\nvar index = {\n Speaker: Speaker,\n Session: Session,\n Player: Player,\n Listener: Listener,\n PlayerView: PlayerView,\n SimulcastPlayer: SimulcastPlayer,\n log: log,\n version: version,\n resetClientId: deleteClientId,\n getClientId: getClientId,\n setBaseUrl: setBaseUrl,\n resumable: resumable\n};\nmodule.exports = index;","function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\nfunction hasOwn(obj, key) {\n return Object.prototype.hasOwnProperty.call(obj, key);\n} // Escape special characters.\n\nfunction escapeRe(str) {\n return str.replace(/[.*+?^$|[\\](){}\\\\-]/g, '\\\\$&');\n} // Return a future date by the given string.\n\nfunction computeExpires(str) {\n var lastCh = str.charAt(str.length - 1);\n var value = parseInt(str, 10);\n var expires = new Date();\n switch (lastCh) {\n case 'Y':\n expires.setFullYear(expires.getFullYear() + value);\n break;\n case 'M':\n expires.setMonth(expires.getMonth() + value);\n break;\n case 'D':\n expires.setDate(expires.getDate() + value);\n break;\n case 'h':\n expires.setHours(expires.getHours() + value);\n break;\n case 'm':\n expires.setMinutes(expires.getMinutes() + value);\n break;\n case 's':\n expires.setSeconds(expires.getSeconds() + value);\n break;\n default:\n expires = new Date(str);\n }\n return expires;\n} // Convert an object to a cookie option string.\n\nfunction convert(opts) {\n var res = ''; // eslint-disable-next-line\n\n for (var key in opts) {\n if (hasOwn(opts, key)) {\n if (/^expires$/i.test(key)) {\n var expires = opts[key];\n if (_typeof(expires) !== 'object') {\n expires += typeof expires === 'number' ? 'D' : '';\n expires = computeExpires(expires);\n }\n res += \";\" + key + \"=\" + expires.toUTCString();\n } else if (/^secure$/.test(key)) {\n if (opts[key]) {\n res += \";\" + key;\n }\n } else {\n res += \";\" + key + \"=\" + opts[key];\n }\n }\n }\n if (!hasOwn(opts, 'path')) {\n res += ';path=/';\n }\n return res;\n}\nexport { hasOwn, escapeRe, computeExpires, convert };","function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; } return _typeof(obj); }\nfunction _extends() {\n _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}\nimport { escapeRe, convert } from './util'; // Check if the browser cookie is enabled.\n\nfunction isEnabled() {\n var key = '@key@';\n var value = '1';\n var re = new RegExp(\"(?:^|; )\" + key + \"=\" + value + \"(?:;|$)\");\n document.cookie = key + \"=\" + value + \";path=/\";\n var enabled = re.test(document.cookie);\n if (enabled) {\n // eslint-disable-next-line\n remove(key);\n }\n return enabled;\n} // Get the cookie value by key.\n\nfunction get(key, decoder) {\n if (decoder === void 0) {\n decoder = decodeURIComponent;\n }\n if (typeof key !== 'string' || !key) {\n return null;\n }\n var reKey = new RegExp(\"(?:^|; )\" + escapeRe(key) + \"(?:=([^;]*))?(?:;|$)\");\n var match = reKey.exec(document.cookie);\n if (match === null) {\n return null;\n }\n return typeof decoder === 'function' ? decoder(match[1]) : match[1];\n} // The all cookies\n\nfunction getAll(decoder) {\n if (decoder === void 0) {\n decoder = decodeURIComponent;\n }\n var reKey = /(?:^|; )([^=]+?)(?:=([^;]*))?(?:;|$)/g;\n var cookies = {};\n var match;\n /* eslint-disable no-cond-assign */\n\n while (match = reKey.exec(document.cookie)) {\n reKey.lastIndex = match.index + match.length - 1;\n cookies[match[1]] = typeof decoder === 'function' ? decoder(match[2]) : match[2];\n }\n return cookies;\n} // Set a cookie.\n\nfunction set(key, value, encoder, options) {\n if (encoder === void 0) {\n encoder = encodeURIComponent;\n }\n if (_typeof(encoder) === 'object' && encoder !== null) {\n /* eslint-disable no-param-reassign */\n options = encoder;\n encoder = encodeURIComponent;\n /* eslint-enable no-param-reassign */\n }\n var attrsStr = convert(options || {});\n var valueStr = typeof encoder === 'function' ? encoder(value) : value;\n var newCookie = key + \"=\" + valueStr + attrsStr;\n document.cookie = newCookie;\n} // Remove a cookie by the specified key.\n\nfunction remove(key, options) {\n var opts = {\n expires: -1\n };\n if (options) {\n opts = _extends({}, options, opts);\n }\n return set(key, 'a', opts);\n} // Get the cookie's value without decoding.\n\nfunction getRaw(key) {\n return get(key, null);\n} // Set a cookie without encoding the value.\n\nfunction setRaw(key, value, options) {\n return set(key, value, null, options);\n}\nexport { isEnabled, get, getAll, set, getRaw, setRaw, remove, isEnabled as isCookieEnabled, get as getCookie, getAll as getAllCookies, set as setCookie, getRaw as getRawCookie, setRaw as setRawCookie, remove as removeCookie };"],"sourceRoot":""}