Skip to content

LightPresetsModule

Source: LightPresetsModule.h

Preset

struct Preset
src/light/drivers/LightPresetsModule.h:318

Public Attributes

uint32_t id = 0

char name = {}

uint8_t channelCount = 3

uint32_t poolOffset = 0

uint32_t poolLen = 0

bool locked =

LightPresetsModule

class LightPresetsModule
src/light/drivers/LightPresetsModule.h:48

Inherits: 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.

LightPresetsModule card

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).