- Rust 100%
cpal pulls in ALSA dev headers on Linux, which made the default build fail anywhere alsa-lib-devel / libasound2-dev wasn't installed. Most operators just want the TUI for animated presets and matelight sync, not the microphone-driven BeatPulse — so flip the default. cargo build --release # default, works everywhere cargo build --release --features mic # opt-in for beat detection BeatPulse still appears in the preset list either way; without mic it just shows the cyan "waiting" heartbeat instead of reacting to audio. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> |
||
|---|---|---|
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
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(/monitorWS, subprotocolmatemon) 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 ondmxbackend.
The local microphone, optionally, for beat-driven scenes.
Quick start
# prerequisites (Fedora):
sudo dnf install rustup 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
The default build skips the microphone / beat-detector feature so it compiles on any machine without extra system libraries. To enable audio-reactive presets, see With microphone below.
Build
The default build produces all three binaries (lightcontrol,
panels, bars) without any system-library dependencies beyond what
the Rust toolchain already needs:
cargo build --release # default: TUI + panels + bars, no mic
In this mode the [k] Beat Pulse preset still works as a slow cyan
"waiting for mic" heartbeat — useful as a calm idle scene — but it
won't react to audio.
With microphone
To make BeatPulse actually listen to the room, build with the mic
feature. This pulls in cpal and
through it the system ALSA library on Linux.
# Fedora
sudo dnf install alsa-lib-devel
# Debian / Ubuntu
sudo apt-get install libasound2-dev
cargo build --release --features mic
The TUI's beat-detector panel (flash bar + BPM + envelope sparkline)
only shows live data with this build; in the default build it shows
the empty --- BPM state.
Quick checks
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.
./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--hostMATELIGHT_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.
./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).
./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/monitorWebSocket feeder + frame sampler.src/beat.rs— cpal capture + energy-onset beat detector (featuremic).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 whilelightcontrolis running. - Beat sensitivity.
src/beat.rsconstants:THRESHOLD(default1.35) — ratio of short to long envelope. Higher = stricter.MIN_DELTA(default0.020) — absolute energy rise required. Suppresses warmup-window false triggers and quiet-room noise.MIN_INTERVAL_MS(default200) — caps detected BPM at 300.
- Matelight unreachable. TUI header will show
matelight: connecting…or the last error.lightcontrolreconnects 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 — 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:8000and the live state WebSocket at/api/v1/websocket_state/. - 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 — this repo's home.
Matelight ecosystem
- jaseg/matelight — the canonical project. WS2801-in-Mate-bottles, 40×16 display, CRAP protocol (UDP/1337). Foundation everything else builds on.
- c-base/matelight — c-base fork of the above.
- c-base/matelight-pixel
— Python/FastAPI + React frontend served at
matelight.cbrp3.c-base.org:8000. - 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
— audio-spectrum analyzer that paints the Matelight from mic input.
Conceptually adjacent to our
BeatPulsepreset; 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 — separate lighting project for the roboclub area, C/MCU-side.
Documentation
- cbag3.c-base.org/artefact/matelight — c-base artefact guide entry for the Matelight (hardware history, build notes).
- c-base/artefact-guide — source of the artefact guide above.