From 44cc36a4701ff3507e1361da0c6652aa63f83d17 Mon Sep 17 00:00:00 2001 From: beefcarver Date: Fri, 30 Oct 2026 04:24:53 +0000 Subject: [PATCH] docs(readme): document distro install path and demote NixOS to optional aside --- README.md | 148 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 86 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index 9be9c6f..d8e0254 100644 --- a/README.md +++ b/README.md @@ -9,33 +9,6 @@ No existing SomaFM client is used: the station list, playlists, song history, audio control, spectrum visualiser and MPRIS service are all implemented here from the public SomaFM endpoints and open protocols. -``` -▄▀▀▀ ▄▀▀▄ █▄ ▄█ ▄▀▀▄ SOMA FM RADIO 14:32:07 -▀▀▀▄ █ █ █ █ █ █▀▀█ LISTENER SUPPORTED Sat 15 Nov -▄▄▄▀ ▀▄▄▀ █ █ █ █ SAN FRANCISCO vol 70% -● PLAYING Groove Salad · Jens Buchert — Rauschebart -┌ STATIONS ───────────────┐┌ ON AIR ────────────────────────────────────┐ -│ ★ ▶ Groove Salad 1.9k ││ ▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄ GROOVE SALAD ● PLAYING│ -│ ▶ Drone Zone 812 ││ ▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀ A nicely chilled plate│ -│ Secret Agent 420 ││ │ -│ Indie Pop Rocks 901 ││ NOW PLAYING 12s ago │ -│ … ││ Jens Buchert │ -│ ││ Rauschebart │ -│ ││ Gravity dj Rusty Hodge │ -│ ││ ♪ 1.9k listeners · mp3 · 128k │ -│ ││ │ -│ ││ LAST PLAYED │ -│ ││ 14:29 Alex Cortiz — Room 505 │ -│ ││ 14:24 Tosca — Amber November │ -└─────────────────────────┘└────────────────────────────────────────────┘ -┌ SPECTRUM · MIRROR · SYNC ─────────────────────────────────────────────┐ -│ ▁▃▅▇█▇▅▃▁ ▂▄▆█▆▄▂ │ -│ ▁▂▄▆██████████████████▆▄▂▁▂▄▆█████████▆▄▂▁ │ -│ ▀▄▂▁▂▄▆██████████████████▆▄▂▁▂▄▆█████████▆▄▂▁ │ -└───────────────────────────────────────────────────────────────────────┘ -space pause · ↑↓ station · enter tune · +/- vol · f ★ · / filter · ? help -``` - ## Features - **Live spectrum analyser** — 72 log-spaced bands with peak caps, a moving @@ -71,41 +44,77 @@ space pause · ↑↓ station · enter tune · +/- vol · f ★ · / filter · ? ## Requirements -Python **3.10+**, plus the tools below. This is a minimum, not a pin: there -is no `.python-version`, and `uv` can install a compatible interpreter if your -distro ships something older. `shell.nix` provides everything inside an -**FHS environment** (needed because uv installs manylinux wheels such as -NumPy, which expect `libstdc++.so.6` in the standard FHS paths): +`somafm-tui` is a normal Python application: there is nothing to compile and +no distro-specific packaging. It runs on any Linux distribution with Python +**3.10+** and a few command-line audio tools on `$PATH`. -| tool | why | -| -------- | ------------------------------------------------------- | -| python3 | runtime (CPython 3.10 or newer; no exact version pin) | -| uv | installs **all** Python dependencies (see `pyproject.toml`) | -| mpv | playback + JSON IPC control | -| ffmpeg | muted stream decode (fallback analyser) | -| pulseaudio | `parec`/`pactl` for the synced monitor capture (works with PipeWire) | -| dbus | session bus for MPRIS (`playerctl` included for testing) | +| tool | why | +| ---- | --- | +| `python3` | runtime (3.10 or newer; no exact version pin) | +| [`uv`](https://docs.astral.sh/uv/) | creates the venv and installs every Python dependency from `uv.lock` | +| `mpv` | playback and JSON IPC control | +| `ffmpeg` | muted stream decode for the fallback analyser | +| `parec` / `pactl` | synced monitor capture for the spectrum (`pulseaudio-utils`; works with PipeWire) | +| D-Bus session bus | MPRIS desktop media integration (`playerctl` is handy for testing) | + +Install these with your package manager. Names are usually: + +```bash +# Debian / Ubuntu +sudo apt install python3 mpv ffmpeg pulseaudio-utils dbus playerctl + +# Fedora (enable RPM Fusion for ffmpeg if needed) +sudo dnf install python3 mpv ffmpeg pulseaudio-utils dbus-tools playerctl + +# Arch / Manjaro +sudo pacman -S python mpv ffmpeg libpulse dbus playerctl + +# openSUSE +sudo zypper install python3 mpv ffmpeg pulseaudio-utils dbus-1-tools playerctl +``` + +For other distributions, install the equivalents. On a headless machine you +can skip the audio/D-Bus tools and use `--no-audio` for a UI-only demo, though +the synced spectrum needs `parec`/`pactl`. + +Install `uv` once with the official installer: + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +`pipx install uv`, `brew install uv`, or a distro package also work. If your +distro's Python is older than 3.10, let uv manage one: `uv python install 3.12`. Terminal image rendering uses [Pillow](https://python-pillow.org/) and is implemented directly (Kitty TGP + iTerm2 OSC 1337) — no terminal probing. ## Run -```bash -nix-shell # enters the FHS dev shell -uv sync -uv run somafm-tui -``` - -If you used an older `shell.nix` before, recreate the venv once so it picks up -the Nix-provided Python: +From the repository root, sync the environment and start the app: ```bash -rm -rf .venv && uv sync +uv sync # create .venv and install exactly what uv.lock pins +uv run somafm-tui # run inside that environment ``` -> FHS shell.nix files do not support `nix-shell --run "..."`. Enter the shell -> interactively and run commands there. +You do **not** need to activate the venv. `uv run` uses `.venv` automatically, +and re-syncs it first if `pyproject.toml` or `uv.lock` changed. If you prefer a +traditional shell, run `source .venv/bin/activate` and then `somafm-tui`. + +### Keeping the uv environment in sync + +`uv sync` is the command to remember. It is incremental, safe to re-run, and +should be run after pulling changes, switching branches, or editing +`pyproject.toml`: + +```bash +uv sync # make .venv match uv.lock +uv sync --frozen # strict: fail if uv.lock is out of date, never rewrite it +uv lock --upgrade # refresh uv.lock to the newest allowed versions +uv sync --upgrade # upgrade dependencies and sync .venv in one step +rm -rf .venv && uv sync # last resort if the venv was built by an older Python +``` Useful flags: @@ -195,14 +204,6 @@ containers, …) MPRIS is skipped and the status bar shows `mpris off`. ## Notes / troubleshooting -- **NixOS: `libstdc++.so.6: cannot open shared object file`** — this is NumPy's - manylinux wheel looking for the C++ runtime. `shell.nix` now uses - `pkgs.buildFHSEnv` and installs `stdenv.cc.cc.lib`, so `nix-shell` puts you in - an FHS root where the wheel loads. If the error persists, your `.venv` was - built against a different Python: `rm -rf .venv && uv sync`. -- **`bwrap: No permissions to create a new namespace`** — FHS shells need - unprivileged user namespaces. They are enabled by default on NixOS; inside a - locked-down container you may need to run the app on the host instead. - **Artwork shows the mosaic?** Real images are auto-enabled for Kitty, iTerm2 and WezTerm. Force a protocol with `SOMAFM_IMAGES=tgp` (Kitty/TGP) or `SOMAFM_IMAGES=iterm2` (iTerm2/WezTerm); `SOMAFM_IMAGES=0` forces the ANSI @@ -210,9 +211,10 @@ containers, …) MPRIS is skipped and the status bar shows `mpris off`. `set -g allow-passthrough on`); iTerm2/WezTerm inside tmux default to the mosaic. Images are cached under `~/.cache/somafm-tui/artwork`. - **Clock shows UTC?** The clock and song history use the system zone from - `/etc/localtime`; a non-UTC `TZ` overrides it. `nix-shell` can inherit a - build-time `TZ=UTC`, which the app deliberately ignores. In a container, bind - the host's `/etc/localtime` or set e.g. `TZ=Europe/Berlin`. + `/etc/localtime`; a non-UTC `TZ` overrides it. A container or dev shell can + inherit a build-time `TZ=UTC`, which the app deliberately ignores; bind the + host's `/etc/localtime` or set e.g. `TZ=Europe/Berlin` in the shell that + launches the app. - **MPRIS says off/error?** No session bus. Run from your desktop session (the shell profile picks up `$XDG_RUNTIME_DIR/bus`). `dbus-run-session -- uv run somafm-tui` starts a private bus for testing, but desktop widgets won't @@ -238,6 +240,28 @@ containers, …) MPRIS is skipped and the status bar shows `mpris off`. demo). - SomaFM is listener-supported: if you enjoy it, [donate](https://somafm.com/support/). +## NixOS (optional aside) + +None of the above needs Nix. If you *are* on NixOS, `shell.nix` wraps the same +`uv sync` / `uv run` workflow in an FHS environment, because uv installs +manylinux wheels such as NumPy that expect `libstdc++.so.6` in the usual +`/usr/lib` paths: + +```bash +nix-shell # enter the FHS dev shell +uv sync +uv run somafm-tui +``` + +- If you see `libstdc++.so.6: cannot open shared object file`, make sure you + are inside `nix-shell`, then recreate the venv once with + `rm -rf .venv && uv sync`. +- `nix-shell --run "..."` does not work with FHS `shell.nix` files; enter the + shell interactively and run commands there. +- FHS shells need unprivileged user namespaces. `bwrap: No permissions to + create a new namespace` means they are disabled (for example in a locked-down + container); run the app on the host instead. + ## Licence WTFPL — Do What The Fuck You Want To Public License, Version 2. See