Control
Source:
Control.h
ControlDescriptor¶
src/core/module/Control.h:150One control's metadata: what it points at, how to render it, and how to persist it.
The value lives in the module's own variable, and this borrows a pointer to it.
Public Attributes¶
void * ptr = nullptr
: the bound variable, which the hot path reads directly
const char * name = nullptr
: the control's name, a flash literal
uintptr_t aux = 0
: a total, an options array, or a unit, by type
ControlType type =
: which storage, widget and mapping apply
int32_t min = 0
: the lower bound, or unused for a text type
int32_t max = 255
: the upper bound, or the buffer size for a text type
int32_t def =
: What the control was born with, for a module whose controls come from data rather than type.
bool hidden = false
: Whether the UI hides this control, which persistence ignores so state survives the toggle.
bool persistLabel = false
: Whether persistence writes this Select's label, for options enumerated fresh each boot.
bool readonly = false
: Whether the UI renders this display-only, for a value tooling pushes rather than a user.
uint8_t minMode = 0
: The mode a reader needs before this control is shown: 0 everyone, 1 expert, 2 developer.
bool numberField = false
: Whether a numeric renders as a number input, for an integer that is an address not a magnitude.
bool fader = false
: render as a vertical fader
bool encoder = false
: render as a rotary encoder
bool switchRow = false
: render in the horizontal switch strip
bool displayStrip = false
: render as the full-width readout
bool live = false
: Whether this is live state rather than configuration, and so is never written to flash.
const char * surfaceTarget = nullptr
: What this surface control drives, one field because each kind drives exactly one thing.
bool(* validate = nullptr
: An optional check applied before every write, so the rule lives with the control.
Public Static Attributes¶
constexpr int32_t kNoDefault = INT32_MIN
: The sentinel meaning no default was declared, so an ordinary control costs nothing.
ControlList¶
src/core/module/Control.h:207The set of controls a module exposes, which is its controls_.
A control binds to a class variable by reference, so the hot path reads it directly. Descriptors live in a fixed-capacity array, with no per-control allocation.
Prior art: MoonLight's addControl, which binds a variable the same way.
Public Methods¶
inline ~ControlList()
: Free the descriptor array, the bound variables being the modules' own.
ControlList() = default
: A list starts empty, and grows as a module declares its controls.
ControlList(const ControlList &) = delete
: A list belongs to one module, so it is never copied.
ControlList & operator=(const ControlList &) = delete
: Nor copy-assigned.
ControlList(ControlList &&) = delete
: Nor moved, the descriptors being pointed into from elsewhere.
ControlList & operator=(ControlList &&) = delete
: Nor move-assigned.
inline void addControl(const char * name, uint8_t & var, uint8_t min = 0, uint8_t max = 255)
: Bind a byte as a slider, the preferred default, whose bounds also clamp writes.
inline void addControl(const char * name, uint16_t & var, uint16_t min = 0, uint16_t max = UINT16_MAX)
: Bind a wide unsigned value, whose bounds default to its own full range.
inline void addControl(const char * name, int16_t & var, int16_t min = INT16_MIN, int16_t max = INT16_MAX)
: Bind a signed value, for a coordinate where negatives are legal.
inline void addControl(const char * name, int32_t & var, int32_t min = INT32_MIN, int32_t max = INT32_MAX)
: Bind a wide signed value, where sixteen bits would wrap.
void addControl(const char * name, int8_t & var, int16_t min = 0, int16_t max = 0) = delete
: A small signed value is either a pin or telemetry, so the caller names which.
inline void addPin(const char * name, int8_t & var, int16_t min = -1, int16_t max = 63)
: Bind a GPIO number, which renders as a number since a pin is an identity not a magnitude.
inline void addControl(const char * name, bool & var)
: Bind a boolean as a toggle, whose range is itself.
inline void addText(const char * name, char * var, uint16_t bufSize = 16, bool()(const char ) validate = nullptr)
: Bind a character buffer as a text input, with an optional check on every write.
inline void addTextArea(const char * name, char * var, uint16_t bufSize = 16, bool()(const char ) validate = nullptr)
: Bind a buffer the UI renders as a resizable multi-line box, such as a script's source.
inline void addFilePath(const char * name, char * var, uint16_t bufSize, const FilePathPick & pick, bool()(const char ) validate = nullptr)
: Bind a buffer naming a file, whose contents the UI edits, with a picker over a directory.
inline void addFilePath(const char * name, char * var, uint16_t bufSize, bool()(const char ) validate = nullptr)
: Bind a file-path control with no picker, which is an editor over one fixed path.
inline void addPassword(const char * name, char * var, uint8_t bufSize = 32)
: Bind a buffer holding a secret, which the API obfuscates rather than sending in clear.
inline void addReadOnly(const char * name, char * var, uint8_t bufSize = 32)
: Bind a buffer the UI shows but never edits.
inline void addReadOnlyInt(const char * name, int8_t & var, const char * unit)
: Bind a small signed telemetry value, shown with the unit suffix the caller owns.
inline void addPalette(const char * name, uint8_t & var, PaletteOptionsFn optionsFn, uint8_t optionCount)
: Bind an index as a palette dropdown, whose options carry their own swatch colors.
inline void addSelect(const char * name, uint8_t & var, const char *const * options, uint8_t optionCount)
: Bind an index as a dropdown over the options array the caller owns.
inline void addProgress(const char * name, uint32_t & var, uint32_t total, bool bytes = true)
: Bind a value as a progress bar against a total, labeled either as bytes or as a count.
inline void addIPv4(const char * name, uint8_t * var)
: Bind four octets as an address, which serializes as its dotted-quad string.
inline void addList(const char * name, ListSource & source)
: Bind a source as a list of rows, which it produces on demand from its own data.
inline void addButton(const char * name)
: Add a momentary button, whose click reaches the module's changed hook rather than storage.
inline void clear()
: Drop every control, which a rebuild does before redeclaring them.
inline uint8_t count() const
: How many controls are declared.
inline const ControlDescriptor & operator[](uint8_t i) const
: One control by index.
inline void setHidden(uint8_t i, bool hidden)
: Hide or show the control last added, which persistence ignores so state survives.
inline void setDefault(uint8_t i, int32_t def)
: Record what a control was born with, for one whose default the type cannot supply.
inline void setReadOnly(uint8_t i, bool readonly)
: Render a control display-only, for a value tooling pushes rather than a user edits.
inline void setAdvanced(uint8_t i, bool advanced = true)
: Mark a control expert-only, which the UI shows from expert mode up.
inline void setDeveloper(uint8_t i)
: Mark a control developer-only: a number that diagnoses the firmware rather than the show.
inline void setNumberField(uint8_t i, bool numberField = true)
: Render a numeric as a number input, for an integer that is an identity not a magnitude.
inline void setPersistLabel(uint8_t i, bool persistLabel = true)
: Persist a Select by its label, for options enumerated fresh each boot.
inline void setFader(uint8_t i, bool fader = true, const char * target = nullptr)
: Render a numeric as a vertical fader, for a level a user rides rather than sets once.
inline void setEncoder(uint8_t i, bool encoder = true, const char * target = nullptr)
: Render a numeric as a rotary encoder, the third surface affordance beside pads and faders.
inline void setSwitchRow(uint8_t i, bool switchRow = true, const char * target = nullptr)
: Render a boolean in the switch strip, so each column is one channel across the surface.
inline void setDisplayStrip(uint8_t i, bool strip = true)
: Render a read-only text as the full-width readout, which shows whatever was last touched.
inline void setLive(uint8_t i, bool live = true)
: Declare a control live state rather than configuration, so it is never written to flash.
ListSource¶
src/core/module/Control.h:98The backing for a list control, which the module owning the data implements.
Rows come straight from that module's own storage rather than being copied here. An editable source addresses its rows by a stable id, so a reference survives a reorder.
Public Methods¶
virtual ~ListSource() = default
: A source outlives its control, and is destroyed through this base.
virtual uint8_t listRowCount() const
: How many rows the list holds, which may change between calls.
virtual void writeListRow(JsonSink & sink, uint8_t row) const
: Append one row's summary, the fields a collapsed row shows.
virtual inline void writeListRowDetail(JsonSink & sink, uint8_t row) const
: Append one row's detail, which by default repeats the summary.
virtual inline void writeListOptionSets(JsonSink &) const
: Append option sets shared across rows, so a repeated select is serialized once.
virtual inline bool restoreList(const char , const char )
: Repopulate the rows from persisted JSON, the model owning its own deserialization.
virtual inline bool persistsList() const
: Whether these rows are worth writing to flash, which a derived list declines.
virtual inline bool isEditableList() const
: Whether this source accepts the four editing operations below.
virtual inline bool listAsPads() const
: Render the rows as a grid of pads, for rows triggered far more often than edited.
virtual inline uint8_t listGridCols() const
: The pad grid's columns, a non-zero value making it a fixed surface with real empty cells.
virtual inline uint8_t listGridRows() const
: The pad grid's rows, read with the columns above.
virtual inline bool addListRow(uint32_t &)
: Append a row with default values, reporting its new stable id.
virtual inline bool deleteListRow(uint32_t)
: Remove one row by id, which a protected row refuses.
virtual inline bool moveListRow(uint32_t, uint8_t)
: Move one row by id, which never changes that id.
virtual inline bool setListRowField(uint32_t, const char , const char )
: Set one field of one row, the source owning which fields are editable.
More info¶
What a control costs¶
A descriptor is a pointer, a name, an auxiliary word, the type, the bounds and some flags. That is about forty-eight bytes on a host, and less on a device. The value itself is the module's own variable, of one to four bytes. A module that overflows the default capacity is probably too complex.
Persistence and rebuilding¶
Values persist through the filesystem module, which overlays them through each pointer. Calling defineControls again clears and rebuilds the set. That is how a conditional control re-evaluates whether it is hidden. The per-type reference is on the type enum, and each addX below binds one type.