diff --git a/env.dist b/env.dist index 7ff0da3..14219a3 100644 --- a/env.dist +++ b/env.dist @@ -1,3 +1,25 @@ +# This is the environment for Groove on Demand. You can (re)populate your own environment +# by running the following command from the command-line: +# +# groove setup +# + +DATABASE_PATH=groove_on_demand.db + +# Admin user credentials +USERNAME=evilchili +PASSWORD=fnord + +# Web interface configuration HOST=127.0.0.1 -PORT==2323 +PORT=2323 +THEMES_PATH=themes +DEFAULT_THEME=blue_train +SECRET_KEY=fnord + +# Media scanner configuration +MEDIA_ROOT=/mnt/grunt/music/FLAC +MEDIA_GLOB=*.mp3,*.flac,*.m4a + +# Set this value to enable debugging DEBUG= diff --git a/static/player.js b/static/player.js deleted file mode 100644 index 3908e36..0000000 --- a/static/player.js +++ /dev/null @@ -1,241 +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', 'progress', 'bar', 'loading', 'playlist', 'list', '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, url, 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.url], - 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)); - - pauseBtn.style.display = 'block'; - }, - onload: function() { - loading.style.display = 'none'; - }, - onend: function() { - self.skip('next'); - }, - onpause: function() { - }, - onstop: function() { - }, - 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); - }, - - /** - * 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)); - } - }, - - /** - * 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(playlist_tracks); - -// Bind our player controls. -playBtn.addEventListener('click', function() { - player.play(); -}); -pauseBtn.addEventListener('click', function() { - player.pause(); -}); -prevBtn.addEventListener('click', function() { - player.skip('prev'); -}); -nextBtn.addEventListener('click', function() { - player.skip('next'); -}); diff --git a/static/styles.css b/static/styles.css deleted file mode 100644 index 5070ab9..0000000 --- a/static/styles.css +++ /dev/null @@ -1,259 +0,0 @@ -html { - width: 100%; - height: 100%; - overflow: hidden; - padding: 0; - margin: 0; - outline: 0; - font-family: 'Clarendon MT Std', sans-serif; -} - -body { - width: 100%; - height: 100%; - padding: 0; - margin: 0; - overflow: hidden; - background: rgb(0,4,16); - background: linear-gradient(0deg, rgba(0,4,16,1) 31%, rgba(1,125,147,1) 97%); -} - -a, a:visited { - text-decoration: none; - color: #f1f2f6; -} -a:active, a:hover { - color: #70bc45; -} - -#container { - overflow-x: wrap; - width: 96%; - height: 96%; - margin: auto; - margin-top: 1em; -} - -#details { - margin-left: 0.25em; - display: flex; - border-bottom: 1px solid rgb(255,255,255,0.3); -} - -#poster { - display: none; - width: 10em; - height: 10em; - background: #DDD; -} -#poster > img { - display: none; -} - - -/* informmation */ -#playlist_title { - margin-bottom: 0.25em; - color: #f1f2f6; -} -#playlist_desc { -} - - - -#player { - width: 100%; - margin: 1em 0; -} - -#controls { - width: 5em; - height: 5em; - vertical-align: middle; - padding-right: 1em; -} -#controls > div { - width: 5em; - height: 5em; -} - - -#track { - color: #70bc45; - font-size: 1.5em; -} - -#track_controls { - display: flex; -} - -#timer { - margin-left:0; - padding-left:0; -} -#duration { -} - -/* Controls */ -.widget { - margin-right: 0.5em; - padding: 0 0.5em; -} -.btn { - cursor: pointer; - opacity: 0.75; -} -.btn:hover { - opacity: 1; -} -#big_button { - position: relative; - background-color: #fff; - border-radius: 50%; - text-align: center; - vertical-align: middle; - line-height: 5em; -} -#playBtn { - font-family: sans-serif; - font-size: 5em; - padding-left: 0.1em; -} -#pauseBtn { - font-family: sans-serif; - display: none; - font-size: 4em; -} -#prevBtn { - color: #fff; - text-align: right; - vertical-align: middle; - line-height: 0.75em; - font-size: 1.5em; - padding:0; -} -#nextBtn { - color: #fff; - text-align: left; - vertical-align: middle; - line-height: 0.75em; - font-size: 1.5em; - padding:0; -} - - -/* Progress */ -#bar { - position: relative; - flex-grow: 1; - text-align: center; - vertical-align: middle; - line-height: 1em; -} -#bar > hr { - border: none; - border-bottom: 1px solid #000; - position: absolute; - height: 1px; - width: calc(100% - 1em); -} - -#progress { - position: relative; - width: 0%; - height: 0.33em; - margin: 0.33em 0; - background-color: #bbb; -} - -/* Loading */ -#loading { - display: none; -} - -/* Plylist */ -#playlist { - display: block; - margin-left: 0.25em; -} -#list { - font-size: 1.25em; -} -.list-song { - padding: 0.25em; -} -.list-song:hover { - cursor: pointer; - background: #f1f2f6; -} - -#footer { - font-family: helvetica, sans-serif; - border-top: 1px solid rgb(128,128,128,0.3); - text-align: right; - color: #888; - font-size: 0.9em; - letter-spacing: 0.1em; - margin: 0; - margin-top: 1em; - padding-top: 1em; -} -#footer a { - color: #aaa; -} - -/* Volume */ -#volume { - display: none; -} -.bar { -} -#barEmpty { - width: 90%; - opacity: 0.5; - cursor: pointer; -} -#barFull { - width: 90%; -} -#sliderBtn { - width: 50px; - height: 50px; - 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; } -} diff --git a/web-templates/playlist.tpl b/web-templates/playlist.tpl deleted file mode 100644 index c38c7d8..0000000 --- a/web-templates/playlist.tpl +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - Groove On Demand - - - - - - - -
- -
-
- -
-
-

{{playlist['name']}}

- {{playlist['description']}} -
-
- - - - - - -
-
-
-
-
-
-
-
-
-
0:00
-
-
-
-
-
0:00
-
-
-
-
-
-
-
- -
- - -