I'm building an experimental Web MIDI app which graphically displays the notes you're playing on an external MIDI keyboard to the browser. I'm having a strange error where the following callback only works if I log it to the console:
// ============================================================================
// Web MIDI API
// ============================================================================
var MIDI = null;
$(document ).ready(function(){
function onMIDISuccess( midiAccess )
{
MIDI = midiAccess;
// Start listening to the MIDI ports!
var selected_input = MIDI.inputs()[0];
console.log( selected_input );
selected_input.onmidimessage = function( event )
{
if( event.data[0] == 144 )
{
// Zero velocity means note OFF
if( event.data[2] == 0 )
$("pianokey[note="+event.data[1]+"]" ).removeClass("active");
// Non-zero velocity means note ON
else
$("pianokey[note="+event.data[1]+"]" ).addClass("active");
}
};
}
function onMIDIFailure( error )
{
console.error( "MIDI Failed! Error: ", error );
}
navigator.requestMIDIAccess().then( onMIDISuccess, onMIDIFailure );
});
What I'm finding is that my code works but only when the line console.log( selected_input );
is included.
Easiest to see what I mean by running my fiddle: http://jsfiddle.net/8sSMe/1/
If you have an external midi keyboard plugged in, you should see the keys light up on screen mimicking what you're playing on your keyboard. Remember, you might have to restart chrome to pickup your keyboard, and you might need to choose a different input from the array for selected_input
. You also might need to turn Web MIDI on in your chrome by going to chrome://flags/#enable-web-midi (also I'm only interested in getting this to work on Chrome). Once you see that it is working, try it with console.log( selected_input );
commented out and it will strangely stop working.
Any ideas?
I think I found the problem...
Scope / Garbage collection
My reference var selected_input = MIDI.outputs()[0];
was occurring in a scope that goes away. So when it goes away, along with it goes the callback response mechanism. Keeping the reference to it in global scope solves the problem. Somehow, console.log()
was perhaps changing the scope.
So have a solution but my theory is just a working solution, I would gladly welcome anyone with more expertise who could corroborate my theory. I don't know how to test if a variable is being garbage collected...?
Alas, the challenges of the Javascript language...