Mixer Daemon

Protocol Reference

The mixer daemon serves two TCP protocol endpoints and an optional WebSocket endpoint. All three provide access to the same underlying state tree, but use different wire formats.


Protocol overview

EndpointPortWire formatUsed by
Mixer EngineTCP:4710Null-terminated JSON textConsoleLink (iOS/iPad)
Mixer HelperTCP:4720Text commands in, UBJSON binary outUA Console (desktop)
WebSocketWS:4721JSON text framesUA Connect (Electron)

All protocols share the same command verbs: get, set, subscribe, unsubscribe, and post.


TCP:4710 — Mixer Engine protocol

Message framing

Messages are UTF-8 text terminated by a null byte (\x00). Multiple messages can arrive in a single TCP segment.

get /devices/0/DeviceOnline/value\0
set /devices/0/outputs/18/Mute/value true\0

Command format

<verb> <path>[?<query_params>] [<value>]\0

Verbs:

VerbDescriptionHas value?
getRead a value or subtreeNo
setWrite a valueYes
subscribeRegister for change notificationsNo
unsubscribeRemove change notificationNo
postAction request (e.g., challenge-response)Optional

Query parameters

Parameters are appended to the path after ?:

  • recursive=1 — Include all children in the response
  • propfilter=value,type — Only include named properties

Response format

Responses are JSON objects, also null-terminated:

{"path":"/devices/0/DeviceOnline/value","data":true}\0

Error responses:

{"path":"/devices/0/nonexistent","error":"Unable to resolve path for get."}\0

Example session

→ get /devices/0/DeviceOnline/value\0
← {"path":"/devices/0/DeviceOnline/value","data":true}\0

→ subscribe /devices/0/outputs/18/Mute/value\0
(no immediate response — notifications arrive on change)

→ set /devices/0/outputs/18/Mute/value true\0
← {"path":"/devices/0/outputs/18/Mute/value","data":true}\0

→ get /?recursive=1&propfilter=value,type\0
← {"path":"/","data":{...entire tree...}}\0

Client identification

On connect, clients may send a JSON identification message:

{"path":"networkID","data":"abc123def456"}\0

The daemon generates unique network and process IDs (hex UUIDs) and echoes them on request.


TCP:4720 — Mixer Helper protocol

Connection handshake

The 4720 protocol begins in text mode and transitions to UBJSON binary after a handshake:

  1. Client connects
  2. Client sends: post command_format?func_id=1 2\0
  3. Server responds with JSON confirming format 2
  4. All subsequent responses are UBJSON-framed binary

Command format (text)

Commands use the same verb/path structure as 4710, with additional query parameters:

get /devices?message_id=abc:1&recursive=1
set /devices/0/inputs/0/Gain/value?message_id=abc:2&cmd_id=set_command 10.0
subscribe /devices/0/inputs/0/Gain/value?message_id=abc:3

Additional parameters:

ParameterDescription
message_idEchoed in response for request/response matching
cmd_idCommand identifier (e.g., set_command)
flatvalue1 for flat value format
func_idFunction identifier for post commands

UBJSON response framing

After the command_format 2 handshake, responses use UBJSON binary framing:

b"UBJS" + uint32_le(payload_length) + ubjson_payload + b"\x00\x00"

The UBJSON payload contains the same {path, data, parameters} structure as JSON responses, but binary-encoded.

UBJSON type markers:

MarkerTypeEncoding
Znull(no data)
Ttrue(no data)
Ffalse(no data)
iint81 byte signed
Uuint81 byte unsigned
Iint162 bytes little-endian
lint324 bytes little-endian
Lint648 bytes little-endian
Dfloat648 bytes big-endian IEEE 754
Sstringlength-prefixed UTF-8
{objectcounted: {#<count> key1 val1 ...
[arraycounted: [#<count> val1 val2 ...

Note: UA's UBJSON implementation uses little-endian for multi-byte integers, which differs from the UBJSON specification (big-endian). Float64 values remain big-endian per IEEE 754.

Object keys are encoded as <length><utf8_bytes> without an S type prefix.

Response with message_id

When a request includes message_id, the response echoes it:

{"path":"/devices/0/Gain/value","data":10.0,"parameters":{"message_id":"abc:1"}}

WS:4721 — WebSocket protocol

The WebSocket endpoint uses JSON text frames. Command and response format matches TCP:4720 (text verb/path commands, JSON responses), but without the UBJSON binary layer.

→ get /devices?message_id=ws:1&recursive=1
← {"path":"/devices","data":{...},"parameters":{"message_id":"ws:1"}}

Subscription and notifications

Subscribing to changes

subscribe /devices/0/outputs/18/Mute/value\0

After subscribing, the daemon pushes a notification whenever the value changes:

{"path":"/devices/0/outputs/18/Mute/value","data":true}\0

Notifications are triggered by:

  • Another client setting a value
  • Hardware readback detecting a physical control change (knob, button)
  • Internal state changes (initialization, metering)

Batch subscribe (4710)

ConsoleLink sends batch subscription requests:

subscribe {"paths":["/devices/0/outputs/18/Mute/value","/devices/0/outputs/18/DimOn/value"]}\0

Metering data

Meter paths

Audio meters are exposed at predictable state tree paths:

/devices/0/inputs/<ch>/meters/0/MeterLevel/value     — current level (dBFS)
/devices/0/inputs/<ch>/meters/0/MeterPeakLevel/value  — peak hold level (dBFS)
/devices/0/inputs/<ch>/meters/0/MeterClip/value       — clip indicator (boolean)

Output meters follow the same pattern under /devices/0/outputs/<ch>/meters/.

MeterPulse heartbeat

The daemon sends /MeterPulse/value at ~10 Hz as an incrementing counter. Clients use this as a heartbeat to confirm the daemon is alive and metering is active.

Meter values

PropertyTypeRangeDescription
MeterLevelfloat-77.0 to 0.0Current RMS level in dBFS
MeterPeakLevelfloat-77.0 to 0.0Peak hold (2s hold, 20 dB/s decay)
MeterClipbooltrue/falseClip indicator (2s hold)

Silence floor is -77.0 dBFS. Meters are computed in software from ALSA PCM capture samples.


State tree paths

The state tree is hierarchical. Key paths for an Apollo x4:

PathTypeDescription
/initializedboolDaemon initialization complete
/SampleRateintCurrent sample rate (Hz)
/DeviceConnectionModestring"TB" (Thunderbolt)
/devices/0/DeviceOnlineboolDevice connected
/devices/0/inputs/<n>/preamps/0/GainfloatPreamp gain (dB)
/devices/0/inputs/<n>/preamps/0/48VboolPhantom power
/devices/0/outputs/18/MuteboolMonitor mute
/devices/0/outputs/18/CRMonitorLevelTaperedfloatMonitor volume (0.0-1.0)
/TotalDSPLoadfloatDSP load percentage

Further reading

Previous
Setup