diff --git a/static/howler.core.min.js b/static/howler.core.min.js deleted file mode 100644 index 3901ac4..0000000 --- a/static/howler.core.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! howler.js v2.2.4 | (c) 2013-2020, James Simpson of GoldFire Studios | MIT License | howlerjs.com */ -!function(){"use strict";var e=function(){this.init()};e.prototype={init:function(){var e=this||n;return e._counter=1e3,e._html5AudioPool=[],e.html5PoolSize=10,e._codecs={},e._howls=[],e._muted=!1,e._volume=1,e._canPlayEvent="canplaythrough",e._navigator="undefined"!=typeof window&&window.navigator?window.navigator:null,e.masterGain=null,e.noAudio=!1,e.usingWebAudio=!0,e.autoSuspend=!0,e.ctx=null,e.autoUnlock=!0,e._setup(),e},volume:function(e){var o=this||n;if(e=parseFloat(e),o.ctx||_(),void 0!==e&&e>=0&&e<=1){if(o._volume=e,o._muted)return o;o.usingWebAudio&&o.masterGain.gain.setValueAtTime(e,n.ctx.currentTime);for(var t=0;t=0;o--)e._howls[o].unload();return e.usingWebAudio&&e.ctx&&void 0!==e.ctx.close&&(e.ctx.close(),e.ctx=null,_()),e},codecs:function(e){return(this||n)._codecs[e.replace(/^x-/,"")]},_setup:function(){var e=this||n;if(e.state=e.ctx?e.ctx.state||"suspended":"suspended",e._autoSuspend(),!e.usingWebAudio)if("undefined"!=typeof Audio)try{var o=new Audio;void 0===o.oncanplaythrough&&(e._canPlayEvent="canplay")}catch(n){e.noAudio=!0}else e.noAudio=!0;try{var o=new Audio;o.muted&&(e.noAudio=!0)}catch(e){}return e.noAudio||e._setupCodecs(),e},_setupCodecs:function(){var e=this||n,o=null;try{o="undefined"!=typeof Audio?new Audio:null}catch(n){return e}if(!o||"function"!=typeof o.canPlayType)return e;var t=o.canPlayType("audio/mpeg;").replace(/^no$/,""),r=e._navigator?e._navigator.userAgent:"",a=r.match(/OPR\/(\d+)/g),u=a&&parseInt(a[0].split("/")[1],10)<33,d=-1!==r.indexOf("Safari")&&-1===r.indexOf("Chrome"),i=r.match(/Version\/(.*?) /),_=d&&i&&parseInt(i[1],10)<15;return e._codecs={mp3:!(u||!t&&!o.canPlayType("audio/mp3;").replace(/^no$/,"")),mpeg:!!t,opus:!!o.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!o.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(o.canPlayType('audio/wav; codecs="1"')||o.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!o.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!o.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(o.canPlayType("audio/x-m4a;")||o.canPlayType("audio/m4a;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(o.canPlayType("audio/x-m4b;")||o.canPlayType("audio/m4b;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(o.canPlayType("audio/x-mp4;")||o.canPlayType("audio/mp4;")||o.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!(_||!o.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!o.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(o.canPlayType("audio/x-flac;")||o.canPlayType("audio/flac;")).replace(/^no$/,"")},e},_unlockAudio:function(){var e=this||n;if(!e._audioUnlocked&&e.ctx){e._audioUnlocked=!1,e.autoUnlock=!1,e._mobileUnloaded||44100===e.ctx.sampleRate||(e._mobileUnloaded=!0,e.unload()),e._scratchBuffer=e.ctx.createBuffer(1,1,22050);var o=function(n){for(;e._html5AudioPool.length0?d._seek:t._sprite[e][0]/1e3),s=Math.max(0,(t._sprite[e][0]+t._sprite[e][1])/1e3-_),l=1e3*s/Math.abs(d._rate),c=t._sprite[e][0]/1e3,f=(t._sprite[e][0]+t._sprite[e][1])/1e3;d._sprite=e,d._ended=!1;var p=function(){d._paused=!1,d._seek=_,d._start=c,d._stop=f,d._loop=!(!d._loop&&!t._sprite[e][2])};if(_>=f)return void t._ended(d);var m=d._node;if(t._webAudio){var v=function(){t._playLock=!1,p(),t._refreshBuffer(d);var e=d._muted||t._muted?0:d._volume;m.gain.setValueAtTime(e,n.ctx.currentTime),d._playStart=n.ctx.currentTime,void 0===m.bufferSource.start?d._loop?m.bufferSource.noteGrainOn(0,_,86400):m.bufferSource.noteGrainOn(0,_,s):d._loop?m.bufferSource.start(0,_,86400):m.bufferSource.start(0,_,s),l!==1/0&&(t._endTimers[d._id]=setTimeout(t._ended.bind(t,d),l)),o||setTimeout(function(){t._emit("play",d._id),t._loadQueue()},0)};"running"===n.state&&"interrupted"!==n.ctx.state?v():(t._playLock=!0,t.once("resume",v),t._clearTimer(d._id))}else{var h=function(){m.currentTime=_,m.muted=d._muted||t._muted||n._muted||m.muted,m.volume=d._volume*n.volume(),m.playbackRate=d._rate;try{var r=m.play();if(r&&"undefined"!=typeof Promise&&(r instanceof Promise||"function"==typeof r.then)?(t._playLock=!0,p(),r.then(function(){t._playLock=!1,m._unlocked=!0,o?t._loadQueue():t._emit("play",d._id)}).catch(function(){t._playLock=!1,t._emit("playerror",d._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction."),d._ended=!0,d._paused=!0})):o||(t._playLock=!1,p(),t._emit("play",d._id)),m.playbackRate=d._rate,m.paused)return void t._emit("playerror",d._id,"Playback was unable to start. This is most commonly an issue on mobile devices and Chrome where playback was not within a user interaction.");"__default"!==e||d._loop?t._endTimers[d._id]=setTimeout(t._ended.bind(t,d),l):(t._endTimers[d._id]=function(){t._ended(d),m.removeEventListener("ended",t._endTimers[d._id],!1)},m.addEventListener("ended",t._endTimers[d._id],!1))}catch(e){t._emit("playerror",d._id,e)}};"data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA"===m.src&&(m.src=t._src,m.load());var y=window&&window.ejecta||!m.readyState&&n._navigator.isCocoonJS;if(m.readyState>=3||y)h();else{t._playLock=!0,t._state="loading";var g=function(){t._state="loaded",h(),m.removeEventListener(n._canPlayEvent,g,!1)};m.addEventListener(n._canPlayEvent,g,!1),t._clearTimer(d._id)}}return d._id},pause:function(e){var n=this;if("loaded"!==n._state||n._playLock)return n._queue.push({event:"pause",action:function(){n.pause(e)}}),n;for(var o=n._getSoundIds(e),t=0;t=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else r.length>=2&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var a;if(!(void 0!==e&&e>=0&&e<=1))return a=o?t._soundById(o):t._sounds[0],a?a._volume:0;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"volume",action:function(){t.volume.apply(t,r)}}),t;void 0===o&&(t._volume=e),o=t._getSoundIds(o);for(var u=0;u0?t/_:t),l=Date.now();e._fadeTo=o,e._interval=setInterval(function(){var r=(Date.now()-l)/t;l=Date.now(),d+=i*r,d=Math.round(100*d)/100,d=i<0?Math.max(o,d):Math.min(o,d),u._webAudio?e._volume=d:u.volume(d,e._id,!0),a&&(u._volume=d),(on&&d>=o)&&(clearInterval(e._interval),e._interval=null,e._fadeTo=null,u.volume(o,e._id),u._emit("fade",e._id))},s)},_stopFade:function(e){var o=this,t=o._soundById(e);return t&&t._interval&&(o._webAudio&&t._node.gain.cancelScheduledValues(n.ctx.currentTime),clearInterval(t._interval),t._interval=null,o.volume(t._fadeTo,e),t._fadeTo=null,o._emit("fade",e)),o},loop:function(){var e,n,o,t=this,r=arguments;if(0===r.length)return t._loop;if(1===r.length){if("boolean"!=typeof r[0])return!!(o=t._soundById(parseInt(r[0],10)))&&o._loop;e=r[0],t._loop=e}else 2===r.length&&(e=r[0],n=parseInt(r[1],10));for(var a=t._getSoundIds(n),u=0;u=0?o=parseInt(r[0],10):e=parseFloat(r[0])}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));var d;if("number"!=typeof e)return d=t._soundById(o),d?d._rate:t._rate;if("loaded"!==t._state||t._playLock)return t._queue.push({event:"rate",action:function(){t.rate.apply(t,r)}}),t;void 0===o&&(t._rate=e),o=t._getSoundIds(o);for(var i=0;i=0?o=parseInt(r[0],10):t._sounds.length&&(o=t._sounds[0]._id,e=parseFloat(r[0]))}else 2===r.length&&(e=parseFloat(r[0]),o=parseInt(r[1],10));if(void 0===o)return 0;if("number"==typeof e&&("loaded"!==t._state||t._playLock))return t._queue.push({event:"seek",action:function(){t.seek.apply(t,r)}}),t;var d=t._soundById(o);if(d){if(!("number"==typeof e&&e>=0)){if(t._webAudio){var i=t.playing(o)?n.ctx.currentTime-d._playStart:0,_=d._rateSeek?d._rateSeek-d._seek:0;return d._seek+(_+i*Math.abs(d._rate))}return d._node.currentTime}var s=t.playing(o);s&&t.pause(o,!0),d._seek=e,d._ended=!1,t._clearTimer(o),t._webAudio||!d._node||isNaN(d._node.duration)||(d._node.currentTime=e);var l=function(){s&&t.play(o,!0),t._emit("seek",o)};if(s&&!t._webAudio){var c=function(){t._playLock?setTimeout(c,0):l()};setTimeout(c,0)}else l()}return t},playing:function(e){var n=this;if("number"==typeof e){var o=n._soundById(e);return!!o&&!o._paused}for(var t=0;t=0&&n._howls.splice(a,1);var u=!0;for(t=0;t=0){u=!1;break}return r&&u&&delete r[e._src],n.noAudio=!1,e._state="unloaded",e._sounds=[],e=null,null},on:function(e,n,o,t){var r=this,a=r["_on"+e];return"function"==typeof n&&a.push(t?{id:o,fn:n,once:t}:{id:o,fn:n}),r},off:function(e,n,o){var t=this,r=t["_on"+e],a=0;if("number"==typeof n&&(o=n,n=null),n||o)for(a=0;a=0;a--)r[a].id&&r[a].id!==n&&"load"!==e||(setTimeout(function(e){e.call(this,n,o)}.bind(t,r[a].fn),0),r[a].once&&t.off(e,r[a].fn,r[a].id));return t._loadQueue(e),t},_loadQueue:function(e){var n=this;if(n._queue.length>0){var o=n._queue[0];o.event===e&&(n._queue.shift(),n._loadQueue()),e||o.action()}return n},_ended:function(e){var o=this,t=e._sprite;if(!o._webAudio&&e._node&&!e._node.paused&&!e._node.ended&&e._node.currentTime=0;t--){if(o<=n)return;e._sounds[t]._ended&&(e._webAudio&&e._sounds[t]._node&&e._sounds[t]._node.disconnect(0),e._sounds.splice(t,1),o--)}}},_getSoundIds:function(e){var n=this;if(void 0===e){for(var o=[],t=0;t=0;if(!e.bufferSource)return o;if(n._scratchBuffer&&e.bufferSource&&(e.bufferSource.onended=null,e.bufferSource.disconnect(0),t))try{e.bufferSource.buffer=n._scratchBuffer}catch(e){}return e.bufferSource=null,o},_clearSound:function(e){/MSIE |Trident\//.test(n._navigator&&n._navigator.userAgent)||(e.src="data:audio/wav;base64,UklGRigAAABXQVZFZm10IBIAAAABAAEARKwAAIhYAQACABAAAABkYXRhAgAAAAEA")}};var t=function(e){this._parent=e,this.init()};t.prototype={init:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,o._sounds.push(e),e.create(),e},create:function(){var e=this,o=e._parent,t=n._muted||e._muted||e._parent._muted?0:e._volume;return o._webAudio?(e._node=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),e._node.gain.setValueAtTime(t,n.ctx.currentTime),e._node.paused=!0,e._node.connect(n.masterGain)):n.noAudio||(e._node=n._obtainHtml5Audio(),e._errorFn=e._errorListener.bind(e),e._node.addEventListener("error",e._errorFn,!1),e._loadFn=e._loadListener.bind(e),e._node.addEventListener(n._canPlayEvent,e._loadFn,!1),e._endFn=e._endListener.bind(e),e._node.addEventListener("ended",e._endFn,!1),e._node.src=o._src,e._node.preload=!0===o._preload?"auto":o._preload,e._node.volume=t*n.volume(),e._node.load()),e},reset:function(){var e=this,o=e._parent;return e._muted=o._muted,e._loop=o._loop,e._volume=o._volume,e._rate=o._rate,e._seek=0,e._rateSeek=0,e._paused=!0,e._ended=!0,e._sprite="__default",e._id=++n._counter,e},_errorListener:function(){var e=this;e._parent._emit("loaderror",e._id,e._node.error?e._node.error.code:0),e._node.removeEventListener("error",e._errorFn,!1)},_loadListener:function(){var e=this,o=e._parent;o._duration=Math.ceil(10*e._node.duration)/10,0===Object.keys(o._sprite).length&&(o._sprite={__default:[0,1e3*o._duration]}),"loaded"!==o._state&&(o._state="loaded",o._emit("load"),o._loadQueue()),e._node.removeEventListener(n._canPlayEvent,e._loadFn,!1)},_endListener:function(){var e=this,n=e._parent;n._duration===1/0&&(n._duration=Math.ceil(10*e._node.duration)/10,n._sprite.__default[1]===1/0&&(n._sprite.__default[1]=1e3*n._duration),n._ended(e)),e._node.removeEventListener("ended",e._endFn,!1)}};var r={},a=function(e){var n=e._src;if(r[n])return e._duration=r[n].duration,void i(e);if(/^data:[^;]+;base64,/.test(n)){for(var o=atob(n.split(",")[1]),t=new Uint8Array(o.length),a=0;a0?(r[o._src]=e,i(o,e)):t()};"undefined"!=typeof Promise&&1===n.ctx.decodeAudioData.length?n.ctx.decodeAudioData(e).then(a).catch(t):n.ctx.decodeAudioData(e,a,t)},i=function(e,n){n&&!e._duration&&(e._duration=n.duration),0===Object.keys(e._sprite).length&&(e._sprite={__default:[0,1e3*e._duration]}),"loaded"!==e._state&&(e._state="loaded",e._emit("load"),e._loadQueue())},_=function(){if(n.usingWebAudio){try{"undefined"!=typeof AudioContext?n.ctx=new AudioContext:"undefined"!=typeof webkitAudioContext?n.ctx=new webkitAudioContext:n.usingWebAudio=!1}catch(e){n.usingWebAudio=!1}n.ctx||(n.usingWebAudio=!1);var e=/iP(hone|od|ad)/.test(n._navigator&&n._navigator.platform),o=n._navigator&&n._navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/),t=o?parseInt(o[1],10):null;if(e&&t&&t<9){var r=/safari/.test(n._navigator&&n._navigator.userAgent.toLowerCase());n._navigator&&!r&&(n.usingWebAudio=!1)}n.usingWebAudio&&(n.masterGain=void 0===n.ctx.createGain?n.ctx.createGainNode():n.ctx.createGain(),n.masterGain.gain.setValueAtTime(n._muted?0:n._volume,n.ctx.currentTime),n.masterGain.connect(n.ctx.destination)),n._setup()}};"function"==typeof define&&define.amd&&define([],function(){return{Howler:n,Howl:o}}),"undefined"!=typeof exports&&(exports.Howler=n,exports.Howl=o),"undefined"!=typeof global?(global.HowlerGlobal=e,global.Howler=n,global.Howl=o,global.Sound=t):"undefined"!=typeof window&&(window.HowlerGlobal=e,window.Howler=n,window.Howl=o,window.Sound=t)}(); \ No newline at end of file diff --git a/static/player.js b/static/player.js deleted file mode 100644 index 5fe7d03..0000000 --- a/static/player.js +++ /dev/null @@ -1,405 +0,0 @@ -/*! - * Howler.js Audio Player Demo - * howlerjs.com - * - * (c) 2013-2020, James Simpson of GoldFire Studios - * goldfirestudios.com - * - * MIT License - */ - -// Cache references to DOM elements. -var elms = ['track', 'timer', 'duration', 'playBtn', 'pauseBtn', 'prevBtn', 'nextBtn', 'playlistBtn', 'volumeBtn', 'progress', 'bar', 'wave', 'loading', 'playlist', 'list', 'volume', 'barEmpty', 'barFull', 'sliderBtn']; -elms.forEach(function(elm) { - window[elm] = document.getElementById(elm); -}); - -/** - * Player class containing the state of our playlist and where we are in it. - * Includes all methods for playing, skipping, updating the display, etc. - * @param {Array} playlist Array of objects with playlist song details ({title, file, howl}). - */ -var Player = function(playlist) { - this.playlist = playlist; - this.index = 0; - - // Display the title of the first track. - track.innerHTML = '1. ' + playlist[0].title; - - // Setup the playlist display. - playlist.forEach(function(song) { - var div = document.createElement('div'); - div.className = 'list-song'; - div.innerHTML = song.title; - div.onclick = function() { - player.skipTo(playlist.indexOf(song)); - }; - list.appendChild(div); - }); -}; -Player.prototype = { - /** - * Play a song in the playlist. - * @param {Number} index Index of the song in the playlist (leave empty to play the first or current). - */ - play: function(index) { - var self = this; - var sound; - - index = typeof index === 'number' ? index : self.index; - var data = self.playlist[index]; - - // If we already loaded this track, use the current one. - // Otherwise, setup and load a new Howl. - if (data.howl) { - sound = data.howl; - } else { - sound = data.howl = new Howl({ - src: [ './' + data.file ], - html5: true, // Force to HTML5 so that the audio can stream in (best for large files). - onplay: function() { - // Display the duration. - duration.innerHTML = self.formatTime(Math.round(sound.duration())); - - // Start updating the progress of the track. - requestAnimationFrame(self.step.bind(self)); - - // Start the wave animation if we have already loaded - wave.container.style.display = 'block'; - bar.style.display = 'none'; - pauseBtn.style.display = 'block'; - }, - onload: function() { - // Start the wave animation. - wave.container.style.display = 'block'; - bar.style.display = 'none'; - loading.style.display = 'none'; - }, - onend: function() { - // Stop the wave animation. - wave.container.style.display = 'none'; - bar.style.display = 'block'; - self.skip('next'); - }, - onpause: function() { - // Stop the wave animation. - wave.container.style.display = 'none'; - bar.style.display = 'block'; - }, - onstop: function() { - // Stop the wave animation. - wave.container.style.display = 'none'; - bar.style.display = 'block'; - }, - onseek: function() { - // Start updating the progress of the track. - requestAnimationFrame(self.step.bind(self)); - } - }); - } - - // Begin playing the sound. - sound.play(); - - // Update the track display. - track.innerHTML = (index + 1) + '. ' + data.title; - - // Show the pause button. - if (sound.state() === 'loaded') { - playBtn.style.display = 'none'; - pauseBtn.style.display = 'block'; - } else { - loading.style.display = 'block'; - playBtn.style.display = 'none'; - pauseBtn.style.display = 'none'; - } - - // Keep track of the index we are currently playing. - self.index = index; - }, - - /** - * Pause the currently playing track. - */ - pause: function() { - var self = this; - - // Get the Howl we want to manipulate. - var sound = self.playlist[self.index].howl; - - // Puase the sound. - sound.pause(); - - // Show the play button. - playBtn.style.display = 'block'; - pauseBtn.style.display = 'none'; - }, - - /** - * Skip to the next or previous track. - * @param {String} direction 'next' or 'prev'. - */ - skip: function(direction) { - var self = this; - - // Get the next track based on the direction of the track. - var index = 0; - if (direction === 'prev') { - index = self.index - 1; - if (index < 0) { - index = self.playlist.length - 1; - } - } else { - index = self.index + 1; - if (index >= self.playlist.length) { - index = 0; - } - } - - self.skipTo(index); - }, - - /** - * Skip to a specific track based on its playlist index. - * @param {Number} index Index in the playlist. - */ - skipTo: function(index) { - var self = this; - - // Stop the current track. - if (self.playlist[self.index].howl) { - self.playlist[self.index].howl.stop(); - } - - // Reset progress. - progress.style.width = '0%'; - - // Play the new track. - self.play(index); - }, - - /** - * Set the volume and update the volume slider display. - * @param {Number} val Volume between 0 and 1. - */ - volume: function(val) { - var self = this; - - // Update the global volume (affecting all Howls). - Howler.volume(val); - - // Update the display on the slider. - var barWidth = (val * 90) / 100; - barFull.style.width = (barWidth * 100) + '%'; - sliderBtn.style.left = (window.innerWidth * barWidth + window.innerWidth * 0.05 - 25) + 'px'; - }, - - /** - * Seek to a new position in the currently playing track. - * @param {Number} per Percentage through the song to skip. - */ - seek: function(per) { - var self = this; - - // Get the Howl we want to manipulate. - var sound = self.playlist[self.index].howl; - - // Convert the percent into a seek position. - if (sound.playing()) { - sound.seek(sound.duration() * per); - } - }, - - /** - * The step called within requestAnimationFrame to update the playback position. - */ - step: function() { - var self = this; - - // Get the Howl we want to manipulate. - var sound = self.playlist[self.index].howl; - - // Determine our current seek position. - var seek = sound.seek() || 0; - timer.innerHTML = self.formatTime(Math.round(seek)); - progress.style.width = (((seek / sound.duration()) * 100) || 0) + '%'; - - // If the sound is still playing, continue stepping. - if (sound.playing()) { - requestAnimationFrame(self.step.bind(self)); - } - }, - - /** - * Toggle the playlist display on/off. - */ - togglePlaylist: function() { - var self = this; - var display = (playlist.style.display === 'block') ? 'none' : 'block'; - - setTimeout(function() { - playlist.style.display = display; - }, (display === 'block') ? 0 : 500); - playlist.className = (display === 'block') ? 'fadein' : 'fadeout'; - }, - - /** - * Toggle the volume display on/off. - */ - toggleVolume: function() { - var self = this; - var display = (volume.style.display === 'block') ? 'none' : 'block'; - - setTimeout(function() { - volume.style.display = display; - }, (display === 'block') ? 0 : 500); - volume.className = (display === 'block') ? 'fadein' : 'fadeout'; - }, - - /** - * Format the time from seconds to M:SS. - * @param {Number} secs Seconds to format. - * @return {String} Formatted time. - */ - formatTime: function(secs) { - var minutes = Math.floor(secs / 60) || 0; - var seconds = (secs - minutes * 60) || 0; - - return minutes + ':' + (seconds < 10 ? '0' : '') + seconds; - } -}; - -// Setup our new audio player class and pass it the playlist. -var player = new Player([ - { - title: 'Ö1 Morgenjournal', - file: 'stream', - howl: null - } -]); - -// Bind our player controls. -playBtn.addEventListener('click', function() { - player.play(); -}); -pauseBtn.addEventListener('click', function() { - player.pause(); -}); -prevBtn.addEventListener('click', function() { - var sound = player.playlist[player.index].howl; - - if (sound && sound.playing()) { - var currentSeek = sound.seek() || 0; - var newSeek = currentSeek - 10; // Subtract 10 seconds - var duration = sound.duration(); - - // Make sure we don't seek beyond the end of the track - if (newSeek > 0) { - sound.seek(newSeek); - } else { - // If seeking would go past the beginning, go to the beginning - sound.seek(0); - } - } -}); -nextBtn.addEventListener('click', function() { - var sound = player.playlist[player.index].howl; - - if (sound && sound.playing()) { - var currentSeek = sound.seek() || 0; - var newSeek = currentSeek + 10; // Add 10 seconds - var duration = sound.duration(); - - // Make sure we don't seek beyond the end of the track - if (newSeek < duration) { - sound.seek(newSeek); - } else { - // If seeking would go past the end, go to the end - sound.seek(duration - 0.1); // Leave a small buffer to avoid issues - } - } -}); -waveform.addEventListener('click', function(event) { - player.seek(event.clientX / window.innerWidth); -}); -playlistBtn.addEventListener('click', function() { - player.togglePlaylist(); -}); -playlist.addEventListener('click', function() { - player.togglePlaylist(); -}); -volumeBtn.addEventListener('click', function() { - player.toggleVolume(); -}); -volume.addEventListener('click', function() { - player.toggleVolume(); -}); - -// Setup the event listeners to enable dragging of volume slider. -barEmpty.addEventListener('click', function(event) { - var per = event.layerX / parseFloat(barEmpty.scrollWidth); - player.volume(per); -}); -sliderBtn.addEventListener('mousedown', function() { - window.sliderDown = true; -}); -sliderBtn.addEventListener('touchstart', function() { - window.sliderDown = true; -}); -volume.addEventListener('mouseup', function() { - window.sliderDown = false; -}); -volume.addEventListener('touchend', function() { - window.sliderDown = false; -}); - -var move = function(event) { - if (window.sliderDown) { - var x = event.clientX || event.touches[0].clientX; - var startX = window.innerWidth * 0.05; - var layerX = x - startX; - var per = Math.min(1, Math.max(0, layerX / parseFloat(barEmpty.scrollWidth))); - player.volume(per); - } -}; - -volume.addEventListener('mousemove', move); -volume.addEventListener('touchmove', move); - -// Setup the "waveform" animation. -var wave = new SiriWave({ - container: waveform, - width: window.innerWidth, - height: window.innerHeight * 0.3, - cover: true, - speed: 0.03, - amplitude: 0.7, - frequency: 2 -}); -wave.start(); - -// Update the height of the wave animation. -// These are basically some hacks to get SiriWave.js to do what we want. -var resize = function() { - var height = window.innerHeight * 0.3; - var width = window.innerWidth; - wave.height = height; - wave.height_2 = height / 2; - wave.MAX = wave.height_2 - 4; - wave.width = width; - wave.width_2 = width / 2; - wave.width_4 = width / 4; - wave.canvas.height = height; - wave.canvas.width = width; - wave.container.style.margin = -(height / 2) + 'px auto'; - - // Update the position of the slider. - var sound = player.playlist[player.index].howl; - if (sound) { - var vol = sound.volume(); - var barWidth = (vol * 0.9); - sliderBtn.style.left = (window.innerWidth * barWidth + window.innerWidth * 0.05 - 25) + 'px'; - } -}; -window.addEventListener('resize', resize); -resize(); diff --git a/static/siriwave.js b/static/siriwave.js deleted file mode 100644 index f93e375..0000000 --- a/static/siriwave.js +++ /dev/null @@ -1,148 +0,0 @@ -/* Modified from https://github.com/CaffeinaLab/SiriWaveJS */ - -(function() { - -function SiriWave(opt) { - opt = opt || {}; - - this.phase = 0; - this.run = false; - - // UI vars - - this.ratio = opt.ratio || window.devicePixelRatio || 1; - - this.width = this.ratio * (opt.width || 320); - this.width_2 = this.width / 2; - this.width_4 = this.width / 4; - - this.height = this.ratio * (opt.height || 100); - this.height_2 = this.height / 2; - - this.MAX = (this.height_2) - 4; - - // Constructor opt - - this.amplitude = opt.amplitude || 1; - this.speed = opt.speed || 0.2; - this.frequency = opt.frequency || 6; - this.color = (function hex2rgb(hex){ - var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, function(m,r,g,b) { return r + r + g + g + b + b; }); - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? - parseInt(result[1],16).toString()+','+parseInt(result[2], 16).toString()+','+parseInt(result[3], 16).toString() - : null; - })(opt.color || '#fff') || '255,255,255'; - - // Canvas - - this.canvas = document.createElement('canvas'); - this.canvas.width = this.width; - this.canvas.height = this.height; - if (opt.cover) { - this.canvas.style.width = this.canvas.style.height = '100%'; - } else { - this.canvas.style.width = (this.width / this.ratio) + 'px'; - this.canvas.style.height = (this.height / this.ratio) + 'px'; - }; - - this.container = opt.container || document.body; - this.container.appendChild(this.canvas); - - this.ctx = this.canvas.getContext('2d'); - - // Start - - if (opt.autostart) { - this.start(); - } -} - -SiriWave.prototype._GATF_cache = {}; -SiriWave.prototype._globAttFunc = function(x) { - if (SiriWave.prototype._GATF_cache[x] == null) { - SiriWave.prototype._GATF_cache[x] = Math.pow(4/(4+Math.pow(x,4)), 4); - } - return SiriWave.prototype._GATF_cache[x]; -}; - -SiriWave.prototype._xpos = function(i) { - return this.width_2 + i * this.width_4; -}; - -SiriWave.prototype._ypos = function(i, attenuation) { - var att = (this.MAX * this.amplitude) / attenuation; - return this.height_2 + this._globAttFunc(i) * att * Math.sin(this.frequency * i - this.phase); -}; - -SiriWave.prototype._drawLine = function(attenuation, color, width){ - this.ctx.moveTo(0,0); - this.ctx.beginPath(); - this.ctx.strokeStyle = color; - this.ctx.lineWidth = width || 1; - - var i = -2; - while ((i += 0.01) <= 2) { - var y = this._ypos(i, attenuation); - if (Math.abs(i) >= 1.90) y = this.height_2; - this.ctx.lineTo(this._xpos(i), y); - } - - this.ctx.stroke(); -}; - -SiriWave.prototype._clear = function() { - this.ctx.globalCompositeOperation = 'destination-out'; - this.ctx.fillRect(0, 0, this.width, this.height); - this.ctx.globalCompositeOperation = 'source-over'; -}; - -SiriWave.prototype._draw = function() { - if (this.run === false) return; - - this.phase = (this.phase + Math.PI*this.speed) % (2*Math.PI); - - this._clear(); - this._drawLine(-2, 'rgba(' + this.color + ',0.1)'); - this._drawLine(-6, 'rgba(' + this.color + ',0.2)'); - this._drawLine(4, 'rgba(' + this.color + ',0.4)'); - this._drawLine(2, 'rgba(' + this.color + ',0.6)'); - this._drawLine(1, 'rgba(' + this.color + ',1)', 1.5); - - if (window.requestAnimationFrame) { - requestAnimationFrame(this._draw.bind(this)); - return; - }; - setTimeout(this._draw.bind(this), 20); -}; - -/* API */ - -SiriWave.prototype.start = function() { - this.phase = 0; - this.run = true; - this._draw(); -}; - -SiriWave.prototype.stop = function() { - this.phase = 0; - this.run = false; -}; - -SiriWave.prototype.setSpeed = function(v) { - this.speed = v; -}; - -SiriWave.prototype.setNoise = SiriWave.prototype.setAmplitude = function(v) { - this.amplitude = Math.max(Math.min(v, 1), 0); -}; - - -if (typeof define === 'function' && define.amd) { - define(function(){ return SiriWave; }); - return; -}; -window.SiriWave = SiriWave; - -})(); diff --git a/static/styles.css b/static/styles.css deleted file mode 100644 index 6383747..0000000 --- a/static/styles.css +++ /dev/null @@ -1,331 +0,0 @@ -/* https://howlerjs.com/assets/howler.js/examples/player/styles.css */ -html { - width: 100%; - height: 100%; - overflow: hidden; - padding: 0; - margin: 0; - outline: 0; -} - -body { - width: 100%; - height: 100%; - padding: 0; - margin: 0; - overflow: hidden; - background: #bb71f3; - background: -moz-linear-gradient(-45deg, #bb71f3 0%, #3d4d91 100%); - background: -webkit-linear-gradient(-45deg, #bb71f3 0%, #3d4d91 100%); - background: linear-gradient(135deg, #bb71f3 0%, #3d4d91 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#bb71f3', endColorstr='#3d4d91', GradientType=1); - font-family: "Helvetica Neue", "Futura", "Trebuchet MS", Arial; - -webkit-user-select: none; - user-select: none; - -webkit-tap-highlight-color: rgba(255, 255, 255, 0); -} - -/* Top Info */ -#title { - position: absolute; - width: 100%; - top: 3%; - line-height: 34px; - height: 34px; - text-align: center; - font-size: 34px; - opacity: 0.9; - font-weight: 300; - color: #fff; - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.33); -} -#timer { - position: absolute; - top: 0; - left: 3%; - text-align: left; - font-size: 26px; - opacity: 0.9; - font-weight: 300; - color: #fff; - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.33); -} -#duration { - position: absolute; - top: 0; - right: 3%; - text-align: right; - font-size: 26px; - opacity: 0.5; - font-weight: 300; - color: #fff; - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.33); -} - -/* Controls */ -.controlsOuter { - position: absolute; - width: 100%; - height: 70px; - bottom: 3%; -} -.controlsInner { - position: absolute; - width: 340px; - height: 70px; - left: 50%; - margin: 0 -170px; -} -.btn { - position: absolute; - cursor: pointer; - opacity: 0.9; - -webkit-filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.33)); - filter: drop-shadow(1px 1px 2px rgba(0, 0, 0, 0.33)); - -webkit-user-select: none; - user-select: none; -} -.btn:hover { - opacity: 1; -} -#playBtn { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEUAAABGCAYAAACaGVmHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QThERThENUFDNkJEMTFFNTk2RTBDMTRBMkYyNjVGMzQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QThERThENUJDNkJEMTFFNTk2RTBDMTRBMkYyNjVGMzQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBOERFOEQ1OEM2QkQxMUU1OTZFMEMxNEEyRjI2NUYzNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBOERFOEQ1OUM2QkQxMUU1OTZFMEMxNEEyRjI2NUYzNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnFM7yIAAAFWSURBVHja7NRJDoMwDEDRcPL2ZoVeLEUtCyoCZPBsf8mS10+Wp5zzK6X0XGdJ0bdpRcnbPgfOESUFzjmKe5wrFLc4NSjucFpQ3OD0oJjHGUExiwOBYg4HEsUMDgaKehxMFLU4FCjqcChR1OBwoIjH4UQRiyMBRRyOJBQxOBJR2HEko7DhaEAhx9GEQoajEQUdRzMKGo4FFHAcSyhgOBZRhnEso3TjeEBpxvGEUo3jEeUWxzPKKU6gFHACpYATKMfegbLDWOcRl/Jr2X7JHI+2gOEZ5RTDI8othieUagwPKM0YllG6MSyiDGNYQgHDsIACjqEZBQ1DIwo6hiYUMgwNKOQYklHYMCSisGNIQhGDIQFFHAYnilgMDhTxGJQoajAoUNRhYKKoxcBAUY8BiWIGAwLFHMYIilmMHhTzGC0objBqUNxhXKG4xSihuMfYo8yB8d9HgAEATyefBJWpw70AAAAASUVORK5CYII='); - width: 69px; - height: 70px; - left: 50%; - margin: auto -34.5px; -} -#pauseBtn { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEUAAABGCAYAAACaGVmHAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDE4MjkzRjNDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDE4MjkzRjRDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBOERFOEQ1Q0M2QkQxMUU1OTZFMEMxNEEyRjI2NUYzNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMTgyOTNGMkM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pne5d1AAAAB8SURBVHja7NCxCQAwAALBuP/QZoEUlinua0G4tD1j83Asv/4GChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFChQoUKBAgQIFCpRXV4ABAOgpXYTDYwEwAAAAAElFTkSuQmCC'); - width: 69px; - height: 70px; - left: 50%; - margin: auto -34.5px; - display: none; -} -#prevBtn { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDE4MjkzRkJDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDE4MjkzRkNDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMTgyOTNGOUM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMTgyOTNGQUM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PndeAH8AAACtSURBVHja7NXJCcAgEAVQEevK0lk6M1aW6CGQQBBn+ephBv7F0wNn8Vd7OWCWnOjd2FpzYk7K2cJAxFEA78cwA6I3porohWlCoDEkBArDQmhjRAgtjApCilFFcDEQBAcTUYinKLcJCqFinGEMYxjDgDFpJkzZwDsSRf2mE4ni9gwEJW1gVZTWNKmgtEdbhELtGRYKvfRIqF4buAnV+xxUUaNu0y9q9KH8oG4BBgDjdpk0jMoz1gAAAABJRU5ErkJggg=='); - width: 35px; - height: 35px; - left: 0; - top: 50%; - margin: -17.5px auto; -} -#nextBtn { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDE4MjkzRjdDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDE4MjkzRjhDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMTgyOTNGNUM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowMTgyOTNGNkM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PiFbkXsAAACvSURBVHja7NZBDoAgDARA9GPiz/yZ8DKsxgMHY1rYBQ5sshdCwiQcWpdSOqWb1BGrSn6RiTJjmKhiDANVjUGiYBgECo6pQdEwJSg6xoJqhtGgVFkeETZBekhjdqZ6g4H5QnXH5Cg/CkadiZmYiZkYdtYGb8QRMDdi144C1jfFd0AG69RG7jNB6nsvV3+IZhgNgo6xIGiYEgQcU4OAYRCIagwSUYxhIMwYJsKEuQQYABTs+qTMuF1rAAAAAElFTkSuQmCC'); - width: 35px; - height: 35px; - right: 0; - top: 50%; - margin: -17.5px auto; -} -#playlistBtn { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MUVBQzMwNzRDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MUVBQzMwNzVDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoxRUFDMzA3MkM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoxRUFDMzA3M0M3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PnWBPa0AAADGSURBVHjaYvz//z/DYAFMDIMIjDpm1DHDwjH/0fDugXAMCxK7AojPAnEHmpo0IFaisTsqIEECLPT+Q4ALlL0bihmQ+LQGYLsYoSXwf2iovAdiYyjbdaCiaQ+S2FkopjtgHK2bCESTC5r4+4GIKuQEjAz2DGQCHhTlDAtaLtoDjSJkoATN7iMzmjrRxO+NljODsZzpwBJNs0bLGShwhToCvWHVQYes7YruGJiFgljKmpEbTa5YKsrRcmbUMaOOGXUMNQBAgAEAm2XFJrn+jrsAAAAASUVORK5CYII='); - width: 35px; - height: 35px; - top: 50%; - left: 3%; - margin: -17.5px auto; -} -#volumeBtn { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACMAAAAjCAYAAAAe2bNZAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyhpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTExIDc5LjE1ODMyNSwgMjAxNS8wOS8xMC0wMToxMDoyMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MUVBQzMwNzBDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MUVBQzMwNzFDNzI0MTFFNTk2RTBDMTRBMkYyNjVGMzQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoxRUFDMzA2RUM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoxRUFDMzA2RkM3MjQxMUU1OTZFMEMxNEEyRjI2NUYzNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtAZ+FgAAAHRSURBVHja7FjRbYMwEIWqC7CCO4IzgjMCHYEV6AjuCHSEMAKMkIwAI5ARXFt9rox1phDA5KMnPSGwOZ4fx/mOVCmVPIu9JE9ke5GRGpejyeQanUapkXlj5lzEIMM1GqjRAyG1eNCLCeAVyDQq9WOdRoHrDeDP7YCM8reGiNQYQER6D6DIGHDc02xFJsfqjF00GDEnRCaBegp+RmMp8oyYERcmAAvMvWl8aLSBuQ2O58D4Ff7eqJiZa4MTF1OYUsZAwF9BKaOw0tsf6pjx+wwVXWU41Pwk1DF2opQRK7+skDIyECMlrv8GfoztwMaW9K7XTqKMujeZV8SQma31eO0iNpkW8L/a3t02Yu7aITL8CDL2S2VE/jqsnnHJ3I8urnpKldhkOEFmdB6TTO7kFveVRScjoExLqBWVTIbsax765RFh7n74GoFMiQefCLXcbWFEhs/MFfeFZGon9fsx1I78PVDPyA3qmXyqnhEzV1lgRT124/rBSq+Dj/Pa7sDUPVesrEGRvUSZMlQ/rSmgCqc7qBZ0B7aQ37RVsb2QJOIp1DcNUDXbg4wFw2qV06j5ZCqQYSE/yYZ1LxVPvjJ86v50p/8ztr96X3JT+v+zKGDfAgwAZkMcn0x+AsMAAAAASUVORK5CYII='); - width: 35px; - height: 35px; - top: 50%; - right: 3%; - margin: -17.5px auto; -} - -/* Progress */ -#waveform { - width: 100%; - height: 30%; - position: absolute; - left: 0; - top: 50%; - margin: -15% auto; - display: none; - cursor: pointer; - opacity: 0.8; - -webkit-user-select: none; - user-select: none; -} -#waveform:hover { - opacity: 1; -} -#bar { - position: absolute; - top: 50%; - left: 0; - width: 100%; - height: 2px; - background-color: rgba(255, 255, 255, 0.9); - box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.33); - opacity: 0.9; -} -#progress { - position: absolute; - top: 0; - left: 0; - width: 0%; - height: 100%; - background-color: rgba(0, 0, 0, 0.1); - z-index: -1; -} - -/* Loading */ -#loading { - position: absolute; - left: 50%; - top: 50%; - margin: -35px; - width: 70px; - height: 70px; - background-color: #fff; - border-radius: 100%; - -webkit-animation: sk-scaleout 1.0s infinite ease-in-out; - animation: sk-scaleout 1.0s infinite ease-in-out; - display: none; -} -@-webkit-keyframes sk-scaleout { - 0% { -webkit-transform: scale(0) } - 100% { - -webkit-transform: scale(1.0); - opacity: 0; - } -} -@keyframes sk-scaleout { - 0% { - -webkit-transform: scale(0); - transform: scale(0); - } 100% { - -webkit-transform: scale(1.0); - transform: scale(1.0); - opacity: 0; - } -} - -/* Plylist */ -#playlist { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - background-color: rgba(0, 0, 0, 0.5); - display: none; -} -#list { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} -.list-song { - width: 100%; - height: 120px; - font-size: 50px; - line-height: 120px; - text-align: center; - font-weight: bold; - color: #fff; - text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.33); -} -.list-song:hover { - background-color: rgba(255, 255, 255, 0.1); - cursor: pointer; -} - -/* Volume */ -#volume { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - background-color: rgba(0, 0, 0, 0.5); - touch-action: none; - -webkit-user-select: none; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - display: none; -} -.bar { - position: absolute; - top: 50%; - left: 5%; - margin: -5px auto; - height: 10px; - background-color: rgba(255, 255, 255, 0.9); - box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.33); -} -#barEmpty { - width: 90%; - opacity: 0.5; - box-shadow: none; - cursor: pointer; -} -#barFull { - width: 90%; -} -#sliderBtn { - width: 50px; - height: 50px; - position: absolute; - top: 50%; - left: 93.25%; - margin: -25px auto; - background-color: rgba(255, 255, 255, 0.8); - box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.33); - border-radius: 25px; - cursor: pointer; -} - -/* Fade-In */ -.fadeout { - webkit-animation: fadeout 0.5s; - -ms-animation: fadeout 0.5s; - animation: fadeout 0.5s; -} -.fadein { - webkit-animation: fadein 0.5s; - -ms-animation: fadein 0.5s; - animation: fadein 0.5s; -} -@keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} -@-webkit-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} -@-ms-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} -@keyframes fadeout { - from { opacity: 1; } - to { opacity: 0; } -} -@-webkit-keyframes fadeout { - from { opacity: 1; } - to { opacity: 0; } -} -@-ms-keyframes fadeout { - from { opacity: 1; } - to { opacity: 0; } -}