docs(readme): document distro install path and demote NixOS to optional aside
This commit is contained in:
1 parent
3866f0277c
commit
44cc36a470
1 file changed
+86
-62
@@ -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
|
||||
|
||||
Reference in new issue
Block a user