Web MIDI in Elm 0.19

Greetings. In Elm 0.18 I did elm-webmidi-ports-minimal to read musical notes from a MIDI controller plugged into the computer’s USB port. It worked great but it relied on a port module and a bit of native JavaScript so it no longer works in 0.19.

Would it be possible to get MIDI back via elm-explorations? I’d be happy to collaborate on this (or to have someone more experienced do it). The necessary API should be about as trivial as they come – while the complete Web MIDI API has a fair bit of stuff in it, the only thing we really need to get started is to recognize when MIDI controllers are plugged into USB and to read MIDI messages from them. The stuff in native.js is all the impure stuff you need for a useful application. Maybe add a polyfill for compatibility with more browsers and some idiomatic error handling.

Each MIDI message coming in from the Web MIDI API is just a raw byte string. The message can be parsed in pure-functional code – the great elm-comidi library already does that.

(It should be noted that the Web MIDI API is wholly separate from the Web Audio API, the latter being more complex.)

3 Likes

What’s the minimal Elm API you’d need?

Wow, that was a quick response! This is literally the entire Elm API for 0.18: WebMidi.elm

It’s possible to connect more than one MIDI controller to the computer at the same time (I tested this and it worked on Mac Chrome). For the Elm API I just merged messages from all controllers into the same message stream, without identifying which controller each message came from. This is fine for many applications.

The Web MIDI API also supports plugging controllers in and out of the computer while our web page is open. The browser fires midi.onstatechange events accordingly. I handled these events entirely on the native JavaScript side, so that the Elm code doesn’t know how many controllers are plugged in at any given time, or any details about them whatsoever. It just gets a stream of notes.

I made each note in the stream into Elm records so fields with details about controllers can be added later. Currently the record just has a midiEvent with the raw MIDI message bytes.

You mentioned that you needed some bindings to JS to get it working though. Can you list the minimal Elm API you need for that? Just share the type annotations for them in a code block in this thread.

I’m not confident that I understand all the details that go into this, but here’s an attempt:

module WebMidi exposing (..)

type alias Message =
    { midiEvent : String }

onMidiMessage : (Message -> msg) -> Sub msg

All names in the code are tentative.

Since Time.every is still a subscription, I assume MIDI messages should be too.

It’s the exact same code as the WebMidi.elm that worked in 0.18 but without the port keyword.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.