Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 67 additions & 33 deletions types/webmidi/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ declare namespace WebMidi {
* exclusive messages is requested or allowed on a given MIDIAccess object.
*/
sysex: boolean;

/**
* This member informs the system whether the ability to utilize any software synthesizers
* installed in the host system is requested or allowed on a given MIDIAccess object.
*/
software: boolean;
}

/**
Expand All @@ -31,22 +37,22 @@ declare namespace WebMidi {
/**
* The MIDI input ports available to the system.
*/
inputs: MIDIInputMap;
readonly inputs: MIDIInputMap;

/**
* The MIDI output ports available to the system.
*/
outputs: MIDIOutputMap;
readonly outputs: MIDIOutputMap;

/**
* The handler called when a new port is connected or an existing port changes the
* state attribute.
*/
onstatechange(e: MIDIConnectionEvent): void;
onstatechange: ((e: MIDIConnectionEvent) => void) | null;

addEventListener(
type: "statechange",
listener: (this: this, e: MIDIConnectionEvent) => any,
listener: (this: this, e: MIDIConnectionEvent) => void,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
Expand All @@ -55,11 +61,22 @@ declare namespace WebMidi {
options?: boolean | AddEventListenerOptions,
): void;

removeEventListener(
type: "statechange",
listener: (this: this, e: MIDIConnectionEvent) => void,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions,
): void;

/**
* This attribute informs the user whether system exclusive support is enabled on
* this MIDIAccess.
*/
sysexEnabled: boolean;
readonly sysexEnabled: boolean;
}

type MIDIPortType = "input" | "output";
Expand All @@ -73,48 +90,48 @@ declare namespace WebMidi {
* A unique ID of the port. This can be used by developers to remember ports the
* user has chosen for their application.
*/
id: string;
readonly id: string;

/**
* The manufacturer of the port.
*/
manufacturer?: string | undefined;
readonly manufacturer?: string;

/**
* The system name of the port.
*/
name?: string | undefined;
readonly name?: string;

/**
* A descriptor property to distinguish whether the port is an input or an output
* port.
*/
type: MIDIPortType;
readonly type: MIDIPortType;

/**
* The version of the port.
*/
version?: string | undefined;
readonly version?: string;

/**
* The state of the device.
*/
state: MIDIPortDeviceState;
readonly state: MIDIPortDeviceState;

/**
* The state of the connection to the device.
*/
connection: MIDIPortConnectionState;
readonly connection: MIDIPortConnectionState;

/**
* The handler called when an existing port changes its state or connection
* attributes.
*/
onstatechange(e: MIDIConnectionEvent): void;
onstatechange: ((e: MIDIConnectionEvent) => void) | null;

addEventListener(
type: "statechange",
listener: (this: this, e: MIDIConnectionEvent) => any,
listener: (this: this, e: MIDIConnectionEvent) => void,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
Expand All @@ -123,6 +140,17 @@ declare namespace WebMidi {
options?: boolean | AddEventListenerOptions,
): void;

removeEventListener(
type: "statechange",
listener: (this: this, e: MIDIConnectionEvent) => void,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions,
): void;

/**
* Makes the MIDI device corresponding to the MIDIPort explicitly available. Note
* that this call is NOT required in order to use the MIDIPort - calling send() on
Expand Down Expand Up @@ -151,28 +179,44 @@ declare namespace WebMidi {
}

interface MIDIInput extends MIDIPort {
type: "input";
onmidimessage(e: MIDIMessageEvent): void;
readonly type: "input";
onmidimessage: ((e: MIDIMessageEvent) => void) | null;

addEventListener(
type: "midimessage",
listener: (this: this, e: MIDIMessageEvent) => any,
listener: (this: this, e: MIDIMessageEvent) => void,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
type: "statechange",
listener: (this: this, e: MIDIConnectionEvent) => any,
listener: (this: this, e: MIDIConnectionEvent) => void,
options?: boolean | AddEventListenerOptions,
): void;
addEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | AddEventListenerOptions,
): void;

removeEventListener(
type: "midimessage",
listener: (this: this, e: MIDIMessageEvent) => void,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: "statechange",
listener: (this: this, e: MIDIConnectionEvent) => void,
options?: boolean | EventListenerOptions,
): void;
removeEventListener(
type: string,
listener: EventListenerOrEventListenerObject,
options?: boolean | EventListenerOptions,
): void;
}

interface MIDIOutput extends MIDIPort {
type: "output";
readonly type: "output";

/**
* Enqueues the message to be sent to the corresponding MIDI port.
Expand All @@ -193,40 +237,30 @@ declare namespace WebMidi {
}

interface MIDIMessageEvent extends Event {
/**
* A timestamp specifying when the event occurred.
*/
receivedTime: number;

/**
* A Uint8Array containing the MIDI data bytes of a single MIDI message.
*/
data: Uint8Array;
readonly data: Uint8Array;
}

interface MIDIMessageEventInit extends EventInit {
/**
* A timestamp specifying when the event occurred.
*/
receivedTime: number;

/**
* A Uint8Array containing the MIDI data bytes of a single MIDI message.
*/
data: Uint8Array;
readonly data: Uint8Array;
}

interface MIDIConnectionEvent extends Event {
/**
* The port that has been connected or disconnected.
*/
port: MIDIPort;
readonly port: MIDIPort;
}

interface MIDIConnectionEventInit extends EventInit {
/**
* The port that has been connected or disconnected.
*/
port: MIDIPort;
readonly port: MIDIPort;
}
}
2 changes: 1 addition & 1 deletion types/webmidi/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"name": "@types/webmidi",
"version": "2.0.9999",
"version": "2.1.9999",
"projects": [
"http://www.w3.org/TR/webmidi/"
],
Expand Down
76 changes: 67 additions & 9 deletions types/webmidi/webmidi-tests.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,84 @@
const onFulfilled = (item: WebMidi.MIDIAccess) => {
const midiPort = item;

// @ts-expect-error inputs property is read-only
midiPort.inputs = new Map<string, WebMidi.MIDIInput>();
// @ts-expect-error outputs property is read-only
midiPort.outputs = new Map<string, WebMidi.MIDIOutput>();
// @ts-expect-error sysexEnabled is read-only
midiPort.sysexEnabled = true;

midiPort.onstatechange = event => {
console.log("onstatechange");
console.log(event);
};
midiPort.addEventListener("statechange", event => {
midiPort.onstatechange = null;

const onStateChange = (event: WebMidi.MIDIConnectionEvent) => {
console.log(event.port);
});

// @ts-expect-error port is read-only
event.port = null;
};
midiPort.addEventListener("statechange", onStateChange);
midiPort.removeEventListener("statechange", onStateChange);

console.log("sysexenabled");
console.log(item.sysexEnabled);

const outputs = item.outputs.values();
for (const op of outputs) {
op.send([0x90, 0x45, 0x7f]);
op.send(new Uint8Array([0x90, 0x45, 0x7f]));
for (const output of outputs) {
// @ts-expect-error id is read-only
output.id = "123";
// @ts-expect-error manufacturer is read-only
output.manufacturer = "456";
// @ts-expect-error name is read-only
output.name = "789";
// @ts-expect-error type is read-only and has to be "output"
output.type = "input";
// @ts-expect-error version is read-only
output.version = "1.0";
// @ts-expect-error state is read-only
output.state = "connected";
// @ts-expect-error connection is read-only
output.connection = "closed";

output.send([0x90, 0x45, 0x7f]);
output.send(new Uint8Array([0x90, 0x45, 0x7f]));
}

const onMidiMessage = (event: WebMidi.MIDIMessageEvent) => {
console.log(event.data);
// @ts-expect-error receivedTime is not present in the spec
console.log(event.receivedTime);
// @ts-expect-error data is read-only
event.data = [];
};

const inputs = midiPort.inputs.values();
for (const input of inputs) {
// @ts-expect-error id is read-only
input.id = "123";
// @ts-expect-error manufacturer is read-only
input.manufacturer = "456";
// @ts-expect-error name is read-only
input.name = "789";
// @ts-expect-error type is read-only and has to be "input"
input.type = "output";
// @ts-expect-error version is read-only
input.version = "1.0";
// @ts-expect-error state is read-only
input.state = "connected";
// @ts-expect-error connection is read-only
input.connection = "closed";

input.onmidimessage = event => {
console.log(event.data);
};
input.addEventListener("midimessage", event => {
console.log(event.data);
});
input.onmidimessage = null;

input.addEventListener("midimessage", onMidiMessage);
input.removeEventListener("midimessage", onMidiMessage);
}

const inputOrOutput = [...inputs, ...outputs][0];
Expand All @@ -44,6 +97,11 @@ const onRejected = (e: Error) => {
console.error(e);
};

const midiOptions: WebMidi.MIDIOptions = {
sysex: true,
software: false,
};

if (navigator.requestMIDIAccess !== undefined) {
navigator.requestMIDIAccess().then(onFulfilled, onRejected);
navigator.requestMIDIAccess(midiOptions).then(onFulfilled, onRejected);
}