Skip to content

Repository files navigation

Lightz

A macOS desktop app for controlling DMX lighting via an Enttec USB DMX Pro Mk2. Built for live environments — fast scene recall, DCA-style fixture groups, multi-channel fixtures with color mixing, and Bitfocus Companion integration.

macOS only. Windows is not supported — the Enttec driver relies on macOS serial port access.


Download & Install

Option A — Build from source (recommended for now)

git clone https://github.com/bhdoggett/lightz.git
cd lightz
npm install
npm run build:mac

Open dist-electron/Lightz-0.2.9-arm64.dmg (Apple Silicon) or Lightz-0.2.9.dmg (Intel) from Finder. Drag Lightz to Applications.

Option B — Download pre-built .dmg

→ All releases

Download the right file for your Mac:

Download For
Lightz-0.2.9-arm64.dmg Apple Silicon (M1 and later)
Lightz-0.2.9.dmg Intel Mac

Double-click the .dmg, drag Lightz to Applications, then open it.

macOS Gatekeeper: Because Lightz is not notarized, macOS may block it on first launch.

  • If you see "Open Anyway" in System Settings → Privacy & Security, click it.
  • If you see "Lightz is damaged and can't be opened", run this in Terminal, then try again:
    xattr -cr /Applications/Lightz.app

Hardware Requirements

  • Enttec USB DMX Pro Mk2 (dual-universe USB-to-DMX interface)
  • macOS 12 Monterey or later (Apple Silicon and Intel supported)

No additional driver needed on macOS 12+. The Enttec Mk2 appears automatically in the Settings device list — no downloads required.

On older macOS versions, you may need to install the driver manually. Download it from the Enttec support page or the FTDI VCP driver page if the device is not detected after plugging in.


First Launch

  1. Plug in the Enttec device via USB.
  2. Open Lightz.
  3. Click the Settings icon (top right).
  4. Under DMX Device, click ↺ Refresh — your device should appear as /dev/cu.usbmodem....
  5. Click the device path to select it, then click Connect.
  6. The connection badge in the header turns green: DMX Connected.

Core Concepts

Full tab — raw channel control

Both DMX universes are displayed as stacked, collapsible sections (Universe 1 above Universe 2). Use this for initial patching and diagnosing which channel controls which fixture. Channel labels show universe-prefixed numbers (e.g. 1-001, 2-001). Click a channel label to name it — named channels become fixtures in the Custom tab automatically.

Custom tab — named fixture control

Your labeled fixtures appear here, grouped by universe and collapsible. Use this during a service. Sections (Scenes, Groups, Fixtures) can be collapsed to reclaim screen space.

Scenes

A scene is a snapshot of all fixture values at a moment in time.

  • Save Scene — click + Save Scene to open a popover, type a name and optional fade duration, click Save.
  • Activate — click a scene button to fade or snap all fixtures to those values.
  • Edit — select a scene, click Edit to rename, change fade time, or delete.
  • Drag to reorder — drag scene buttons left/right to rearrange.

Groups (DCA-style)

Groups work like a soundboard DCA — a master control that scales a set of fixtures together.

  • Create a group via + Group in the Custom tab.
  • Each fixture can belong to only one group. The group color appears on the master fader fill and as an indicator dot on sub-faders.
  • ○ (Full) — forces all fixtures in the group to 255 regardless of scene values.
  • ✕ (Mute) — silences all fixtures in the group.
  • Fader — scales output proportionally (50% = half brightness).
  • Groups reset to 100% on every app launch — they are session controls, not saved state.

Light Visualizer

A 2D stage view that simulates your lighting output — works with or without DMX hardware connected.

  • Sticky bottom panel — drag-resizable, collapsible, or pop out to a separate window.
  • Stage layout — fixtures render as colored circles at their current intensity and color. Drag them to arrange a room layout.
  • Grid editing — click the pencil icon to enter edit mode. Fixtures snap to grid points. Add/remove rows and columns with edge +/- buttons.
  • Ghost-based drag — dragging a light shows a ghost circle with snap indicators at the target position. Invalid placements (collisions, out of bounds) show red indicators. Fixtures stay in place until you drop.
  • Marquee selection — click and drag on empty stage space to draw a selection rectangle. Selected lights get an accent outline. Drag any selected light to move the whole group together, maintaining relative positions.
  • Cmd+click — toggle individual lights in/out of the selection.
  • Delete/Backspace — removes selected lights from the grid (returns them to unplaced).
  • Fit/Scroll mode — toggle between stretching the grid to fit the window or using a fixed-proportion grid with zoom and scrolling. In scroll mode, grid cells are always square regardless of window size.
  • Multiple lights per channel — one DMX channel often controls several physical fixtures. Duplicate a light with + to add more visual instances on the same channel.
  • Unplaced fixtures — fixtures not yet positioned appear in a sidebar. Click to select, Shift-click for range, Cmd-click to toggle. Drag onto the grid — hold Shift during drag to place vertically instead of horizontally.
  • Group overrides — mute, full, and fader states from groups are reflected in the visualizer.
  • Labels toggle — click the tag icon to show/hide fixture names and intensity percentages. Hover any light to see its info.
  • Pop-out window — detach the visualizer to a separate window (great for a second monitor), dock it back with one click.

Kill Switch

✕ All Off is always visible in the tab bar. Clicking it zeros all 512 channels on both universes immediately and clears the active scene.

Shows

A show file captures your entire rig: fixture definitions, scenes, group setup, and device settings.

  • Shows are saved to ~/Documents/Lightz/ as named JSON files — no file picker needed.
  • Click Shows in the header to open, save, or manage shows.
  • + New Show clears all fixtures, scenes, and groups (device settings preserved).
  • Share show files by copying the .json files from ~/Documents/Lightz/.

Adding Fixtures

Single-channel fixtures (dimmers, simple pars)

From the Custom tab: Click + Add Channels → select channels by range (1-8, 1,3,5) or by clicking the channel grid → name each fixture → Add Fixtures.

From the Full tab: Click any channel label on a fader to type a name. Named channels become fixtures in the Custom tab automatically.

Multi-channel custom fixtures (moving heads, RGB/RGBW pars, etc.)

Click + Add Custom Fixture to open the fixture builder:

  1. Name the fixture (becomes the master fader label).
  2. Set the Starting Channel and Universe.
  3. Add channels one by one — each channel has a role (Red, Green, Blue, Amber, White, UV, Dimmer, Strobe, Other) and a label.
  4. Link toggles whether a channel follows the master fader. Linked channels scale together; unlinked channels are independent.
  5. Save as Template to reuse this fixture layout for other fixtures of the same type.

Multi-channel fixtures appear in the Custom tab as a fader card with:

  • Master fader — scales all linked sub-channels proportionally.
  • Color swatch / picker — click to open an HSV color picker that drives the RGB, Amber channels together. White and UV channels are left untouched by the color picker and are controlled independently via their sub-faders.
  • ⚙ Gear button — reopens the fixture editor to rename, add/remove channels, or change roles.
  • Expand (›) — reveals all individual sub-faders with role-colored fills (red, green, blue, etc.) and link toggles beneath each.
  • Link toggles — click the chain icon below a sub-fader to unlink it from the master (e.g. to lock a strobe channel independently).

Color mixing behavior

  • RGB/RGBW: The color picker controls Red, Green, Blue, and derives Amber from warm tones automatically.
  • White channel: Lightens the displayed color toward white when raised — controlled only via its sub-fader, not the picker.
  • UV channel: Contributes to the color display but is not set by the color picker — control it via its sub-fader.

Settings

Setting Description
DMX Device Auto-detects USB serial devices. Click Refresh, then select your Enttec path.
Companion HTTP Port Default: 5551. Change only if another service uses that port. Restart required.

Bitfocus Companion Integration

Lightz runs a local HTTP server that Companion can call to fire scenes.

Method Endpoint Description
GET /status Health check → { status: "ok" }
GET /scenes List all scenes → [{ id, name }]
POST /scenes/:id/activate Activate a scene by slug ID

Setup in Companion

  1. Add a button → action type: Generic HTTP
  2. Method: POST
  3. URL: http://localhost:5551/scenes/<scene-slug>/activate
  4. The scene slug is shown in the Settings modal next to each scene name.

Keyboard & Interaction Tips

Action How
Type a channel value Click the value number above any fader to type a DMX value (0–255)
Rename a fixture Click the channel label or fixture name on any fader
Clear a fixture name Rename to empty — removes the fixture
Reorder scenes Drag a scene button left or right
Fire a scene Click the scene button
All Off (kill switch) Click ✕ All Off in the tab bar — zeros all channels on both universes
Open color picker Click the color swatch on a multi-channel fixture master fader
Edit a custom fixture Click the ⚙ gear icon on the fixture master fader
Expand sub-faders Click the arrow on a multi-channel fixture
Link/unlink a sub-fader Click the chain icon beneath the sub-fader label
Collapse a section Click the section header (Scenes, Groups, Universe 1, Universe 2, etc.)
Marquee-select lights Click and drag on empty stage space in edit mode
Toggle light selection Cmd+click a light on the visualizer stage
Move selected lights Drag any selected light — group moves together
Unplace selected lights Press Delete or Backspace with lights selected
Multi-select unplaced Shift-click (range) or Cmd-click (toggle) in unplaced sidebar
Place vertically Hold Shift while dragging unplaced fixtures onto the grid

Technical Notes

Enttec USB DMX Pro Mk2 — Dual-Port Initialization

The Mk2 exposes two independent DMX output ports. Universe 1 is routed to Port 1 and Universe 2 to Port 2 automatically — no configuration needed.

The Mk2 uses an undocumented binary protocol on top of standard serial (250000 baud, 8N2). Two initialization packets must be sent immediately after the serial port opens, or Port 2 will silently ignore all writes:

Purpose Packet (hex)
Enable API2 mode 7E 0D 04 00 AD 88 D0 C8 E7
Assign both ports as DMX outputs 7E CB 02 00 01 01 E7

These packets are not in the official Enttec documentation. They were sourced from the QLC+ open-source codebase (enttecdmxusbpro.cpp).

Once initialized, each universe is sent as a standard Pro API packet on a dedicated interval:

Universe Port label Interval
U1 0x06 every 30ms, starting immediately
U2 0xa9 every 30ms, starting 15ms after U1

The 15ms stagger prevents the two ~518-byte packets from colliding in the serial write buffer. At 250kbaud each packet takes ~20.7ms to clock out, so back-to-back sends in the same tick cause the second packet to be silently dropped.


Development

Prerequisites

  • Node.js 20+
  • Xcode Command Line Tools — xcode-select --install (required for native serialport)

Commands

npm install          # install dependencies (also runs electron-rebuild)
npm run dev          # launch Electron in development mode
npm run dev:web      # launch web version in browser (no Electron)
npm test             # run test suite
npm run build:mac    # build distributable .dmg files
npm run build:web    # build static web SPA to dist-web/

Output DMGs: dist-electron/Lightz-<version>[-arm64].dmg

Project Structure

electron/
  main/index.ts         Electron entry, BrowserWindow, IPC wiring
  preload/index.ts      contextBridge — typed window.electronAPI
  dmx.ts                DmxManager — hardware + group multipliers
  server.ts             Express — Companion HTTP server
  store.ts              electron-store — config persistence
  ipc.ts                ipcMain handlers
  shows-library.ts      Named show file read/write
  slug.ts               Scene ID slug generation

src/
  shared/
    types.ts            Domain types — Fixture, Scene, Group, Config
    dmx-utils.ts        Shared interpolation and clamping math
    electron-api.d.ts   Window.electronAPI type declarations
  renderer/
    App.tsx             Root — header, show management, modal routing
    main.tsx            Electron entry — wraps App in ElectronApiProvider
    main-web.tsx        Web entry — wraps App in WebApiProvider with demo config
    globals.css         CSS custom properties (design tokens)
    api/
      types.ts          LightzApi interface — platform-agnostic API surface
      context.tsx       ApiContext + useApi() hook
      electron-provider Wraps window.electronAPI for Electron
      web-provider      In-memory store with demo config for web
      demo-config       Pre-loaded demo show data
    components/         Folder-per-component (ComponentName/index.ts barrel)
      LightVisualizer   2D stage visualizer with draggable lights, grid editor
      PopoutWindow      Renders children in a separate browser window
      RawFader          Base fader (value, slider, toggle, label)
      MultiFixtureFader Multi-channel fixture card with color picker
      ScenesStrip       Scene buttons row with save/edit popover
      GroupFader        DCA-style group master with ○/✕ overrides
      GroupStrip        Horizontal group rack
      ...               (19 components total)
    views/
      MainView          Tab bar, section layout, fixture/scene/group wiring
      LiveView          Full raw-channel view (both universes, collapsible)
    hooks/
      useDmxState       In-memory DMX channel state
    utils/
      colorSync         RGB/RGBW color math
      gangFader         Proportional ratio math for linked channel scaling

vite.web.config.ts      Standalone Vite config for web build
Dockerfile              Multi-stage build for Coolify deployment

Tech Stack

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages