From 778636297212c6e764cdb9bb667895202f2d5eec Mon Sep 17 00:00:00 2001 From: Yan Minagawa Date: Wed, 10 Jun 2026 10:27:34 +0200 Subject: [PATCH] docs: write README with build, usage, keys, and tuning notes Covers prerequisites (alsa-lib-devel on Fedora / libasound2-dev on Debian), default vs --no-default-features build, the three binaries with concrete invocations, the TUI keybindings and --preset CLI aliases, a sketch of the architecture, and beat-detector tuning notes. Co-Authored-By: Claude Opus 4.7 --- README.md | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) diff --git a/README.md b/README.md index e69de29..7228a5f 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,270 @@ +# lightcontrol + +Rust tooling for the **c-base mainhall** lighting rig. One TUI for animated +presets driving the whole hall via `dmxbackend`, plus two focused one-shot +binaries for the wall panels and the SonicPulse LED bars. + +Talks to: + +- **dmxbackend** at `dmx.cbrp3.c-base.org:8000` (REST + WebSocket) for the + 48 DMX-routed fixtures. +- **matelight** at `matelight.cbrp3.c-base.org:8081` (`/monitor` WS, + subprotocol `matemon`) for live pixel sync of the hall lights to whatever + is playing on the Mate-crate display. +- **ArtNet** node at `10.0.0.146:6454` (default) for the Stairville + SonicPulse LED bars that aren't on `dmxbackend`. + +The local microphone, optionally, for beat-driven scenes. + +--- + +## Quick start + +```bash +# prerequisites (Fedora): +sudo dnf install rustup alsa-lib-devel pkgconf-pkg-config +rustup-init -y && source "$HOME/.cargo/env" + +# build everything +cargo build --release + +# fire up the TUI against the live rig +./target/release/lightcontrol +``` + +On Debian/Ubuntu the equivalent of `alsa-lib-devel` is +`libasound2-dev`. If you don't want microphone support and can't or won't +install ALSA dev libs, see [No-mic build](#no-mic-build) below. + +--- + +## Build + +The default build enables the `mic` cargo feature, which pulls in +[`cpal`](https://crates.io/crates/cpal) and through it the system ALSA +library. The TUI's beat-detector and the `BeatPulse` preset rely on it. + +```bash +cargo build --release # default: TUI + panels + bars + mic +``` + +### No-mic build + +```bash +cargo build --release --no-default-features +``` + +Identical behaviour except the BeatPulse preset shows a slow cyan +"waiting for mic" heartbeat instead of reacting to audio. Useful on +build hosts that don't have ALSA dev headers, or on machines with no +audio input. + +### Quick checks + +```bash +cargo test # unit tests for presets + detector +cargo clippy --all-targets -- -D warnings +``` + +--- + +## Binaries + +### `lightcontrol` — main TUI + +Animated presets driving every fixture in the mainhall through +`dmxbackend`'s `/api/v1/websocket_state/` at 25 fps. + +```bash +./target/release/lightcontrol # interactive TUI +./target/release/lightcontrol --preset rainbows # launch straight in +./target/release/lightcontrol --check # dump fixture list +./target/release/lightcontrol --host dmx.example:8000 # different backend +./target/release/lightcontrol --matelight ws://.../monitor # custom mate +``` + +Environment variables: +- `DMX_HOST` — overrides `--host` +- `MATELIGHT_URL` — overrides `--matelight` + +The TUI shows a header (host, fixture count, FPS, matelight + mic status), +a live **beat detector panel** (flash bar + BPM + envelope sparkline), and +the preset list with the active preset highlighted. + +#### Keys + +| Key | Preset | +|-----|--------| +| `1` | Rainbows | +| `2` | Blue House | +| `3` | 70th Disco | +| `4` | Jungle | +| `5` | Lasertec | +| `6` | Police | +| `7` | Mirror Ball (blue fade) | +| `8` | Morning Light (sunrise) | +| `9` | Orange/Green Mirror Ball | +| `m` | Matelight Sync (live) | +| `s` | Gabba Strobe (white, fast) | +| `r` | Red Strobe (fast) | +| `L` | Blue Strobe (fast) — capital L; `b` is blackout | +| `p` | Pink Strobe (fast) | +| `k` | Beat Pulse (mic-driven) | +| `0` / `b` | Blackout | +| `↑` / `↓` + `Enter` | Navigate list | +| `q` / `Esc` / `Ctrl-C` | Quit | + +#### `--preset` CLI aliases + +Lower-cased and matched verbatim — useful for shell scripting / OBS +integration: + +| Preset | Aliases | +|--------|---------| +| Rainbows | `rainbow`, `rainbows`, `1` | +| Blue House | `blue`, `bluehouse`, `blue-house`, `2` | +| 70th Disco | `disco`, `disco70`, `70th`, `70th-disco`, `3` | +| Jungle | `jungle`, `4` | +| Lasertec | `lasertec`, `laser`, `5` | +| Police | `police`, `polizei`, `6` | +| Mirror Ball | `mirror`, `mirrorball`, `mirror-ball`, `discoball`, `kugel`, `7` | +| Morning Light | `morning`, `sunrise`, `dawn`, `sonnenaufgang`, `morgen`, `8` | +| Orange/Green Ball | `orangegreen`, `orange-green`, `orange`, `green`, `kürbis`, `9` | +| Matelight Sync | `matelight`, `mate`, `sync`, `m` | +| Gabba Strobe | `gabba`, `strobe`, `strobo`, `stroboscope`, `s` | +| Red Strobe | `red`, `rot`, `redstrobe`, `r` | +| Blue Strobe | `blau`, `bluestrobe`, `blue-strobe`, `l` | +| Pink Strobe | `pink`, `magenta`, `pinkstrobe`, `p` | +| Beat Pulse | `beat`, `beatpulse`, `kick`, `mic`, `audio`, `k` | +| Blackout | `off`, `blackout`, `0` | + +#### Beat detector panel + +``` +┌─ beat detector ────────────────┬─ envelope (last ~4 s) ─────────────────┐ +│ BEAT █████████████ │ ▂▃▆▇▆▃▁▂▇▆▃▁▂▇▆▃▁▂▃▆▇▆▃▁▂▇▆▃▁▂▇▆▃▁▂ │ +│ level ████████████░░░░░░░░ │ │ +│ 128.4 BPM beats=47 last 0.08s ago │ │ +└────────────────────────────────┴────────────────────────────────────────┘ +``` + +The flash bar fires on every detected beat in the current per-beat hue +palette. The level bar is the live short-window envelope. The sparkline +plots the last ~4 seconds of envelope at 20 Hz, scaled with a ×2.5 +boost so quiet rooms still show shape. + +**Pre-show diagnostic:** put on the playlist, look at the panel. Solid +BPM + regular flashes → detector locked. No flashes → mic not picking +up, check `pavucontrol` recording tab. Constant strobing → too much +noise, raise `MIN_DELTA` in `src/beat.rs` (default `0.020`, try +`0.035`). + +### `panels` — Showtec PAR 56 wall panels (one-shot) + +Hits the `LED Par 56` fixtures via `dmxbackend`'s WebSocket, sends one +frame, exits. Useful for setup checks or quick scene calls from a +script. + +```bash +./target/release/panels --color red # red wash +./target/release/panels --color "#1a3f8f" --dim 180 # custom hex + dimmer +./target/release/panels --color off # blackout +./target/release/panels --dry-run --color magenta # print, don't send +``` + +Colors: `red`, `green`, `blue`, `white`, `yellow`, `orange`, `magenta`, +`cyan`, `off`, or any `#RRGGBB`. + +### `bars` — Stairville SonicPulse LED Bar 10 (ArtNet direct) + +The bars aren't routed through `dmxbackend`, so this one talks ArtNet +UDP directly to the node at `10.0.0.146:6454` (4 bars × 39 channels = +156 channels in universe 2). + +```bash +./target/release/bars --color magenta # paint all 4 bars +./target/release/bars --color "#ff5500" --dim 200 +./target/release/bars --poll # ArtPoll discovery +./target/release/bars --sweep 0-15 # walk universes 0-15 to find them +./target/release/bars --broadcast --color blue # broadcast if unicast fails +./target/release/bars --dry-run --color red # print the packet, don't send +``` + +If `--color` does nothing visible: try `--poll` first to confirm the +node is on the LAN, then `--sweep` to find which universe the bars +actually listen on. The factory default is 0; many nodes are set to +different universes per harness. + +--- + +## Architecture + +``` + ┌──────────────────────────┐ + │ c-base mainhall lights │ + └──────────────────────────┘ + ▲ ▲ + DMX over │ │ ArtNet (UDP/6454) + │ │ → 10.0.0.146 → 4 SonicPulse bars + │ │ + ┌────────────────────┴──┐ │ + │ dmxbackend (aiohttp) │ │ + │ dmx.cbrp3:8000 │ │ + │ REST /api/v1/... │ │ + │ WS /api/v1/ │ │ + │ websocket_state │ │ + └────────┬──────────────┘ │ + │ │ + ┌────────┴────────────────┴──┐ + │ lightcontrol (this repo) │ + │ │ + │ ┌─────────┐ ┌─────────┐ │ ws://matelight:8081 + │ │ engine │ │ matelight ─────────────/monitor (matemon) + │ │ (presets│ │ feeder │ │ binary RGB frames → + │ │ @25fps)│ │ │ │ drive hall via sample + │ └────┬────┘ └─────────┘ │ + │ │ │ local microphone (cpal) + │ │ ┌─────────┐ │ ←─────────────────────── + │ ├──────┤ beat │ │ energy-onset detector + │ │ │ detector│ │ → BeatPulse preset + │ │ └─────────┘ │ + │ ▼ │ + │ binaries: │ + │ lightcontrol (TUI) │ + │ panels (one-shot) │ + │ bars (ArtNet, ad-hoc) │ + └────────────────────────────┘ +``` + +Source layout: +- `src/lib.rs` — shared types (Fixture/Element/Channel), HTTP client, + re-exports. +- `src/presets.rs` — the 15 animated presets + render dispatch. +- `src/matelight.rs` — matelight `/monitor` WebSocket feeder + frame + sampler. +- `src/beat.rs` — cpal capture + energy-onset beat detector (feature + `mic`). +- `src/main.rs` — TUI binary, engine loop, key handling. +- `src/bin/panels.rs` — wall panels one-shot. +- `src/bin/bars.rs` — SonicPulse ArtNet driver. + +--- + +## Tuning notes + +- **Mic input device.** On laptops with both built-in mic and a desk + feed, PulseAudio/PipeWire may pick the wrong one. Fix in + `pavucontrol` → Recording tab while `lightcontrol` is running. +- **Beat sensitivity.** `src/beat.rs` constants: + - `THRESHOLD` (default `1.35`) — ratio of short to long envelope. + Higher = stricter. + - `MIN_DELTA` (default `0.020`) — absolute energy rise required. + Suppresses warmup-window false triggers and quiet-room noise. + - `MIN_INTERVAL_MS` (default `200`) — caps detected BPM at 300. +- **Matelight unreachable.** TUI header will show + `matelight: connecting…` or the last error. `lightcontrol` reconnects + every 3 s. The Matelight preset falls back to a slow dim-white pulse + meanwhile. +- **Photosensitivity.** Gabba/Red/Blue/Pink strobes are hard 12.5 Hz + square-wave alternations at the engine's Nyquist rate. Don't fire + them at a crowd that hasn't been warned.