Name matrix inputs, fix the meter scale, add output meters

Found on the live S31 (read-only, plus meter subscriptions):

- Matrix inputs are named at /Matrix_Inputs/N/Channel_Input/name (an
  address missing from DiGiCo's 2014 list). Their names now appear in
  every matrix-send dropdown, preset and the new matrix_in_N_name
  variables, falling back to "Matrix In N" when empty. Matrix inputs also
  get trim and phase.
- Console names are space-padded where the surface wraps them; every name
  is now trimmed and its whitespace runs collapsed ("LEAD V RESI").
- Meter values are inverted: 127 is silence and lower is louder, about
  1 dB per step below full scale (silent channels read 127, the room mic
  36-48). The module treated 127 as peak. Level meters now read dBFS
  (approximate), gauges span -60..0 dBFS, signal and peak thresholds are
  in dBFS; gain reduction reads dB of reduction, 127 meaning none.
- Bus and matrix outputs have meters (/Aux_Outputs, /Group_Outputs and
  /Matrix_Outputs/N/Output/meter): new signal, peak, value and gauge
  feedbacks and "Buss meters" / "Matrix meters" presets.

3002 presets, 2.7 MB. npm test: 425 checks pass on Node 25 and on
Companion's Node 22. Deployed and checked on the booth Companion 5.1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-20 10:25:39 -04:00
co-authored by Claude Opus 5.5
parent 9f64d20a24
commit 52777f3d7c
11 changed files with 436 additions and 152 deletions
+44 -23
View File
@@ -6,7 +6,7 @@ This connection does two things:
matrix outputs, control groups, graphic EQs, snapshots) and builds its dropdowns, variables and
presets from the live names. Faders, mutes, solos, pans, aux sends, group assigns, matrix sends,
control groups, graphic EQs, per-channel switches (phantom, EQ in, filters, inserts ...) and
snapshots are covered, with feedbacks, variables, rotary-encoder presets and input meters.
snapshots are covered, with feedbacks, variables, rotary-encoder presets and input and output meters.
2. **Relays the DiGiCo iPad app.** An S-Series console talks to exactly one iPad at a time. Companion
takes that slot and the iPad apps connect to this computer instead; everything an app sends is
forwarded to the console unchanged, and everything the console sends is copied to every app, so
@@ -60,10 +60,13 @@ and anything they change reaches this module too, so feedbacks follow moves made
On every connect (and on the **Reload** action, and automatically after the console was silent for
20 seconds and comes back) the module asks for the console name, the matrix, control group and graphic EQ
counts, the buss types and modes, every name, the session name, the snapshot list, and the fader, mute,
counts, the buss types and modes, every name (inputs, busses, matrix inputs and outputs, control groups, graphic EQs), the session name, the snapshot list, and the fader, mute,
solo and pan of everything that answered. The console does not answer the input and buss counts, so an
entity exists when its **name** answered; entities that never answer are hidden from dropdowns, variables
and presets. Dropdown entries read `1 · KICK In`, `24 · Monitors (group)`, `3 · Message · cue 4`.
and presets. Dropdown entries read `1 · KICK In`, `24 · Monitors (group)`, `3 · Message · cue 4`. The console pads names
with trailing spaces and wraps long ones with runs of spaces; every name is trimmed and its whitespace collapsed to single
spaces when it arrives, so dropdowns, variables and presets show `Studio TB`, not `Studio TB `. A matrix input with
no name reads `Matrix In N`.
When a name, a buss mode or the snapshot list changes, the definitions are rebuilt a moment later.
Sends, group assigns, matrix sends, graphic EQ gains and the per-channel switches are **not** bulk-loaded:
each is read the first time a button or action needs it.
@@ -89,7 +92,7 @@ is not known yet.
| Matrix | output mute, fader set/adjust; matrix send on/off, level set/adjust |
| Control groups | mute, solo, fader set/adjust |
| Graphic EQ | in/out, band gain set/adjust (bands 1-32) |
| Channel strip | per input and per buss: phantom, phase, pad, EQ in, compressor in, gate in, high-pass in, low-pass in, delay in, insert A/B in (on/off); trim (-40 to +40 dB), analog gain (0 to 60 dB), filter frequencies (20 to 20000 Hz) (set/adjust; trim also on matrix outputs) |
| Channel strip | per input and per buss: phantom, phase, pad, EQ in, compressor in, gate in, high-pass in, low-pass in, delay in, insert A/B in (on/off); trim (-40 to +40 dB), analog gain (0 to 60 dB), filter frequencies (20 to 20000 Hz) (set/adjust; trim also on matrix outputs and matrix inputs, phase also on matrix inputs) |
| Snapshots | fire (pick from the list or type an index), next, previous |
| Console | reload, raw OSC, relay: forget all iPads |
@@ -116,12 +119,12 @@ own value changes.
* Boolean (button colour): input muted / solo; aux send on; group assigned; buss muted / solo; matrix output muted /
solo; control group muted / solo; **matrix send on**; **graphic EQ in**; snapshot is current; fader level above/below
a threshold; aux send level above/below; console link alive; relay has an iPad; every channel-strip switch
(phantom, phase, pad, EQ in, compressor in, gate in, high-pass in, low-pass in, delay in, insert A/B in); and the meter
feedbacks below.
(phantom, phase, pad, EQ in, compressor in, gate in, high-pass in, low-pass in, delay in, insert A/B in; phase also
per matrix input); and the meter feedbacks (signal present, peak hold) for inputs, busses and matrix outputs.
* Value (put live numbers in button text with a preset's local variable): input fader and pan; aux send level, On/Off
and pan; buss / matrix / control group fader; **matrix send level**; **graphic EQ band gain**; trim, analog gain and
filter frequency per input and buss (trim also per matrix output); current snapshot name; input meter value. Levels
read `-inf` at or below -90 dB.
filter frequency per input and buss (trim also per matrix output and matrix input); current snapshot name; meter level
text (see **Meters**). Levels read `-inf` at or below -90 dB.
* Numeric, for gauges (see **Gauges** below): the `*_pos` position feedbacks, `input_pan_num` / `send_pan_num` and
`geq_band_db`.
* Advanced image bars (**legacy image**, deprecated by Companion 5.1, kept so existing buttons keep working): input
@@ -142,7 +145,7 @@ number you feed to a gauge through a button local variable:
| `input_fader_pos`, `buss_fader_pos`, `matrix_fader_pos`, `cg_fader_pos`, `send_level_pos`, `matrix_send_level_pos` | 0-100 | fader / send position on a fader taper; unknown reads 0 |
| `input_pan_num`, `send_pan_num` | 0-1 | the console's pan, 0.5 = centre (unknown reads 0.5) |
| `geq_band_db` | -12 to +12 | graphic EQ band gain in dB (unknown reads 0) |
| `input_meter_pos` | 0-100 | input meter (0-127 scaled); has the *Meter* option level / gate / compressor reduction |
| `input_meter_pos`, `buss_meter_pos`, `matrix_meter_pos` | 0-100 | meter position: levels over -60..0 dBFS (-inf = 0), gain reduction over 0..20 dB; the input meter has the *Meter* option level / gate / compressor reduction |
The fader taper maps +10 dB = 100, +5 = 87.5, 0 = 75, -5 = 65, -10 = 55, -20 = 40, -30 = 28, -40 = 18, -50 = 11 and
-60 = 6 (straight lines in between), falls to about 1 just above -90 dB, and reads 0 at or below -90 dB (off).
@@ -158,7 +161,7 @@ To add a gauge to your own button in Companion 5.1:
## Variables
`input_N_name|fader|mute|pan`, `buss_N_name|mode|stereo|fader|mute`, `matrix_N_name|fader|mute`,
`input_N_name|fader|mute|pan`, `buss_N_name|mode|stereo|fader|mute`, `matrix_N_name|fader|mute`, `matrix_in_N_name`,
`cg_N_name|fader|mute` (only for entities that exist), `snapshot_index|name|cue|count`, `console_name`,
`session_name`, `connected`, `relay_clients`, `relay_client_ips` and `last_change`. Use them as
`$(label:input_1_name)` with the connection's label. There are no per-send variables: use the value feedbacks.
@@ -178,25 +181,42 @@ buttons.
| Sends to *aux name* | One section per named aux buss: per input an **On/off** button (green when on, shows the level) and a **Level (knob)** (turn = send level, press = on/off, with a gauge) |
| Group *group name* | One section per named group buss: per input an **Assign** toggle, green when assigned |
| Matrix, Control groups | Mute and fader knob (with a gauge) per output / group |
| Matrix sends to *output name* | One section per matrix output: per matrix input an **On/off** button (green when on; shows `Matrix In N` and the level) and a **Level (knob)** (turn = send level, press = on/off, with a gauge) |
| Matrix sends to *output name* | One section per matrix output: per matrix input an **On/off** button (green when on; shows the matrix input's name and the level) and a **Level (knob)** (turn = send level, press = on/off, with a gauge) |
| Graphic EQs | One **In/out** toggle per graphic EQ, green when in |
| Snapshots | **Fire** per snapshot (green when current), next, previous, current (display) |
| Input meters | Level, gate gain reduction and compressor gain reduction buttons per input, each with a vertical gauge at the right edge (green below 70, amber 70-90, red above 90) |
| Buss meters, Matrix meters | One level meter button per named buss and per matrix output, same vertical gauge |
| Console | Reload, connection status, relay status |
Busses and control groups with no name are unused slots and get no presets. If the preset list would exceed
3000 entries or 4 MB, the per-input gate / compressor reduction meter presets are left out first, then the
3200 entries or 4 MB, the per-input gate / compressor reduction meter presets are left out first, then the
per-input aux send level knobs, and a warning is logged.
## Meters
Input meters are subscribed on the console the first time a meter feedback renders (ids start at 5000 so
they never collide with an iPad's). The console then streams values 0-127 several times a second; the
module re-checks the meter feedbacks at most 10 times a second. Level is the post-fader input meter; gate and
compressor gain reduction are the two reduction meters. There is no known buss meter address, so busses
have no meters. The console keeps one subscription table: an iPad connecting clears it (`/Meters/clear`),
and the module re-subscribes half a second after it sees that pass through the relay. Two iPads watching
different banks both receive the mixed stream. The module never sends `/Meters/clear` itself.
Meters are subscribed on the console the first time a meter feedback renders (ids start at 5000, so they never collide
with an iPad's: input meters 5000-5260, buss meters 5400 + N, matrix output meters 5450 + N). The console then streams
integer values 0-127 several times a second, only for the ones that changed, and the module re-checks the meter
feedbacks at most 10 times a second, and only the buttons showing the meter that moved.
**The scale is inverted and approximate.** A level meter value is about the **dB below full scale**: 0 = full scale,
42 = about -42 dBFS, **127 = silence (-inf)**. A gain reduction meter value is about the **dB of reduction** (0-12 is
typical, 127 = inactive). It has not been calibrated against a reference tone, so treat the numbers as roughly 1 dB per
step, not as a measurement.
| Feedback | What it shows |
| --- | --- |
| `input_meter_value`, `buss_meter_value`, `matrix_meter_value` | text: `-42` or `-inf` (dBFS, approx.); gain reduction meters: `3` (dB) |
| `input_meter_pos`, `buss_meter_pos`, `matrix_meter_pos` | gauge position 0-100: levels over -60..0 dBFS, gain reduction over 0..20 dB |
| `input_signal`, `buss_signal`, `matrix_signal` | signal present: level above a dBFS threshold (option, default -50; gain reduction meters: any reduction) |
| `input_peak`, `buss_peak`, `matrix_peak` | level at or above a dBFS value (option, default -1) held for the *Hold* time; not for gain reduction meters |
Input meters are level (post-fader), gate gain reduction and compressor gain reduction. Output meters exist for aux
busses, group busses (the address follows the buss's current aux / group side) and matrix outputs; they are level meters.
Control groups and matrix inputs have no meter. The console keeps one subscription table: an iPad connecting clears it
(`/Meters/clear`), and the module re-subscribes half a second after it sees that pass through the relay (and after a
reconnect). Two iPads watching different banks both receive the mixed stream. The module never sends `/Meters/clear`
itself.
## Troubleshooting
@@ -224,17 +244,18 @@ Levels, sends and pans are floats too. Numbers are 1-based, snapshot indexes 0-b
| `/Console/Aux_Outputs/types` | 25 x i | 1 = aux, 0 = group |
| `/Console/{Aux_Outputs,Group_Outputs,Input_Channels}/modes` | i per buss / input | 2 = stereo, 1 = mono |
| `/Console/Session/Filename` | s | |
| `/Input_Channels/N/Channel_Input/name`, `/Aux_Outputs/N/Buss_Trim/name`, `/Group_Outputs/N/Buss_Trim/name`, `/Matrix_Outputs/N/Buss_Trim/name`, `/Control_Groups/N/name`, `/Graphic_EQ/N/name` | s | matrix inputs have no name address |
| `/Input_Channels/N/Channel_Input/name`, `/Matrix_Inputs/N/Channel_Input/name`, `/Aux_Outputs/N/Buss_Trim/name`, `/Group_Outputs/N/Buss_Trim/name`, `/Matrix_Outputs/N/Buss_Trim/name`, `/Control_Groups/N/name`, `/Graphic_EQ/N/name` | s | names arrive padded; the module cleans them |
| `/{Input_Channels,Aux_Outputs,Group_Outputs,Matrix_Outputs,Control_Groups}/N/{fader,mute,solo}` | f | fader in dB, -150 = -inf |
| `/Input_Channels/N/Panner/pan` | f | 0..1, 0.5 = centre |
| `/Input_Channels/N/Aux_Send/M/{send_level,send_on,send_pan}` | f | |
| `/Input_Channels/N/Group_Send/M/group` | f | |
| `/Matrix_Inputs/N/Matrix_Send/M/{send_level,send_on}` | f | |
| `/Matrix_Inputs/N/Matrix_Send/M/{send_level,send_on}` | f | a matrix send floors at -90 dB |
| `/Matrix_Inputs/N/Channel_Input/{trim,phase}` | f | |
| `/Graphic_EQ/N/{geq_in,geq_gain_1..32}` | f | |
| `/Input_Channels/N/{Channel_Input,Filters,Channel_Delay,EQ,Dynamics,Insert}/...` and the buss equivalents | f | the channel-strip switches and values above |
| `/Snapshots/Current_Snapshot`, `/Snapshots/count` | i | |
| `/Snapshots/names` | one `/Snapshots/name` `iiis` per snapshot: index, cue x 100, ?, name | |
| `/Snapshots/Fire_Snapshot_number`, `/Snapshots/Fire_Next_Snapshot`, `/Snapshots/Fire_Prev_Snapshot` | none | write-only int |
| `/Input_Channels/N/Channel_Input/post_meter`, `/Input_Channels/N/Dynamics/GR_meter` | none | send `,ii [id, kind]` (kind 1 level and gate, 4 compressor) to subscribe |
| `/Meters/values` | `ii...` | pushed pairs `[id, value]`, value 0..127 |
| `/Input_Channels/N/Channel_Input/post_meter`, `/Input_Channels/N/Dynamics/GR_meter`, `/{Aux_Outputs,Group_Outputs,Matrix_Outputs}/N/Output/meter` | none | send `,ii [id, kind]` (kind 1 level and gate and outputs, 4 compressor) to subscribe |
| `/Meters/values` | `ii...` | pushed pairs `[id, value]`, value 0..127: inverted scale, 127 = silence / inactive |
| `/Meters/clear` | none | clears every subscription on the console; sent by iPad apps, never by this module |