Module: midiwire

midiwire - Browser-based MIDI controller framework A lightweight, zero-dependency library for creating web-based MIDI controllers. Features declarative HTML binding via data attributes, programmatic APIs, bidirectional MIDI communication, SysEx support, voice management, and more. Works with the Web MIDI API in Chrome, Firefox, and Opera. Provides multiple integration approaches from fully declarative (HTML-only) to fully programmatic (JavaScript-only). ## Features - Declarative binding via data attributes (zero JavaScript) - Programmatic binding with full control - Bidirectional MIDI communication (send/receive) - SysEx support - Patch management (save/load presets) - Hotplug device detection - Comprehensive event system - DX7 voice/parameter management
Source:
See:
Examples
// Device manager with UI integration
import { createMIDIDeviceManager } from "midiwire";

const deviceManager = await createMIDIDeviceManager({
  onStatusUpdate: (message, state) => {
    document.getElementById("status").textContent = message;
  }
});

// Setup device dropdown
const select = document.getElementById("device-select");
const channelSelect = document.getElementById("channel-select");
await deviceManager.setupSelectors({
  output: select,
  channel: channelSelect
});
// Quick start - Auto-binding with data attributes
import { createMIDIController } from "midiwire";

const midi = await createMIDIController({
  channel: 1,
  selector: "[data-midi-cc]",
  watchDOM: true
});

// In your HTML:
// <input type="range" min="0" max="127" data-midi-cc="74" data-midi-label="Filter">
// <input type="range" min="0" max="127" data-midi-cc="7" data-midi-label="Volume">
// Programmatic binding
import { MIDIController } from "midiwire";

const midi = new MIDIController({ channel: 1 });
await midi.init();
await midi.connect("My Synth");

const cutoff = document.getElementById("cutoff");
midi.bind(cutoff, { cc: 74 });

Methods

(static) createMIDIController(optionsopt) → {Promise.<MIDIController>}

Create and initialize a MIDI controller with optional auto-binding. This factory function creates a MIDIController instance, initializes it, and optionally sets up declarative binding using DataAttributeBinder. Perfect for getting started quickly or when using data attributes.
Parameters:
Name Type Attributes Default Description
options MIDIControlsOptions <optional>
{} Configuration options
Source:
Throws:
If MIDI access is denied or browser doesn't support Web MIDI API
Type
MIDIAccessError
Returns:
A promise resolving to the initialized MIDIController instance
Type
Promise.<MIDIController>
Examples
// Quick start with auto-binding
const midi = await createMIDIController({
  selector: "[data-midi-cc]",
  watchDOM: true
});
// Auto-bind with specific device and output channel
const midi = await createMIDIController({
  output: "My Synth",
  outputChannel: 2,
  selector: "[data-midi-cc]",
  onReady: (controller) => {
    console.log("MIDI ready!");
  }
});
// Auto-bind with separate input/output channels
const midi = await createMIDIController({
  inputChannel: 1,
  outputChannel: 2,
  selector: "[data-midi-cc]",
  watchDOM: true
});
// Programmatic binding (no auto-bind)
const midi = await createMIDIController({
  autoConnect: false,
  outputChannel: 1
});
await midi.device.connectOutput("My Synth");
const slider = document.getElementById("cutoff");
midi.bind(slider, { cc: 74 });
// With SysEx support
const midi = await createMIDIController({
  sysex: true,
  onReady: (controller) => {
    // Send SysEx after connection
    controller.sendSysEx([0x41, 0x10, 0x42]);
  }
});

(static) createMIDIDeviceManager(optionsopt) → {Promise.<MIDIDeviceManager>}

Create a MIDIDeviceManager with an integrated MIDIController. This factory function creates a complete device management solution including MIDIController, auto-binding (optional), and device manager UI helpers. Perfect for applications that need device selection UI and status management.
Parameters:
Name Type Attributes Default Description
options MIDIDeviceManagerOptions <optional>
{} Configuration options
Source:
Throws:
If MIDI access is denied or browser doesn't support Web MIDI API
Type
MIDIAccessError
Returns:
A promise resolving to the initialized MIDIDeviceManager instance
Type
Promise.<MIDIDeviceManager>
Examples
// Basic device manager
const deviceManager = await createMIDIDeviceManager({
  outputChannel: 1,
  onStatusUpdate: (message, state) => {
    console.log(message);
  }
});

// Access the MIDIController via deviceManager.midi
const midi = deviceManager.midi;
midi.bind(document.getElementById("cutoff"), { cc: 74 });
// With auto-connect and status UI
const deviceManager = await createMIDIDeviceManager({
  output: "My Synth",
  outputChannel: 2,
  selector: "[data-midi-cc]",
  onStatusUpdate: (message, state) => {
    const statusEl = document.getElementById("status");
    statusEl.textContent = message;
    statusEl.className = state;
  }
});
// Complete UI integration with device dropdown
const deviceManager = await createMIDIDeviceManager({
  inputChannel: 1,
  outputChannel: 2,
  sysex: true,
  onStatusUpdate: (message, state) => {
    document.getElementById("status").textContent = message;
  },
  onReady: async (midi, dm) => {
    // Setup device and channel selection
    const deviceSelect = document.getElementById("device-select");
    const channelSelect = document.getElementById("channel-select");
    await dm.setupSelectors({
      output: deviceSelect,
      channel: channelSelect
    });
  }
});
// With separate input/output devices and channels
const deviceManager = await createMIDIDeviceManager({
  inputChannel: 1,
  outputChannel: 2,
  input: "My MIDI Keyboard",
  output: "My Synth Module",
  onStatusUpdate: (message, state) => {
    document.getElementById("status").textContent = message;
  },
  onReady: async (midi, dm) => {
    // Setup input and output device selectors
    const inputSelect = document.getElementById("input-select");
    const outputSelect = document.getElementById("output-select");
    const channelSelect = document.getElementById("channel-select");
    await dm.setupSelectors({
      input: inputSelect,
      output: outputSelect,
      channel: channelSelect
    });
  }
});

Type Definitions

MIDIControlsOptions

Options for createMIDIController()
Type:
  • Object
Properties:
Name Type Attributes Default Description
selector string <optional>
"[data-midi-cc]" CSS selector for auto-binding elements that have data-midi-* attributes
inputChannel number <optional>
1 Input MIDI channel (1-16)
outputChannel number <optional>
1 Output MIDI channel (1-16)
output string | number <optional>
MIDI output device name, ID, or index to auto-connect to
sysex boolean <optional>
false Request SysEx access for sending/receiving system exclusive messages
autoConnect boolean <optional>
true Auto-connect to first available output device
watchDOM boolean <optional>
false Automatically bind dynamically added elements using MutationObserver
onReady function <optional>
Callback when MIDI is ready, receives (controller) as parameter
onError function <optional>
Error handler for MIDI access errors
input string | number <optional>
MIDI input device name, ID, or index to connect to for receiving MIDI
Source:
Examples
// Basic auto-binding
const options = {
  selector: "[data-midi-cc]",
  outputChannel: 1,
  watchDOM: true
};
// Connect to specific device
const options = {
  output: "My MIDI Keyboard",
  outputChannel: 2,
  sysex: true
};
// With separate input/output channels
const options = {
  inputChannel: 1,
  outputChannel: 2,
  input: "My MIDI Controller",
  output: "My Synth"
};

MIDIDeviceManagerOptions

Options for createMIDIDeviceManager()
Type:
  • Object
Properties:
Name Type Attributes Default Description
onStatusUpdate function <optional>
Callback for status updates (message: string, state: string)
onConnectionUpdate function <optional>
Callback when connection status changes (device: Object, midi: MIDIController)
inputChannel number <optional>
1 Input MIDI channel (1-16)
outputChannel number <optional>
1 Output MIDI channel (1-16)
output string | number <optional>
MIDI output device name, ID, or index to auto-connect to
sysex boolean <optional>
false Request SysEx access
onReady function <optional>
Callback when MIDI is ready, receives (midi: MIDIController, deviceManager: MIDIDeviceManager)
onError function <optional>
Error handler for MIDI access errors
selector string <optional>
"[data-midi-cc]" CSS selector for auto-binding controls
watchDOM boolean <optional>
false Automatically bind dynamically added elements
input string | number <optional>
MIDI input device name, ID, or index to connect to
Source:
Examples
// Basic device manager setup
const options = {
  outputChannel: 1,
  onStatusUpdate: (message, state) => updateStatusUI(message, state)
};
// Full device manager with UI integration
const options = {
  output: "My Synth",
  outputChannel: 2,
  sysex: true,
  selector: "[data-midi-cc]",
  watchDOM: true,
  onStatusUpdate: (message, state) => {
    console.log(message);
    document.getElementById("status").textContent = message;
  },
  onReady: async (midi, deviceManager) => {
    // Setup device dropdown and channel selector
    const deviceSelect = document.getElementById("device-select");
    const channelSelect = document.getElementById("channel-select");
    await deviceManager.setupSelectors({
      output: deviceSelect,
      channel: channelSelect
    });
  }
};
// With separate input/output channels
const options = {
  inputChannel: 1,
  outputChannel: 2,
  input: "My MIDI Controller",
  output: "My Synth",
  onStatusUpdate: (message, state) => updateStatusUI(message, state)
};