refactor media module, change --env to --root

This commit moves the media scanner out of the db module and into
a new module, media. We also change the --env parameter to --root,
which takes a path to a directory where the default configuration
and the transcoded media cache will live.
This commit is contained in:
evilchili 2022-12-31 10:45:22 -08:00
parent 3bb2f83464
commit 17a6dcb4d2
7 changed files with 38 additions and 9 deletions

View File

@ -23,7 +23,8 @@ pip3 install https://github.com/evilchili/grooveondemand/releases/download/beta/
### 2. Generate the default configuration ### 2. Generate the default configuration
``` ```
~/.local/bin/groove setup > ~/.groove mkdir ~/.groove
~/.local/bin/groove setup > ~/.groove/defaults
``` ```
### 3. Set the Media Root ### 3. Set the Media Root

View File

@ -23,8 +23,8 @@ 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/defaults, which may contain the following variables as well. See
# the --env paramter. # also the --root paramter.
# Set this one. The path containing your media files # Set this one. The path containing your media files
MEDIA_ROOT= MEDIA_ROOT=
@ -32,6 +32,15 @@ MEDIA_ROOT=
# the kinds of files to import # the kinds of files to import
MEDIA_GLOB=*.mp3,*.flac,*.m4a 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. # where to store the groove_on_demand.db sqlite database.
DATABASE_PATH=~ DATABASE_PATH=~
@ -56,12 +65,12 @@ app = typer.Typer()
@app.callback() @app.callback()
def main( def main(
context: typer.Context, context: typer.Context,
env: Optional[Path] = typer.Option( root: Optional[Path] = typer.Option(
Path('~/.groove'), Path('~/.groove'),
help="Path to the Groove on Demand environment", 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)) load_dotenv(stream=io.StringIO(SETUP_HELP))
debug = os.getenv('DEBUG', None) debug = os.getenv('DEBUG', None)
logging.basicConfig( logging.basicConfig(

View File

@ -4,7 +4,7 @@ import os
from pathlib import Path from pathlib import Path
from groove.exceptions import ConfigurationError, ThemeMissingException, ThemeConfigurationError 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." _reinstall_hint = "You might need to reinstall Groove On Demand to fix this error."
@ -27,11 +27,29 @@ def media_root():
return path 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): def media(relpath):
path = media_root() / Path(relpath) path = media_root() / Path(relpath)
return path return path
def transcoded_media(relpath):
path = cache_root() / Path(relpath)
return path
def static_root(): def static_root():
dirname = os.environ.get('STATIC_PATH', 'static') dirname = os.environ.get('STATIC_PATH', 'static')
path = root() / Path(dirname) path = root() / Path(dirname)

View File

@ -1,7 +1,7 @@
from slugify import slugify from slugify import slugify
from groove.db.manager import database_manager 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.shell.base import BasePrompt, command
from groove.exceptions import InvalidPathError from groove.exceptions import InvalidPathError
from groove import db from groove import db

View File

@ -9,7 +9,7 @@ def encode(args: List, uri: str) -> str:
Encode a request and cryptographically sign it. This serves two purposes: Encode a request and cryptographically sign it. This serves two purposes:
First, it enables the handler that receives the request to verify that the 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. 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. transmission.
Args: Args:

View File

@ -5,7 +5,8 @@ from unittest.mock import MagicMock
from sqlalchemy import func from sqlalchemy import func
import groove.exceptions 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): def test_scanner(monkeypatch, in_memory_db):