Source:
ControlSurface.h
ControlSurface¶
A control surface is a view of the state ControlModule owns, kept in step in both directions.
Enumerations¶
| Name | Description |
|---|---|
SurfaceControl |
Which bank a surface control belongs to, so a kind plus an index names exactly one control. |
RingStyle |
What an LED ring draws as well as where it points, a pan ring filling from the center and a volume ring from one end. |
SurfaceControl¶
Which bank a surface control belongs to, so a kind plus an index names exactly one control.
| Value | Description |
|---|---|
Switch |
|
Encoder |
|
Fader |
|
Pad |
RingStyle¶
What an LED ring draws as well as where it points, a pan ring filling from the center and a volume ring from one end.
| Value | Description |
|---|---|
Single |
|
Volume |
|
Pan |
|
Fan |
|
Off |
ControlSurface¶
src/core/util/ControlSurface.h:50One attached surface, implemented by a transport and called when the state it mirrors changes.
Public Methods¶
virtual ~ControlSurface() = default
: Destroyed through this interface, since ControlModule holds surfaces by base pointer.
virtual void sendValue(SurfaceControl kind, uint8_t index, uint8_t value)
: A control's position changed, value being 0..255, the unit every surface control uses.
virtual inline void sendRing(uint8_t index, uint8_t value, RingStyle style)
: An encoder's ring: where it points and what it draws, defaulting to the position alone.
virtual inline void sendColor(uint8_t index, uint8_t r, uint8_t g, uint8_t b)
: A pad's color. Does nothing by default: most transports have no color at all.
virtual inline void sendColors(const uint8_t * rgb, uint8_t count)
: Several colors at once, rgb being countRGB triples, defaulting to a sendColor loop.
virtual inline void sendLabel(uint8_t index, const char * text)
: A name for a control, where the transport can show one. Does nothing by default.
More info¶
Why a surface mirrors rather than syncs¶
ControlModule owns the state: switch1..8, encoder1..8, fader1..8, and what each drives. A surface holds no copy, which is what lets two attach at once and stay in step, a phone running Open Stage Control and a desk on the rack. It is also why inbound is not a method here. A surface writes through the same control path the HTTP API and the UI use, so it gains no privilege and there is no second copy to reconcile.
Feedback is not an echo¶
On a motorized desk the motors move because the host sends positions back, and on an Akai APC the pads have no meaning until the host lights them. The surface is often the output device, and this interface is how it gets driven.
Why four verbs¶
The hardware has four kinds of feedback, and folding them into one would force every transport to pretend:
| Verb | What it carries |
|---|---|
sendValue |
a position: a motor, an Open Stage Control widget, an LED bar |
sendRing |
a position and the style the ring draws, which the APC40 mk2 (CC 0x18/0x38) and the X-Touch MINI (CC 1-8) both carry on a separate CC |
sendColor |
a color, for an RGB grid, in per-vendor SysEx with no shared structure |
sendLabel |
text, where the transport has somewhere to put it, such as a scribble strip |
Why the unimplemented three stay¶
Everything past sendValue has a default, so a transport implements only what its hardware can do. OSC overrides one method, a GPIO surface lights an LED, and an APC transport overrides the color verbs. OSC is the only transport today, so the other three have no implementer yet. They are kept because their shapes come from the hardware rather than a guess, and a default each means a transport that cannot do one writes no code for it.