minor bugfixes, started the README
This commit is contained in:
parent
7caf3302db
commit
83f32d82ed
74
README.md
74
README.md
|
@ -1,3 +1,75 @@
|
||||||
# Groove On Demand
|
# 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.
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import io
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
@ -20,33 +21,33 @@ from groove.exceptions import ConfigurationError
|
||||||
from groove.console import Console
|
from groove.console import Console
|
||||||
|
|
||||||
SETUP_HELP = """
|
SETUP_HELP = """
|
||||||
Please make sure you set MEDIA_ROOT and SECRET_KEY in your environment.
|
# 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
|
# By default, Groove on Demand will attempt to load these variables from
|
||||||
~/.groove, which may contain the following variables as well. See also
|
# ~/.groove, which may contain the following variables as well. See also
|
||||||
the --env paramter.
|
# the --env paramter.
|
||||||
|
|
||||||
# Set this one. The path containing your media files
|
# Set this one. The path containing your media files
|
||||||
MEDIA_ROOT=
|
MEDIA_ROOT=
|
||||||
|
|
||||||
# the kinds of files to import
|
# 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.
|
# where to store the groove_on_demand.db sqlite database.
|
||||||
# DATABASE_PATH=~
|
DATABASE_PATH=~
|
||||||
|
|
||||||
# Try 'groove themes' to see a list of available themes.
|
# Try 'groove themes' to see a list of available themes.
|
||||||
# DEFAULT_THEME=blue_train
|
DEFAULT_THEME=blue_train
|
||||||
|
|
||||||
# Web interface configuration
|
# Web interface configuration
|
||||||
# HOST=127.0.0.1
|
HOST=127.0.0.1
|
||||||
# PORT=2323
|
PORT=2323
|
||||||
|
|
||||||
# Set this to a suitably random string.
|
# Set this to a suitably random string.
|
||||||
SECRET_KEY=much secret very private
|
SECRET_KEY=
|
||||||
|
|
||||||
# Console configuration
|
# Console configuration
|
||||||
# EDITOR=
|
EDITOR=vim
|
||||||
# CONSOLE_WIDTH=auto
|
CONSOLE_WIDTH=auto
|
||||||
"""
|
"""
|
||||||
|
|
||||||
app = typer.Typer()
|
app = typer.Typer()
|
||||||
|
@ -61,6 +62,7 @@ def main(
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
load_dotenv(env.expanduser())
|
load_dotenv(env.expanduser())
|
||||||
|
load_dotenv(stream=io.StringIO(SETUP_HELP))
|
||||||
debug = os.getenv('DEBUG', None)
|
debug = os.getenv('DEBUG', None)
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format='%(message)s',
|
format='%(message)s',
|
||||||
|
@ -86,13 +88,8 @@ def setup(context: typer.Context):
|
||||||
"""
|
"""
|
||||||
(Re)Initialize Groove on Demand.
|
(Re)Initialize Groove on Demand.
|
||||||
"""
|
"""
|
||||||
print(dedent(
|
sys.stderr.write("Interactive setup is not yet available. Sorry!\n")
|
||||||
"""
|
print(dedent(SETUP_HELP))
|
||||||
Interactive setup is not yet available. Sorry!
|
|
||||||
|
|
||||||
{SETUP_HELP}
|
|
||||||
"""
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
@app.command()
|
@app.command()
|
||||||
|
|
|
@ -68,7 +68,7 @@ class PlaylistEditor:
|
||||||
try:
|
try:
|
||||||
with self.path as fh:
|
with self.path as fh:
|
||||||
fh.write(playlist.as_yaml.encode())
|
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:
|
except (IOError, OSError, FileNotFoundError) as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
raise RuntimeError("Could not invoke the editor! If the error persists, try enabling DEBUG mode.")
|
raise RuntimeError("Could not invoke the editor! If the error persists, try enabling DEBUG mode.")
|
||||||
|
|
|
@ -73,7 +73,7 @@ class Playlist:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self) -> str:
|
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
|
@property
|
||||||
def slug(self) -> str:
|
def slug(self) -> str:
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
/*!
|
/*!
|
||||||
|
* This player is a modified version of:
|
||||||
|
*
|
||||||
* Howler.js Audio Player Demo
|
* Howler.js Audio Player Demo
|
||||||
* howlerjs.com
|
* howlerjs.com
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue
Block a user