djipco / webmidi

Tame the Web MIDI API. Send and receive MIDI messages with ease. Control instruments with user-friendly functions (playNote, sendPitchBend, etc.). React to MIDI input with simple event listeners (noteon, pitchbend, controlchange, etc.).
Apache License 2.0
1.54k stars 115 forks source link

Creating a device selector dropdown causes an Uncaught TypeError #23

Closed jesseverhage closed 7 years ago

jesseverhage commented 7 years ago

Last week, I created a website to visualize an art project using MIDI. In order for everybody on the team to be able to use it, I made a dropdown to select the MIDI device. Last week, this was all functioning all-right, without any errors (Win10, Google Chrome, most recent version).

Today, with identical code, I keep getting this error on running the generateDeviceDropdown() function, which runs on pageload in my application. The error and function can be found below.

Uncaught TypeError: Cannot read property 'inputs' of undefined at WebMidi._updateInputs (webmidi.min.js:30) at WebMidi._updateInputsAndOutputs (webmidi.min.js:30) at WebMidi._processStateChange (webmidi.min.js:30) at WebMidi._onInterfaceStateChange (webmidi.min.js:30)

function generateDeviceDropdown(){
    WebMidi.enable(function(err) { 
    //error collector
    if (err) console.log("WebMidi could not be enabled");
    //generate dropdown with MIDI inputs    
    var dropdown = document.getElementById("midiDeviceSelector");
    for (var i=0; i<(WebMidi.inputs.length); i++)
    {
        var option = document.createElement("option");
        option.text=WebMidi.inputs[i].name;
        option.value=i;
        dropdown.add(option);
    }
    WebMidi.disable();
  }
);
}

A way to prevent this error, is to add a breakpoint for debugging literally anywhere in the WebMidi.enable() function inside the generateDeviceDropDown() function. After resuming script execution there is no error. Any idea what could be causing this behaviour?

djipco commented 7 years ago

Please tell me which precise version of Chrome you have (i.e. 61.0.3163.100). Did you happen to notice if Chrome was updated since last week?

jesseverhage commented 7 years ago

My Chrome version is 61.0.3163.100. I'm not sure if it was updated since last week. I also tried Opera, which gave me identical results (version 48.0.2685.32).

djipco commented 7 years ago

You really had me stumped for a while there... The problem is that you call WebMidi.disable() a tiny fraction of a second after enabling it. This means that statechange events do not even have time to be processed.

I never expected WebMidi.disable() to be called so soon. Your code did highlight an issue though: the statechange event listeners were not properly removed when disable() is called. Version 2.0.0-rc.9 fixes that problem.

By the way, unless you explicitely want to shut down MIDI, there is no real need to call disable(). If you don't, it'll simply get disposed of when the page is closed.

Thanks for reporting the issue!

jesseverhage commented 7 years ago

Thanks for the quick fix!