midiwire 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -38
- package/dist/bindings/DataAttributeBinder.d.ts +188 -0
- package/dist/bindings/DataAttributeBinder.d.ts.map +1 -0
- package/dist/core/EventEmitter.d.ts +42 -0
- package/dist/core/EventEmitter.d.ts.map +1 -0
- package/dist/core/MIDIConnection.d.ts +191 -0
- package/dist/core/MIDIConnection.d.ts.map +1 -0
- package/dist/core/MIDIController.d.ts +1031 -0
- package/dist/core/MIDIController.d.ts.map +1 -0
- package/dist/core/MIDIDeviceManager.d.ts +252 -0
- package/dist/core/MIDIDeviceManager.d.ts.map +1 -0
- package/dist/core/errors.d.ts +57 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/index.d.ts +337 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/midiwire.es.js +610 -589
- package/dist/midiwire.umd.js +1 -1
- package/dist/utils/dx7/DX7Bank.d.ts +186 -0
- package/dist/utils/dx7/DX7Bank.d.ts.map +1 -0
- package/dist/utils/dx7/DX7Voice.d.ts +417 -0
- package/dist/utils/dx7/DX7Voice.d.ts.map +1 -0
- package/dist/utils/dx7/index.d.ts +3 -0
- package/dist/utils/dx7/index.d.ts.map +1 -0
- package/dist/utils/midi.d.ts +97 -0
- package/dist/utils/midi.d.ts.map +1 -0
- package/dist/utils/sysex.d.ts +32 -0
- package/dist/utils/sysex.d.ts.map +1 -0
- package/dist/utils/validators.d.ts +56 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/package.json +5 -1
- package/src/bindings/DataAttributeBinder.js +0 -8
- package/src/core/EventEmitter.js +0 -1
- package/src/core/MIDIConnection.js +0 -18
- package/src/core/MIDIController.js +1 -58
- package/src/core/MIDIDeviceManager.js +34 -5
- package/src/core/MIDIDeviceManager.test.js +126 -0
- package/src/core/errors.js +4 -4
- package/src/utils/midi.js +0 -19
package/README.md
CHANGED
|
@@ -36,60 +36,82 @@ Or use directly in the browser from a CDN like [jsDelivr](https://www.jsdelivr.c
|
|
|
36
36
|
|
|
37
37
|
<!-- Or specify a version if needed -->
|
|
38
38
|
<script type="module">
|
|
39
|
-
import { createMIDIController } from "https://cdn.jsdelivr.net/npm/midiwire@0.
|
|
39
|
+
import { createMIDIController } from "https://cdn.jsdelivr.net/npm/midiwire@0.8.0/+esm";
|
|
40
40
|
</script>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
## Quick Start
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
midiwire provides three API levels to match your needs. Choose the one that fits your project:
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
<!DOCTYPE html>
|
|
49
|
-
<html lang="en">
|
|
50
|
-
<body>
|
|
51
|
-
<h1>Synth Editor</h1>
|
|
52
|
-
|
|
53
|
-
<label>
|
|
54
|
-
Filter Cutoff
|
|
55
|
-
<input type="range" min="0" max="127" data-midi-cc="74">
|
|
56
|
-
</label>
|
|
57
|
-
|
|
58
|
-
<label>
|
|
59
|
-
Resonance
|
|
60
|
-
<input type="range" min="0" max="127" data-midi-cc="71">
|
|
61
|
-
</label>
|
|
62
|
-
|
|
63
|
-
<script type="module">
|
|
64
|
-
import { createMIDIController } from "midiwire";
|
|
65
|
-
|
|
66
|
-
await createMIDIController({
|
|
67
|
-
outputChannel: 1,
|
|
68
|
-
selector: "[data-midi-cc]"
|
|
69
|
-
});
|
|
70
|
-
</script>
|
|
71
|
-
</body>
|
|
72
|
-
</html>
|
|
73
|
-
```
|
|
47
|
+
### High-Level API: `MIDIDeviceManager`
|
|
74
48
|
|
|
75
|
-
|
|
49
|
+
For complete web UI integration with automatic device selectors and status management.
|
|
76
50
|
|
|
77
51
|
```javascript
|
|
78
|
-
import {
|
|
52
|
+
import { MIDIDeviceManager } from "midiwire";
|
|
53
|
+
|
|
54
|
+
const manager = new MIDIDeviceManager({
|
|
55
|
+
onStatusUpdate: (msg, state) => console.log(msg),
|
|
56
|
+
onConnectionUpdate: (output, input) => console.log("Connected!"),
|
|
57
|
+
});
|
|
79
58
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
output: "
|
|
59
|
+
// Setup all selectors at once (returns MIDIController)
|
|
60
|
+
const midi = await manager.setupSelectors({
|
|
61
|
+
output: "#output-select",
|
|
62
|
+
input: "#input-select",
|
|
63
|
+
channel: "#channel-select",
|
|
64
|
+
onConnect: ({ device, type }) => console.log(`${type}: ${device.name}`)
|
|
83
65
|
});
|
|
84
66
|
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
|
|
67
|
+
// Use the MIDI controller directly
|
|
68
|
+
midi.channel.sendCC(1, 100);
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Best for**: Complete web applications with device selection UI
|
|
72
|
+
|
|
73
|
+
### Mid-Level API: `MIDIController`
|
|
74
|
+
|
|
75
|
+
The main programmatic API for device management, MIDI messaging, and patch handling.
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
import { MIDIController, CONTROLLER_EVENTS } from "midiwire";
|
|
79
|
+
|
|
80
|
+
const midi = new MIDIController({ outputChannel: 1 });
|
|
81
|
+
await midi.init();
|
|
88
82
|
|
|
89
|
-
// Send MIDI
|
|
83
|
+
// Send MIDI messages
|
|
90
84
|
midi.channel.sendCC(74, 64);
|
|
85
|
+
midi.channel.sendNoteOn(60, 100);
|
|
86
|
+
|
|
87
|
+
// Device management
|
|
88
|
+
await midi.device.connect("My Synth");
|
|
89
|
+
const devices = midi.device.getOutputs();
|
|
90
|
+
|
|
91
|
+
// Patch management
|
|
92
|
+
midi.patch.save("My Settings");
|
|
91
93
|
```
|
|
92
94
|
|
|
95
|
+
**Best for**: Programmatic MIDI control, synth editors, and controllers
|
|
96
|
+
|
|
97
|
+
### Low-Level API: `MIDIConnection`
|
|
98
|
+
|
|
99
|
+
Direct Web MIDI API wrapper for raw MIDI access and custom implementations.
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
import { MIDIConnection } from "midiwire";
|
|
103
|
+
|
|
104
|
+
const connection = new MIDIConnection({ sysex: true });
|
|
105
|
+
await connection.requestAccess();
|
|
106
|
+
await connection.connect("My Device");
|
|
107
|
+
|
|
108
|
+
// Send raw MIDI
|
|
109
|
+
connection.send([0x90, 60, 100]); // Note on
|
|
110
|
+
connection.sendSysEx([0x41, 0x10, 0x42]); // SysEx
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Best for**: Custom MIDI implementations and direct protocol control
|
|
114
|
+
|
|
93
115
|
### Full API Documentation
|
|
94
116
|
|
|
95
117
|
For complete API documentation with examples, see **[API Documentation](https://alexferl.github.io/midiwire/module-midiwire.html)**.
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative MIDI binding system using HTML data attributes. Enables zero-JavaScript
|
|
3
|
+
* MIDI controller creation by scanning the DOM for data-midi-* attributes and automatically
|
|
4
|
+
* binding elements to MIDIController.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - **Auto-discovery**: Scans DOM for data-midi-* attributes
|
|
8
|
+
* - **7-bit CC**: Bind with `data-midi-cc="74"` (e.g., Filter Cutoff)
|
|
9
|
+
* - **14-bit CC**: Bind with `data-midi-msb="74" data-midi-lsb="75"` for high resolution
|
|
10
|
+
* - **Custom ranges**: Use HTML min/max attributes or `data-midi-min`/`data-midi-max`
|
|
11
|
+
* - **Channel override**: `data-midi-channel="2"` to use channel 2 instead of default
|
|
12
|
+
* - **Value inversion**: `data-midi-invert="true"` to invert the value mapping
|
|
13
|
+
* - **De bouncing**: `data-midi-debounce="100"` for high-frequency updates (ms)
|
|
14
|
+
* - **Auto-binding**: Watch DOM for dynamically added/removed elements with MutationObserver
|
|
15
|
+
* - **Labeling**: `data-midi-label="Filter Cutoff"` for patch saving
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // 7-bit CC binding
|
|
19
|
+
* <input type="range" min="0" max="127" data-midi-cc="74" data-midi-label="Filter Cutoff">
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // 14-bit high-resolution binding
|
|
23
|
+
* <input type="range" min="0" max="16383" data-midi-msb="74" data-midi-lsb="75" data-midi-label="Pitch Bend">
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // With channel override and inversion
|
|
27
|
+
* <input type="range" min="0" max="127" data-midi-cc="7" data-midi-channel="2" data-midi-invert="true" data-midi-label="Volume">
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* // With custom range
|
|
31
|
+
* <input type="range" min="-100" max="100" data-midi-cc="10" data-midi-label="Pan">
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Complete setup with auto-binding
|
|
35
|
+
* const midi = new MIDIController();
|
|
36
|
+
* const binder = new DataAttributeBinder(midi);
|
|
37
|
+
*
|
|
38
|
+
* // Bind existing elements
|
|
39
|
+
* binder.bindAll();
|
|
40
|
+
*
|
|
41
|
+
* // Enable auto-binding for dynamically added elements
|
|
42
|
+
* binder.enableAutoBinding();
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // Manual binding with custom selector
|
|
46
|
+
* const binder = new DataAttributeBinder(midi, "[data-midi-cc]");
|
|
47
|
+
* binder.bindAll();
|
|
48
|
+
*/
|
|
49
|
+
export class DataAttributeBinder {
|
|
50
|
+
/**
|
|
51
|
+
* Create a new DataAttributeBinder instance for declarative MIDI binding
|
|
52
|
+
*
|
|
53
|
+
* @param {MIDIController} controller - MIDIController instance to bind elements to
|
|
54
|
+
* @param {string} [selector="[data-midi-cc]"] - CSS selector for elements to bind. Defaults to looking for data-midi-cc or data-midi-msb/lmb attributes
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // Basic usage
|
|
58
|
+
* const midi = new MIDIController();
|
|
59
|
+
* const binder = new DataAttributeBinder(midi);
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // With custom selector
|
|
63
|
+
* const binder = new DataAttributeBinder(midi, ".midi-control");
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Bind after MIDI is ready
|
|
67
|
+
* const midi = new MIDIController();
|
|
68
|
+
* midi.on(midi.READY, () => {
|
|
69
|
+
* const binder = new DataAttributeBinder(midi);
|
|
70
|
+
* binder.bindAll();
|
|
71
|
+
* });
|
|
72
|
+
*/
|
|
73
|
+
constructor(controller: MIDIController, selector?: string);
|
|
74
|
+
controller: MIDIController;
|
|
75
|
+
selector: string;
|
|
76
|
+
observer: MutationObserver;
|
|
77
|
+
/**
|
|
78
|
+
* Bind all matching elements in the document to MIDI Controller. Searches the DOM for elements
|
|
79
|
+
* that match the selector and have data-midi-* attributes. Skips already bound elements (marked
|
|
80
|
+
* with data-midi-bound attribute). Automatically handles both 7-bit CC and 14-bit CC configurations.
|
|
81
|
+
*
|
|
82
|
+
* @returns {void}
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* // Bind all elements with data-midi-cc or data-midi-msb/lmb attributes
|
|
86
|
+
* binder.bindAll();
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* // Bind after DOM is loaded
|
|
90
|
+
* document.addEventListener("DOMContentLoaded", () => {
|
|
91
|
+
* binder.bindAll();
|
|
92
|
+
* });
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // Bind after MIDI is ready
|
|
96
|
+
* midi.on(midi.READY, () => {
|
|
97
|
+
* binder.bindAll();
|
|
98
|
+
* });
|
|
99
|
+
*/
|
|
100
|
+
bindAll(): void;
|
|
101
|
+
/**
|
|
102
|
+
* Enable automatic binding of dynamically added elements using MutationObserver.
|
|
103
|
+
* Watches the DOM for new elements that match the selector and have data-midi-* attributes,
|
|
104
|
+
* automatically binding them when they're added. Also handles cleanup of removed elements.
|
|
105
|
+
*
|
|
106
|
+
* @returns {void}
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* // Enable and forget - perfect for single page apps
|
|
110
|
+
* binder.enableAutoBinding();
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // Add controls dynamically
|
|
114
|
+
* binder.enableAutoBinding();
|
|
115
|
+
* // Later, when you add new UI controls:
|
|
116
|
+
* const newSlider = document.createElement("input");
|
|
117
|
+
* newSlider.type = "range";
|
|
118
|
+
* newSlider.setAttribute("data-midi-cc", "71");
|
|
119
|
+
* document.getElementById("controls").appendChild(newSlider);
|
|
120
|
+
* // Automatically bound!
|
|
121
|
+
*/
|
|
122
|
+
enableAutoBinding(): void;
|
|
123
|
+
/**
|
|
124
|
+
* Disable automatic binding and clean up the MutationObserver. Stops watching for
|
|
125
|
+
* dynamically added/removed elements and disconnects the observer to prevent memory leaks.
|
|
126
|
+
*
|
|
127
|
+
* @returns {void}
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* // Temporarily disable auto-binding
|
|
131
|
+
* binder.disableAutoBinding();
|
|
132
|
+
* // Make bulk DOM changes
|
|
133
|
+
* updateAllControls();
|
|
134
|
+
* // Re-enable when done
|
|
135
|
+
* binder.enableAutoBinding();
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* // Clean up when done with the binder
|
|
139
|
+
* binder.disableAutoBinding();
|
|
140
|
+
* binder.destroy();
|
|
141
|
+
*/
|
|
142
|
+
disableAutoBinding(): void;
|
|
143
|
+
/**
|
|
144
|
+
* Parse MIDI configuration from an element's data attributes. Extracts MIDI binding
|
|
145
|
+
* configuration including CC numbers, channel, range, inversion, and debouncing settings.
|
|
146
|
+
* Validates the configuration and returns null if invalid. Handles both 7-bit CC
|
|
147
|
+
* (data-midi-cc) and 14-bit CC (data-midi-msb + data-midi-lsb) configurations.
|
|
148
|
+
*
|
|
149
|
+
* @param {HTMLElement} element - The element to parse attributes from
|
|
150
|
+
* @returns {Object|null} Configuration object or null if invalid
|
|
151
|
+
* @private
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // 7-bit CC configuration
|
|
155
|
+
* // <input type="range" min="0" max="127" data-midi-cc="74" data-midi-invert="true">
|
|
156
|
+
* // Returns: { cc: 74, min: 0, max: 127, invert: true }
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* // 14-bit CC configuration
|
|
160
|
+
* // <input type="range" min="0" max="16383" data-midi-msb="74" data-midi-lsb="75">
|
|
161
|
+
* // Returns: { msb: 74, lsb: 75, is14Bit: true, min: 0, max: 16383 }
|
|
162
|
+
*/
|
|
163
|
+
private _parseAttributes;
|
|
164
|
+
/**
|
|
165
|
+
* Clean up resources and disconnect any active observers. Disables auto-binding if active
|
|
166
|
+
* and disconnects the MutationObserver to prevent memory leaks. Call this when done with
|
|
167
|
+
* the binder instance.
|
|
168
|
+
*
|
|
169
|
+
* @returns {void}
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* // Clean up when done
|
|
173
|
+
* const binder = new DataAttributeBinder(midi);
|
|
174
|
+
* binder.bindAll();
|
|
175
|
+
* binder.enableAutoBinding();
|
|
176
|
+
*
|
|
177
|
+
* // Later, when cleaning up
|
|
178
|
+
* binder.destroy();
|
|
179
|
+
*
|
|
180
|
+
* @example
|
|
181
|
+
* // Clean up in response to user action
|
|
182
|
+
* document.getElementById("cleanup-btn").addEventListener("click", () => {
|
|
183
|
+
* binder.destroy();
|
|
184
|
+
* });
|
|
185
|
+
*/
|
|
186
|
+
destroy(): void;
|
|
187
|
+
}
|
|
188
|
+
//# sourceMappingURL=DataAttributeBinder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataAttributeBinder.d.ts","sourceRoot":"","sources":["../../src/bindings/DataAttributeBinder.js"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH;IACE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,wBApBW,cAAc,aACd,MAAM,EAuBhB;IAHC,2BAA4B;IAC5B,iBAAwB;IACxB,2BAAoB;IAGtB;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,WAlBa,IAAI,CAiChB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,qBAhBa,IAAI,CAuEhB;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,sBAfa,IAAI,CAoBhB;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,yBAgDC;IAED;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAjBa,IAAI,CAmBhB;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight browser-compatible event emitter.
|
|
3
|
+
* Provides publish/subscribe functionality for MIDI events
|
|
4
|
+
* without external dependencies. Implements standard event
|
|
5
|
+
* emitter pattern: register listeners with on(), emit events
|
|
6
|
+
* with emit(), remove listeners with off(). Listener cleanup
|
|
7
|
+
* is automatic via returned unsubscribe functions.
|
|
8
|
+
*/
|
|
9
|
+
export class EventEmitter {
|
|
10
|
+
events: Map<any, any>;
|
|
11
|
+
/**
|
|
12
|
+
* Register an event listener
|
|
13
|
+
* @param {string} event - Event name
|
|
14
|
+
* @param {Function} handler - Event handler function
|
|
15
|
+
* @returns {Function} Unsubscribe function
|
|
16
|
+
*/
|
|
17
|
+
on(event: string, handler: Function): Function;
|
|
18
|
+
/**
|
|
19
|
+
* Register a one-time event listener
|
|
20
|
+
* @param {string} event - Event name
|
|
21
|
+
* @param {Function} handler - Event handler function
|
|
22
|
+
*/
|
|
23
|
+
once(event: string, handler: Function): void;
|
|
24
|
+
/**
|
|
25
|
+
* Remove an event listener
|
|
26
|
+
* @param {string} event - Event name
|
|
27
|
+
* @param {Function} handler - Event handler function
|
|
28
|
+
*/
|
|
29
|
+
off(event: string, handler: Function): void;
|
|
30
|
+
/**
|
|
31
|
+
* Emit an event
|
|
32
|
+
* @param {string} event - Event name
|
|
33
|
+
* @param {*} data - Event data
|
|
34
|
+
*/
|
|
35
|
+
emit(event: string, data: any): void;
|
|
36
|
+
/**
|
|
37
|
+
* Remove all event listeners
|
|
38
|
+
* @param {string} [event] - Optional event name to clear specific event
|
|
39
|
+
*/
|
|
40
|
+
removeAllListeners(event?: string): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=EventEmitter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../../src/core/EventEmitter.js"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH;IAEI,sBAAuB;IAGzB;;;;;OAKG;IACH,UAJW,MAAM,+BAWhB;IAED;;;;OAIG;IACH,YAHW,MAAM,2BAShB;IAED;;;;OAIG;IACH,WAHW,MAAM,2BAehB;IAED;;;;OAIG;IACH,YAHW,MAAM,QACN,GAAC,QAeX;IAED;;;OAGG;IACH,2BAFW,MAAM,QAQhB;CACF"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { EventEmitter } from './EventEmitter.js';
|
|
2
|
+
export namespace CONNECTION_EVENTS {
|
|
3
|
+
let DEVICE_CHANGE: string;
|
|
4
|
+
let IN_DEV_CONNECTED: string;
|
|
5
|
+
let IN_DEV_DISCONNECTED: string;
|
|
6
|
+
let OUT_DEV_CONNECTED: string;
|
|
7
|
+
let OUT_DEV_DISCONNECTED: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Low-level Web MIDI API connection handler. Manages:
|
|
11
|
+
* - MIDI device access/request
|
|
12
|
+
* - Device enumeration (inputs/outputs)
|
|
13
|
+
* - Device connection/disconnection
|
|
14
|
+
* - Hotplug detection and events
|
|
15
|
+
* - Raw MIDI message sending/receiving
|
|
16
|
+
* - SysEx message handling
|
|
17
|
+
* - Connection state tracking
|
|
18
|
+
*
|
|
19
|
+
* NOTE: Typically used internally by MIDIController. Most applications
|
|
20
|
+
* should use MIDIController instead for higher-level APIs.
|
|
21
|
+
* @extends EventEmitter
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Basic usage
|
|
25
|
+
* const connection = new MIDIConnection({ sysex: true });
|
|
26
|
+
* await connection.requestAccess();
|
|
27
|
+
* await connection.connect("My MIDI Device");
|
|
28
|
+
* connection.send([0x90, 60, 100]); // Note on
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Listening for device changes
|
|
32
|
+
* connection.on(CONNECTION_EVENTS.DEVICE_CHANGE, ({ device, state }) => {
|
|
33
|
+
* console.log(`${device.name} is now ${state}`);
|
|
34
|
+
* });
|
|
35
|
+
*/
|
|
36
|
+
export class MIDIConnection extends EventEmitter {
|
|
37
|
+
/**
|
|
38
|
+
* @param {Object} options
|
|
39
|
+
* @param {boolean} [options.sysex=false] - Request SysEx access
|
|
40
|
+
*/
|
|
41
|
+
constructor(options?: {
|
|
42
|
+
sysex?: boolean;
|
|
43
|
+
});
|
|
44
|
+
options: {
|
|
45
|
+
sysex: boolean;
|
|
46
|
+
};
|
|
47
|
+
midiAccess: MIDIAccess;
|
|
48
|
+
output: any;
|
|
49
|
+
input: any;
|
|
50
|
+
/**
|
|
51
|
+
* Request MIDI access from the browser. Sets up hotplug detection and
|
|
52
|
+
* emits events when devices connect/disconnect.
|
|
53
|
+
*
|
|
54
|
+
* @returns {Promise<void>}
|
|
55
|
+
* @throws {MIDIAccessError} If MIDI is not supported or access is denied
|
|
56
|
+
*
|
|
57
|
+
* @emits CONNECTION_EVENTS.DEVICE_CHANGE - When any MIDI device state changes
|
|
58
|
+
* @emits CONNECTION_EVENTS.IN_DEV_CONNECTED - When an input device connects
|
|
59
|
+
* @emits CONNECTION_EVENTS.IN_DEV_DISCONNECTED - When an input device disconnects
|
|
60
|
+
* @emits CONNECTION_EVENTS.OUT_DEV_CONNECTED - When an output device connects
|
|
61
|
+
* @emits CONNECTION_EVENTS.OUT_DEV_DISCONNECTED - When an output device disconnects
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* // Request basic MIDI access
|
|
65
|
+
* await connection.requestAccess();
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // Request with SysEx support
|
|
69
|
+
* const connection = new MIDIConnection({ sysex: true });
|
|
70
|
+
* await connection.requestAccess();
|
|
71
|
+
*/
|
|
72
|
+
requestAccess(): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Connect to a MIDI output device. Can connect by index, name, or ID.
|
|
75
|
+
*
|
|
76
|
+
* @param {string|number} [device] - Device name, ID, or index (defaults to first available)
|
|
77
|
+
* @returns {Promise<void>}
|
|
78
|
+
* @throws {MIDIConnectionError} If MIDI access not initialized
|
|
79
|
+
* @throws {MIDIDeviceError} If device not found or index out of range
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // Connect to first available device
|
|
83
|
+
* await connection.connect();
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* // Connect by index
|
|
87
|
+
* await connection.connect(0);
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* // Connect by name
|
|
91
|
+
* await connection.connect("My MIDI Keyboard");
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* // Connect by device ID
|
|
95
|
+
* await connection.connect("input-12345");
|
|
96
|
+
*/
|
|
97
|
+
connect(device?: string | number): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Connect to a MIDI input device for receiving messages
|
|
100
|
+
* @param {string|number} [device] - Device name, ID, or index (defaults to first available)
|
|
101
|
+
* @param {Function} onMessage - Callback for incoming MIDI messages
|
|
102
|
+
* @returns {Promise<void>}
|
|
103
|
+
* @throws {MIDIConnectionError} If MIDI access not initialized
|
|
104
|
+
* @throws {MIDIValidationError} If onMessage is not a function
|
|
105
|
+
* @throws {MIDIDeviceError} If device not found or index out of range
|
|
106
|
+
*/
|
|
107
|
+
connectInput(device?: string | number, onMessage: Function): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Disconnect from current output
|
|
110
|
+
*/
|
|
111
|
+
disconnectOutput(): void;
|
|
112
|
+
/**
|
|
113
|
+
* Disconnect from current input
|
|
114
|
+
*/
|
|
115
|
+
disconnectInput(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Disconnect from both output and input
|
|
118
|
+
*/
|
|
119
|
+
disconnect(): void;
|
|
120
|
+
/**
|
|
121
|
+
* Check if currently connected to an output
|
|
122
|
+
* @returns {boolean}
|
|
123
|
+
*/
|
|
124
|
+
isConnected(): boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Get current output device info
|
|
127
|
+
* @returns {Object|null}
|
|
128
|
+
*/
|
|
129
|
+
getCurrentOutput(): any | null;
|
|
130
|
+
/**
|
|
131
|
+
* Get current input device info
|
|
132
|
+
* @returns {Object|null}
|
|
133
|
+
*/
|
|
134
|
+
getCurrentInput(): any | null;
|
|
135
|
+
/**
|
|
136
|
+
* Get all available MIDI outputs
|
|
137
|
+
* @returns {Array<{id: string, name: string, manufacturer: string}>}
|
|
138
|
+
*/
|
|
139
|
+
getOutputs(): Array<{
|
|
140
|
+
id: string;
|
|
141
|
+
name: string;
|
|
142
|
+
manufacturer: string;
|
|
143
|
+
}>;
|
|
144
|
+
/**
|
|
145
|
+
* Get all available MIDI inputs
|
|
146
|
+
* @returns {Array<{id: string, name: string, manufacturer: string}>}
|
|
147
|
+
*/
|
|
148
|
+
getInputs(): Array<{
|
|
149
|
+
id: string;
|
|
150
|
+
name: string;
|
|
151
|
+
manufacturer: string;
|
|
152
|
+
}>;
|
|
153
|
+
/**
|
|
154
|
+
* Send a MIDI message to the connected output. Automatically converts
|
|
155
|
+
* Arrays to Uint8Array for Web MIDI API compatibility.
|
|
156
|
+
*
|
|
157
|
+
* @param {Uint8Array|Array<number>} message - MIDI message bytes (e.g., [0x90, 60, 100])
|
|
158
|
+
* @param {number} [timestamp=performance.now()] - Optional timestamp for scheduled sending
|
|
159
|
+
* @returns {void}
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* // Send a note on message (channel 1, note C4, velocity 100)
|
|
163
|
+
* connection.send([0x90, 60, 100]);
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* // Send a note off message
|
|
167
|
+
* connection.send([0x80, 60, 0]);
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* // Send a control change
|
|
171
|
+
* connection.send([0xB0, 7, 64]); // Volume to 64
|
|
172
|
+
*/
|
|
173
|
+
send(message: Uint8Array | Array<number>, timestamp?: number): void;
|
|
174
|
+
/**
|
|
175
|
+
* Send a System Exclusive (SysEx) message. Requires sysex: true in constructor options.
|
|
176
|
+
*
|
|
177
|
+
* @param {Array<number>} data - SysEx data bytes (without F0/F7 wrapper)
|
|
178
|
+
* @param {boolean} [includeWrapper=false] - If true, wraps data with F0/F7 bytes
|
|
179
|
+
* @returns {void}
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* // Send a basic SysEx message (will be wrapped with F0/F7)
|
|
183
|
+
* connection.sendSysEx([0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7F]);
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* // Send pre-wrapped SysEx message
|
|
187
|
+
* connection.sendSysEx([0xF0, 0x41, 0x10, 0x42, 0xF7], false);
|
|
188
|
+
*/
|
|
189
|
+
sendSysEx(data: Array<number>, includeWrapper?: boolean): void;
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=MIDIConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MIDIConnection.d.ts","sourceRoot":"","sources":["../../src/core/MIDIConnection.js"],"names":[],"mappings":";;;;;;;AAqCA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IACE;;;OAGG;IACH,sBAFG;QAA0B,KAAK,GAAvB,OAAO;KACjB,EAWA;IARC;eAJS,OAAO;MAOf;IAED,uBAAsB;IACtB,YAAkB;IAClB,WAAiB;IAGnB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAlBa,OAAO,CAAC,IAAI,CAAC,CAqEzB;IAED;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACH,iBArBW,MAAM,GAAC,MAAM,GACX,OAAO,CAAC,IAAI,CAAC,CAkDzB;IAED;;;;;;;;OAQG;IACH,sBAPW,MAAM,GAAC,MAAM,wBAEX,OAAO,CAAC,IAAI,CAAC,CA2CzB;IAED;;OAEG;IACH,yBAEC;IAED;;OAEG;IACH,wBAKC;IAED;;OAEG;IACH,mBAGC;IAED;;;OAGG;IACH,eAFa,OAAO,CAInB;IAED;;;OAGG;IACH,oBAFa,MAAO,IAAI,CAUvB;IAED;;;OAGG;IACH,mBAFa,MAAO,IAAI,CAUvB;IAED;;;OAGG;IACH,cAFa,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,CAAC,CAiBnE;IAED;;;OAGG;IACH,aAFa,KAAK,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAC,CAAC,CAiBnE;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAhBW,UAAU,GAAC,KAAK,CAAC,MAAM,CAAC,cACxB,MAAM,GACJ,IAAI,CA+BhB;IAED;;;;;;;;;;;;;;OAcG;IACH,gBAZW,KAAK,CAAC,MAAM,CAAC,mBACb,OAAO,GACL,IAAI,CAwBhB;CACF;6BAjb4B,mBAAmB"}
|