diff --git a/README.md b/README.md index 2cc18fd..7a47bb5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,75 @@ # Groove On Demand -WIP. See https://linernotes.club/@evilchili/109372059926262668 +Groove on Demand is a self-hosted application for creating and sharing music playlists. It streams music directly from your local media library using HTML5 audio and a Javascript player built on [Howler.js](https://github.com/goldfire/howler.js) and features a robust interactive command-line tool for managing the playlist database. + +`[ insert session capture here ]` + +## Installation + +### Prerequisites and Disclaimers + +Groove on Demand was developed against python 3.10 and should work on anything 3.7 or above. Minimal testing was done on this front. + +I have no idea if it will function on platforms besides Linux. Code was written to be portable but not tested to be portable. I also don't know if the dependencies support diverse platforms or not. `¯\_(ツ)_/¯` + +### 1. Download the latest release + +[ check the releases tab ] + +``` +wget https://github.com/evilchili/grooveondemand/releases/grooveondemand-0.9.tar.gz +``` + +### 2. Install + +``` +pip3 install grooveondemand-0.9.tar.gz +``` + +### 3. Generate the default configuration + +``` +~/.local/bin/groove setup > ~/.groove +``` + +### 4. Set the Media Root + +Edit `~/.groove` and defined `MEDIA_ROOT` to point to the directory containing your local audio files. For example: + +``` +MEDIA_ROOT=/media/audio/lossless +``` + +## Setting up the Databse + +Before creating playlists, you must scan your media and build a database of tracks. Do this by running: + +``` +groove scan +``` + +This may take a long time depending on the size of your library and the capabilities of your system. Progress will be displayed as the scan progresses. + +## Start the Interactive Shell + +Groove On Demand's interactive shell is optimized for quickly creating new playlists with as few keystrokes as possible. Start it by running: + +``` +groove shell +``` + +Use the `help` command to explore. + +## Serving Playlists + +Start the web server application by running: + +``` +groove server +``` + +It is strongly recommended you place the app behind a web proxy. + +## Okay, But Why? + +Because I wanted Mixtapes-as-a-Service but without the hassle of dealing with a third party, user authentication, and related shenanigans. Also I hadn't written code in a few years and was worried I was forgetting how to do it. I am not entirely reassured on that point. diff --git a/groove/cli.py b/groove/cli.py index 45cc840..14dd780 100644 --- a/groove/cli.py +++ b/groove/cli.py @@ -1,3 +1,4 @@ +import io import logging import os import sys @@ -20,33 +21,33 @@ from groove.exceptions import ConfigurationError from groove.console import Console SETUP_HELP = """ -Please make sure you set MEDIA_ROOT and SECRET_KEY in your environment. -By default, Groove on Demand will attempt to load these variables from -~/.groove, which may contain the following variables as well. See also -the --env paramter. +# Please make sure you set MEDIA_ROOT and SECRET_KEY in your environment. +# By default, Groove on Demand will attempt to load these variables from +# ~/.groove, which may contain the following variables as well. See also +# the --env paramter. # Set this one. The path containing your media files MEDIA_ROOT= # the kinds of files to import -# MEDIA_GLOB=*.mp3,*.flac,*.m4a +MEDIA_GLOB=*.mp3,*.flac,*.m4a # where to store the groove_on_demand.db sqlite database. -# DATABASE_PATH=~ +DATABASE_PATH=~ # Try 'groove themes' to see a list of available themes. -# DEFAULT_THEME=blue_train +DEFAULT_THEME=blue_train # Web interface configuration -# HOST=127.0.0.1 -# PORT=2323 +HOST=127.0.0.1 +PORT=2323 # Set this to a suitably random string. -SECRET_KEY=much secret very private +SECRET_KEY= # Console configuration -# EDITOR= -# CONSOLE_WIDTH=auto +EDITOR=vim +CONSOLE_WIDTH=auto """ app = typer.Typer() @@ -61,6 +62,7 @@ def main( ) ): load_dotenv(env.expanduser()) + load_dotenv(stream=io.StringIO(SETUP_HELP)) debug = os.getenv('DEBUG', None) logging.basicConfig( format='%(message)s', @@ -86,13 +88,8 @@ def setup(context: typer.Context): """ (Re)Initialize Groove on Demand. """ - print(dedent( - """ - Interactive setup is not yet available. Sorry! - - {SETUP_HELP} - """ - )) + sys.stderr.write("Interactive setup is not yet available. Sorry!\n") + print(dedent(SETUP_HELP)) @app.command() diff --git a/groove/editor.py b/groove/editor.py index 783af9b..7a03107 100644 --- a/groove/editor.py +++ b/groove/editor.py @@ -68,7 +68,7 @@ class PlaylistEditor: try: with self.path as fh: fh.write(playlist.as_yaml.encode()) - subprocess.check_call([os.environ['EDITOR'], self.path.name]) + subprocess.check_call([os.environ.get('EDITOR', 'vim'), self.path.name]) except (IOError, OSError, FileNotFoundError) as e: logging.error(e) raise RuntimeError("Could not invoke the editor! If the error persists, try enabling DEBUG mode.") diff --git a/groove/playlist.py b/groove/playlist.py index 99c4384..99207b0 100644 --- a/groove/playlist.py +++ b/groove/playlist.py @@ -73,7 +73,7 @@ class Playlist: @property def url(self) -> str: - return f"http://{os.environ['HOST']}:{os.environ['PORT']}/{self.slug}" + return f"http://{os.environ['HOST']}:{os.environ['PORT']}/playlist/{self.slug}" @property def slug(self) -> str: diff --git a/groove/static/static/player.js b/groove/static/static/player.js index 3908e36..3edfe2a 100644 --- a/groove/static/static/player.js +++ b/groove/static/static/player.js @@ -1,4 +1,6 @@ /*! + * This player is a modified version of: + * * Howler.js Audio Player Demo * howlerjs.com *