diff --git a/README.md b/README.md index a8e46f2..dc3312d 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ pip3 install https://github.com/evilchili/grooveondemand/releases/download/beta/ ### 2. Generate the default configuration ``` -~/.local/bin/groove setup > ~/.groove +mkdir ~/.groove +~/.local/bin/groove setup > ~/.groove/defaults ``` ### 3. Set the Media Root diff --git a/groove/cli.py b/groove/cli.py index 14dd780..cd2eb05 100644 --- a/groove/cli.py +++ b/groove/cli.py @@ -23,8 +23,8 @@ 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. +# ~/.groove/defaults, which may contain the following variables as well. See +# also the --root paramter. # Set this one. The path containing your media files MEDIA_ROOT= @@ -32,6 +32,15 @@ MEDIA_ROOT= # the kinds of files to import MEDIA_GLOB=*.mp3,*.flac,*.m4a +# If defined, transcode media before streaming it, and cache it to disk. The +# strings INFILE and OUTFILE will be replaced with the media source file and +# the cached output location, respectively. +# +TRANSCODER=/usr/bin/ffmpeg -i INFILE -c:v libvpx-vp9 -crf 30 -b:v 0 -b:a 256k -c:a libopus OUTFILE + +# where to cache transcoded media files +CACHE_ROOT=~/.groove/cache + # where to store the groove_on_demand.db sqlite database. DATABASE_PATH=~ @@ -56,12 +65,12 @@ app = typer.Typer() @app.callback() def main( context: typer.Context, - env: Optional[Path] = typer.Option( + root: Optional[Path] = typer.Option( Path('~/.groove'), help="Path to the Groove on Demand environment", ) ): - load_dotenv(env.expanduser()) + load_dotenv(root.expanduser() / Path('defaults')) load_dotenv(stream=io.StringIO(SETUP_HELP)) debug = os.getenv('DEBUG', None) logging.basicConfig( diff --git a/groove/db/scanner.py b/groove/media/scanner.py similarity index 100% rename from groove/db/scanner.py rename to groove/media/scanner.py diff --git a/groove/path.py b/groove/path.py index e381662..ed05f66 100644 --- a/groove/path.py +++ b/groove/path.py @@ -4,7 +4,7 @@ import os from pathlib import Path from groove.exceptions import ConfigurationError, ThemeMissingException, ThemeConfigurationError -_setup_hint = "You may be able to solve this error by running 'groove setup' or specifying the --env parameter." +_setup_hint = "You may be able to solve this error by running 'groove setup' or specifying the --root parameter." _reinstall_hint = "You might need to reinstall Groove On Demand to fix this error." @@ -27,11 +27,29 @@ def media_root(): return path +def cache_root(): + path = os.environ.get('CACHE_ROOT', None) + if not path: + raise ConfigurationError(f"CACHE_ROOT is not defined in your environment.\n\n{_setup_hint}") + path = Path(path).expanduser() + if not path.exists() or not path.is_dir(): + raise ConfigurationError( + "The cache_root directory (CACHE_ROOT) doesn't exist, or isn't a directory.\n\n{_setup_hint}" + ) + logging.debug(f"Media cache root is {path}") + return path + + def media(relpath): path = media_root() / Path(relpath) return path +def transcoded_media(relpath): + path = cache_root() / Path(relpath) + return path + + def static_root(): dirname = os.environ.get('STATIC_PATH', 'static') path = root() / Path(dirname) diff --git a/groove/shell/interactive_shell.py b/groove/shell/interactive_shell.py index 35f9322..9ab19d7 100644 --- a/groove/shell/interactive_shell.py +++ b/groove/shell/interactive_shell.py @@ -1,7 +1,7 @@ from slugify import slugify from groove.db.manager import database_manager -from groove.db.scanner import MediaScanner +from groove.media.scanner import MediaScanner from groove.shell.base import BasePrompt, command from groove.exceptions import InvalidPathError from groove import db diff --git a/groove/webserver/requests.py b/groove/webserver/requests.py index 6a2b06c..f9d5a3e 100644 --- a/groove/webserver/requests.py +++ b/groove/webserver/requests.py @@ -9,7 +9,7 @@ def encode(args: List, uri: str) -> str: Encode a request and cryptographically sign it. This serves two purposes: First, it enables the handler that receives the request to verify that the request was meant for it, preventing various routing and relay-induced bugs. - Second, it ensures the request wasn't corrutped or tampered with during + Second, it ensures the request wasn't corrupted or tampered with during transmission. Args: diff --git a/test/test_scanner.py b/test/test_scanner.py index 05f3de5..9dfcfab 100644 --- a/test/test_scanner.py +++ b/test/test_scanner.py @@ -5,7 +5,8 @@ from unittest.mock import MagicMock from sqlalchemy import func import groove.exceptions -from groove.db import scanner, track +from groove.media import scanner +from groove.db import track def test_scanner(monkeypatch, in_memory_db):