Compute the bulk assignment of a whole stagebox onto channels, each port keyed by
its own channel number: capture_NN → channel[startChannel + NN − 1] for every port
on the chosen side. This is the one-action fast setup — in1 → ch1, in2 → ch2, … — and
the keying is what keeps it honest when a port is missing from the node: the gap leaves
that one channel unassigned and every later port stays on its true number, instead of the
whole bank silently renumbering by list position. A port whose name carries no number is
skipped into StageboxAssignPlan.unnumbered, never assigned by position. The
inverse clear plan carries the same mapping (the caller unpatches each channel).
Range-aware (issue #332) — three bounds, and they are not interchangeable:
the box's declared width bounds what may be assigned to it. count above the
box's own width is REFUSED (exceedsBoxWidth), never truncated: an S-0808 is 8 in and
an S-1608 is 16, and handing either channels it does not have is the bug this guard
exists for;
the 40-slot AUDIO fabric bounds where that audio lands. With a fabricBase from
planStageboxFabric, a placement ending past slot 39 is REFUSED
(exceedsAudioFabric) — those channels are not in the frame at all;
channelCount — the CONSOLE's own width. This one is a legitimate partial fit (the
desk is simply narrower than the box), so it still drops the overhanging ports into
StageboxAssignPlan.skipped rather than refusing.
Neither bound is the head-amp one: preamp CH addressing is a separate 48-slot space where
an S-1608 based at 0x20 legitimately reaches CH 47 (see reac-slots.ts).
Pure: it maps the box's own ports (already read from the nodes) onto a channel range, so
it is fully unit-tested.
Compute the bulk assignment of a whole stagebox onto channels, each port keyed by its own channel number:
capture_NN → channel[startChannel + NN − 1]for every port on the chosen side. This is the one-action fast setup —in1 → ch1, in2 → ch2, …— and the keying is what keeps it honest when a port is missing from the node: the gap leaves that one channel unassigned and every later port stays on its true number, instead of the whole bank silently renumbering by list position. A port whose name carries no number is skipped into StageboxAssignPlan.unnumbered, never assigned by position. The inverseclearplan carries the same mapping (the caller unpatches each channel).Range-aware (issue #332) — three bounds, and they are not interchangeable:
countabove the box's own width is REFUSED (exceedsBoxWidth), never truncated: an S-0808 is 8 in and an S-1608 is 16, and handing either channels it does not have is the bug this guard exists for;fabricBasefrom planStageboxFabric, a placement ending past slot 39 is REFUSED (exceedsAudioFabric) — those channels are not in the frame at all;channelCount— the CONSOLE's own width. This one is a legitimate partial fit (the desk is simply narrower than the box), so it still drops the overhanging ports into StageboxAssignPlan.skipped rather than refusing.Neither bound is the head-amp one: preamp CH addressing is a separate 48-slot space where an S-1608 based at
0x20legitimately reaches CH 47 (seereac-slots.ts).Pure: it maps the box's own ports (already read from the nodes) onto a channel range, so it is fully unit-tested.