From affcf2d7dc51d422eb9b9e60ac271711e571ffa4 Mon Sep 17 00:00:00 2001 From: evilchili Date: Tue, 5 Mar 2024 22:51:04 -0800 Subject: [PATCH] updating readme --- README.md | 36 +++++++++++++++++++++++------------- croaker/cli.py | 38 ++++++++++++-------------------------- croaker/path.py | 9 ++------- croaker/server.py | 7 +++++-- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 074b567..f9710b3 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Croaker -A command-and-control web application for icecast / liquidaudio, with helpers for D&D session music. + +A shoutcast audio playlist designed for serving D&D session music. ## What? Why? -Because I run an online D&D game, which includes a background music stream for my players. The stream is controlled by a bunch of bash scripts I cobbled together which are functional but brittle. Also, this currently requires me to have a terminal window open to my media server to control liquidsoap directly, and I'd rather integrate the music controls directly with the rest of my DM tools, all of which run on my laptop. A web-based commmand-and-control app lets me use vanilla HTTP requests to control liquidsoap. +Because I run an online D&D game, which includes a background music stream for my players. The stream used to be served by liquidsoap and controlled by a bunch of bash scripts I cobbled together which are functional but brittle, and liquidsoap is a nightmare for the small use case. Also, this currently requires me to have a terminal window open to my media server to control liquidsoap directly, and I'd rather integrate the music controls directly with the rest of my DM tools, all of which run on my laptop. *Now that is a powerful yak! -- Aesop Rock (misquoted)* - ## Quick Start (Server) This assumes you have a functioning icecast2 installation already. @@ -24,34 +24,44 @@ This assumes you have a functioning icecast2 installation already. Now start the server, which will begin streaming the `session_start` playlist: ``` -% croaker server start -Daemonizing webserver on http://0.0.0.0:8003, pidfile and output in ~/.dnd/croaker +% croaker start +INFO Daemonizing controller on (localhost, 8003); pidfile and logs in ~/.dnd/croaker ``` -## Quick Start (Client) +Connnect to the command & control server: + ``` -% mkdir -p ~/.dnd/croaker -% croaker setup > ~/.dnd/croaker/defaults # only the client config is required -% vi ~/.dnd/croaker/defaults # adjust to taste +% telnet localhost 8003 +Trying 127.0.0.1... +Connected to croaker.local. +Escape character is '^]'. +HELP +PLAY $PLAYLIST_NAME - Switch to the specified playlist. +FFWD - Skip to the next track in the playlist. +HELP - Display command help. +KTHX - Close the current connection. +STOP - Stop Croaker. +OK ``` Switch to battle music -- roll initiative! ``` -% croaker play battle +PLAY battle OK ``` Skip this track and move on to the next: ``` -% croaker skip +FFWD OK ``` Stop the server: ``` -% croaker stop -OK +STOP +Shutting down. +Connection closed by foreign host. ``` diff --git a/croaker/cli.py b/croaker/cli.py index 8ca8c68..bff121d 100644 --- a/croaker/cli.py +++ b/croaker/cli.py @@ -19,25 +19,18 @@ SETUP_HELP = """ # Root directory for croaker configuration and logs. See also croaker --root. CROAKER_ROOT=~/.dnd/croaker -## COMMAND AND CONTROL WEBSERVER - -# Please make sure you set SECRET_KEY in your environment if you are running -# the command and control webserver. Clients do not need this. -SECRET_KEY= - -# Where the record the webserver daemon's PID -PIDFILE=~/.dnd/croaker/croaker.pid - -HOST=0.0.0.0 -PORT=8003 - -## MEDIA - # where to store playlist sources -PLAYLIST_ROOT=~/.dnd/croaker/playlists +#PLAYLIST_ROOT=$CROAKER_ROOT/playlists # where to cache transcoded media files -CACHE_ROOT=~/.dnd/croaker/cache +#CACHE_ROOT=$CROAKER_ROOT/cache + +# Where the record the daemon's PID +#PIDFILE=$CROAKER_ROOT/croaker.pid + +# Command and Control TCP Server bind address +HOST=0.0.0.0 +PORT=8003 # the kinds of files to add to playlists MEDIA_GLOB=*.mp3,*.flac,*.m4a @@ -47,11 +40,6 @@ MEDIA_GLOB=*.mp3,*.flac,*.m4a # the cached output location, respectively. TRANSCODER=/usr/bin/ffmpeg -i INFILE '-hide_banner -loglevel error -codec:v copy -codec:a libmp3lame -q:a 2' OUTFILE -## LIQUIDSOAP AND ICECAST - -# The liquidsoap executable -LIQUIDSOAP=/usr/bin/liquidsoap - # Icecast2 configuration for Liquidsoap ICECAST_PASSWORD= ICECAST_MOUNT= @@ -108,13 +96,11 @@ def setup(context: typer.Context): @app.command() def start( context: typer.Context, - daemonize: bool = typer.Option(True, help="Daemonize the webserver."), + daemonize: bool = typer.Option(True, help="Daemonize the server."), ): """ - Start the Croaker command and control webserver. + Start the Croaker command and control server. """ - logger.debug("Switching to session_start playlist...") - logger.debug("Starting server...") if daemonize: server.daemonize() else: @@ -124,7 +110,7 @@ def start( @app.command() def stop(): """ - Terminate the webserver process and liquidsoap. + Terminate the server. """ server.stop() diff --git a/croaker/path.py b/croaker/path.py index e5883f8..2e81eb1 100644 --- a/croaker/path.py +++ b/croaker/path.py @@ -10,15 +10,10 @@ def root(): def cache_root(): - path = Path(os.environ.get("CACHE_ROOT", root() / Path("cache"))).expanduser() + path = Path(os.environ.get("CACHE_ROOT", root() / "cache")).expanduser() return path def playlist_root(): - path = Path(os.environ.get("PLAYLIST_ROOT", root() / Path("playlsits"))).expanduser() - return path - - -def transcoded_media(relpath): - path = cache_root() / Path(relpath + ".webm") + path = Path(os.environ.get("PLAYLIST_ROOT", root() / "playlists")).expanduser() return path diff --git a/croaker/server.py b/croaker/server.py index d46b2db..94c5d8a 100644 --- a/croaker/server.py +++ b/croaker/server.py @@ -73,9 +73,12 @@ class CroakerServer(socketserver.TCPServer): def tell_controller(self, msg): self._queue.put(msg) + def bind_address(self): + return (os.environ["HOST"], int(os.environ["PORT"])) + def daemonize(self) -> None: - logger.info(f"Daemonizing controller; pidfile and output in {path.root()}") - super().__init__((os.environ["HOST"], int(os.environ["PORT"])), RequestHandler) + logger.info(f"Daemonizing controller on {self.bind_address()}; pidfile and output in {path.root()}") + super().__init__(self.bind_address(), RequestHandler) self._context.pidfile = self._pidfile() self._context.stdout = open(path.root() / Path("croaker.out"), "wb")