dmx-mainhall-foo/README.md
Yan Minagawa fbb303a322 docs: add related-projects section to README
Links to c-base/dmxbackend (the backend this tool talks to), the
matelight ecosystem (jaseg/matelight upstream, c-base fork,
matelight-pixel frontend, the c-matelight gitea org with the freshest
code, and mlaudiospectrum for the audio-reactive prior art), other
c-base lighting (roboclub-lighting), and the artefact guide entry for
the Matelight hardware history.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-10 10:31:11 +02:00

320 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
---
## Related projects
### c-base backend & infrastructure
- **[c-base/dmxbackend](https://github.com/c-base/dmxbackend)** — the
aiohttp service this tool talks to. ArtNet/HTTP-WebSocket/MQTT bridge
for the mainhall lights. Hosts the fixture API at
`dmx.cbrp3.c-base.org:8000` and the live state WebSocket at
`/api/v1/websocket_state/`.
- **[c-base/c-base-map](https://github.com/c-base/c-base-map)** —
interactive map of c-base areas and interfaces. Useful context for
where the fixtures actually sit in space.
- **[code.c-base.org/t/dmx-mainhall-foo](https://code.c-base.org/t/dmx-mainhall-foo)** —
this repo's home.
### Matelight ecosystem
- **[jaseg/matelight](https://github.com/jaseg/matelight)** — the
canonical project. WS2801-in-Mate-bottles, 40×16 display, CRAP
protocol (UDP/1337). Foundation everything else builds on.
- **[c-base/matelight](https://github.com/c-base/matelight)** — c-base
fork of the above.
- **[c-base/matelight-pixel](https://github.com/c-base/matelight-pixel)**
— Python/FastAPI + React frontend served at
`matelight.cbrp3.c-base.org:8000`.
- **[code.c-base.org/c-matelight](https://code.c-base.org/c-matelight)**
— the active production org on c-base's Gitea (fresher than the
GitHub mirror). Contains `matelight`, `matelight-original`,
`matelight-pixel`, `c-matelight`.
- **[c-base/mlaudiospectrum](https://github.com/c-base/mlaudiospectrum)**
— audio-spectrum analyzer that paints the Matelight from mic input.
Conceptually adjacent to our `BeatPulse` preset; if you want to push
audio reactivity into the Matelight itself (instead of the hall),
this is the prior art.
### Other c-base lighting
- **[c-base/roboclub-lighting](https://github.com/c-base/roboclub-lighting)**
— separate lighting project for the roboclub area, C/MCU-side.
### Documentation
- **[cbag3.c-base.org/artefact/matelight](https://cbag3.c-base.org/artefact/matelight)**
— c-base artefact guide entry for the Matelight (hardware history,
build notes).
- **[c-base/artefact-guide](https://github.com/c-base/artefact-guide)**
— source of the artefact guide above.