Tools for Behringer X32 / Midas M32 consoles — emulator, remote GUI, show recording.
tabula is a set of tools around Behringer X32 / Midas M32 consoles, written in Go: a console emulator, and a client that connects to a console (or to the emulator) and serves a web GUI to inspect and drive it, record shows and replay them, and later share them with live viewers.
| Binary | Role |
|---|---|
tabula-emu |
Pure console emulator. Speaks the console’s OSC protocol on UDP 10023 so that X32-Edit, M32-Edit, Mixing Station, Maillot’s tools — and the tabula client — can connect to it. Optional read-only HTTP debug page showing the stored state, the traffic and every request it did not understand. It is not a console UI. |
tabula |
Client. Connects to a console or to tabula-emu over OSC and serves a web GUI on an HTTP port: connection setup, every console menu, recording, replay… |
Both share the same library (pkg/).
| Package | Content |
|---|---|
pkg/osc |
OSC 1.0 codec with the console’s leniencies (missing type tags, node replies without a slash). |
pkg/schema |
The parameter tree: every address, its type, range, steps and how it is written in node/scene text. Built from Maillot’s protocol document and checked against real scene files. |
pkg/scene |
Scene file (.scn) read/write. |
pkg/state |
In-memory state store with a change feed; used by the emulator (as the console’s memory) and by the client (as a mirror of the console). |
pkg/emu |
The emulator’s protocol server and debug HTTP page. |
pkg/console |
The client side of the protocol: discovery, full sync, /xremote keepalive, meters, rate-limited writes, library commands. |
pkg/session |
Recording and replay; exports for audio editors. |
pkg/audio |
Audio capture of the console’s USB card: one WAV file per track, sync with the session. |
/info, /xinfo, /status, get/set of every parameter, node-address set with multiple type tags, /node, / (echoed), /xremote change fan-out to the other clients (10 s lease)..scn./node and with Maillot’s X32GetScene → identical node lines.Driven by the unknown-request log while connecting the real editors:
/-prefs, /-stat, /-show, /-libs, /-action, /-undo, /-usb, /-urec, /-insert, /-ha (1126 nodes; formats checked against a real M32C’s values cached by M32-Edit)./meters/0…16 with synthetic levels following the mix, /subscribe, /formatsubscribe, /batchsubscribe, /renew, /unsubscribe./fx/N/par/NN): fields follow the effect type (switching effect loads its defaults); all 61 effects modelled, with ranges, steps, formats and defaults matching M32-Edit’s built-in tables; 57 of 61 real parameter lines round-trip byte for byte, the other 4 (older firmware spellings) load and are written in today’s form./save, /load, /copy, /delete, /rename, /add (cues), /showdump, with listings in /-show and /-libs, optionally kept in a directory (-library). Scene safes and snippet filters are not applied yet./-action/* (go scene/snippet/cue, clear solo, undo checkpoint and undo, init) and computed status (/-insert, /-ha/NN/index from sources and input routing, /-stat/solo).-presets imports M32-Edit’s library (channel, effect and routing presets)./-action/setrtasrc (channels, buses, graphic EQs, pre/post EQ), shaped by low cut, EQ and graphic EQ./config/linkcfg, with the rules of M32-Edit’s offline logic (see docs/emulator.md).docs/testing-with-editors.md).pkg/console: discovery (broadcast /xinfo), full sync via /node (window of 32 requests), /xremote renewal, writes refused until armed; tested end to end against the emulator.POST /api/library)..scn, opens in M32-Edit) + time-stamped log of every change (who/what/when) + markers (pkg/session).docs/API.md; tabula -record records unattended.pkg/audio): an external recorder (arecord, parecord, ffmpeg or a custom command; no cgo) streams the card, one WAV file per track (24-bit by default, RF64 past 4 GiB, headers refreshed every 2 s), named from the console’s routing; first-sample time and clock drift measured from the arrival of the samples and kept in meta.json; free space watched, clean stop before the disk is full; device listing; -audio-* flags (docs/recording.md).access.json, revocable at once (docs/access.md).docs/README.md).[0, 1] on the wire and quantized to a fixed number of steps (faders 1024, sends 161, EQ frequency 201…).-8.25 → -8.3); positive levels carry a sign (+0.3), zero does not (0.0)./node dump: hold below 10 ms, release below 10 ms or above 999 ms, positive fader levels.