Skip to content

Proposal for MIDIInterface object in addition to MIDIAccess and MIDIPort. #156

Closed
@objectkit

Description

@objectkit

I'm hesitant to present this question/proposal/request for clarification here, as it may have been put forward already, but I didn't find anything and I feel the need to put if forward, so I'm taking the chance.

At the moment MIDIPorts are presented in MIDIPortMaps available via MIDIAccess#inputs and MIDIAccess#outputs attributes. As such, the only way to group MIDIPorts together to represent an individual physical device is to iterate the MIDIInputMap and the MIDIOutputMap, and if a MIDIPort has the same MIDIPort#name and MIDIPort#manufacturer as another, to group them together on the assumption that they belong to the same physical (or virtual?) device. Please forgive the flawed use of MIDIPortMap iteration and CoffeeScript used here

navigator.requestMIDIAccess()
    .then (midiAccess) ->
        model = {}
        for midiInputPort of midiAccess.inputs
            key = "#{midiInputPort.manufacturer} #{midiInputPort.name}"
            if not model[key]?
                model[key] =
                    manufacturer:   midiInputPort.manufacturer
                    name:           midiInputPort.name
                    id:             midiInputPort.id
                    inputs:         []
                    outputs:        []
            model[key].inputs.push midiInputPort.id

        for midiOutputPort of midiAccess.outputs
            key = "#{midiOutputPort.manufacturer} #{midiOutputPort.name}"
            if not model[key]?
                model[key] =
                    manufacturer:   midiOutputPort.manufacturer
                    name:           midiOutputPort.name
                    id:             midiOutputPort.id
                    inputs:         []
                    outputs:        []
            model[key].outputs.push midiOutputPort.id

        console.info JSON.stringify model, null, "\t"

This seems to assume that physical devices have either only 1 MIDI input and 1 MIDI output, or, that no-one will ever have more than one of the same device connected to their machine at the same time. I feel this is a shortfall of the API as I currently understand it. If I have missed something, I would much appreciate clarification, but just in case I haven't, I present the following hypothetical scenario.

The iConnectMIDI 4+ has 4 MIDI DIN INs and 4 MIDI DIN OUTs. (It also has virtual MIDI which I will sidestep for the moment as I want to bring this up later).

With only a single device attached to a computer, 4 MIDIInputPorts and 4 MIDIOutputPorts will be presented correctly by the API as it stands. As an app dev, assuming no foreknowledge of a connected device, I could iterate the available inputs and outputs of MIDIAccess, and judge by the #name and #manufacturer attributes presented, that a single device with 4 MIDIInputPorts and 4 MIDIOutputPorts is available to the system, and present that to a view in a hypothetical app.

This is fine. But in the case, rare as it may be, that a user has 2 iConnectMIDI4+ devices attached, if I were to use the same device identification strategy, my app would present a single device with 8 MIDIInput ports and 8 MIDIOutput ports! If I had foreknowledge of the device specification, I could accommodate this and correctly present 2 views, one for each device... but I feel that would be unnecessary foreknowledge in the context of a MIDI app.

Instead, I would propose the introduction of a MIDIInterface object. Again, forgive the flawed coffeescript, but if it was introduced, then this would be possible:

navigator.requestMIDIAccess()
    .then (midiAccess) ->
        model = {}
        for midiInterface in midiAccess.midiIterfaces
            descriptor =

                manufacturer:   midiInterface.manufacturer
                name:           midiInterface.name
                id:             midiInterface.id
                inputs:         []
                outputs:        []

            for midiInputPort in midiInterface.inputs
                descriptor.inputs.push midiInputPort.id

            for midiOutputPort in midiInterface.outputs
                descriptor.outputs.push midiOutputPort.id

            key = "#{midiInterface.manufacturer} #{midiInterface.name}"
            model[key] = descriptor

        console.info JSON.stringify model, null, "\t"

MIDIInterface, like MIDIAcess and MIDIPort could implement the statechange handler.

  • MIDIAccess statechange could show that a new MIDIInterface is available, or a previously connected one has disconnected.
  • MIDIInterface statechange could show that a previously connected MIDIPort associated with the MIDIInterface has disconnected, or in the case of virtual midi, that a new MIDIPort has become available to it.
  • MIDIPort statechange could then focus on MIDIPorts opening, pending, closing, and MIDIPorts could have a midiInterface attribute to track back to its parent MIDIInterface.

This would have a lot of advantages for presenting views, as well as simplifying event management from where I see it.

But then again, I've only just started with the API and there may be other means to do this, and if there are, I would appreciate some feedback as to how to do this with the present API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions