import { EventEmitter } from './EventEmitter.js'; import { MIDIConnection } from './MIDIConnection.js'; export namespace CONTROLLER_EVENTS { let READY: string; let ERROR: string; let DESTROYED: string; let DEV_OUT_CONNECTED: string; let DEV_OUT_DISCONNECTED: string; let DEV_IN_CONNECTED: string; let DEV_IN_DISCONNECTED: string; let CH_CC_SEND: string; let CH_CC_RECV: string; let CH_NOTE_ON_SEND: string; let CH_NOTE_ON_RECV: string; let CH_NOTE_OFF_SEND: string; let CH_NOTE_OFF_RECV: string; let CH_PC_SEND: string; let CH_PC_RECV: string; let CH_PITCH_BEND_SEND: string; let CH_PITCH_BEND_RECV: string; let CH_MONO_PRESS_SEND: string; let CH_MONO_PRESS_RECV: string; let CH_POLY_PRESS_SEND: string; let CH_POLY_PRESS_RECV: string; let CH_ALL_SOUNDS_OFF_SEND: string; let CH_RESET_CONTROLLERS_SEND: string; let CH_LOCAL_CONTROL_SEND: string; let CH_ALL_NOTES_OFF_SEND: string; let CH_OMNI_OFF_SEND: string; let CH_OMNI_ON_SEND: string; let CH_MONO_ON_SEND: string; let CH_POLY_ON_SEND: string; let SYS_EX_SEND: string; let SYS_EX_RECV: string; let SYS_CLOCK_RECV: string; let SYS_START_RECV: string; let SYS_CONTINUE_RECV: string; let SYS_STOP_RECV: string; let SYS_MTC_RECV: string; let SYS_SONG_POS_RECV: string; let SYS_SONG_SEL_RECV: string; let SYS_TUNE_REQ_RECV: string; let SYS_ACT_SENSE_RECV: string; let SYS_RESET_RECV: string; let MIDI_RAW: string; let PATCH_SAVED: string; let PATCH_LOADED: string; let PATCH_DELETED: string; } /** * Main controller for browser-based MIDI operations. Provides APIs for: * - Device management (connect/disconnect, enumerate devices) * - Control binding (DOM elements <-> MIDI CC) * - MIDI messaging (send/receive CC, Note, SysEx) * - Patch management (save/load presets) * - Event handling (MIDI messages, connection changes, errors) * @extends EventEmitter * * @example * // Basic initialization * const midi = new MIDIController({ inputChannel: 1, outputChannel: 1 }); * await midi.init(); * * @example * // Bind UI controls to MIDI CCs * const volumeSlider = document.getElementById("volume"); * midi.bind(volumeSlider, { cc: 7 }); // Bind CC 7 (volume) * * @example * // Send MIDI messages * midi.channel.sendCC(74, 64); // Send CC 74 (filter cutoff) value 64 * midi.channel.sendNoteOn(60, 100); // Play middle C with velocity 100 * midi.channel.sendNoteOff(60); // Stop middle C * * @example * // Listen for MIDI events * midi.on(CONTROLLER_EVENTS.CH_CC_RECV, ({ cc, value, channel }) => { * console.log(`CC ${cc} received: ${value}`); * }); * * @example * // Save and load patches * const patch = midi.patch.get("My Patch"); * midi.patch.save("My Patch"); * midi.patch.load("My Patch"); */ export class MIDIController extends EventEmitter { /** * @param {Object} options * @param {number} [options.inputChannel=1] - Input MIDI channel (1-16) * @param {number} [options.outputChannel=1] - Output MIDI channel (1-16) * @param {string|number} [options.output] - MIDI output device * @param {string|number} [options.input] - MIDI input device * @param {boolean} [options.sysex=false] - Request SysEx access * @param {boolean} [options.autoConnect=true] - Auto-connect to first available output * @param {Function} [options.onReady] - Callback when MIDI is ready * @param {Function} [options.onError] - Error handler */ constructor(options?: { inputChannel?: number; outputChannel?: number; output?: string | number; input?: string | number; sysex?: boolean; autoConnect?: boolean; onReady?: Function; onError?: Function; }); options: { inputChannel: number; outputChannel: number; output?: string | number; input?: string | number; sysex: boolean; autoConnect: boolean; onReady?: Function; onError?: Function; }; connection: MIDIConnection; bindings: Map; state: { controlChange: Map; programChange: Map; pitchBend: Map; monoPressure: Map; polyPressure: Map; }; initialized: boolean; /** * Initialize MIDI access. Requests browser permission and connects to devices. * Emits "ready" event on success, "error" event on failure. * * @returns {Promise} * @throws {MIDIAccessError} If MIDI access is denied or browser doesn't support Web MIDI * * @emits CONTROLLER_EVENTS.READY - When initialization succeeds * @emits CONTROLLER_EVENTS.ERROR - When initialization fails * * @example * // Basic initialization * const midi = new MIDIController(); * await midi.init(); * * @example * // Initialization with custom options * const midi = new MIDIController({ * channel: 2, * sysex: true, * autoConnect: false * }); * await midi.init(); * * @example * // With event listeners * const midi = new MIDIController(); * midi.on(CONTROLLER_EVENTS.READY, (controller) => { * console.log("MIDI ready!"); * }); * midi.on(CONTROLLER_EVENTS.ERROR, (error) => { * console.error("MIDI error:", error); * }); * await midi.init(); */ init(): Promise; /** * Initialize namespace bindings * This must be called after all private methods are defined * @private */ private _initNamespaces; /** * Device-related MIDI operations * @namespace */ device: { /** * Connect to a MIDI output device * @param {string|number} device - Device name, ID, or index * @returns {Promise} * @example * // Connect by device name * await midi.device.connect("Korg minilogue xd"); * * @example * // Connect by device index * await midi.device.connect(0); */ connect: any; /** * Disconnect from current MIDI device * @returns {Promise} */ disconnect: any; /** * Connect to a MIDI input device * @param {string|number} device - Device name, ID, or index * @returns {Promise} * @example * // Connect to device by name * await midi.device.connectInput("Korg microKEY"); */ connectInput: any; /** * Disconnect from the MIDI input device * @returns {Promise} * @example * await midi.device.disconnectInput(); */ disconnectInput: any; /** * Switch to a different output device * @param {string|number} output - New device name, ID, or index * @returns {Promise} */ connectOutput: any; /** * Disconnect from the MIDI output device * @returns {Promise} * @example * await midi.device.disconnectOutput(); */ disconnectOutput: any; /** * Get current output device info * @returns {Object|null} Device info with id, name, manufacturer * @example * const device = midi.device.getCurrentOutput(); * if (device) { * console.log(`Connected to ${device.name}`); * } */ getCurrentOutput: any; /** * Get current input device info * @returns {Object|null} Device info with id, name, manufacturer */ getCurrentInput: any; /** * List all available MIDI output devices * @returns {Array<{id: string, name: string, manufacturer: string}>} * @example * const outputs = midi.device.getOutputs(); * outputs.forEach(device => { * console.log(`${device.name} by ${device.manufacturer}`); * }); */ getOutputs: any; /** * List all available MIDI input devices * @returns {Array<{id: string, name: string, manufacturer: string}>} */ getInputs: any; }; /** * Channel-specific MIDI operations * @namespace */ channel: { /** * Send a note on message * @param {number} note - Note number (0-127) * @param {number} [velocity=64] - Note velocity (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {void} * @example * // Play middle C (60) with velocity 100 * midi.channel.sendNoteOn(60, 100); * * @example * // Play note 64 (E4) on channel 5 * midi.channel.sendNoteOn(64, 80, 5); */ sendNoteOn: any; /** * Send a note off message * @param {number} note - Note number (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @param {number} [velocity=0] - Release velocity (0-127) * @returns {void} * @example * // Stop middle C * midi.channel.sendNoteOff(60); */ sendNoteOff: any; /** * Send a control change message * @param {number} cc - CC number (0-127, e.g., 7 for volume, 74 for filter cutoff) * @param {number} value - CC value (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {void} * @example * // Set volume (CC 7) to 100 on default channel * midi.channel.sendCC(7, 100); * * @example * // Set filter cutoff (CC 74) to 64 on channel 2 * midi.channel.sendCC(74, 64, 2); */ sendCC: any; /** * Get current value of a CC * @param {number} cc - CC number (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {number|undefined} Current CC value or undefined if not set * @example * const volume = midi.channel.getCC(7); * if (volume !== undefined) { * console.log(`Current volume: ${volume}`); * } */ getCC: any; /** * Send a program change message * @param {number} program - Program number (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {void} * @example * // Change to program 5 on default channel * midi.channel.sendPC(5); */ sendPC: any; /** * Get current program for a channel * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {number|undefined} Current program or undefined if not set */ getPC: any; /** * Send a pitch bend message * @param {number} value - Pitch bend value (0-16383, center = 8192) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {void} * @example * // Bend pitch up (value > 8192) * midi.channel.sendPitchBend(10000); * * @example * // Return to center (no bend) * midi.channel.sendPitchBend(8192); */ sendPitchBend: any; /** * Get current pitch bend value for a channel * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {number|undefined} Current pitch bend value or undefined if not set */ getPitchBend: any; /** * Send a channel pressure (aftertouch) message * @param {number} pressure - Pressure value (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {void} * @example * // Send channel pressure at max (127) * midi.channel.sendMonoPressure(127); */ sendMonoPressure: any; /** * Get current channel pressure for a channel * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {number|undefined} Current pressure value or undefined if not set */ getMonoPressure: any; /** * Send a polyphonic key pressure (polyphonic aftertouch) message * @param {number} note - Note number (0-127) * @param {number} pressure - Pressure value (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {void} * @example * // Send poly pressure for middle C * midi.channel.sendPolyPressure(60, 100); */ sendPolyPressure: any; /** * Get current polyphonic pressure for a note on a channel * @param {number} note - Note number (0-127) * @param {number} [channel] - MIDI channel (defaults to controller's default channel) * @returns {number|undefined} Current pressure value or undefined if not set */ getPolyPressure: any; /** * Send All Sounds Off message (CC 120, value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} * @example * // Stop all sounds on channel 1 * midi.channel.allSoundsOff(1); * * @example * // Send to all channels * midi.channel.allSoundsOff(); */ allSoundsOff: any; /** * Send Reset All Controllers message (CC 121, value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} */ resetControllers: any; /** * Send Local Control On/Off message (CC 122) * @param {boolean} enabled - true for on (value 127), false for off (value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} * @example * // Turn off local control on channel 1 * midi.channel.localControl(false, 1); */ localControl: any; /** * Send All Notes Off message (CC 123, value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} */ allNotesOff: any; /** * Send Omni Mode Off message (CC 124, value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} */ omniOff: any; /** * Send Omni Mode On message (CC 125, value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} */ omniOn: any; /** * Send Mono Mode On message (CC 126) * @param {number} [channels=1] - Number of channels for mono mode (0-16, 0=omni) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} */ monoOn: any; /** * Send Poly Mode On message (CC 127, value 0) * @param {number} [channel] - MIDI channel (1-16). If not provided, sends to all channels * @returns {void} */ polyOn: any; }; /** * System-level MIDI operations * @namespace */ system: { /** * Send a SysEx message * @param {Array} data - SysEx data bytes (0-127) * @param {boolean} [includeWrapper=false] - If true, data already includes F0/F7 * @returns {void} * @throws {Error} If SysEx not enabled in controller options * @example * // Send data with wrapper * midi.system.sendEx([0xF0, 0x42, 0x30, 0x00, 0x01, 0x2F, 0x12, 0xF7], true); * * @example * // Send data without wrapper (wrapper added automatically) * midi.system.sendEx([0x42, 0x30, 0x00, 0x7F]); */ sendEx: any; /** * Send a timing clock message (0xF8) * Typically used for synchronizing tempo-dependent devices * @returns {void} * @example * // Send clock pulse (usually 24 pulses per quarter note) * midi.system.sendClock(); */ sendClock: any; /** * Send a start message (0xFA) * Indicates start of playback from beginning of song * @returns {void} */ start: any; /** * Send a continue message (0xFB) * Indicates resume playback from current position * @returns {void} */ continue: any; /** * Send a stop message (0xFC) * Indicates stop playback * @returns {void} */ stop: any; /** * Send an MTC quarter frame message * @param {number} data - MTC quarter frame data (0-127) * @returns {void} * @example * midi.system.sendMTC(0x00); // First quarter frame */ sendMTC: any; /** * Send a song position pointer message * @param {number} position - Song position in beats (0-16383) * @returns {void} * @example * midi.system.sendSongPosition(0); // Beginning of song */ sendSongPosition: any; /** * Send a song select message * @param {number} song - Song/sequence number (0-127) * @returns {void} * @example * midi.system.sendSongSelect(0); // Select first song */ sendSongSelect: any; /** * Send a tune request message (0xF6) * Requests analog synthesizers to tune themselves * @returns {void} */ sendTuneRequest: any; /** * Send an active sensing message (0xFE) * Used to indicate controller is still active * @returns {void} */ sendActiveSensing: any; /** * Send a system reset message (0xFF) * Resets all devices to power-up default state * @returns {void} */ sendSystemReset: any; }; /** * Patch management operations * @namespace */ patch: { /** * Get current state as a patch object * @param {string} [name="Unnamed Patch"] - Patch name * @returns {PatchData} Patch data object * @example * const patch = midi.patch.get("My Patch"); * console.log(patch.channels); */ get: any; /** * Apply a patch to the controller * @param {PatchData} patch - Patch object to apply * @returns {Promise} * @throws {MIDIValidationError} If patch format is invalid * @example * const patch = { name: "My Patch", channels: { 1: { ccs: { 7: 100 } } } }; * await midi.patch.set(patch); */ set: any; /** * Save a patch to localStorage * @param {string} name - Patch name * @param {Object} [patch] - Optional patch object (will use get() if not provided) * @returns {string} Storage key used * @example * midi.patch.save("My Favorite Settings"); */ save: any; /** * Load a patch from localStorage * @param {string} name - Patch name * @returns {PatchData|null} Patch object or null if not found * @example * const patch = midi.patch.load("My Patch"); * if (patch) { * await midi.patch.set(patch); * } */ load: any; /** * Delete a patch from localStorage * @param {string} name - Patch name * @returns {boolean} Success * @example * const success = midi.patch.delete("Old Patch"); */ delete: any; /** * List all saved patches * @returns {Array<{name: string, patch: PatchData}>} Array of patch objects with name and data * @example * const patches = midi.patch.list(); * patches.forEach(p => { * console.log(p.name); * }); */ list: any; }; /** * Bind a DOM element to a MIDI CC for bidirectional control. Automatically handles * value normalization based on element type (slider, knob, etc.) and MIDI range (0-127). * Sends initial MIDI value when binding if controller is initialized. * * @param {HTMLElement} element - DOM element to bind (e.g., input range, number input) * @param {Object} config - Binding configuration * @param {number} config.cc - CC number (0-127, e.g., 7 for volume, 74 for filter cutoff) * @param {number} [config.min=0] - Minimum input value (auto-detected from element if available) * @param {number} [config.max=127] - Maximum input value (auto-detected from element if available) * @param {number} [config.channel] - MIDI channel (defaults to controller's default channel) * @param {boolean} [config.invert=false] - Invert the value mapping * @param {boolean} [config.is14Bit=false] - Use 14-bit CC (MSB + LSB, requires msb/lsb config) * @param {number} [config.msb] - MSB CC number for 14-bit control * @param {number} [config.lsb] - LSB CC number for 14-bit control * @param {Function} [config.onInput] - Optional callback for value updates (receives normalized element value) * @param {Object} [options={}] - Additional options * @param {number} [options.debounce=0] - Debounce delay in ms for high-frequency updates * @returns {Function} Unbind function - Call to remove binding and cleanup event listeners * * @example * // Basic slider binding * const volumeSlider = document.getElementById("volume"); * const unbindVolume = midi.bind(volumeSlider, { cc: 7 }); // CC 7 = Channel Volume * * @example * // Binding with custom range and inversion * const filterKnob = document.getElementById("filter"); * midi.bind(filterKnob, { * cc: 74, // CC 74 = Filter Cutoff * min: 0, // Knob minimum value * max: 127, // Knob maximum value * invert: true // Invert value (useful for cutoff - higher CC = brighter) * }); * * @example * // 14-bit high-resolution control * const fineTune = document.getElementById("fine-tune"); * midi.bind(fineTune, { * is14Bit: true, * msb: 0, // CC 0 = MSB * lsb: 32 // CC 32 = LSB * }); * * @example * // With debouncing for high-frequency updates * const lfoRate = document.getElementById("lfo-rate"); * midi.bind(lfoRate, { cc: 76 }, { debounce: 50 }); // 50ms debounce * * @example * // Using callback to update display * const pitchSlider = document.getElementById("pitch"); * const pitchDisplay = document.getElementById("pitch-value"); * midi.bind(pitchSlider, { * cc: 75, * onInput: (value) => { * pitchDisplay.textContent = Math.round(value); * } * }); */ bind(element: HTMLElement, config: { cc: number; min?: number; max?: number; channel?: number; invert?: boolean; is14Bit?: boolean; msb?: number; lsb?: number; onInput?: Function; }, options?: { debounce?: number; }): Function; /** * Create a binding between an element and MIDI CC * @private * @param {HTMLElement} element - DOM element to bind * @param {Object} config - Binding configuration * @param {Object} options - Additional binding options * @returns {Object} Binding object with element, config, handler, and destroy function */ private _createBinding; /** * Unbind a control * @param {HTMLElement} element */ unbind(element: HTMLElement): void; /** * Clean up resources * @returns {Promise} */ destroy(): Promise; /** * Connect to MIDI output device * @private * @param {string|number|undefined} device - Device identifier (name, ID, index) or undefined for auto-connect * @returns {Promise} */ private _connect; /** * Disconnect from current MIDI output device * @private * @returns {Promise} */ private _disconnect; /** * Connect to MIDI input device * @private * @param {string|number} device - Input device identifier (name, ID, index) * @returns {Promise} */ private _connectInput; /** * Disconnect from MIDI input device * @private * @returns {Promise} */ private _disconnectInput; /** * Connect to MIDI output device * @private * @param {string|number} output - Output device identifier (name, ID, index) * @returns {Promise} */ private _connectOutput; /** * Disconnect from MIDI output device * @private * @returns {Promise} */ private _disconnectOutput; /** * Get current output device information * @private * @returns {Object|null} Current output device info with id, name, manufacturer or null if not connected */ private _getCurrentOutput; /** * Get current input device information * @private * @returns {Object|null} Current input device info with id, name, manufacturer or null if not connected */ private _getCurrentInput; /** * Get list of available MIDI output devices * @private * @returns {Array} Array of output device objects with id, name, manufacturer */ private _getOutputs; /** * Get list of available MIDI input devices * @private * @returns {Array} Array of input device objects with id, name, manufacturer */ private _getInputs; /** * Send raw MIDI data * @param {Array} data - MIDI message bytes */ send(data: Array): void; /** * Send Note On message * @private * @param {number} note - Note number (0-127) * @param {number} velocity - Note velocity (0-127, default 64) * @param {number} channel - MIDI channel (1-16, default outputChannel) * @returns {void} */ private _sendNoteOn; /** * Send Note Off message * @private * @param {number} note - Note number (0-127) * @param {number} channel - MIDI channel (1-16, default outputChannel) * @param {number} velocity - Release velocity (0-127, default 0) * @returns {void} */ private _sendNoteOff; /** * Send Control Change message * @private * @param {number} cc - CC number (0-127) * @param {number} value - CC value (0-127) * @param {number} channel - MIDI channel (1-16, default outputChannel) * @returns {void} */ private _sendCC; /** * Send Program Change message * @private * @param {number} program - Program number (0-127) * @param {number} channel - MIDI channel (1-16, default outputChannel) * @returns {void} */ private _sendPC; /** * Get current Program Change value for channel * @private * @param {number} channel - MIDI channel (1-16, default inputChannel) * @returns {number|undefined} Program number or undefined if not set */ private _getPC; /** * Get current Control Change value * @private * @param {number} cc - CC number (0-127) * @param {number} channel - MIDI channel (1-16, default inputChannel) * @returns {number|undefined} CC value or undefined if not set */ private _getCC; /** * Send Pitch Bend message on specified channel * @private * @param {number} value - Pitch bend value (0-16383, where 8192 is center) * @param {number} [channel=this.options.outputChannel] - MIDI channel (1-16) * @returns {void} */ private _sendPitchBend; /** * Get current Pitch Bend value for a channel * @private * @param {number} channel - MIDI channel (1-16, default inputChannel) * @returns {number|undefined} Pitch bend value (0-16383) or undefined if not set */ private _getPitchBend; /** * Send Channel Pressure (Aftertouch) message * @private * @param {number} pressure - Pressure value (0-127) * @param {number} channel - MIDI channel (1-16, default outputChannel) * @returns {void} */ private _sendMonoPressure; /** * Get current Channel Pressure (Aftertouch) value for a channel * @private * @param {number} channel - MIDI channel (1-16, default inputChannel) * @returns {number|undefined} Pressure value (0-127) or undefined if not set */ private _getMonoPressure; /** * Send Polyphonic Key Pressure (Polyphonic Aftertouch) message * @private * @param {number} note - Note number (0-127) * @param {number} pressure - Pressure value (0-127) * @param {number} channel - MIDI channel (1-16, default outputChannel) * @returns {void} */ private _sendPolyPressure; /** * Get current Polyphonic Pressure (Aftertouch) value for a specific note on a channel * @private * @param {number} note - Note number (0-127) * @param {number} [channel=this.options.inputChannel] - MIDI channel (1-16) * @returns {number|undefined} Pressure value (0-127) or undefined if not set */ private _getPolyPressure; /** * @private */ private _allSoundsOff; /** * @private */ private _resetControllers; /** * @private */ private _localControl; /** * @private */ private _allNotesOff; /** * @private */ private _omniOff; /** * @private */ private _omniOn; /** * @private */ private _monoOn; /** * @private */ private _polyOn; /** * Send SysEx (System Exclusive) message * @private * @param {Array} data - SysEx data bytes (0-127) * @param {boolean} [includeWrapper=false] - If true, data already includes F0/F7 * @returns {void} * @example * this._sendSysEx([0x42, 0x30, 0x00, 0x7F]) // Send without wrapper * this._sendSysEx([0xF0, 0x42, 0x30, 0xF7], true) // Send with wrapper */ private _sendSysEx; /** * Send MIDI Timing Clock message (System Real-Time) * @private * @returns {void} */ private _sendClock; /** * Send MIDI Start message (System Real-Time) * @private * @returns {void} */ private _sendStart; /** * Send MIDI Continue message (System Real-Time) * @private * @returns {void} */ private _sendContinue; /** * Send MIDI Stop message (System Real-Time) * @private * @returns {void} */ private _sendStop; /** * Send MTC (MIDI Time Code) quarter frame message * @private * @param {number} data - MTC quarter frame data (0-127) * @returns {void} */ private _sendMTC; /** * Send Song Position Pointer message (System Common) * @private * @param {number} position - Song position in beats (0-16383) * @returns {void} */ private _sendSongPosition; /** * Send Song Select message (System Common) * @private * @param {number} song - Song/sequence number (0-127) * @returns {void} */ private _sendSongSelect; /** * Send Tune Request message (System Common) * @private * @returns {void} */ private _sendTuneRequest; /** * Send Active Sensing message (System Real-Time) * @private * @returns {void} */ private _sendActiveSensing; /** * Send System Reset message (System Real-Time) * @private * @returns {void} */ private _sendSystemReset; /** * Handle incoming MIDI messages from input device * @private * @param {Object} event - MIDI message event * @param {Array} event.data - MIDI message bytes * @param {number} event.midiwire - Timestamp * @returns {void} */ private _handleMIDIMessage; /** * Get current state as a patch object * @private * @param {string} [name="Unnamed Patch"] - Patch name * @returns {PatchData} Patch data object with channels, settings, and metadata */ private _getPatch; /** * Apply a patch to the controller * @private * @param {PatchData} patch - Patch object to apply * @returns {Promise} * @throws {MIDIValidationError} If patch format is invalid */ private _setPatch; /** * Apply patch data for version 1.0 format * @private * @param {PatchData} patch - Patch object to apply * @returns {Promise} */ private _applyPatchV1; /** * Save a patch to localStorage * @private * @param {string} name - Patch name * @param {PatchData} [patch] - Optional patch object (will use get() if not provided) * @returns {string} Storage key used */ private _savePatch; /** * Load a patch from localStorage * @private * @param {string} name - Patch name * @returns {PatchData|null} Patch object or null if not found */ private _loadPatch; /** * Delete a patch from localStorage * @private * @param {string} name - Patch name * @returns {boolean} Success status */ private _deletePatch; /** * List all saved patches from localStorage * @private * @returns {Array<{name: string, patch: PatchData}>} Sorted array of patch objects */ private _listPatches; } /** * Complete patch data structure for saving/loading controller state */ export type PatchData = any; /** * Channel-specific MIDI data */ export type ChannelData = any; /** * Control binding settings */ export type SettingData = any; //# sourceMappingURL=MIDIController.d.ts.map