XOSC
Forward any USB input — keyboard, MIDI, gamepad, serial — as OSC, to anything.
XOSC is a tiny Windows desktop utility that listens for keyboard, MIDI, gamepad, or serial input and forwards it as OSC over UDP — to Resolume Arena, Avolites, QLab, or anything else that speaks OSC. The mapping graph is React Flow in an Electron renderer; the Node main process owns the OSC sender, serial port, and global hotkeys. Built for VJs and live-event operators who want "press the button you want to bind" plumbing without writing a driver.
- TypeScript
- Electron
- electron-vite
- React
- React Flow
- Zustand
- Astro
- Web MIDI API
- HTML5 Gamepad API
- node-osc
- serialport
- NSIS
- GitHub Actions
XOSC opens a UDP socket and turns whatever the
operating system reports — a key on a USB keypad, MIDI Note 60
on channel 1, button 9 on a generic gamepad, the ASCII line
"BTN1_DOWN\n" coming out of an Arduino at
115 200 baud — into an OSC packet at
127.0.0.1:7000. Designed for Resolume Arena; works
for any OSC receiver. One window, no daemons, no service to
install.
The input matrix
- Keyboard — any key code with modifier capture (Ctrl / Alt / Shift / Meta). Discrete trigger, plus ASCII string payload for receivers that want the raw key name.
- MIDI via Web MIDI — Note On/Off, CC, Pitch Bend, Program Change. Channel and note number forward as OSC args; CC numbers fan out to addressable output nodes.
- Gamepad via the HTML5 Gamepad API, polled at 60 Hz. Buttons fire discrete triggers; axes forward raw floats. Up to four pads addressable independently.
- Serial on any COM port via
node-serialport, line-buffered. Each unique line is its own trigger — wire an Arduino with five push-buttons and you have five named OSC events.
Signal chain
Capture → match → emit. The OS reports an
event; the input bus normalizes it to a stable signature
(midi:noteOn:1:60, kbd:F13,
serial:COM4:BTN1_DOWN); the React Flow mapping
graph routes it to every wired output node; each output node
owns its host:port and emits a UDP packet. Pulse,
Toggle, and Hold arg modes
determine the payload shape. Multiple outputs fire in parallel
— fan out to two Resolume machines, an Avolites desk, and a
QLab cue stack at the same time.
How it's split
The renderer is React + React Flow: the mapping graph, the
listeners that don't need Node (keyboard, Web MIDI, Gamepad
API), and every UI surface. The main process owns the
Node-only pieces: the node-osc UDP sender,
serialport for COM input, Electron's
globalShortcut for system-wide hotkeys, and a
JSON config file at %APPDATA%\XOSC. IPC is a thin
command channel — the renderer asks main to send OSC, register
a shortcut, or open a serial port; main streams events back.
Ten themes, no purple-cyan-glossy
The whole UI is driven by a flat token map applied to
:root — eight dark themes (Solder, Phosphor,
Blueprint, Sodium, Rack, Console, Vapor, Obsidian) and two
light (Bone, Newsprint). Each one repaints both the marketing
site and the in-app graph live with no reload. The defaults
are tuned for FOH operators staring at the screen for hours
— high-contrast monospace, no gloss, no gradients, no glow.
How it ships
Tagging vX.Y.Z kicks GitHub Actions, which builds
on windows-latest, runs NSIS for
the installer, and uploads
XOSC-Setup-X.Y.Z.exe to the GitHub release. The
Astro site at xosc.gamingworld.uk
auto-fetches the latest release for its download button. The
whole pipeline is just release patch →
git push --tags. Currently Windows-only and
unsigned; macOS / Linux builds are scoped for after the
mapping-graph editor lands its v0.2 polish pass.
Why "XOSC"
The X stands for "any" — any input, any output, any receiver. The original brief was a single binding for one Resolume macro from a USB foot-pedal; once the mapping graph existed, every other input class was a half-day of plumbing. The whole project is the FL-Studio "press the button you want to bind" experience, applied to OSC.
Straight from the source
The project's own README.
Rendered in place — every link, image, and code block carried over from the repo. The page below is what a contributor would see opening the project for the first time.
XOSC
Map any input → any output. Built for Resolume, works for anything.
XOSC is a tiny Electron app that listens for keyboard, MIDI, gamepad, serial, OSC-in, Art-Net DMX, or HID-keyboard RFID input and forwards it as OSC, DMX, serial, or video-player commands to wherever you need it.
It's the FL-Studio-style "press the button you want to bind" experience, applied to the full A/V plumbing stack.
- Site & download: https://xosc.gamingworld.uk
- Platform: Windows 11 only (Peak Technologies publisher; unsigned).
What's in v0.8.0
- Settings router — full-screen Settings modal (Ctrl+,) with 9 panes, every interactive control tooltipped, and a context-aware help drawer (
?button per pane). - DMX protocol depth — HTP / LTP / smart merge, sACN priority byte, ArtPoll discovery, GDTF / QXF / OFL fixture imports, color-space-aware HSV output, Art-Net Timecode RX, and per-frame JSONL capture.
- Live DMX inspector — 32×16 grid, source-attributed coloring (graph, pad, art-net-in, test), per-universe FPS + priority overrides.
- RFID input — HID-keyboard burst detector with configurable terminator / burst rate / prefix, per-reader test scan, and a global "scan now" listen-mode overlay. New
RfidIngraph node. - Video player windows — frameless playback windows on any monitor, named playlists with enable/disable + reorder, WebGL2 effect chain interface (passthrough in v1, room for crossfade / grade / etc), and a
PlayerOutgraph node with play / advance / random / fade actions.
Repo layout
xosc/
├── VERSION # single source of truth
├── justfile # `just` for everything
├── package.json # Electron app
├── electron/ # main + preload (Node)
├── src/ # renderer (React)
├── installer/nsis/ # NSIS script
├── scripts/ # bump-version, changelog
├── web/ # Astro site (xosc.gamingworld.uk)
├── docs/ # markdown source — published to web
├── CHANGELOG.md # auto-appended on release
└── .github/workflows/ # build + release + deploy
Building
You need: Node 20+, just, and on Windows: NSIS for the installer.
just # list recipes
just dev # hot-reload Electron
just build # produce dist/xosc-X.Y.Z.exe
just package # + NSIS installer dist/XOSC-Setup-X.Y.Z.exe
just release patch # bump → build → package
Cutting a release: tag vX.Y.Z and push. GitHub Actions builds on windows-latest and uploads the installer to the GitHub release. The website auto-fetches the latest release for its download button.
Architecture in one paragraph
Renderer holds the mapping graph (React Flow), input listeners that don't need Node (keyboard / Web MIDI / Gamepad API / HID-keyboard RFID), and every UI surface. Main process owns the things only Node can do: node-osc UDP, serialport, globalShortcut, the DMX engine (Art-Net / sACN / Open DMX / Enttec Pro / Slow-break), the inbound Art-Net listener + ArtPoll responder, the video-player BrowserWindow manager, and a JSON config in %APPDATA%/XOSC. IPC is a thin command channel — renderer asks, main does it, main streams events back.
Video-player windows are extra renderer processes; they share the preload bundle so window.xoscPlayer IPC works the same way the main renderer's window.xosc does.
See docs/ for the user-facing manual.
Build something like this
Want a tool like this for your shop?
We've shipped this kind of thing before. Twenty-minute intro call, no slides.