dnd-music-console/croaker/cli.py

134 lines
3.1 KiB
Python
Raw Normal View History

2024-03-01 01:00:17 -08:00
import io
import logging
import os
import sys
from pathlib import Path
from textwrap import dedent
from typing import List, Optional
import typer
from dotenv import load_dotenv
from typing_extensions import Annotated
import croaker.path
from croaker.exceptions import ConfigurationError
from croaker.playlist import Playlist
2024-03-05 22:15:51 -08:00
from croaker.server import server
2024-03-01 01:00:17 -08:00
SETUP_HELP = """
# Root directory for croaker configuration and logs. See also croaker --root.
CROAKER_ROOT=~/.dnd/croaker
2024-03-05 22:51:04 -08:00
# where to store playlist sources
#PLAYLIST_ROOT=$CROAKER_ROOT/playlists
2024-03-01 01:00:17 -08:00
2024-03-05 22:51:04 -08:00
# Where the record the daemon's PID
#PIDFILE=$CROAKER_ROOT/croaker.pid
2024-03-01 01:00:17 -08:00
2024-03-05 22:51:04 -08:00
# Command and Control TCP Server bind address
HOST=0.0.0.0
2024-03-01 01:00:17 -08:00
PORT=8003
# the kinds of files to add to playlists
MEDIA_GLOB=*.mp3,*.flac,*.m4a
# Icecast2 configuration for Liquidsoap
ICECAST_PASSWORD=
ICECAST_MOUNT=
ICECAST_HOST=
ICECAST_PORT=
ICECAST_URL=
"""
app = typer.Typer()
app_state = {}
2024-03-05 22:21:56 -08:00
logger = logging.getLogger('cli')
2024-03-01 01:00:17 -08:00
@app.callback()
def main(
context: typer.Context,
root: Optional[Path] = typer.Option(
Path("~/.dnd/croaker"),
help="Path to the Croaker environment",
),
debug: Optional[bool] = typer.Option(None, help="Enable debugging output"),
):
load_dotenv(root.expanduser() / Path("defaults"))
load_dotenv(stream=io.StringIO(SETUP_HELP))
if debug is not None:
if debug:
2024-03-05 22:15:51 -08:00
os.environ["DEBUG"] = "1"
2024-03-01 01:00:17 -08:00
else:
del os.environ["DEBUG"]
logging.basicConfig(
2024-03-05 22:15:51 -08:00
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
2024-03-01 01:00:17 -08:00
level=logging.DEBUG if debug else logging.INFO,
)
try:
croaker.path.root()
croaker.path.playlist_root()
2024-03-01 01:00:17 -08:00
except ConfigurationError as e:
sys.stderr.write(f"{e}\n\n{SETUP_HELP}")
sys.exit(1)
@app.command()
def setup(context: typer.Context):
"""
(Re)Initialize Croaker.
"""
sys.stderr.write("Interactive setup is not yet available. Sorry!\n")
print(dedent(SETUP_HELP))
@app.command()
def start(
context: typer.Context,
2024-03-05 22:51:04 -08:00
daemonize: bool = typer.Option(True, help="Daemonize the server."),
2024-03-01 01:00:17 -08:00
):
"""
2024-03-05 22:51:04 -08:00
Start the Croaker command and control server.
2024-03-01 01:00:17 -08:00
"""
2024-03-06 17:04:08 -08:00
server.start(daemonize=daemonize)
2024-03-01 01:00:17 -08:00
@app.command()
def stop():
"""
2024-03-05 22:51:04 -08:00
Terminate the server.
2024-03-01 01:00:17 -08:00
"""
server.stop()
@app.command()
def add(
playlist: str = typer.Argument(
...,
help="Playlist name",
),
theme: Optional[bool] = typer.Option(False, help="Make the first track the theme song."),
tracks: Annotated[Optional[List[Path]], typer.Argument()] = None,
):
"""
Recursively add one or more paths to the specified playlist.
Tracks can be any combination of individual audio files and directories
containing audio files; anything not already on the playlist will be
added to it.
2024-03-01 01:00:17 -08:00
If --theme is specified, the first track will be designated the playlist
"theme." Theme songs get played first whenever the playlist is loaded,
after which the playlist order is randomized.
"""
pl = Playlist(name=playlist)
pl.add(tracks, make_theme=theme)
print(pl)
if __name__ == "__main__":
app.main()