out to launch
outToLaunch · outputOUT TO LAUNCH — turns a Novation Launchpad Mini Mk3 into a live 9×9 RGB VIDEO MONITOR. Takes ONE video input, downsamples it to a 9×9 grid on the GPU (each cell is a TAPS×TAPS box-average of its slice of the frame, so it does not alias/flicker on moving video), and pushes those 81 pixels to a BOUND Launchpad's LEDs in real time via the batch-RGB SysEx. The Mini Mk3's WHOLE addressable surface IS a 9×9 grid — the 8×8 pads (11..88) + the top CC row (91..98) + the right scene column (19..89) + the corner logo (99) — and in programmer-mode numbering every button is row*10+col for row/col 1..9, so the downsample maps DIRECTLY onto the hardware, UPRIGHT: the bottom-left of the frame lands on pad 11 (bottom-left), the top-right on the logo (99). It has NO video output — it is a SINK, an endpoint (like a monitor at the end of a chain, except the monitor is a grid of buttons). BIND from the card: Connect (gesture-gated Web-MIDI sysex, no eager prompt) then pick a Launchpad output; bindMonitor claims EXCLUSIVE LED control of that device (it enters programmer mode + its LEDs are driven by the video), so a bound Launchpad CANNOT be used for control at the same time — out to launch takes it over. Two knobs shape the look: BRIGHT (0..1) scales overall LED brightness; GAMMA (0.5..3, default 2.2) deepens/lifts the mid-tones (both applied identically to the LEDs AND the on-card preview, so the preview matches the hardware exactly). Architecture: the module's pure-GL factory box-averages the input into a tiny 9×9 FBO and readPixels the 81 RGBA texels each frame (exposed via read('grid9x9')); the CARD's throttled ~30 fps rAF loop reads that grid, draws the 9×9 preview, maps it to LED colours (monitorGridToLeds), and setMonitorFrame()s it (diffed → only changed LEDs sent, batched into one SysEx ≈413 bytes/frame — trivial over USB-MIDI). pullExempt keeps the readback fresh even when the card is off-screen. The monitor binding is INDEPENDENT of the clip-launcher's L/R units, so out to launch on one Launchpad and LAUNCHPAD CONTROL on another run simultaneously (one owner per physical device; same-device sharing is refused via isOutputClaimed). On unbind / node-delete the device is released (LEDs cleared, returned to Live mode). USAGE: patch a source (CAMERA / a generator / a clip) → VIDEO in, Connect + pick your Launchpad, and dial BRIGHT/GAMMA — a tiny confidence monitor, a lo-fi VJ output, or lighting a Launchpad from a live feed. The pure surface mapping (lpMonitorIndex / rgb8ToLp / monitorGridToLeds) lives in $lib/control/launchpad/launchpad-sysex.
the faceplate
inputs
| id | cable | what it does |
|---|---|---|
in | video | The video frame to display. It is box-averaged down to a 9x9 RGB grid and pushed to the bound Launchpad's LEDs; with nothing patched the grid is black (LEDs off). Accepts any video-domain source (the engine upcasts mono-video and image to video). RGB video stream |
params
| id | label | range | default | curve |
|---|---|---|---|---|
bright | Bright | 0..1 | — | linear |
gamma | Gamma | 0.5..3 | — | linear |
controls
| control | what it does |
|---|---|
| Bright | BRIGHT (0..1, default 1) scales the overall LED brightness — every cell's RGB is multiplied by this before it's sent, so lower values dim the whole monitor (useful because the RGB LEDs are very bright). Applied identically to the on-card preview. |
| Gamma | GAMMA (0.5..3, default 2.2) is the gamma exponent applied to each colour channel before scaling. 1 is a literal what-you-see map; above 1 deepens the mid-tones and blacks (usually flatters the bright LEDs on a moving source); below 1 lifts dim detail. Applied identically to the on-card preview. |
| Out to launch connect {n} | CONNECT LAUNCHPAD asks the browser for Web MIDI with sysex — a permission that must be granted from a real click, and that the whole module is inert without — and then lists the Launchpad outputs attached to this machine. Picking one from that list is what binds it as a monitor; the list and the UNBIND that releases it live on the faceplate's own surface, because a roster enumerated from the machine is not something a control can declare in advance. Pressing CONNECT again re-asks and re-lists, which is how you pick up a Launchpad that was plugged in after the first time. |
source
out-to-launch.ts on GitHub.