LightPresetsModule
Source:
LightPresetsModule.h
Preset¶
src/light/drivers/LightPresetsModule.h:318Public Attributes¶
uint32_t id = 0
char name = {}
uint8_t channelCount = 3
uint32_t poolOffset = 0
uint32_t poolLen = 0
bool locked =
LightPresetsModule¶
src/light/drivers/LightPresetsModule.h:48Inherits:
MoonModule,ListSource
The reusable light-preset library — a Drivers submodule (child role preset) that owns a set of NAMED channel-role wirings, each editable in its own row and referenced by many drivers.
A "light preset" is a channel-role layout: role r at channel i says channel i of a light carries role r (Red/Green/Blue/White/WarmWhite/Yellow/UV, and the fixture roles Pan/Tilt/…). A curated set of real fixtures is SEEDED as read-only (locked) rows on first boot: the colour orders (RGB, GRB, BGR, RGBW, GRBW, WRGB), the multi-channel LED/par fixtures (Curtain GRB6, Lightbar RGBWYP, RGBCCT, IRGB), and moving heads (MH BeeEyes 15, MH BeTopper 32, MH 19x15W-24). A user adds custom named wirings alongside them. A driver stores only a preset's STABLE id; it resolves that id here at cold-path rebuild time into its own Correction (see deriveCorrection) and holds nothing else. So building a wiring once makes it reusable across every driver, and reordering / deleting other presets never disturbs a reference (the id is invariant; the row index is not).
Storage is uncapped. A preset is exactly as wide as its fixture — role bytes live in one dynamic pool (rolePool_, a ScratchBuffer), each preset a {poolOffset, channelCount} slice. No fixed channel ceiling: a moving head can declare as many channels as it has. The pool is touched only on the cold path (edit / restore); nothing binds a control to it, so it is free to reallocate — the control-bind stable-address rule that pins DriverBase's arrays does not apply.
It's the first consumer of the editable-list primitive (EditableListSource): the whole add / delete / reorder / per-field-edit UI comes from that, reused rather than re-built (custom palettes reuse the same primitive later). The per-row fields are the preset's name, its channel count, and one role picker per channel.
Hot-path guarantee. The render loop never reads this module. A driver resolves its preset id into its own Correction offset cache ONCE per config change (deriveCorrection); per-light apply() reads only that cache. A library preset costs exactly what an inline one did per light.

Public Methods¶
virtual inline ModuleRole role() const override
: Role for type identification (no RTTI needed).
virtual inline bool userEditable() const override
: Whether the user may delete or replace this module from the UI.
inline uint32_t defaultId() const
: The id of the first preset (a safe default reference for a fresh driver / a dangling id).
inline uint8_t presetCount() const
: Row count / name / id accessors so a driver can build its preset Select (names for the options, ids for the stable reference it stores).
inline constchar * nameAt(uint8_t i) const
inline uint32_t idAt(uint8_t i) const
inline uint8_t indexOfId(uint32_t id) const
inline bool presetHasSynthChannel(uint32_t id) const
: Resolve id into out — fill its brightness LUT + channel-role offsets from the preset's wiring.
inline bool deriveCorrection(uint32_t id, uint8_t brightness, Correction & out) const
inline LightPresetsModule()
virtual inline void setup() override
: Default lifecycle propagates to children.
virtual inline void prepare() override
: Tier-3 of the control-change split (see onControlChanged above): the module (re)allocates / recomputes whatever derived state it owns — an effect's heap, a Layer's mapping LUT, the Drivers output buffer.
virtual inline void release() override
virtual inline void defineControls() override
: defineControls MUST be idempotent and pure: only controls_.clear() + controls_.addX().
inline uint8_t listRowCount() const override
inline void writeListRow(JsonSink & sink, uint8_t row) const override
inline void writeListOptionSets(JsonSink & sink) const override
: The row's editable field descriptors: name (text), channels (the fixture width), and one role Select per channel — rendered generically by the editable-list primitive.
inline void writeListRowDetail(JsonSink & sink, uint8_t row) const override
inline bool isEditableList() const override
inline bool addListRow(uint32_t & outId) override
inline bool deleteListRow(uint32_t id) override
inline bool moveListRow(uint32_t id, uint8_t to) override
inline bool setListRowField(uint32_t id, constchar * field, constchar * valueJson) override
inline bool restoreList(constchar * json, constchar * key) override
: Persist: the presets List round-trips as a JSON array (each row carries its roles array).
Public Static Attributes¶
constexpruint8_t kMaxPresets = 32
Public Static Methods¶
static inline LightPresetsModule * active()
: The boot library (exactly one under Drivers).