# Web MIDI in Elm 0.19

**URL:** https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580
**Category:** Request Feedback
**Created:** [November 21, 2018, 5:35pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580 "2018-11-21T17:35:42Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![lassik](https://avatars.discourse-cdn.com/v4/letter/l/ee7513/32.png) [@lassik](https://discourse.elm-lang.org/u/lassik)
#### Post date: [November 21, 2018, 5:35pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/1 "2018-11-21T17:35:42Z")

</div>

Greetings. In Elm 0.18 I did [`elm-webmidi-ports-minimal`](https://github.com/lassik/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`](https://github.com/lassik/elm-webmidi-ports-minimal/blob/master/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.)

---

<div class="post-metadata">

### Author: ![evancz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/evancz/32/16_2.png) [@evancz](https://discourse.elm-lang.org/u/evancz)
#### Post date: [November 21, 2018, 5:38pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/2 "2018-11-21T17:38:16Z")

</div>

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

---

<div class="post-metadata">

### Author: ![lassik](https://avatars.discourse-cdn.com/v4/letter/l/ee7513/32.png) [@lassik](https://discourse.elm-lang.org/u/lassik)
#### Post date: [November 21, 2018, 5:45pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/3 "2018-11-21T17:45:19Z")

</div>

Wow, that was a quick response! This is literally the entire Elm API for 0.18: [`WebMidi.elm`](https://github.com/lassik/elm-webmidi-ports-minimal/blob/master/src/WebMidi.elm)

---

<div class="post-metadata">

### Author: ![lassik](https://avatars.discourse-cdn.com/v4/letter/l/ee7513/32.png) [@lassik](https://discourse.elm-lang.org/u/lassik)
#### Post date: [November 21, 2018, 5:58pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/4 "2018-11-21T17:58:44Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![evancz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/evancz/32/16_2.png) [@evancz](https://discourse.elm-lang.org/u/evancz)
#### Post date: [November 21, 2018, 7:52pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/5 "2018-11-21T19:52:08Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![lassik](https://avatars.discourse-cdn.com/v4/letter/l/ee7513/32.png) [@lassik](https://discourse.elm-lang.org/u/lassik)
#### Post date: [November 21, 2018, 10:16pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/6 "2018-11-21T22:16:04Z")

</div>

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`](https://package.elm-lang.org/packages/elm/time/latest/Time#every) is still a subscription, I assume MIDI messages should be too.

---

<div class="post-metadata">

### Author: ![lassik](https://avatars.discourse-cdn.com/v4/letter/l/ee7513/32.png) [@lassik](https://discourse.elm-lang.org/u/lassik)
#### Post date: [November 21, 2018, 10:28pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/7 "2018-11-21T22:28:44Z")

</div>

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

---

<div class="post-metadata">

### Author: ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)
#### Post date: [December 1, 2018, 10:28pm UTC](https://discourse.elm-lang.org/t/web-midi-in-elm-0-19/2580/8 "2018-12-01T22:28:48Z")

</div>

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