{"id":399,"date":"2010-11-09T16:15:14","date_gmt":"2010-11-09T15:15:14","guid":{"rendered":"http:\/\/www.abumarkub.net\/abublog\/?page_id=399"},"modified":"2015-05-22T19:13:08","modified_gmt":"2015-05-22T18:13:08","slug":"midibridge","status":"publish","type":"page","link":"https:\/\/abumarkub.net\/abublog\/?page_id=399","title":{"rendered":"Midibridge"},"content":{"rendered":"<p><strong>[ Deprecated: Chrome 43 supports MIDI natively, see this <a href=\"http:\/\/abumarkub.net\/abublog\/?p=963\">post<\/a> ]<\/strong><\/p>\n<p><a href=\"#introduction\">1) Introduction<\/a><br \/>\n<a href=\"#quick-start\">2) Quick start guide<\/a><br \/>\n<a href=\"#documentation\">3) Documentation<\/a><br \/>\n<a href=\"#midi-out\">4) About midi out<\/a><br \/>\n<a href=\"#earlier-versions\">5) Earlier versions<\/a><br \/>\n<a href=\"#flash\">6) What about Flash?<\/a><br \/>\n<a href=\"#known-issues\">7) Known issues<\/a><br \/>\n<a href=\"#roadmap\">8) Forthcoming features<\/a><\/p>\n<p><a name=\"introduction\"><\/a> <strong>Introduction<\/strong><\/p>\n<p>The midibridge is a Javascript API for interacting with the midi devices on your computer.<\/p>\n<p>It provides methods for detecting the midi devices and for connecting these devices with each other.<\/p>\n<p>The midibridge itself is considered a midi device as well, so it can be connected to the detected devices.<\/p>\n<p>The midibridge can generate and send midi events to midi output devices, and receive midi events from midi input devices.<\/p>\n<p>The midibridge can also filter and alter midi events.<\/p>\n<p>A sequencer for playing back midi files is implemented as well, recording will be added in a later version.<\/p>\n<p>A midi output device is a physical output port on your computer, a virtual output port or a software synthesizer. It can also be a sequencer, a file or a function.<\/p>\n<p>A midi input device is a physical or virtual input port, a sequencer, a file or a function.<\/p>\n<p>A midi device can be both in- and output. The midibridge itself for instance is both in- and output because it can send and receive midi events.<\/p>\n<p>The actual interaction with the midi devices on your computer is done by a Java applet. The midibridge automatically adds the applet to your webpage.<\/p>\n<p>The midibridge has no visual parts, it is &#8216;headless&#8217; code. You could say the midibridge enables you to write a &#8216;front-end&#8217; on top of the applet.<\/p>\n<p>Midi Devices -> Java Applet -> Javascript Midibridge API -> a GUI in Javascript, Flash, SVG, C# (Silverlight)<\/p>\n<p>Because the midibridge is written in native Javascript, you can use it conflict-free with any Javascript framework.<\/p>\n<p><a name=\"quick-start\"><\/a> <strong>Quick start guide<\/strong><\/p>\n<p><strong>1)<\/strong> Download the <a href=\"https:\/\/github.com\/abudaan\/midibridge-js\/zipball\/master\" target=\"blank\" title=\"abumarkub midibridge javascript\" rel=\"abumarkub midibridge javascript\">zip file<\/a> from Github.<\/p>\n<p><strong>2)<\/strong> In this zip file you&#8217;ll find an index.html and 3 folders: \/java contains a Java archive (jar) file, \/lib contains a Javascript file (minified and non-minified) and \/examples contains the code examples of this documentation.<\/p>\n<p>On your webserver, put the jar file in a folder called &#8220;java&#8221; and the minified javascript file in the folder where you usually store your javascript libraries. Personally, i put the Javascript libraries that i use in a project in a &#8220;lib&#8221; folder, and the project specific javascript files in a folder &#8220;js&#8221;.<\/p>\n<p><strong>3)<\/strong> Include the file midibridge-0.5.3.min.js in your webpage. If you use a Javascript framework (jQuery, YUI, Dojo, etc.), include it right after you&#8217;ve included the framework. See the index.html in the zip.<\/p>\n<p><strong>4)<\/strong> Start the midibridge. The page has to be fully loaded before you start the midibridge, so call the init function of the midibridge inside your onload handler:<\/p>\n<pre><code>window.addEventListener('load', function() {\n    midiBridge.init(function(midiEvent) {\n        console.log(midiEvent);\n    });\n}, false);\n<\/code><\/pre>\n<p><strong>5)<\/strong> Done! If you have a midikeyboard connected to you computer, play some notes and you&#8217;ll hear a piano sound. Also you will see that the midi events are printed to your console.<\/p>\n<p><a name=\"documentation\"><\/a> <strong>Documentation<\/strong><\/p>\n<p>By adding the midibridge to your html page, a global variable <code>midiBridge<\/code> is created. Below follows a list of the methods that you can call on the <code>midiBridge<\/code> object. There is also a bunch of handy static members that you use in your code:<\/p>\n<p>&#8211;\u00a0<a href=\"#init\">init()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#sendMidiEvent\">sendMidiEvent(status, channel, data1, data2)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#getDevices\">getDevices()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#refreshDevices\">refreshDevices()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#connectAllInputs\">connectAllInputs()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#connectFirstInput\">connectFirstInput()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#connectFirstOutput\">connectFirstOutput()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#connectAllInputsToFirstOutput\">connectAllInputsToFirstOutput()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#addConnection\">addConnection(input,output,filter)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#removeConnection\">removeConnection(input,output)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#disconnectAll\">disconnectAll()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#getNoteName\">getNoteName(midiNoteNumber,mode)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#getNoteNumber\">getNoteNumber(noteName,octave)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#getStatus\">getStatus(statusCode)<\/a><br \/>\n&#8211;\u00a0<a href=\"#loadBase64String\">loadBase64String(base64String)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#playBase64String\">playBase64String(base64String)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#startSequencer\">startSequencer()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#pauseSequencer\">pauseSequencer()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#stopSequencer\">stopSequencer()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#closeSequencer\">closeSequencer()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#getSequencerPosition\">getSequencerPosition()<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#setSequencerPosition\">setSequencerPosition(microseconds)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#getNiceTime\">getNiceTime(microseconds)<\/a><br \/>\n&#8211;\u00a0<a href=\"#getObject\">getObject(id)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#MidiMessage\">MidiMessage(jsonString)<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#statics\">List of static members<\/a><\/p>\n<p><a name=\"init\"><\/a> <code>init()<\/code><\/p>\n<p>The init method of the midibridge adds an extra div to the body of your html page, and in this div the Java applet gets loaded. After the applet has loaded, it detects all currently connected midi in- and outputs. Then it automatically connects all midi inputs to the midibridge. Also, the first found midi output gets connected to all midi inputs and to the midibridge.<\/p>\n<p>This way you can start playing your midi keyboard directly after the midibridge is initialized. When you play, the callback method that you have passed as an argument to the init function will be called. In the example above, the incoming midi events are only printed to the console, but i&#8217;m sure you can come up with something more funky.<\/p>\n<p>You can also call the init method with a configuration object as argument, this object may contain one or all of the following keys:<\/p>\n<ul>\n<li><code>ready<\/code> : [function] callback function that gets called as soon as the midibridge is ready\/initialized<\/li>\n<li><code>error<\/code> : [function] callback function that gets called in case of an error, for instance the user does not have a Java plugin or an outdated version or the user is using a not-supported browser<\/li>\n<li><code>data<\/code> : [function] callback that gets called when midi data has arrived<\/li>\n<li><code>javaDir<\/code> : [string] the folder where you store the midiapplet.jar on your webserver, defaults to &#8220;java&#8221;<\/li>\n<li><code>connectFirstInput<\/code> : [true,false] the first found midi input device gets connected automatically, defaults to false<\/li>\n<li><code>connectAllInputs<\/code> : [true,false] all found midi input devices get connected automatically, defaults to false<\/li>\n<li><code>connectFirstOutput<\/code> : [true,false] the first found midi output device gets connected automatically, defaults to false<\/li>\n<li><code>connectAllInputsToFirstOutput<\/code> : [true,false] all found midi input devices will be automatically connected to the first found midi output device, defaults to true<\/li>\n<li><code>debug<\/code> : [true,false] when set to true, some debug information is printed to the console, eg: the filtered MIDI messages, see next bullet<\/li>\n<li><code>midiCommands<\/code> : [array] an array with the types of MIDI messages that the midibridge is passing to the data handler, defaults to: <code>[midiBridge.NOTE_OFF,<br \/>\n midiBridge.NOTE_ON,<br \/>\n midiBridge.CONTROL_CHANGE,<br \/>\n midiBridge.PITCH_BEND,<br \/>\n midiBridge.PROGRAM_CHANGE]<\/code> this setting overrules the filter setting on MIDI connections, see <a href=\"#addConnection\">addConnection()<\/a>.<\/li>\n<\/ul>\n<p><!--\nOnly one of the 3 keys <code>connectAllInputsToFirstOutput<\/code>, <code>connectAllInputs<\/code> and <code>connectFirstOutput<\/code> can be true; if you set one of them to true, the other two will be set to false automatically.\n--> In the example below all midi inputs get connected to the midibridge, but they will not be connected to the first midi output, i.e. you won&#8217;t hear a sound when you play your keyboard(s).<\/p>\n<p>Also, all messages from the midibridge are printed to a div in the html page.<\/p>\n<pre><code>window.addEventListener('load', function() {\n\n    var contentDiv = document.getElementById('content');\n    contentDiv.innerHTML += 'midibridge says:&lt;br\/&gt;';\n\n    midiBridge.init({\n        connectAllInputs: true,\n\n        ready: function(msg){\n            contentDiv.innerHTML += msg + '&lt;br\/&gt;';\n        },\n        error: function(msg) {\n            contentDiv.innerHTML += msg + '&lt;br\/&gt;';\n        },\n        data: function(midiEvent) {\n            contentDiv.innerHTML += midiEvent + '&lt;br\/&gt;';\n        }\n    });\n\n\n}, false);\n<\/code><\/pre>\n<p>You can check this example <a href=\"..\/midibridge\/examples\/configobject.html\" target=\"blank\">here<\/a>.<\/p>\n<p><a name=\"sendMidiEvent\"><\/a> <code>sendMidiEvent(status, channel, data1, data2)<\/code><\/p>\n<p>With this method you can send midi events to the applet. You can use this method for instance to make a vitual keyboard. Here is a code snippet to help you started:<\/p>\n<pre><code>window.addEventListener('load', function() {\n\n    midiBridge.init(function(midiEvent) {\n        console.log(midiEvent);\n    });\n\n    var contentDiv = document.getElementById(\"content\");\n    contentDiv.innerHTML += \"&lt;div id='playAnote'&gt;play a note&lt;\/div&gt;\";\n    var playNote = document.getElementById(\"playAnote\");\n    playNote.style.textDecoration = \"underline\";\n\n    playNote.addEventListener(\"click\",function(){\n        midiBridge.sendMidiEvent(midiBridge.NOTE_ON,1,80,100);\n    }, false);\n};\n<\/code><\/pre>\n<p>Now if you click on &#8220;play a note&#8221;, you should hear a note.<\/p>\n<p>You can check this example <a href=\"..\/midibridge\/examples\/playnote.html\" target=\"blank\">here<\/a>.<\/p>\n<p><a name=\"getDevices\"><\/a> <code>getDevices()<\/code><\/p>\n<p>This method returns a JSON object that contains all midi devices that were detected on your computer when the midibridge was initialized.<\/p>\n<pre><code>window.addEventListener('load', function() {\n\n    var contentDiv = document.getElementById('content');\n\n    midiBridge.init({\n        connectAllInputsToFirstOutput: false,\n\n        ready: function(msg){\n            var devices = midiBridge.getDevices();\n            for(var i = 0, max = devices.length; i &lt; max; i++) {\n\n                var device  = devices[i];\n                var id      = device.id;\n                var type    = device.type;\n                var name    = device.name;\n                var descr   = device.descr;\n                var available = device.available;\n                contentDiv.innerHTML += id + ' : ' + type+ ' : ' + name+ ' : ' + descr+ ' : ' + available + '&lt;br\/&gt;';\n            }\n        },\n    });\n\n}, false);\n<\/code><\/pre>\n<p>The parameter <code>available<\/code> shows whether the device is currently in use or not. For instance if your midi keyboard was connected to a softsynth at the time you started the midibridge, that midi keyboard will be listed but the parameter available will be set to false.<\/p>\n<p>You can check this example <a href=\"..\/midibridge\/examples\/getdevices.html\" target=\"blank\">here<\/a>.<\/p>\n<p><a name=\"refreshDevices\"><\/a> <code>refreshDevices()<\/code><\/p>\n<p>You can use this method if your midi configuration has changed after you have started the midibridge. For instance if you connect a new midi device to your computer.<\/p>\n<p>If you call this method, all current connections between your midi devices between your midi inputs and the midibridge will be disconnected.<\/p>\n<p><a name=\"connectAllInputs\"><\/a> <code>connectAllInputs()<\/code><\/p>\n<p>By calling this method, all detected midi inputs will be connected to the midibridge. You can also achieve this if you call the <code>init()<\/code> method with a configuration object, and then set the key <code>connectAllInputs<\/code> to true.<\/p>\n<p><a name=\"connectFirstInput\"><\/a> <code>connectFirstInput()<\/code><\/p>\n<p>By calling this method, the first detected midi input will be connected to the midibridge. You can also achieve this if you call the init() method with a configuration object, and then set the key <code>connectFirstInput<\/code> to true.<\/p>\n<p>This method does not connect a midi output, so you can use this configuration for instance if your application only has a visual representation of the midi events.<\/p>\n<p>NOTE: Sometimes the first midi input is not the device that you actually want to connect. In this case use <code>getDevices()<\/code> to check what id has been assigned to the midi input that you want to connect to the midibridge, and establish the connection with <code>addConnection(midiInputId,midiOutputId)<\/code>. This also applies to <code>connectFirstOutput<\/code>.<\/p>\n<p><a name=\"connectFirstOutput\"><\/a> <code>connectFirstOutput()<\/code><\/p>\n<p>By calling this method, the first detected midi output will be connected to the midibridge. You can also achieve this if you call the init() method with a configuration object, and then set the key <code>connectFirstOutput<\/code> to true.<\/p>\n<p>This method does not connect a midi input, so you can use this configuration for instance if your application has a virtual keyboard, or if you attach the regular keyboard to the midibridge.<\/p>\n<pre><code>window.addEventListener('load', function() {\n\n    midiBridge.init({\n        connectFirstOutput : true\n        ready : function(msg) {\n            connectKeyboard();\n        },\n        error : function(msg) {\n            console.log(msg);\n        }\n    });\n\n    var noteNumbers = {\n        \/\/white keys\n        65 : 48,     \/\/key a -&gt; note c\n        83 : 50,     \/\/key s -&gt; note d\n        68 : 52,     \/\/key d -&gt; note e\n        70 : 53,     \/\/key f -&gt; note f\n        71 : 55,     \/\/key g -&gt; note g\n        72 : 57,     \/\/key h -&gt; note a\n        74 : 59,     \/\/key j -&gt; note b\n        75 : 60,     \/\/key k -&gt; note c\n        76 : 62,     \/\/key l -&gt; note d\n        186 : 64,    \/\/key ; -&gt; note e\n        222 : 65,    \/\/key : -&gt; note f\n        \/\/black keys\n        87 : 49,     \/\/key w -&gt; note c#\/d\u266d\n        69 : 51,     \/\/key e -&gt; note d#\/e\u266d\n        84 : 54,     \/\/key t -&gt; note f#\/g\u266d\n        89 : 56,     \/\/key y -&gt; note g#\/a\u266d\n        85 : 58,     \/\/key u -&gt; note a#\/b\u266d\n        79 : 61,     \/\/key o -&gt; note c#\/d\u266d\n        80 : 63      \/\/key p -&gt; note d#\/e\u266d\n    }\n\n    var keysPressed = {};\n\n    var connectKeyboard = function(){\n\n        document.addEventListener('keydown', function(e) {\n            if(e.which === 32) {\n                midiBridge.sendMidiEvent(midiBridge.CONTROL_CHANGE, 1, 64, 127);\n            } else if(noteNumbers[e.which] &amp;amp;&amp;amp; !keysPressed[e.which]) {\n                midiBridge.sendMidiEvent(midiBridge.NOTE_ON, 1, noteNumbers[e.which], 100);\n                keysPressed[e.which] = true;\n            }\n        }, false);\n\n\n        document.addEventListener('keyup', function(e) {\n            if(e.which === 32) {\n                midiBridge.sendMidiEvent(midiBridge.CONTROL_CHANGE, 1, 64, 0);\n            } else if(noteNumbers[e.which]) {\n                midiBridge.sendMidiEvent(midiBridge.NOTE_OFF, 1, noteNumbers[e.which], 0);\n                keysPressed[e.which] = false;\n            }\n        }, false);\n    };\n\n\n}, false);\n<\/code><\/pre>\n<p>The spacebar is used for the sustainpedal. Pressing a sustainpedal is a control change event. The controller number of the sustainpedal is 64 and 127 means pedal down, 0 means pedal up.<\/p>\n<p>You can check this example <a href=\"..\/midibridge\/examples\/regularkeyboard.html\" target=\"blank\">here<\/a>.<\/p>\n<p><a name=\"connectAllInputsToFirstOutput\"><\/a> <code>connectAllInputsToFirstOutput()<\/code><\/p>\n<p>By calling this method, all detected midi inputs will be connected to the midibridge, and all inputs will also be connected to the first detected midi output.<\/p>\n<p>This is the default configuration of the midibridge, so you can also achieve this if you call the <code>init()<\/code> method with no arguments, or with a callback function as argument.<\/p>\n<p>It is interesting to know that the applet duplicates all midi events that arrive from your midi inputs (e.g. your midi keyboard). One event travels on to the midibridge and thus is available in Javascript. The other event travels to a midi out device if a midi output is connected to that midi input.<\/p>\n<p><a name=\"addConnection\"><\/a><\/p>\n<p><code>addConnection(input,output,filter)<\/code> You can set up a connection between any midi input and midi output device by passing the ids of the devices as arguments to this method. You can lookup the id of an device in the JSON object that is returned when you call <code>getDevices()<\/code> or <code>refreshDevices()<\/code>.<\/p>\n<p>The id of the midi input and the midi output can also be set to <code>-1<\/code>. If you for instance only want to capture midi events in your application without connecting to an output device, you can set the id of the midi output to <code>-1<\/code>. If you set both the midi input and the midi outport to <code>-1<\/code>, nothing will happen.<\/p>\n<p>The <code>filter<\/code> argument is an optional argument that you can use to pass an array with midi message types (status codes) that you are not interested in. If a midi message of one of the specified types is generated by an external midi input, the message will not be passed on to the midibridge. You can specify the midi message types with a decimal number (224), a hexadecimal number (0xF0) or with a human readable midibridge constant (midiBridge.PITCH_BEND). In the example below pitch bend midi messages will be filtered.<\/p>\n<p>The code below shows you how you could implement functionality that allows the users to set up midi connections:<\/p>\n<pre><code>window.addEventListener('load', function() {\n\n    var contentDiv = document.getElementById('content');\n    var currentMidiInputId = -1;\n    var currentMidiOutputId = -1;\n\n    \/\/create a dropdown box for the midi inputs\n    var midiInputs = document.createElement('select');\n    midiInputs.setAttribute('id', 'midi-in');\n    contentDiv.appendChild(midiInputs);\n    midiInputs.addEventListener('change', function(e) {\n        var device = midiInputs.options[midiInputs.selectedIndex];\n        currentMidiInputId = device.id;\n        var result = midiBridge.addConnection(currentMidiInputId, currentMidiOutputId, [midiBridge.PITCH_BEND]);\n        parseResult(result);\n    }, false);\n\n    \/\/create a dropdown box for the midi outputs\n    var midiOutputs = document.createElement('select');\n    midiOutputs.setAttribute('id', 'midi-out');\n    contentDiv.appendChild(midiOutputs);\n    midiOutputs.addEventListener('change', function(e) {\n        var device = midiOutputs.options[midiOutputs.selectedIndex];\n        currentMidiOutputId = device.id;\n        var result = midiBridge.addConnection(currentMidiInputId, currentMidiOutputId, [midiBridge.PITCH_BEND]);\n        parseResult(result);\n    }, false);\n\n    var devices;\n\n    midiBridge.init({\n        connectAllInputsToFirstOutput : false,\n\n        ready : function(msg) {\n            devices = midiBridge.getDevices();\n            populateDropDownMenus()\n        },\n\n        error : function(msg) {\n            contentDiv.innerHTML += msg + '&lt;br\/&gt;';\n        },\n\n        data : function(midiEvent) {\n            contentDiv.innerHTML += midiEvent + '&lt;br\/&gt;';\n        }\n\n    });\n\n    var populateDropDownMenus = function() {\n\n        midiInputs.appendChild(createOption('-1', 'choose a midi input'));\n        midiOutputs.appendChild(createOption('-1', 'choose a midi output'));\n\n        for(var deviceId in devices) {\n            var device = devices[deviceId];\n            if(device.type === 'input' &amp;amp;&amp;amp; device.available === 'true') {\n                midiInputs.appendChild(createOption(device.id, device.name))\n            } else if(device.type === 'output' &amp;amp;&amp;amp; device.available === 'true') {\n                midiOutputs.appendChild(createOption(device.id, device.name))\n            }\n        }\n    }\n\n    var createOption = function(id, label) {\n        var option = document.createElement('option');\n        option.setAttribute('id', id);\n        option.innerHTML = label;\n        return option;\n    }\n\n    var parseResult = function(data){\n        contentDiv.innerHTML += data.msg + ' : ' + currentMidiInputId + ' : ' + currentMidiOutputId + '&lt;\/br&gt;';\n    }\n\n\n}, false);\n<\/code><\/pre>\n<p>You can check this example <a href=\"..\/midibridge\/examples\/patchpanel.html\" target=\"blank\">here<\/a>.<\/p>\n<p><a name=\"removeConnection\"><\/a> <code>removeConnection(input,output)<\/code><\/p>\n<p>You can remove a connection between a midi input and a midi output by passing their respective ids as arguments to this method.<\/p>\n<p><a name=\"disconnectAll\"><\/a> <code>disconnectAll()<\/code><\/p>\n<p>This method does exactly what you would expect: it disconnects all current connections between midi in- and output and between your midi inputs and the midibridge<\/p>\n<p><a name=\"getNoteName\"><\/a> <code>getNoteName(midiNoteNumber,mode)<\/code><\/p>\n<p>Returns the name of the note based on the midi notenumber. Midi notenumbers are part of the midi standard and range between 0 and 127. The central C (261.626 Hz in 440 pitch) has notenumber 60.<\/p>\n<p>The parameter <code>mode<\/code> can be one of the following values:<\/p>\n<ul>\n<li><code>midiBridge.NOTE_NAMES_SHARP<\/code> : the black keys will be named sharps, so notenumber 61 will be called C#<\/li>\n<li><code>midiBridge.NOTE_NAMES_FLAT<\/code> : the black keys will be named flats, so notenumber 61 will be called D\u266d<\/li>\n<li><code>midiBridge.NOTE_NAMES_ENHARMONIC_SHARP<\/code> : all keys will be named sharps, so notenumber 60 will be called B#, notenumber 62 will be called C## (double sharp)<\/li>\n<li><code>midiBridge.NOTE_NAMES_ENHARMONIC_FLAT<\/code> : all keys will be named flats, notenumber 64 will be called F\u266d, notenumber 62 will be called E\u266d\u266d (double flat)<\/li>\n<\/ul>\n<p><a name=\"getNoteNumber\"><\/a> <code>getNoteNumber(midiName,octave)<\/code><\/p>\n<p>Returns the midi notenumber based on the name of the note and the octave. Octave -1 is the lowest possible octave number, octave 9 the highest possible. A regular 88 key keyboard ranges between A-1 and C7.<\/p>\n<p><a name=\"getStatus\"><\/a> <code>getStatus(statusCode)<\/code><\/p>\n<p>Returns a string representation of the status byte of the midi message. For instance <code>midiBridge.getStatus(midiBridge.NOTE_ON)<\/code> returns &#8220;NOTE ON&#8221;.<\/p>\n<p><a name=\"loadBase64String\"><\/a> <code>loadBase64String(base64String)<\/code><\/p>\n<p>Loads a base64 encoded MIDI file in the sequencer and return an object containing data about the loaded MIDI file.<\/p>\n<ul>\n<li><code>microseconds<\/code>: duration of the MIDI file in microseconds<\/li>\n<li><code>ticklength<\/code>: duration of the MIDI file in ticks<\/li>\n<li><code>ticks<\/code>: number of ticks in the MIDI file<\/li>\n<\/ul>\n<p>There are several ways of getting a MIDI file as base64 string into your application.<\/p>\n<p>1) By using html5 drag and drop functionality with the File API, <a href='http:\/\/abumarkub.net\/midibridge\/examples\/base64.html' title='abumarkub midibridge base64 example' target='blank'>see this example<\/a>.<\/p>\n<p>2) By using the File API, <a href='http:\/\/abumarkub.net\/midibridge\/examples\/playmidifile.html' title='abumarkub midibridge play MIDI file example' target='blank'>see this example<\/a>.<\/p>\n<p>3) Store the MIDI file as a base64 string in a Javascript variable, <a href='http:\/\/abumarkub.net\/midibridge\/examples\/playmidifile.html' title='abumarkub midibridge play MIDI file example' target='blank'>see also this example<\/a>. The Javascript file <a href='http:\/\/abumarkub.net\/midibridge\/examples\/lib\/chopin_opus18.mid.js' target='blank' title='abumarkub midibridge chopin midi file base64'>chopin_opus18.mid.js<\/a> contains a global variable chopin_opus18 that contains the MIDI file as base64 string.<\/p>\n<p>4) Since global variables are bad code practise, loading base64 MIDI files from a webserver is preferred over option 3. Encoding MIDI files on the server can be done with a single line of php code:<\/p>\n<pre><code>&lt;?php\n\n$tmpFile = \"tmp.mid\";\n\n\/\/store the uploaded MIDI file in a temporarily file file_put_contents(tmpFile, file_get_contents(\"php:\/\/input\",r));\n\n\/\/read the temp file, base64 encode it and echo it back echo base64_encode(file_get_contents($tmpFile));\n\n?&gt;\n<\/code><\/pre>\n<p><a name=\"playBase64String\"><\/a> <code>playBase64String(base64String)<\/code><\/p>\n<p>Same as <code>loadBase64String(base64String)<\/code> but the file starts playing immediately.<\/p>\n<p><a name=\"startSequencer\"><\/a> <code>startSequencer()<\/code><\/p>\n<p>If a MIDI file is loaded the sequencer starts playing the file at the current position.<\/p>\n<p><a name=\"pauseSequencer\"><\/a> <code>pauseSequencer()<\/code><\/p>\n<p>Pauses the sequencer. Note: pause does not toggle, so you have to call <code>startSequencer()<\/code> to unpause the sequencer.<\/p>\n<p><a name=\"stopSequencer\"><\/a> <code>stopSequencer()<\/code><\/p>\n<p>Stops the sequencer and rewinds sets the position of the file back to the start.<\/p>\n<p><a name=\"closeSequencer\"><\/a> <code>closeSequencer()<\/code><\/p>\n<p>Stops the sequencers and then closes it. You have to call <code>loadBase64String(base64String)<\/code> or <code>playBase64String(base64String)<\/code> to open a sequencer again.<\/p>\n<p><a name=\"getSequencerPosition\"><\/a> <code>getSequencerPosition()<\/code><\/p>\n<p>Gets the position of the MIDI file in the sequencer in microseconds.<\/p>\n<p><a name=\"setSequencerPosition\"><\/a> <code>setSequencerPosition(microseconds)<\/code><\/p>\n<p>Sets the position of the MIDI file in the sequencer in microseconds.<\/p>\n<p><a name=\"getNiceTime\"><\/a> <code>getNiceTime(microseconds)<\/code><\/p>\n<p>Converts microseconds to the time format m:ss:SSS.<\/p>\n<p>Typically used to display the sequencer position of the MIDI file.<\/p>\n<p><a name=\"getObject\"><\/a> <code>getObject(id)<\/code><\/p>\n<p>Returns a reference to the object in the html page whose id is specified. It is used for getting a reference to the applet, but you can also use it for getting a reference to any other type of object. For instance for getting the swf object if your application is built with Flash, see <a href=\"#flash\">What about Flash?<\/a><\/p>\n<p><a name=\"MidiMessage\"><\/a> <code>MidiMessage(jsonString)<\/code><\/p>\n<p>An internal class of the midibrigde that is used for storage and easy handling of the midi events that arrive from the applet. The applet sends midi events as JSON strings to the midibridge. The midibridge uses the native <code>JSON.parse()<\/code> method to parse this string into a JSON object.<\/p>\n<p>The MidiMessage class has 2 useful methods that you might need in your code <code>toString()<\/code> and <code>toJSONString()<\/code>. The first method is handy for printing the midi incoming events to a log, and the latter can be used if you want to send the midi event to Flash or another technology. See the offical <a href=\"http:\/\/www.json.org\/index.html\" target=\"blank\" title=\"abumarkub midibridge js JSON\" rel=\"abumarkub midibridge js JSON\">JSON website<\/a> for more information. Flash programmers might be interested in the <a href=\"https:\/\/github.com\/mikechambers\/as3corelib\" target=\"blank\" title=\"abumarkub midibridge js JSON\" rel=\"abumarkub midibridge js JSON\">JSON library of Mike Chambers<\/a>.<\/p>\n<p><a name=\"statics\"><\/a> <strong>Static members<\/strong> Besides methods, there are also a bunch of very handy static members that you can use:<\/p>\n<ul>\n<li><code>midiBridge.version<\/code> : version of the midibridge as string<\/li>\n<li><code>midiBridge.ready<\/code> : set to true if the midiBridge has been initialized successfully, otherwise set to false<\/li>\n<li><code>midiBridge.NOTE_NAMES_SHARP<\/code> : &#8220;sharp&#8221; see <a href=\"#getNoteNumber\">getNoteNumber()<\/a><\/li>\n<li><code>midiBridge.NOTE_NAMES_FLAT<\/code> : &#8220;flat&#8221; see <a href=\"#getNoteNumber\">getNoteNumber()<\/a><\/li>\n<li><code>midiBridge.NOTE_NAMES_ENHARMONIC_SHARP<\/code> : &#8220;enh-sharp&#8221; see <a href=\"#getNoteNumber\">getNoteNumber(<\/a>)<\/li>\n<li><code>midiBridge.NOTE_NAMES_ENHARMONIC_FLAT<\/code> : &#8220;enh-flat&#8221; see <a href=\"#getNoteNumber\">getNoteNumber()<\/a><\/li>\n<li><code>midiBridge.NOTE_OFF<\/code> : 0x80 (128)<\/li>\n<li><code>midiBridge.NOTE_ON<\/code> : 0x90 (144)<\/li>\n<li><code>midiBridge.POLY_PRESSURE<\/code> : 0xA0 (160)<\/li>\n<li><code>midiBridge.CONTROL_CHANGE<\/code> : 0xB0 (176)<\/li>\n<li><code>midiBridge.PROGRAM_CHANGE<\/code> : 0xC0 (192)<\/li>\n<li><code>midiBridge.CHANNEL_PRESSURE<\/code> : 0xD0 (208)<\/li>\n<li><code>midiBridge.PITCH_BEND<\/code> : 0xE0 (224)<\/li>\n<li><code>midiBridge.SYSTEM_EXCLUSIVE<\/code> : 0xF0 (240)<\/li>\n<\/ul>\n<p><a name=\"midi-out\"> <\/a><strong>About midi out<\/strong><\/p>\n<p>If you&#8217;re on Windows or Linux, the latency of the Java Sound Synthesizer makes it almost impossible to play. On Windows you can also choose the Microsoft GS Wavetable Synth and with some soundcards you may get a decent latency (i was told the Realtek AC97 perfoms pretty well).<\/p>\n<p>On a Mac you can just select a default midi synthesizer (Java Sound Synthesizer) and start playing with no noticeable latency.<\/p>\n<p>Latency is caused by both the drivers of your soundcard and the way your synthesizer works. Most modern softsynths hardly cause any latency, but even with the latest M-Audio pro cards you&#8217;ll experience latency when using the Java Sound Synthesizer or the Microsoft GS Wavetable Synth.<\/p>\n<p>So we need to be able to connect to some real softsynths like <a href=\"http:\/\/www.pianoteq.com\/\" target=\"_blank\" rel=\"abumarkub midibridge java applet command line flash actionscript\" title=\"abumarkub midibridge Pianoteq\">Pianoteq<\/a> or <a href=\"http:\/\/www.applied-acoustics.com\/products\/\" target=\"_blank\" rel=\"abumarkub midibridge java applet command line flash actionscript\" title=\"abumarkub midibridge Lounge Lizard\">Lounge Lizard<\/a> and for this we need a virtual midi driver.<\/p>\n<p>If you&#8217;re on a Mac, you&#8217;re lucky because such a thing is already installed on your machine. It is called IAC Driver and you&#8217;ll find it if you open the Audio MIDI Setup in your Applications folder.<\/p>\n<p>If you are on Windows you can download LoopBe1 from <a href=\"http:\/\/www.nerds.de\" target=\"_blank\">nerds.de<\/a> and Linux users can check <a href=\"http:\/\/alsa.opensrc.org\/index.php\/VirMidi\" target=\"_blank\">VirMidi<\/a><\/p>\n<p>Below i&#8217;ll give a brief explanation for every driver.<\/p>\n<p>&#8211;\u00a0<a href=\"#loopbe\">LoopBe<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#iac\">IAC<\/a> \u00a0\u00a0<br \/>\n&#8211;\u00a0<a href=\"#virmidi\">VirMidi<\/a><\/p>\n<p><a name=\"loopbe\"> <\/a><strong>LoopBe1<\/strong><\/p>\n<p>Download it from <a href=\"http:\/\/nerds.de\/en\/download.html\" target=\"_blank\" rel=\"abumarkub midibridge java applet command line flash actionscript\" title=\"abumarkub midibridge LoopBe\">nerds.de<\/a> and run the installer. After the installation has finished LoopBe is up and running and will automatically start with Windows (if you don&#8217;t want this, run msconfig and remove the LoopBe startup service).<\/p>\n<p>Now LoopBe Internal MIDI will be listed as both a midi input as well as a midi output when you call <code>getDevices()<\/code>. You can setup a connection betweein your favorite keyboard as input device and LoopBe Internal MIDI as output with <code>addConnection()<\/code>.<\/p>\n<p>Now open your favorite softsynth and go to the midi settings and set your synth&#8217;s midi input to LoopBe Internal MIDI. Here is a screendump of what this looks like in Pianteq:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.abumarkub.net\/abublog\/wp-content\/uploads\/2010\/02\/Pianoteq-LoopBe-Abumarkub-midibridge.jpg\" alt=\"Pianoteq LoopBe Abumarkub midibridge\" title=\"Pianoteq LoopBe Abumarkub midibridge\" width=\"597\" height=\"680\" class=\"alignnone size-full wp-image-193\" \/><\/p>\n<p>You should now be able to play your softsynth while midi data is passing thru the midibridge, and dependent on your soundcard&#8217;s driver, with very low latency.<\/p>\n<p>Please notice that LoopBe1 is only free for non-commercial use. For commercial use you need to acquire a license after a 30-day evolution period. But for only \u20ac 11,90 inc VAT it&#8217;s really a bargain. If you are willing to spend an extra 5 euro on top, i would recommend to buy LoopBe1 bigger brother LoopBe30, which gives you up to 30 virtual midi ports! Check <a href=\"http:\/\/nerds.de\/en\/order.html\" target=\"_blank\">here<\/a>.<\/p>\n<p><a name=\"iac\"><\/a> <strong>IAC<\/strong><\/p>\n<p>Open your Finder, go to menu Go -> Applications and scroll down till you&#8217;ve found a folder named Utilities. Open the folder Utilities and double click on Audio MIDI Setup. If you only see a window with Audio Devices, go to Window -> Show MIDI Window.<\/p>\n<p>In the window that subsequently opens, you should see an icon named IAC Driver. IAC stands for Inter-Application Communication, and that is exactly what it does.<\/p>\n<p>If the icon is greyed out double click it and check the box \u201cDevice is online\u201d in the popup that appears. Now you should have a window like:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.abumarkub.net\/abublog\/wp-content\/uploads\/2010\/02\/Picture-4.png\" alt=\"IAC-Driver-Abumarkub-midibridge\" title=\"IAC-Driver-Abumarkub-midibridge\" width=\"504\" height=\"534\" class=\"alignnone size-full wp-image-194\" \/><\/p>\n<p>Don&#8217;t worry if looks a little different on your machine. You should see at least 1 port in the \u201cPorts\u201d part of the screen. If not, simply click the plus sign to add a port. I recommend to add a least 2 ports to the IAC Driver.<\/p>\n<p>Close this popup and the Audio MIDI Setup. Now &#8220;IAC Driver IAC Bus 1&#8221; (or something alike) will be listed as midi input when you call <code>getDevices()<\/code>.<\/p>\n<p>Set up a connection between your favorite keyboard as input device and &#8220;IAC Driver IAC Bus 1&#8221; as output with <code>addConnection()<\/code>. Open your favorite softsynth and go to the midi settings and set your synth&#8217;s midi input to &#8220;IAC Driver IAC Bus 1&#8221;. Here is a screendump of what this looks like in Lounge Lizard:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.abumarkub.net\/abublog\/wp-content\/uploads\/2010\/02\/Picture-7.png\" alt=\"Lounge Lizard IAC input Abumarkub midibridge\" title=\"Lounge Lizard IAC input Abumarkub midibridge\" width=\"866\" height=\"482\" class=\"alignnone size-full wp-image-195\" \/><\/p>\n<p>Now you can play your softsynth while midi data is passing thru the midibridge.<\/p>\n<p><a name=\"virmidi\"><\/a> <strong>VirMidi<\/strong><\/p>\n<p>If you are using Ubuntu or Kubuntu, there is a thread about VirMidi on the <a href=\"http:\/\/ubuntuforums.org\/showthread.php?p=6616182\" target=\"blank\">Ubuntu forum<\/a><\/p>\n<p>Because snd-virmidi is a kernel module, you can simply load this module by typing <code>sudo modprobe snd-virmidi<\/code> on the command line.<\/p>\n<p>Now if you call <code>getDevices()<\/code>, you should see at least 4 additional devices listed.<\/p>\n<p>Set up a connection between your keyboard as input device and one of the virtual midi ports as output with <code>addConnection()<\/code>. Connect this output to the input of your favorite softsynth, for instance in Pianoteq this would look like:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/www.abumarkub.net\/abublog\/wp-content\/uploads\/2010\/11\/VirMidi-Kubuntu-Pianoteq-midibridge-abumarkub.jpg\" alt=\"VirMidi Kubuntu Pianoteq midibridge abumarkub\" title=\"VirMidi Kubuntu Pianoteq midibridge abumarkub\" width=\"599\" height=\"677\" class=\"alignnone size-full wp-image-429\" \/><\/p>\n<p>Now you can play your softsynth while midi data is passing thru the midibridge.<\/p>\n<p>Pianoteq is available for both 32 and 64 bits Linux, so if you want to try it yourself you can download a demo version <a href=\"http:\/\/pianoteq.com\/try\" target=\"_blank\">over here<\/a>.<\/p>\n<p><a name=\"earlier-versions\"> <\/a><strong>Earlier versions<\/strong><\/p>\n<p>I started this project in the summer of 2008. Since then i have released 5 versions:<\/p>\n<ul>\n<li><a href=\"http:\/\/abumarkub.net\/midibridge\/v1\/fp10\/\" target=\"blank\">proof of concept<\/a> : With dynamical sound generation, a chord finder, a color organ, midi learn functionality, a virtual keyboard and an adjustable pitch bend controller that acts upon the generated sound<\/li>\n<li><a href=\"http:\/\/abumarkub.net\/midibridge\/v2\/fp10\/\" target=\"blank\">version 2<\/a> : With all features of the proof of concept, but with an extra swf that sits between the applet and the application swf. This extra swf connects on one site via ExternalInternface to the applet, and on the other side via LocalConnection to the application swf.<\/li>\n<li><a href=\"http:\/\/abumarkub.net\/midibridge\/v3\/\" target=\"blank\">version 3<\/a> : The in-between swf removed again, dynamical sound generation replaced by midi out. A very simple GUI: virtual keyboard, chord finder and pich bend controller removed, simple animation added in.<\/li>\n<li><a href=\"http:\/\/abumarkub.net\/midibridge\/v4\/\" target=\"blank\">version 4<\/a> : FluidSynth softsynth added that allows you to use Soundfont files at choice. Also the midibridge is able to generate midi events itself. Virtual keyboard added again<\/li>\n<li><a href=\"http:\/\/abumarkub.net\/abublog\/?p=381\" target=\"blank\">version 5<\/a> : Same as version 4 but you can also export the code to a standalone AIR version.<\/li>\n<\/ul>\n<p>In my blogposts you can still find information about the earlier versions. This might be confusing and therefor i have started this page where you can find only up to date information about the latest, and thus featured release. Some of this information can also be found in various posts, but if it appears here as well it is still valid for the current release.<\/p>\n<p>With this version, the development of all earlier versions of the midibridge will be frozen. The reason for this is that with this new version i have redefined what the midibridge exactly is.<\/p>\n<p>In former version of the midibridge i have added too much GUI functionality. As explained in the <a href=\"#introduction\">introduction<\/a>, the new midibridge provides only a compact set of methods that allows you to interact transparently with the midi devices on your computer, but leaves the GUI totally up to you.<\/p>\n<p>So therefor the new version has no control panel, virtual keyboard, midi learn functionality and so on. I have provided code examples for the basic features of the midibridge and i will add some more examples for more advanced features like sound generation soon. Also i might develop some configurable UI plugins for the midibridge (alike jQuery UI) somewhere in the future.<\/p>\n<p>Another reason for stripping down the midibridge to its core is that former versions were too much tied to Flash and Actionscript. In modern browsers Flash is no longer the only reasonable choice for creating compelling animations. This applies to dynamically generating sound as well.<\/p>\n<p>What&#8217;s more, the latency of <a href=\"https:\/\/wiki.mozilla.org\/Audio_Data_API\" target=\"blank\" title=\"abumarkub midibridge mozilla audio data API\" rel=\"abumarkub midibridge mozilla audio data API\">Mozilla&#8217;s Audio Data API<\/a> allows you to set the minimal audio buffer as low as 512 samples, which results in a latency of only 512\/44100 \u2248 11.6 ms(!). In Flash the minimal buffer size is 2048 (recommended) which results in an almost un-playable latency of 2048\/44100 \u2248 46ms.<\/p>\n<p>To summarize the benefits of the new approach:<\/p>\n<ul>\n<li>the midibridge now only takes 5K of code<\/li>\n<li>it makes it much easier to add the midibridge to your code<\/li>\n<li>it gives you more control over what your website\/application looks like<\/li>\n<li>it does not impose a specific client side language on you<\/li>\n<\/ul>\n<p>The only downside is that the new version is not compatible with the earlier versions. However, you can still use it; the code is fully functional and remains available at GitHub and Google Code. You are encouraged to switch to the new version though.<\/p>\n<p>Code at GitHub (version 5):<\/p>\n<p><a href=\"http:\/\/github.com\/abudaan\/javamidi\" rel=\"abumarkub midibridge java applet command line flash\" title=\"abumarkub midibridge Java classes\" target=\"blank\">http:\/\/github.com\/abudaan\/javamidi<\/a><\/p>\n<p><a href=\"http:\/\/github.com\/abudaan\/flashmidi\" rel=\"abumarkub midibridge java applet command line flash\" title=\"abumarkub midibridge Actionscript classes\" target=\"blank\">http:\/\/github.com\/abudaan\/flashmidi<\/a><\/p>\n<p>Code at Google Code (version 5):<\/p>\n<p><a href=\"http:\/\/code.google.com\/p\/miditoflash\/downloads\/\" rel=\"abumarkub midibridge java applet command line flash\" title=\"abumarkub midibridge Actionscript and Java classes\" target=\"blank\">http:\/\/code.google.com\/p\/miditoflash\/downloads\/<\/a><\/p>\n<p>As i mentioned above, the earlier version had both a web and an AIR version. The Air version uses <a href=\"http:\/\/help.adobe.com\/en_US\/FlashPlatform\/reference\/actionscript\/3\/flash\/desktop\/NativeProcess.html\" target=\"blank\" rel=\"abumarkub midibridge actionscript java air\" title=\"Air 2.0 NativeProcess\">NativeProcess<\/a> to start a Java program on the commandline, and communicates with this program via its standard input and standard output.<\/p>\n<p>I am not yet sure what to do with the AIR version. You can use both Actionscript and Javascript in an AIR app, but i am actually looking for another way of creating a browser-less application. Any suggestions are welcome.<\/p>\n<p><a name=\"flash\"><\/a> <strong>What about Flash?<\/strong><\/p>\n<p>The midibridge is fully accessible from Actionscript 3.0 if you use the <a href=\"http:\/\/help.adobe.com\/en_US\/FlashPlatform\/reference\/actionscript\/3\/flash\/external\/ExternalInterface.html\" target=\"blank\" title=\"abumarkub midibridge javascript flash\" rel=\"abumarkub midibridge javascript flash\">ExternalInterface<\/a>.<\/p>\n<p>You probably want to load Flash before you initialize the midibridge so you can show some loading animation. In Actionscript you have to test when the page has fully loaded and then call the <code>init()<\/code> function of the midibridge.<\/p>\n<p>First a Timer is set up to check if the midibridge object is <code>null<\/code>. As soon as the midibridge object exists, Flash creates callback handlers for Javascript: these are methods that can be called directly from Javascript.<\/p>\n<p>Flash also calls the global Javascript method <code>callFromFlash()<\/code>. You can name it anything you like btw. The first parameter determines what action of the midibridge is requested:<\/p>\n<pre><code>package {\n\n    import flash.display.Sprite;\n    import flash.events.TimerEvent;\n    import flash.external.ExternalInterface;\n    import flash.utils.Timer;\n\n\n    public class Main extends Sprite {\n        private var _readyTimer:Timer = new Timer(1, 1);\n\n        public function Main() {\n            if(ExternalInterface.available) {\n                _readyTimer.addEventListener(TimerEvent.TIMER, check);\n                _readyTimer.start();\n            } else {\n                trace('ExternalInterface not avaible in this browser');\n            }\n        }\n\n        public function midibridgeReady(msg:String):void {\n            var jsonString:String = ExternalInterface.call('callFromFlash', 'getDevices');\n            trace(jsonString);\n        }\n\n        public function midibridgeError(msg:String):void {\n            trace(msg);\n        }\n\n        public function midibridgeData(msg:String):void {\n            trace(msg);\n        }\n\n        private function check(e:TimerEvent = null):void {\n            try {\n                if(ExternalInterface.call('midiBridge') !== null) {\n                    ExternalInterface.addCallback('midibridgeReady', midibridgeReady);\n                    ExternalInterface.addCallback('midibridgeError', midibridgeError);\n                    ExternalInterface.addCallback('midibridgeData', midibridgeData);\n                    ExternalInterface.call('callFromFlash', 'start');\n                    _readyTimer.stop();\n                } else {\n                    _readyTimer = new Timer(100, 1);\n                    _readyTimer.addEventListener(TimerEvent.TIMER, check);\n                    _readyTimer.start();\n                }\n            } catch(err1:SecurityError) {\n                trace(err1.message);\n            } catch(err2:Error) {\n                trace(err2.message);\n            }\n        }\n    }\n\n\n}\n<\/code><\/pre>\n<p>Now back in Javascript, the call to <code>callFromFlash()<\/code> gets processed. The first parameter was &#8220;start&#8221; so the midibridge gets initialized. As you can see, the callback handlers of the midibridge get directly connected to the Javascript callback handlers of Flash. This way data and messages are routed from the midibridge to Flash:<\/p>\n<pre><code>\/**\n * You can only call global functions from Flash, therefor we declare a single global function that is used for all\n * communication with the Flashplayer.\n *\n *\/\n\n function callFromFlash() {\n\n    \/**\n     * getObject is utility function of midiBridge, it is used to get the Applet object,\n     * but it can also be used to get the swf object\n     *\n     * flashapp is the id of the swf object in the html page.\n     *\/\n    var flashObject = midiBridge.getObject('flashapp');\n\n    \/**\n     * convert the arguments to a array, the first argument is the msgId.\n     * the msgId is used to determine what the Flashplayer wants from the midibridge\n     *\/\n    var args = Array.prototype.slice.call(arguments);\n    var msgId = args[0];\n\n\n    switch(msgId) {\n\n        case 'start':\n            midiBridge.init({\n                connectAllInputsToFirstOutput : true,\n\n                ready : function(msg) {\n                    flashObject.midibridgeReady(msg);\n                    return msg;\n                },\n\n                error : function(msg) {\n                    flashObject.midibridgeError(msg);\n                },\n\n                data : function(midiEvent) {\n                    flashObject.midibridgeData(midiEvent.toString());\n                }\n\n            });\n            break;\n\n        case 'getDevices':\n            return midiBridge.getDevices();\n            break;\n    }\n\n\n};\n<\/code><\/pre>\n<p>You can check this example <a href=\"..\/midibridge\/examples\/flash.html\" target=\"blank\">here<\/a>.<\/p>\n<p><a name=\"known-issues\"><\/a> <strong>Known issues<\/strong><\/p>\n<p>Currently the midibridge does not work with the Icedtea Java plugin on Linux.<\/p>\n<p><a name=\"roadmap\"><\/a> <strong>Forthcoming features<\/strong><\/p>\n<p>In a future release i will add more functionality to the sequencer. The following methods will be implemented.<\/p>\n<p>getSequencerTickPosition(); setSequencerTickPosition(ticks); recordMidi(file); setTempo(tempo);<\/p>\n<p>For more feature requests or other suggestions, please drop me a line!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ Deprecated: Chrome 43 supports MIDI natively, see this post ] 1) Introduction 2) Quick start guide 3) Documentation 4) About midi out 5) Earlier versions 6) What about Flash? 7) Known issues 8) Forthcoming features Introduction The midibridge is a Javascript API for interacting with the midi devices on your computer. It provides methods [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-399","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=\/wp\/v2\/pages\/399","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=399"}],"version-history":[{"count":101,"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=\/wp\/v2\/pages\/399\/revisions"}],"predecessor-version":[{"id":1025,"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=\/wp\/v2\/pages\/399\/revisions\/1025"}],"wp:attachment":[{"href":"https:\/\/abumarkub.net\/abublog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=399"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}