version: 1 description: Binary protocol between Node sequencer and C ALSA MIDI backend # Frame format: [record_type: uint8][payload_length: uint16le][payload: bytes...] # Header size: 3 bytes # High bit set (0x80+) means C → Node direction frame: - name: record_type type: uint8 - name: payload_length type: uint16 # Type mapping used by codegen types: uint8: { c_type: uint8_t, c_put: put_u8, c_get: get_u8, node_write: writeUInt8, node_read: readUInt8, size: 1 } uint16: { c_type: uint16_t, c_put: put_u16, c_get: get_u16, node_write: writeUInt16LE, node_read: readUInt16LE, size: 2 } records: HELLO: id: 0x01 direction: node_to_c description: Protocol version handshake fields: - name: version type: uint8 DEFINE_PATTERN: id: 0x02 direction: node_to_c description: Define or redefine a pattern (clears existing data) fields: - name: pattern_id type: uint16 - name: steps type: uint8 note: Total step count e.g. 16 for a one-bar pattern at 16th-note resolution - name: channel type: uint8 note: MIDI channel 0-15 CLEAR_PATTERN: id: 0x03 direction: node_to_c description: Remove all notes and sub-pattern references from a pattern fields: - name: pattern_id type: uint16 ADD_NOTE: id: 0x04 direction: node_to_c description: Add a note event to a pattern at a specific step fields: - name: pattern_id type: uint16 - name: step type: uint8 note: 0-based step index within the pattern - name: note type: uint8 note: MIDI note number 0-127 (middle C = 60) - name: velocity type: uint8 note: 0-127 - name: duration_steps type: uint8 note: Duration in steps (1 = one step) ADD_SUB_PATTERN: id: 0x05 direction: node_to_c description: Schedule a sub-pattern to start at a given step within a parent pattern fields: - name: pattern_id type: uint16 note: Parent pattern ID - name: step type: uint8 note: Step within parent at which the sub-pattern begins playing - name: sub_pattern_id type: uint16 PLAY: id: 0x06 direction: node_to_c description: Start playing a pattern from step 0 fields: - name: pattern_id type: uint16 STOP: id: 0x07 direction: node_to_c description: Stop all playback and send MIDI all-notes-off fields: [] SET_TEMPO: id: 0x08 direction: node_to_c description: Set global tempo (applies immediately, even mid-sequence) fields: - name: bpm_x10 type: uint16 note: "BPM × 10 for 0.1 BPM resolution — e.g. 1200 = 120.0 BPM" PREVIEW_NOTE: id: 0x09 direction: node_to_c description: Play a single note immediately without affecting sequencer state fields: - name: channel type: uint8 - name: note type: uint8 - name: velocity type: uint8 - name: duration_ms type: uint16 note: Note-off will be sent after this many milliseconds ADD_TRACK: id: 0x0A direction: node_to_c description: Add a pattern as an independently-looping track fields: - name: pattern_id type: uint16 REMOVE_TRACK: id: 0x0B direction: node_to_c description: Remove a track and stop its playback fields: - name: pattern_id type: uint16 PLAY_TRACKS: id: 0x0C direction: node_to_c description: Start the multi-track engine with all added tracks fields: [] SET_TRACK_MUTE: id: 0x0D direction: node_to_c description: Mute or unmute a track without resetting its position fields: - name: pattern_id type: uint16 - name: muted type: uint8 ACK: id: 0x81 direction: c_to_node description: Acknowledge a received command fields: - name: acked_type type: uint8 note: Record type being acknowledged ERROR: id: 0x82 direction: c_to_node description: Report an error condition fields: - name: code type: uint8 - name: context_type type: uint8 note: Record type that triggered this error BEAT_TICK: id: 0x83 direction: c_to_node description: Timing notification sent on every sequencer step fields: - name: pattern_id type: uint16 - name: step type: uint8 note: Current step within the pattern (0-based) - name: beat type: uint8 note: Current beat number within the current cycle (wraps at 255) PATTERN_END: id: 0x84 direction: c_to_node description: Notification that a pattern has completed one full cycle fields: - name: pattern_id type: uint16