W3C

Web MIDI API

W3C Working Draft 25 October 2012

This version:
http://www.w3.org/TR/2012/WD-webmidi-20121025/
Latest published version:
http://www.w3.org/TR/webmidi/
Previous published version:
none
Latest editor's draft:
https://dvcs.w3.org/hg/audio/raw-file/tip/midi/specification.html
Editors:
Jussi Kalliokoski
Chris Wilson, Google

Abstract

Some user agents have connected music devices, such as synthesizers, keyboard and other controllers, and drum machines. The widely adopted Musical Instrument Digital Interface (MIDI) protocol enables electronic musical instruments, controllers and computers to communicate and synchronize with each other. MIDI does not transmit audio signals: instead, it sends event messages about musical notes, controller signals for parameters such as volume, vibrato and panning, cues and clock signals to set the tempo, and system-specific MIDI communications (e.g. to remotely store synthesizer-specific patch data). This same protocol has become a standard for non-musical uses, such as show control, lighting and special effects control.

This specification defines an API supporting the MIDI protocol, enabling web applications to enumerate and select MIDI input and output devices on the client system and send and receive MIDI messages. It is intended to enable non-music MIDI applications as well as music ones, by providing low-level access to the MIDI devices available on the users' systems. At the same time, the Web MIDI API is not intended to become a semantic controller platform; it is designed to expose the mechanics of MIDI input and output interfaces, and the practical aspects of sending and receiving MIDI messages, without identifying what those actions might mean semantically.

To some users, "MIDI" has become synonymous with Standard MIDI Files and General MIDI. That is not the intent of this API; the use case of simply playing back a .SMF file is not within the purview of this specification (it could be considered a different format to be supported by the HTML5 <audio> element, for example). The Web MIDI API is intended to enable direct access to devices that respond to MIDI - external synthesizers or lighting systems, for example, or even the software synthesizers that are built in to many common operating systems. The Web MIDI API is also explicitly designed to enable a new class of applications on the web that can respond to MIDI controller inputs - using external hardware controllers with physical buttons, knobs and sliders (as well as musical controllers like keyboard, guitar or wind instrument controllers) to control web applications.

The Web MIDI API is also expected to be used in conjunction with other APIs and elements of the web platform, notably the Web Audio API and High-Resolution Time. This API is also intended to be familiar to users of MIDI APIs on other systems, such as Apple's CoreMIDI and Microsoft's Windows MIDI API.

Status of This Document

This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.

This document was published by the Audio Working Group as a First Public Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-audio@w3.org (subscribe, archives). All feedback is welcome.

Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.

This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

Note: On 1 November 2012 we edited the document in place to remove an incorrect statement about expectations for this document.

Table of Contents

1. Introduction

This section is non-normative.

The Web MIDI API specification defines a means for web developers to enumerate, manipulate and access MIDI devices - for example interfaces that may provide hardware MIDI ports with other devices plugged in to them and USB devices that support the USB-MIDI specification. Having a Web API for MIDI enables web applications that use existing software and hardware synthesizers, hardware music controllers and light systems and other mechanical apparatus controlled by MIDI.

This API has been defined with a wide variety of use cases in mind. The approaches taken by this API are similar to those taken in Apple's CoreMIDI API and Microsoft's Windows MIDI API; that is, the API is designed to represent the low-level software protocol of MIDI, in order to enable developers to build powerful MIDI software on top. The API enables the developer to enumerate input and output interfaces, and send and receive MIDI messages, but (similar to the aforementioned APIs) it does not attempt to semantically define or interpret MIDI messages beyond what is necessary to robustly support current devices.

The Web MIDI API is not intended to directly implement high-level concepts such as sequencing; it does not directly support Standard MIDI Files, for example, although a Standard MIDI File player can be built on top of the Web MIDI API. It is also not intended to semantically capture patches or controller assignments, as General MIDI does; such interpretation is outside the scope of the Web MIDI API (though again, General MIDI can easily be utilized through the Web MIDI API).

The Web MIDI API consists of the following set of interfaces and objects, as well as some supporting interfaces:

2. Conformance

As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.

The key words must, must not, required, should, should not, recommended, may, and optional in this specification are to be interpreted as described in [RFC2119].

This specification defines conformance criteria that apply to a single product: the user agent that implements the interfaces that it contains.

Implementations that use ECMAScript to implement the APIs defined in this specification must implement them in a manner consistent with the ECMAScript Bindings defined in the Web IDL specification [WEBIDL], as this specification uses that specification and terminology.

3. Terminology

The concepts queue a task and fires a simple event are defined in [HTML5].

The terms event handlers and event handler event types are defined in [HTML5].

The term Uint8Array is defined in [TYPED-ARRAYS].

The term DOMHighResTimeStamp is defined in the High Resolution Time Specification.

4. Security and privacy considerations

There are two primary security and privacy concerns with adding the Web MIDI API to the web platform:

  1. Allowing the enumeration of the user's MIDI interfaces is a potential target for fingerprinting (that is, uniquely identifying a user by the specific MIDI interfaces they have connected). Note that in this context, what can be enumerated is the MIDI interfaces - not, for example, an individual sampler or synthesizer plugged into a MIDI interface, as these would not be enumerated, unless those devices are connected to the host computer with USB (USB-MIDI devices typically have their own MIDI interface, and would be enumerated). The interfaces that could be fingerprinted are equivalent to MIDI "ports". This potential needs to be further investigated; the vast majority of systems have relatively few MIDI interfaces attached, so it is possible this is of little concern in practice.
  2. Additionally, combined access to input and output ports on a given device (the ability to send and receive system exclusive messages, in particular) might allow sophisticated developers to query and test for particular MIDI-connected devices, such as samplers, and either using the presence of those devices for more precise fingerprinting, destroying data (erasing samples or patches on the devices), attempting to capture data from the devices (e.g. downloading samples from samplers, then uploading to the network), or simply initiating malicious action (e.g. sending MIDI commands to a lighting control system to turn lights on and off).

These issues will be further explored prior to this specification becoming a Recommendation. In the meantime, the suggested security model explicitly allows user agents to require the user's approval before giving access to MIDI devices, although it is not currently required to prompt the user for this approval. It is noted that some web systems (e.g. Java) give access to MIDI interfaces without prompting, although this may not be the security model that this specification eventually uses.

5. Obtaining Access to MIDI Interfaces Available to the User Agent

[NoInterfaceObject]
interface NavigatorMIDIAccess {
    void getMIDIAccess (NavigatorMIDIAccessSuccessCallback successCallback, optional NavigatorMIDIAccessErrorCallback? errorCallback);
};

5.1.1 Methods

getMIDIAccess

Obtains an interface to enumerate and request access to MIDI devices on the user's system.

This call may prompt the user for access to MIDI devices. If the user accepts or the call is otherwise approved, successCallback is invoked, with a MIDIAccess object as its argument.

If the user declines or the call is denied, the errorCallback (if any) is invoked.

When the getMIDIAccess() method is called, the user agent must run the following steps:

  1. Let successCallback be the callback indicated by the method's first argument.

  2. Let errorCallback be the callback indicated by the method's second argument, if any, or null otherwise.

  3. If successCallback is null, abort these steps.

  4. Return, and run the following steps asynchronously.

  5. Optionally, e.g. based on a previously-established user preference, for security reasons, or due to platform limitations, jump to the step labeled failure below.

  6. Optionally, e.g. based on a previously-established user preference, jump to the step labeled success below.

  7. Prompt the user in a user-agent-specific manner for permission to provide the entry script's origin with a MIDIAccess object representing control over user's MIDI devices.

    If permission is denied, jump to the step labeled failure below. If the user never responds, this algorithm stalls on this step.

  8. success: Let access be the MIDIAccess object for which access has been granted.

  9. Queue a task to invoke successCallback with access as its argument, and return.

  10. Failure: If errorCallback is null, abort these steps.

  11. Let error be a new NavigatorMIDIAccessError object whose code attribute has the numeric value 1 (PERMISSION_DENIED ).

  12. Queue a task to invoke errorCallback with error as its argument.

The task source for these tasks is the user interaction task source.

ParameterTypeNullableOptionalDescription
successCallbackNavigatorMIDIAccessSuccessCallback
errorCallbackNavigatorMIDIAccessErrorCallback
Return type: void
Navigator implements NavigatorMIDIAccess;

All instances of the Navigator type are defined to also implement the NavigatorMIDIAccess interface.

6. MIDIAccess Interface

This interface provides the methods to enumerate MIDI input and output devices, and obtain access to an individual device.

[NoInterfaceObject]
interface MIDIAccess {
    sequence<MIDIPort> enumerateInputs ();
    sequence<MIDIPort> enumerateOutputs ();
    MIDIInput          getInput (MIDIPort or DOMString or short target);
    MIDIOutput         getOutput (MIDIPort or DOMString or short target);
};

6.1 Methods

enumerateInputs
Returns a list of the MIDI input ports available on the system.
No parameters.
Return type: sequence<MIDIPort>
enumerateOutputs
Returns a list of the MIDI output ports available on the system.
No parameters.
Return type: sequence<MIDIPort>
getInput
Acquires access to the input MIDIPort requested as a MIDIInput instance.

When the getInput() is invoked, the user agent must run the following steps:

  1. Let target be the MIDIPort argument. If the target is a DOMString, target will be a MIDIPort whose fingerprint matches the supplied DOMString. If target is a short, target will be a MIDIPort that matches the supplied index in the sequence returned by enumerateInputs(). If the target parameter is a DOMString and there is no MIDIPort that matches the fingerprint, or if the target parameter is a short outside the bounds of available MIDI inputs, throw a TYPE_ERROR exception.

  2. If target is not a MIDIPort instance, or if the MIDIPort is not a valid MIDI input port, throw a TYPE_ERROR exception.

  3. If target is not available for access, throw a REFERENCE_ERROR exception.

  4. If made necessary by the underlying system APIs, reserve the corresponding port for use within the current process.

  5. Return a MIDIInput object corresponding to the target argument.

ParameterTypeNullableOptionalDescription
targetMIDIPort or DOMString or short The input port to be requested.
Return type: MIDIInput
getOutput
Acquires access to the output MIDIPort requested as a MIDIOutput instance.

When the getOutput() is invoked, the user agent must run the following steps:

  1. Let target be the MIDIPort argument. If the target is a DOMString, target will be a MIDIPort whose fingerprint matches the supplied DOMString. If target is a short, target will be a MIDIPort that matches the supplied index in the sequence returned by enumerateOutputs(). If the target parameter is a DOMString and there is no MIDIPort that matches the fingerprint, or if the target parameter is a short outside the bounds of available MIDI inputs, throw a TYPE_ERROR exception.

  2. If target is not a MIDIPort instance, or if the MIDIPort is not a valid MIDI output port, throw a TYPE_ERROR exception.

  3. If target is not available for access, throw a REFERENCE_ERROR exception.

  4. If made necessary by the underlying system APIs, reserve the corresponding port for use within the current process.

  5. Return a MIDIOutput object corresponding to the target argument.

ParameterTypeNullableOptionalDescription
targetMIDIPort or DOMString or short The output port to be requested.
Return type: MIDIOutput

7. MIDIPort Interface

This interface represents a MIDI input or output port.

Whenever the MIDI port corresponding the MIDIPort is disconnected or becomes unavailable, if supported by the underlying system the UA should run the following steps:

  1. Fire a simple event named disconnect at the object.

Whenever the MIDI port corresponding the MIDIPort is connected or reconnected, the UA must run the following steps:

  1. Fire a simple event named connect at the object.

Note

The disconnect and connect events may not be applicable to all MIDI ports or OS APIs. For example, some system APIs do not dynamically notify applications when MIDI ports become available or unavailable. Therefore the semantic here is should, rather than must.

It is also important to note again that the MIDIPort represents an input or output interface, not necessarily an endpoint MIDI device; it is not possible, using this system, to be notified when a synthesizer is plugged into a 5-pin DIN MIDI port on a hardware MIDI interface.

enum MIDIPortType {
    "input",
    "output"
};
Enumeration description
input If a MIDIPort is an input port, the type member must be this value.
output If a MIDIPort is an output port, the type member must be this value.
[NoInterfaceObject]
interface MIDIPort : EventTarget {
    readonly attribute MIDIPortType type;
    readonly attribute DOMString    name;
    readonly attribute DOMString    manufacturer;
    readonly attribute DOMString    version;
    readonly attribute DOMString    fingerprint;
    [TreatNonCallableAsNull]
             attribute callback?    ondisconnect;
    [TreatNonCallableAsNull]
             attribute callback?    onconnect;
};

7.1 Attributes

fingerprint of type DOMString, readonly

A unique ID of the port. This can be used by developers to remember ports the user has chosen for different applications. The User Agent should make sure the fingerprint is unique to only that port if possible.

manufacturer of type DOMString, readonly

The manufacturer of the port.

name of type DOMString, readonly

The system name of the port.

onconnect of type callback, nullable

This event handler, of type connect, should be supported by all objects implementing the MIDIPort interface.

ondisconnect of type callback, nullable

This event handler, of type disconnect, should be supported by all objects implementing the MIDIPort interface.

type of type MIDIPortType, readonly

A descriptor property to distinguish whether the port is an input or an output port. For MIDIOutput, this must be "output". For MIDIInput, this must be "input".

version of type DOMString, readonly

The version of the port.

7.2 MIDIInput Interface

MIDIInput implements MIDIPort;

All instances of the MIDIInput type are defined to also implement the MIDIPort interface.

[NoInterfaceObject]
interface MIDIInput {
    [TreatNonCallableAsNull]
             attribute callback? onmessage;
};

7.2.1 Attributes

onmessage of type callback, nullable

This event handler, of type message, must be supported by all objects implementing MIDIInput interface.

Whenever the MIDI port corresponding the MIDIInput sends a MIDI message, the UA must run the following steps:

  1. Let port be the MIDIInput.

  2. Let messages be a newly constructed sequence<MIDIMessage> corresponding the MIDI messages the port sent.

  3. Let event be a newly constructed MIDIEvent, with the MIDIMessages attribute set to messages.

  4. Fire an event named message at the object, using the event as the event object.

7.3 MIDIOutput Interface

MIDIOutput implements MIDIPort;

All instances of the MIDIOutput type are defined to also implement the MIDIPort interface.

[NoInterfaceObject]
interface MIDIOutput {
    void sendMIDIMessage (MIDIMessage message);
    void sendMessage (short status, optional short? data1, optional optional short? data2);
};

7.3.1 Methods

sendMIDIMessage

Enqueues the message to be sent to the corresponding MIDI port.

ParameterTypeNullableOptionalDescription
messageMIDIMessage The message to be enqueued to be sent at the appropriate time (message.timestamp). If message.timestamp is zero or null, the message is to be sent as soon as possible.
Return type: void
sendMessage

Enqueues a simple MIDI message of three or fewer bytes to be sent to the corresponding MIDI port. This method of sending does not utilize timestamps - the message will be sent as soon as possible - and also is not to be used for system exclusive messages (i.e. any MIDI messages over three bytes in length).

ParameterTypeNullableOptionalDescription
statusshort The status byte of a simple MIDI message.
data1short The first data byte of a simple MIDI message, if requested.
data2optional short The second data byte of a simple MIDI message, if requested.
Return type: void

8. MIDIMessage Interface

[NoInterfaceObject]
dictionary MIDIMessage {
    DOMHighResTimeStamp timestamp;
    Uint8Array          data;
};

8.1 Dictionary MIDIMessage Members

data of type Uint8Array

A Uint8Array signifying the data the message contains.

timestamp of type DOMHighResTimeStamp

A DOMHighResTimeStamp signifying when the event occurred or should occur. For MIDIMessages received by a MIDIInput, this is required to be set; for MIDIMessages that are passed to sendMIDIMessage() on a MIDIOutput, this may explicitly be set to zero or null to represent "as soon as possible".

8.2 MIDIEvent Interface

[NoInterfaceObject]
interface MIDIEvent : Event {
    readonly attribute MIDIMessage[] MIDIMessages;
};

8.2.1 Attributes

MIDIMessages of type array of MIDIMessage, readonly

An array of MIDIMessages associated with the event.

A. References

A.1 Normative references

[HTML5]
Ian Hickson; David Hyatt. HTML5. 29 March 2012. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/html5
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Internet RFC 2119. URL: http://www.ietf.org/rfc/rfc2119.txt
[TYPED-ARRAYS]
David Herman, Kenneth Russell. Typed Arrays Khronos Working Draft. (Work in progress.) URL: https://www.khronos.org/registry/typedarray/specs/latest/
[WEBIDL]
Cameron McCormack. Web IDL. 27 September 2011. W3C Working Draft. (Work in progress.) URL: http://www.w3.org/TR/2011/WD-WebIDL-20110927/