Source:
InputMapping.h
InputMapping¶
The binding table behind every input service: a row says what one input does to one control.
Shared by button, infrared and every later transport, because the half that differs between them is only how the event is detected. What happens next is identical, so it lives here once rather than in each module.
Functions¶
| Return | Name | Description |
|---|---|---|
bool |
firePadRow inline |
Fire the pad in a grid position, false when there is nothing there: why through the list. |
bool |
runInputAction inline |
Apply an action to its target through the one primitive every transport uses, false when the row is unassigned or names something absent. |
bool |
runInputLevel inline |
Drive a target with a continuous value, rescaled into the control's own range: why this is separate from the event path. |
void |
writeInputActionFields inline |
The action half of a row as a document, emitted by every service so one row shape renders wherever it came from. |
bool |
targetTypeIsNumbered inline |
Whether a target type is numbered; a named test, so a future unnumbered type reads clearly. |
void |
composeTarget inline |
Build the stored target string from a type and a number, the two being how a user edits it rather than how it is kept. |
void |
decomposeTarget inline |
Read a stored target back into a type and a number for the editor: what an unrepresentable one reads as. |
void |
writeInputTargetOptions inline |
The target-type options as a shared set, emitted once per list rather than per row. |
void |
writeInputTargetDetailField inline |
The target half alone, for an input whose value is the reading: a kind and a value would be stored, shown and ignored. |
void |
writeInputActionDetailFields inline |
The action half as editable fields, so a user retargets an input without the interface: why a Set is not always offered. |
bool |
setInputActionField inline |
Set one action field from a row edit; false for a field this does not own, so a module can try its own afterwards. |
firePadRow¶
inline
inline bool firePadRow(MoonModule & mod, uint8_t slot, const char * label, char * outStatus, size_t statusLen)
Fire the pad in a grid position, false when there is nothing there: why through the list.
runInputAction¶
inline
Apply an action to its target through the one primitive every transport uses, false when the row is unassigned or names something absent.
runInputLevel¶
inline
Drive a target with a continuous value, rescaled into the control's own range: why this is separate from the event path.
writeInputActionFields¶
inline
The action half of a row as a document, emitted by every service so one row shape renders wherever it came from.
targetTypeIsNumbered¶
inline
Whether a target type is numbered; a named test, so a future unnumbered type reads clearly.
composeTarget¶
inline
Build the stored target string from a type and a number, the two being how a user edits it rather than how it is kept.
decomposeTarget¶
inline
Read a stored target back into a type and a number for the editor: what an unrepresentable one reads as.
writeInputTargetOptions¶
inline
The target-type options as a shared set, emitted once per list rather than per row.
writeInputTargetDetailField¶
inline
The target half alone, for an input whose value is the reading: a kind and a value would be stored, shown and ignored.
writeInputActionDetailFields¶
inline
inline void writeInputActionDetailFields(JsonSink & sink, const InputAction & a, bool hasRelease = true)
The action half as editable fields, so a user retargets an input without the interface: why a Set is not always offered.
setInputActionField¶
inline
Set one action field from a row edit; false for a field this does not own, so a module can try its own afterwards.
Variables¶
| Return | Name | Description |
|---|---|---|
constexpr int |
kMinActionValue constexpr |
What a row's value may hold, stated once and used by both the editor's bounds and the field that parses an edit. |
constexpr int |
kMaxActionValue constexpr |
|
constexpr unsigned long |
kMaxPadNumber constexpr |
The largest pad a target may name; a number past it addresses nothing, so it is refused rather than wrapped. |
constexpr const char * |
kTargetTypes constexpr |
The target types an input can point at, a type plus a number: why only the surface. |
constexpr uint8_t |
kTargetTypeCount constexpr |
|
constexpr unsigned long |
kTargetTypeMaxNumber constexpr |
The highest number each target type has, indexed by type, so a parse cannot accept a control that does not exist. |
kMinActionValue¶
constexpr
What a row's value may hold, stated once and used by both the editor's bounds and the field that parses an edit.
kMaxActionValue¶
constexpr
kMaxPadNumber¶
constexpr
The largest pad a target may name; a number past it addresses nothing, so it is refused rather than wrapped.
kTargetTypes¶
constexpr
The target types an input can point at, a type plus a number: why only the surface.
kTargetTypeCount¶
constexpr
kTargetTypeMaxNumber¶
constexpr
The highest number each target type has, indexed by type, so a parse cannot accept a control that does not exist.
InputAction¶
src/core/util/InputMapping.h:86What one physical input does: a target control, and how the input changes it.
Public Attributes¶
char target = ""
: "Module.control", empty for an unassigned row
Kind kind =
: which of the three this row does
int16_t value = 0
: Set: what to write. Delta: the signed nudge. Toggle: unused.
Public Methods¶
inline bool assigned() const
: Whether this row names a target at all.
Public Types¶
enum Kind
: How the input changes its target; a toggle is its own kind because a delta cannot express it.
| Value | Description |
|---|---|
Toggle |
read the current value, write its inverse. A light switch. |
Set |
write value. A momentary hold writes 1 then 0; a pad writes a slot. |
Delta |
add value to the target, clamped to its declared bounds. A nudge. |
More info¶
The target is a string, and the surface is the recommended one¶
A row names Module.control, so an input can drive the control surface or a module control directly. Both are the same mechanism with no special case: the surface is a recommendation rather than a rule. Driving the surface is the better path, since one place then shows what the device's controls do and every transport reaches the same switch.
The editor offers only the surface. An earlier draft also offered a few module controls directly, which was a second path to the same place. Two ways to say one thing is the split brain the two-step model exists to avoid, and it left a user wondering which a given row used. A row can still name any control through the interface, which is the escape hatch for anything the surface does not carry yet.
A pad is a row, not a control¶
A pad grid renders from a list, so a pad is reached through that list rather than by control name. Every such list already publishes each row's slot and accepts an activate field, so this needs to know nothing about presets. Any module that grows a pad grid therefore becomes targetable by every input at once. Resolving it here rather than in each service is what makes a button, a remote and every later transport reach a pad the same way.
A pad fires on the press alone. A release firing it again would re-apply the same preset for no reason, and would make a momentary row unusable.
An event and a reading are different shapes¶
A press carries no number, so a Set row writes the fixed value it was given and zero on release. An analog input's value IS the reading, so a row's stored value has nothing to say, and the two paths stay separate rather than sharing a parameter. They differ in what they do with every kind: a toggle or a delta driven fifty times a second is not something a user can mean.
A reading arrives in the range every surface control uses and is rescaled to whatever the target holds. So a pedal is configured once and works on any target, rather than needing a range per target.
Reading and writing in the control's own units¶
A value is read through the scheduler, which answers at the control's declared width. Reading the raw pointer as a byte was wrong, a wider control holding a large value reading back truncated. The surface's own byte reader clamps too, so a positive delta wrote the wrong number and a negative one could never move a control down. A mapping nudges the CONTROL rather than the surface, so it reads in the control's units and clamps to the control's own bounds.
A select and a palette store their option COUNT, so the last valid index is one below it. Clamping to the count produced a value the writer clamped again, and a delta that overshot stopped short of the end instead of landing on it.
A Set needs a release to clear it¶
A button reports letting go; a remote does not, since a code arrives as a single event with no matching release. So a Set is offered only where a release exists to clear it, or it would write its value and latch forever. An input without one offers toggle and delta, which are both complete in one event.
A target the vocabulary cannot express does nothing¶
The whole suffix of a name must parse, and the number must be in that type's own range. A trailing character would otherwise fire the wrong pad, and a number past the range would wrap through the cast and fire another one entirely. One shared bound would let a number past the surface's count through: it parses, it is stored, and it dispatches to nothing.
A target set through the interface to something the editor cannot represent reads back as unassigned, so the dropdown shows nothing while the row keeps working. That is the honest reading, and silently rewriting it would be worse.