Skip to content

PreviewDriver

Source: PreviewDriver.h

PreviewDriver

class PreviewDriver
src/light/drivers/PreviewDriver.h:42

Inherits: DriverBase

Streams a true-shape 3D preview to the web UI over the binary WebSocket.

The preview is a POINT LIST, not a dense grid: only the real lights are sent, at their real (x,y,z) positions. This is the proven MoonLight model (virtual grid → physical sparse lights; positions sent once at mapping time, channels per frame). Two message types — PreviewDriver owns both wire formats; the HTTP server is a domain-neutral BinaryBroadcaster that just writes the bytes: 0x03 coordinate table (sent when the geometry changes — every LUT/layout rebuild via prepare — and when a new client connects, so a refresh gets it; never per-frame): [0x03][count:u32][bx:u8][by:u8][bz:u8][stride:u16][(x,y,z):u8×3 × count] bx/by/bz = bounding-box extent (for client centring); positions are 1 byte/axis (a layout box ≤255/axis is the realistic case). count is u32 so a >65535-light panel (big ArtNet/HUB75 walls) isn't capped by the wire format — it matches nrOfLightsType (u32 on PSRAM boards).

0x02 per-frame channels: [0x02][count:u32][stride:u16][(r,g,b) × count] RGB by driver index, every stride-th light. The browser positions triple i at coord-table entry i*stride. count is the number of points actually kept after lattice downsampling (the lights whose position satisfies pos ≡ 0 mod stride) — a client sizes its buffer from this count, not from the light total. stride rises above 1 only when the point set would exceed the runtime send-buffer cap (min(display, memory)); below the cap every light is sent (stride 1), so a sparse layout streams in full.

PreviewDriver card

Public Attributes

uint8_t fps = 24 : Preview stream rate (Hz), independent of render FPS.

Public Methods

virtual inline bool userEditable() const override : The 3D preview the web UI renders streams from this driver.

inline void setBroadcaster(BinaryBroadcaster * b) : Set the sink each message is pushed to (HttpServerModule, as a BinaryBroadcaster).

inline void setResumableFramesForTest(bool on) : Test-only: flip the resumableFrames A/B directly (production toggles it through the control + affectsPrepare path).

virtual inline bool hasCorrectionControls() const override : Preview shows the raw logical buffer, no correction.

virtual inline void defineDriverControls() override : Bind the controls: fps (1-60) and resumableFrames (the downsampled-frame transport A/B).

virtual inline void setSourceBuffer(Buffer * buf) override : Point the driver at the sparse driver buffer the LED/ArtNet drivers also read (the MappingLUT fills it with exactly the real lights).

virtual inline void prepare() override : A rebuild (layout add/replace/remove, resize, modifier change) ran — the light set / positions may have changed, so rebuild + broadcast the coordinate table (the MoonLight "positions once at mapping time").

virtual inline void release() override : Clear every shared status string on release — fail buffer, config error, and config warning — so a stopped driver leaves nothing behind (frees the owned failBuf_; retracts the warning the same "clear only MY status" way as the error), then chain to MoonModule::release() so any ScratchBuffer the driver holds frees on disable and children recurse.

virtual inline bool affectsPrepare(constchar * name) const override : The resumableFrames A/B flips the transport AND which buffers exist, so a change re-runs prepare (which allocates them when ON, frees them when OFF) — the standard "config change applies live" path, off the render thread.

virtual inline void tick() override : Per-tick: (re)stream the coordinate table when the geometry or client set changed, then stream one color frame if the previous one finished draining.

inline void buildAndSendCoordTable() : Build (or rebuild) the cached coordinate table from the layout's real lights and broadcast it (the 0x03 message).

inline bool sendFrame() : Stream one per-frame 0x02 RGB message straight from the producer buffer — no intermediate copy.