This document exists to catalog the full set of OSC messages used for control and display between the Knobbler4 Max for Live device and a physical interface, such as an app or TouchOSC running on an iPad. Because the standard OSC protocol is used, you are free to develop alternative interfaces to interact with Knobbler4.
Throughout this document, a trailing N on an address (e.g. /valN, /bparamN) means the slot/index is appended directly to the address string (/val0, /val1, …). Where an index is instead carried as the message argument, it is written as {N} (e.g. /xyJoin {N}). Knobbler parameter slots are 0-indexed (MAX_SLOTS = 32); Bluhand device slots are 1-indexed (1–16).
Implementation note: The device dispatches inbound OSC through a per-module route registry (src/k4-*.ts, each exporting a routes: Route[] table merged in src/knobbler.ts). Outbound addresses are emitted via osc(...). This document is kept in sync with those tables.
Sets the value of Slot N, as a float between 0 and 1, inclusive. If Slot N is already mapped, Knobbler will then quietly update the assigned parameter in the Live set with the value. If Slot N is not mapped and there is a selected parameter in the Live Set, then that parameter will be mapped to Slot N and resulting name, color, and value messages will be sent to update the tablet.
Removes the mapping for Slot N. Has side effects of messages sent from Knobbler to tablet to update name, color, and value to unassigned values.
Sets the value of the parameter mapped to Slot N to its default value. Does so in a way to trigger an update back to the tablet. (A legacy space-separated alias /default val with the slot as a suffix is also accepted.)
Maps the device parameter identified by mapId (the Bluhand map identifier) to Knobbler Slot N. Used to promote a Bluhand device parameter into a persistent Knobbler slot.
Swaps the full mapping (parameter, output min/max range, custom name, persisted settings) between Knobbler Slot N and Slot m. If Slot m is unmapped this is effectively a move (Slot N ends up empty). XY pad pairs involving either slot are split first. Triggers a state re-push for both slots. Only sent when the device advertises the swap capability in its /ack//pong reply.
Switch the Live display to the track corresponding to Slot N.
Join Slot N and Slot N+1 into an X-Y pad pair, where N (the left slot index) is the message argument, not an address suffix. Both slots must not already be part of a pair. Triggers an /xyPairs response. Knobbler pairs persist with the Live set.
Split a previously joined X-Y pad pair, where N (the left slot index) is the message argument. Triggers an /xyPairs response.
Updates the device name for Slot N.
Updates the parameter name for Slot N.
The automation state for the parameter in Slot N.
The number of quantization steps for the parameter in Slot N. Continuous (non-quantized) parameters will have a value of zero. On/off buttons will have a value of 2.
A JSON-encoded array of individual item names for each quantized step. The array is empty if a parameter is not quantized.
Updates the track name for Slot N.
Updates the slider for Slot N to the given value.
Updates the color of the slider for Slot N to the one given. Must be a hexidecimal string in the form RRGGBBAA.
Updates the string representation of Slot N's mapped parameter value, e.g. (-6db or 2.5KHz).
A JSON-encoded array of left slot indices for active X-Y pad pairs. e.g. [3, 7] means slots 3+4 and 7+8 are joined. Sent on refresh, page load, join, split, and Live set load.
The Bluhand page controls the selected device in Live: 16 device-parameter slots, parameter banks, rack variations/macros, transport, and device/track navigation.
Sets the value of Slot N (1–16), as a float between 0 and 1, inclusive. Knobbler will then quietly update the corresponding parameter in the selected device in the Live set with the value.
Sets the value of the parameter mapped to Slot N to its default value. Does so in a way to trigger an update back to the tablet. (A legacy space-separated alias /bdefault bval with the slot as a suffix is also accepted.)
Maps the Bluhand device parameter identified by mapId into Bluhand Slot N.
Go to bank index N.
If not looking at the first bank, has the effect of switching the Tablet to the previous bank of parameters. Causes a full update of slot names and values.
If more banks of parameters are available, then switch the Tablet to the next bank of parameters. Causes a full update of slot names and values.
Toggles the on/off (activator) state of the currently selected device.
Randomize the macro controls of the currently selected rack.
Create a new rack variation from the current macro state.
Delete the rack variation at index idx.
Recall (select) the rack variation at index idx.
Triggers an undo action in the Live set, reverting the last change.
Triggers a redo action in the Live set, reapplying the last undone change.
For shortcut button N (1–8), maps the button to the selected device if it is not yet mapped. If already mapped, focuses the Live UI on the mapped device.
For shortcut button N (1–8), removes the mapping.
Updates the current track / device name in the display (format: TrackName > DeviceName).
JSON-encoded array of available parameter banks for the selected device, each { name, sel }.
Updates the text that indicates the current bank, e.g. "Bank 2 of 6".
The on/off (activator) state of the currently selected device.
Rack variation state for the selected device: { count, selected }, or an empty string when the selected device has no variations.
Updates the parameter name for Slot N.
The automation state for the parameter in Slot N.
The number of quantization steps for the parameter in Slot N. Continuous (non-quantized) parameters will have a value of zero. On/off buttons will have a value of 2.
A JSON-encoded array of individual item names for each quantized step. The array is empty if a parameter is not quantized.
Updates the slider for Slot N to the given value.
Updates the color of the slider for Slot N to the one given. Must be a hexidecimal string in the form RRGGBBAA.
Updates the string representation of Slot N's mapped parameter value, e.g. (-6db or 2.5KHz).
Updates the shortcut button N to the given color value (RRGGBBAA).
Updates the device name displayed beneath the shortcut button N.
Live object ID number for the currently selected track (−1 if none).
Live object ID number for the currently selected device (−1 if none).
JSON-stringified array of device objects. See the source file src/consts.ts to see the field ID definitions. e.g.
[
[5,8,"Knobbler4-v26","FFF034",0]
]
Navigate to the given chain by ID in the Live UI.
Navigate to the given device by ID in the Live UI.
Navigate to the given track by ID in the Live UI.
If collapsing a rack, this message is sent to Live so that it can hide the chain devices display in that rack. Otherwise every rack will eventually be fully expanded and that gets overwhelming / messy.
Toggles the fold state (expand / collapse) of a group.
The single-track ("sidebar") mixer controls the currently selected track. Addresses have no strip index — they always target the selected track. (For the multi-strip mixer, see "Multi-Track Mixer" below, where addresses are indexed /mixer/{N}/....)
Sets the volume of the selected track (0.0–1.0).
Sets the pan of the selected track (−1.0 to 1.0).
Sets the crossfader assignment value of the selected track.
Sets the level of send N (1–12) on the selected track.
Resets the selected track's volume to its default value.
Resets the selected track's pan to center.
Resets the selected track's crossfader assignment to its default.
Resets send N on the selected track to its default value.
Toggles the mute state of the selected track.
Toggles the solo state of the selected track.
Toggles crossfader assignment A for the selected track.
Toggles crossfader assignment B for the selected track.
Arms the selected track for recording.
Disarms the selected track.
Disables input monitoring/routing for the selected track.
JSON-stringified list of color values for the 12 possible return tracks. e.g.
[
"#10A4EE","#00BFAF","#990000",
"#990000","#990000","#990000",
"#990000","#990000","#990000",
"#990000","#990000","#990000"
]
Indicates the type of track - normal, group, return, or main. See src/consts.ts for the track type definitions.
Indicates whether the track is armed for recording.
Indicates whether input is enabled for the current track.
The track volume level. 0.85 is 0.0db.
The pan position for the track.
The crossfader value for the track. 0 = A, 1 = none, 2 = B.
The amount to send to return track N, with N being a value from 1-12.
The number of return tracks.
Indicates if the A or B crossfader buttons are selected for the given track.
The volume automation state for the selected track (0 = none, 1 = playing, 2 = overridden).
Indicates the Solo state of the track.
The number of tracks currently soloed across the entire set. Useful for showing a global solo indicator.
Indicates the Mute state of the track.
The color of the current track, in integer form ((r<<16) + (g<<8) + b)
Indicates whether the track has audio output. Controls the enabled state of some mixer components, e.g. the volume slider.
String value of the current track volume level. Displayed above the volume slider in the mixer.
String representation of the selected track's pan (e.g. "20L").
Confirms the current enabled/disabled state of the single-track mixer's output meters.
Indicates whether the currently selected track is frozen.
The multi-track mixer provides a full-screen, horizontally scrollable mixer with per-strip observers. The device uses a windowed approach — observers are only active for visible strips. Strip indices are absolute (matching the position in /visibleTracks).
Sets the visible window for the multi-track mixer. The value is a JSON array [leftIndex, visibleCount]. The device will set up observers for strips from leftIndex to leftIndex + visibleCount - 1. Sending [0, 0] tears down all observers and deactivates the mixer.
Enables or disables output level meter observers for all visible strips. Meters are off by default. Only tracks with audio output will have meter observers.
Sets the volume for strip N.
Sets the pan for strip N.
Resets volume for strip N to its default value.
Resets pan for strip N to its default value.
Sets the send level for strip N to the given return track.
Resets the send level for strip N to the given return track's default value.
Toggles the mute state for strip N.
Toggles the solo state for strip N.
Arms strip N for recording.
Disarms strip N.
Disables input routing for strip N.
Toggles crossfader assignment A for strip N.
Toggles crossfader assignment B for strip N.
Sent as chunked data (/visibleTracks/chunk). Each entry is [type, id, name, color, null, null, parentId]. Type values are defined in src/consts.ts. parentId is the group track ID (0 if not in a group). Sent on mixer open, track list changes, and color changes.
The track name for strip N.
The track color for strip N (hex string).
The track type for strip N (see src/consts.ts).
The volume level for strip N.
String representation of strip N's volume (e.g. "-6.0 dB").
The pan position for strip N.
String representation of strip N's pan (e.g. "20L").
The mute state for strip N.
The solo state for strip N.
Whether strip N is armed for recording.
Whether input is enabled for strip N.
Whether strip N has audio output.
Whether crossfader A is assigned for strip N.
The volume automation state for strip N. Values match Ableton's automation state enum (0 = none, 1 = playing, 2 = overridden).
Whether crossfader B is assigned for strip N.
Send levels for strip N.
Batched meter values for all visible strips, sent as a single message every ~30ms when meters are enabled. The value is a flat JSON array [L0, R0, V0, L1, R1, V1, ...] where each group of 3 values represents left channel, right channel, and combined output level for one strip. Strip index N's values are at offsets N*3 (left), N*3+1 (right), N*3+2 (level). Array length = visibleCount * 3. All values are floats (0.0-1.0).
Confirms the current meters enabled/disabled state.
The number of return tracks (same for all strips).
Displays information about the currently selected parameter in Live. The device follows Live's selected parameter and pushes updates to the app. Supports locking the display to a specific parameter.
Activates the current parameter observer. The device will begin following Live's selected parameter.
Deactivates the current parameter observer and tears down all observers.
Sets the value of the currently displayed parameter, as a float between 0 and 1.
Resets the currently displayed parameter to its default value.
Locks (1) or unlocks (0) the current parameter display. When locked, the display stays on the current parameter even if the user selects a different parameter in Live. On unlock, the display updates to whichever parameter is currently selected.
The parameter name.
The name of the device containing the parameter.
The name of the track containing the device.
The color of the track, as a hex string (e.g. #FF0034).
The parameter value, scaled to 0-1.
The string representation of the parameter value (e.g. "-6.0 dB", "2.5 kHz").
The string representation of the parameter's minimum value.
The string representation of the parameter's maximum value.
The toolbar mixes transport state (pushed from the device) with button presses (sent by the tablet). /metronome and /tempo flow in both directions — the device pushes the current state, and the tablet sends them to change it.
Indicates if the arrangement overdub button is engaged.
JSON-encoded array of cue point objects.
[
{
"idx": {number},
"name": {string},
"time": {number},
"disp": {string},
},
...
}
time is in beats; disp is a formatted bar.beat.16th string.
Indicates if the session automation record button is engaged.
Indicates that automation has been overridden, and is available to be re-enabled.
Indicates whether the metronome is enabled.
Indicates if Live is playing.
Indicates if Live is recording.
Indicates whether the arrangement loop is enabled. (Distinct from the network feedback-loop /loop message in the Misc section, which is sent by the tablet and carries no argument.)
The current tempo value.
The arrangement playhead position, in beats. Streamed while playing (trailing-edge throttle, ~20Hz) and re-pushed on reconnect.
The length of the arrangement (Live's last_event_time), in beats. Polled (not observable) and re-pushed on reconnect.
The arrangement time signature, as two integers. Used by the app to render /songPos as bar.beat.16th.
The arrangement loop brace start, in beats. Echoed back after an inbound /loopStart so the app's loop handles converge after a drag.
The arrangement loop brace length, in beats.
Toggles the metronome.
Sets the tempo in BPM.
Tap-tempo input; successive taps set the tempo.
Jumps to the cue point at live_set cue_points {idx}.
Jumps to the cue point at index idx and starts playback from there.
Sets the arrangement playhead (current_song_time) to the given position in beats (clamped to ≥ 0). Immediately echoes the new position back via /songPos.
Sets the arrangement loop brace start, in beats (clamped to ≥ 0).
Sets the arrangement loop brace length, in beats (clamped to ≥ 0).
Toggles a cue point at the current playhead position (Live's set_or_delete_cue).
Renames the cue point at live_set cue_points {idx}; the new name is the message argument.
Deletes the cue point at index idx by jumping to it and toggling it off (the Live API has no direct cue-point delete).
Jumps to the previous cue point.
Jumps to the next cue point.
Toggles the arrangement loop.
Triggers Live's "Capture MIDI".
Toggles arrangement overdub.
Toggles session automation record.
Re-enables automation that has been overridden.
Starts playback.
Stops playback.
Toggles record mode.
Response to a /syn message to facilitate connection setup. The value is a string containing the device version number followed by capability flags (e.g. 61 mxr mkMap swap). mxr indicates support for the multi-track mixer; mkMap indicates support for mapping Bluhand parameters into Knobbler slots.
Response to a /ping message to keep the network connection "warmed up". Like /ack, the value contains the device version and capability flags (e.g. 61 mxr mkMap swap).
The device version string, sent on connect.
Asks the app to push its full state to the device (current page, current-parameter visibility, mixer view, etc.). Sent after a /syn handshake.
Tells the app to clear all cached OSC data (full reset).
Sent when one of the tabs in the Max for Live device is clicked, to keep the app's page in sync. The tablet may also send /page/X to drive the device. X can be:
A batched set of OSC messages combined into a single JSON object. Each key is an OSC address and each value is the message payload. Example:
{"/param1":"Filter Freq","/val1":0.5,"/valStr1":"2.5 kHz"}
Batching is only used when the client advertises the batch capability in its /syn handshake. Messages are flushed every 10ms or when the buffer exceeds 1KB. Chunked data (/start, /end, /chunk suffixes) and meter messages are never batched.
Update the "active" state of the Toggle Input interface button.
A request for an /ack response to facilitate a UX feedback loop when configuring the connections. The value is an optional string containing the client version followed by capability flags (e.g. 1.2.0 batch). The device stores the client version and capabilities for feature negotiation. Triggers a /sendState message internally to push full state to the app.
Sent every 5 seconds when a connection is configured. Intended to keep the network connection "warm". May carry a client version + capability string like /syn.
Configures the device's output target (the tablet's reachable host:port). Sent during connection setup so the device knows where to send outbound OSC.
Requests a full refresh of all device state to the app.
Requests (re)initialization of the device's menu state.
If the currently selected track has active input routing (i.e. has a value other than "None" selected under the "MIDI From" or "Audio From" dropdowns), then the input routing selection will be stored internally in the device and the track will be set to None.
If the track input is currently set to None, then if the prior input setting was stored it will be restored, otherwise the first input will be chosen.
This is useful when recording automation over existing MIDI clips, since the recording state of a MIDI/Instrument track cannot be disabled. Simply disable the input with this message, record your automation overdub, then re-enable the inputs when needed. The underlying MIDI clips will not be modified.
Sent out as part of the network startup sequence to detect network loops (e.g. the send and receive destination being the same). If the device receives its own /loop echo, outbound communication is halted until the host or port values are changed (a fresh /connect re-probes).
The Clip View provides session view clip grid control including clip launching, recording, scene management, and real-time state updates. The device uses a windowed approach — observers are only active for the visible portion of the grid.
Sets the visible window for the clip grid. The value is a JSON array [left, top, right, bottom] representing track and scene indices. Sending triggers observer setup for the visible range. Debounced at 250ms.
Requests the full scene list. Triggers a /clips/scenes chunked response.
Launch a clip: [trackIdx, sceneIdx]. Fires the clip slot and selects it in Live.
Record into a clip slot: [trackIdx, sceneIdx]. Fires the clip slot for recording and selects it.
Delete a clip: [trackIdx, sceneIdx].
Set the stop button for a clip slot: [trackIdx, sceneIdx, val].
Stop all clips on the given track.
Stop all clips in the Live set.
Launch a scene by index.
Rename a scene: [sceneIdx, name].
Set a scene's color: [sceneIdx, hexStr].
Set a clip's color: [trackIdx, sceneIdx, hexStr].
Bulk update clip properties. Array of {t, sc, n?} objects. Currently supports setting clip name.
Capture and insert a new scene (equivalent to Live's "Capture and Insert Scene" command).
Full grid snapshot: { left, top, clips: rows }. Each cell is {s, n?, c?, hsb, ps?, hc?} where s is the clip state, n is the clip name, c is the color, hsb is has_stop_button, ps is playing_status (group tracks only), and hc is has_child_clips (group tracks only).
Batched cell state updates: [{t, sc, s, n?, c?, hsb, ps?, hc?}]. Sent when individual cells change state.
Sent as chunked data (/clips/scenes/chunk). Array of {n, c?} objects for all scenes, where n is the scene name and c is the optional color.
The index of the currently selected scene.
Track info updates. Either a full batch { left, tracks: [{n, c}] } or an individual update { t, n?, c? } for name or color changes.
Large payloads (e.g. /visibleTracks, /clips/scenes) are split into chunks so they survive UDP packet-size limits. A chunked transfer for prefix /foo is:
/foo/start {count} — begins the transfer, value is the total item count/foo/chunk {JSON array} — one or more chunks of items/foo/end {checksum} — ends the transferChunked data is never batched (see /batch). Whether a payload is chunked depends on client capabilities negotiated in the /syn handshake; clients lacking the capability receive the full payload as a single /foo message.
The source contains a src/k4-browser.ts module that emits /browser/view, /browser/items (chunked), and /browser/error, intended for browsing/loading Live's device browser. It is not currently wired into the entry route registry (src/knobbler.ts) and has no inbound routes, so it is not part of the active protocol. Document it here once it is integrated.