The fundamental issue: mxlSleepUntil/mxlSleepForNs blocks the entire
thread, making LWS unresponsive and causing control commands to hang.
Meanwhile, LWS poll(1) adds latency that makes grain timing unreliable.
Solution: run node->process() in a dedicated thread that can freely use
mxlSleepUntil for precise grain timing, while the main thread runs
control_server->poll(10) for LWS event handling.
Passthrough now uses mxlSleepUntil(deadline) matching the mxl-gst-sink
Cursor pattern, with 2-grain read delay for buffering.
- control_server: add Connection: close header + always return -1 after
HTTP response to force-close connection. Without this, lws_service()
blocks forever after the first POST /cmd, freezing the node process loop.
- passthrough: initialize read_index_ to runtime.headIndex when reader
is added (prevents TOO_EARLY errors on first read)
- passthrough: handle MXL_ERR_OUT_OF_RANGE_TOO_EARLY in addition to
TOO_LATE (both jump to head index)
- passthrough: use grain_info.index as writer index instead of separate
write_index_ counter (MXL writers must use TAI-based grain indices)
- passthrough: reduce grain read timeout from 100ms to 20ms for tighter
loop with LWS poll
- node_runner: add 'status' command handler that sends node status
back via control server
- Node control server now accepts HTTP POST /cmd for command dispatch
(in addition to existing WebSocket control)
- Added NodeControlClient: engine sends commands to nodes via HTTP POST
- New REST endpoints:
POST /api/graph/nodes/:id/connect-input - connect node input to MXL flow
POST /api/graph/nodes/:id/connect-output - create new MXL flow + connect output
POST /api/graph/nodes/:id/disconnect-port - remove reader/writer
POST /api/graph/nodes/:id/command - send raw command to node
- Flow IDs now use proper UUID v4 format (MXL requires standard UUIDs)
- Flow definitions use NMOS format (urn:x-nmos:format:video)
- Engine passes --mxl-domain to node processes
- User-provided node IDs (via 'id' field in POST body)
- End-to-end verified: testsrc → passthrough → new MXL output flow
- Use lws_http_get_uri_and_method() for proper HTTP method detection
(GET, POST, PUT, DELETE all supported)
- Handle GET/DELETE in LWS_CALLBACK_HTTP without waiting for body
- Support user-provided node IDs via config.id field
- Fixes all REST API endpoints hanging on GET requests
LWS v4.x requires an HTTP mount with LWSMPRO_CALLBACK to properly
route WebSocket upgrade requests to the dmf-control protocol handler.
Without this, WS connections were rejected with 403 Forbidden.