Engine infraestructure of the CueMS system
Project description
cuems-engine
Current release: v0.1.0rc2 — see CHANGELOG.md.
Timecode-driven audio, video, and DMX cueing engine with OSCQuery control.
- Source / issues: stagesoft/cuems-engine on GitHub
- API reference (HTML): stagesoft.github.io/cuems-engine
cuems-engine is the Python runtime at the heart of the CueMS (Cue Management System). It synchronises audio, video, and DMX playback across one or more nodes using MIDI Timecode (MTC), exposing a live control surface over OSC and WebSocket.
It is composed of:
cuemsengine— a Python package providing the full engine runtime, core primitives, and player orchestrationcontroller-engine— the systemd-managed master service that drives timecode, dispatches cues, and coordinates all nodesnode-engine— the systemd-managed per-node service that arms and fires players (audio, video, DMX) on receiving cue commands
Overview
The engine models show control as a deterministic, timecode-synchronised pipeline:
MTC Timecode → Controller Engine → Cue Dispatch → Node Engine → Player Lifecycle → Output
├── Audio (JACK)
├── Video (Gradient)
└── DMX
- MTC Timecode drives the system clock — all scheduling and playback boundaries are derived from it
- Controller Engine owns the cue list, tracks playback state, and coordinates the node fleet
- Cue Dispatch selects the next cue, handles pre/post-waits, arming, and go-trigger logic
- Node Engine receives commands over NNG, manages subprocess lifecycles, and reports status back
- Player Lifecycle wraps audio (via JACK), video (via
gradient-motiond), and DMX subprocesses - Output delivers the final media signal to the physical hardware
Architecture
Controller Engine: ControllerEngine
ControllerEngine is the master process (scripts/controller_engine.py). Responsibilities:
- Manage the WebSocket interface for the show editor
- Host the Ossia/OSCQuery device tree for live parameter control
- Run as MTC master — generate and distribute the timecode reference
- Monitor the node fleet via NNG, detect failures, and trigger restarts
- Track cue status and broadcast updates to connected clients
Typical deployment:
systemctl enable controller-engine
systemctl start controller-engine
Node Engine: NodeEngine
NodeEngine is the per-node process (scripts/node_engine.py). Responsibilities:
- Accept cue commands from the controller over NNG
- Manage the deploy workflow — rsync project assets to the node before playback
- Arm and launch audio, video, and DMX players as subprocesses
- Register OSC/OSCQuery endpoints for each active player
- Synchronise playback start to the MTC timecode from the controller
Typical deployment (on each playback node):
systemctl enable node-engine
systemctl start node-engine
Core: core/
Shared base layer used by both engines:
BaseEngine— abstract engine base; owns the asyncio event loop,ConfigManager, OSCQuery client/server lifecycle, MTC listener integration, and the ongoing/next cue pointersEngineStatus— structured data model for engine statelibmtc— MIDI Timecode master helper
Communications: comms/
NNG-based message transport between controller and nodes:
ControllerCommunications— controller-side NNG publisher and WebSocket bridgeNodeCommunications— node-side NNG receiver and command dispatcherAsyncCommsThread— asyncio/thread bridge for non-blocking NNG I/ONodesHub— node operation enum and shared data models
Cues: cues/
Cue execution layer — the unit of show control:
CueHandler— singleton managing the armed-cue registry and video player indexActionHandler— action cue dispatch with a three-phase hook system (before_dispatch,after_dispatch,wrap_dispatch) and NNG status sinkarm_cue— cue arming workflow (pre-load, readiness check)run_cue— single-shot cue playback (audio, video, DMX)loop_cue— loop/multiplay cue execution with MTC-boundary pollinghelpers— timing utilities (find_timing, pre/post-wait calculation)
Players: players/
Player subprocess management and hardware I/O:
PlayerHandler— singleton owning all active player instances; handles layer routing, canvas setup, and OSC communication with subprocessesAudioMixer— JACK-based audio mixing and routingJackConnectionManager— JACK port connection managementAudioPlayer— audio client subprocess wrapperVideoPlayer— video client subprocess wrapper (delegates togradient-motiond)DmxPlayer— DMX output subprocess wrapperGradientClient— OSC client for communicating withgradient-motiondPlayer— abstract base player interface
OSC / OSCQuery: osc/
Protocol layer for live parameter control and editor communication:
OssiaNodes— Ossia device tree node management (parameter registration, type mapping)OssiaClient/OssiaServer— OSCQuery client/server lifecycle wrappersWebSocketOscHandler— bidirectional WebSocket-to-OSC bridge between the show editor and the enginehelpers— OSC value routing and callback injection utilitiesendpoints— OSCQuery endpoint registration helpersPyOsc— pure-Python OSC fallback for environments without Ossia
Tools: tools/
Operational utilities used by both engines:
CuemsDeploy— rsync-based project asset deployment to nodes; mandatory-file precheck, progress streaming, startup and inactivity watchdog timeoutsMtcListener— MIDI Timecode decoder with 24h rollover detection and quarter-frame interpolationPortHandler— dynamic OSC port allocationdisplay_conf— display and canvas configuration parsersystem_ports— system MIDI port enumeration
Core Concepts
- MTC Timecode — the authoritative temporal reference for all playback scheduling and boundary evaluation
- Cue — a discrete show event (audio, video, DMX, or action) with pre/post-wait offsets and arming state
- Player — a managed subprocess that owns a single media channel and communicates back via OSC
- Deploy — the rsync-based transfer of project assets to a node before playback begins
- OSCQuery — the bidirectional device-tree protocol used for live parameter exposure and editor control
- NNG — the low-latency message transport between the controller and node engines
Design Goals
- Deterministic — identical timecode inputs produce identical playback; all scheduling derives from MTC
- Modular — clean separation between timecode, cue logic, player management, and transport layers
- Real-time capable — asyncio-based event loop suitable for continuous execution under systemd
- Observable — structured logging for all engine events; silent failures are a constitution violation
- TDD-disciplined — every production code path is preceded by a failing test; see
tests/ - Embeddable —
cuemsenginecan be imported and driven programmatically outside the CLI entry points
Installation
PyPI
pip install cuemsengine
Debian package
The debian/bookworm branch carries the packaging metadata. Two packages are produced:
| Package | Description |
|---|---|
cuems-engine |
Core engine runtime — controller and node engines |
cuems-engine-mock |
Mock player binaries for headless/CI environments without audio or video hardware |
Build from source:
git clone --branch debian/bookworm https://github.com/stagesoft/cuems-engine.git
cd cuems-engine
dpkg-buildpackage -us -uc
sudo dpkg -i ../cuems-engine_*.deb
System-package dependencies installed automatically: python3-pyossia (>= 2.0.0), python3-systemd (>= 235), cuems-utils, cuems-common.
Binaries are installed to /usr/lib/cuems/bin/; systemd service files are provided by the cuems-common package.
Development
Prerequisites
- Python 3.11 (managed via pyenv)
- Poetry
- System packages:
python3-pyossia,python3-systemd,libjack-jackd2-dev
Editable install
# From the repo root
poetry install
# Or, when the package is already installed system-wide under /usr/lib/cuems,
# replace it with a symlink to this source tree:
./scripts/link-dev.sh
Restart the controller-engine and node-engine services after symlinking to pick up source changes. To restore the installed package, reinstall the Debian package.
Run tests
cd src
pytest
Useful markers:
pytest -m unit # fast unit tests only
pytest -m "not slow" # skip long-running tests
pytest -m integration # integration tests (requires hardware or mocks)
pytest --cov=cuemsengine # with coverage report
Code style
black src/
isort src/
flake8 src/
Copyright notice
Copyright © 2026 Stagelab Coop SCCL. Authors: Alexander Ramos, Ion Reguera (ion@stagelab.coop) and Adrià Masip (adria@stagelab.coop).
This work is part of cuems-engine. It is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.
The SPDX short form of this notice is: SPDX-License-Identifier: GPL-3.0-or-later.
License
This project is licensed under the terms of the GNU General Public License v3.0 or later (GPL-3.0-or-later).
You are free to use, modify, and redistribute this software under the conditions set by the license. Any derivative work must also be distributed under the same license terms.
See the LICENSE file for the full license text.
Summary of Terms
-
Permissions:
- Use for any purpose
- Study and modify the source code
- Redistribute original or modified versions
-
Conditions:
- Source code must be made available when distributing
- Modifications must be licensed under GPL v3 or later
- Include a copy of the license and preserve notices
-
Limitations:
- Provided without warranty
- No liability for damages or misuse
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cuemsengine-0.1.0rc2.tar.gz.
File metadata
- Download URL: cuemsengine-0.1.0rc2.tar.gz
- Upload date:
- Size: 127.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c7fea91ce3a1f275180d18c615ee69c61a1df8cf4b2e1bb271039c64d09d7102
|
|
| MD5 |
7d3905dd9aee7b9babacd53be67ddc19
|
|
| BLAKE2b-256 |
97ac9a7b212d586ed1837a50b47529fefcfc88230b43ab9f997347729c809afb
|
Provenance
The following attestation bundles were made for cuemsengine-0.1.0rc2.tar.gz:
Publisher:
pypi-publish.yml on stagesoft/cuems-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cuemsengine-0.1.0rc2.tar.gz -
Subject digest:
c7fea91ce3a1f275180d18c615ee69c61a1df8cf4b2e1bb271039c64d09d7102 - Sigstore transparency entry: 1574117982
- Sigstore integration time:
-
Permalink:
stagesoft/cuems-engine@853c67b5a39fce619d724daf5a00913aabc4ef11 -
Branch / Tag:
refs/tags/v0.1.0rc2 - Owner: https://github.com/stagesoft
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@853c67b5a39fce619d724daf5a00913aabc4ef11 -
Trigger Event:
release
-
Statement type:
File details
Details for the file cuemsengine-0.1.0rc2-py3-none-any.whl.
File metadata
- Download URL: cuemsengine-0.1.0rc2-py3-none-any.whl
- Upload date:
- Size: 153.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
960f44e948a2922e0e3bda4853119436f552f6bcbadd4aaa78fcbbb24a196920
|
|
| MD5 |
ea65eceea11927d01ae220498d3487ac
|
|
| BLAKE2b-256 |
705236fc6ab0a8e65f58ebd8a028b0ccf9a35c805cf6bf8ee6b41af7b630fddd
|
Provenance
The following attestation bundles were made for cuemsengine-0.1.0rc2-py3-none-any.whl:
Publisher:
pypi-publish.yml on stagesoft/cuems-engine
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cuemsengine-0.1.0rc2-py3-none-any.whl -
Subject digest:
960f44e948a2922e0e3bda4853119436f552f6bcbadd4aaa78fcbbb24a196920 - Sigstore transparency entry: 1574118005
- Sigstore integration time:
-
Permalink:
stagesoft/cuems-engine@853c67b5a39fce619d724daf5a00913aabc4ef11 -
Branch / Tag:
refs/tags/v0.1.0rc2 - Owner: https://github.com/stagesoft
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@853c67b5a39fce619d724daf5a00913aabc4ef11 -
Trigger Event:
release
-
Statement type: