Skip to content

Instantly share code, notes, and snippets.

@marcoscaceres
Created December 12, 2012 23:57
Show Gist options
  • Save marcoscaceres/4272845 to your computer and use it in GitHub Desktop.
Save marcoscaceres/4272845 to your computer and use it in GitHub Desktop.
Rewrite of Chris' implementation of Web MIDI API.
(function(exports, global, perf) {
'use strict';
var jazzInstances = [];
if ('getMIDIAccess' in exports) {
return; // namespace is taken already, bail!
}
exports.getMIDIAccess = getMIDIAccess;
function getMIDIAccess(successCallback, errorCallback) {
if (typeof successCallback !== 'function') {
throw new TypeError('expected function');
}
new MIDIAccess(successCallback, errorCallback);
}
//creates instances of the Jazz plugin (http://jazz-soft.net/)
function JazzInstance() {
if (!this instanceof JazzInstance) {
return new JazzInstance();
}
var jazz = loadPlugin(),
timeZero = 0,
perfTimeZero = perf.now(),
interfaces = {
timeZero: {
get: function() {
return timeZero;
}
},
perfTimeZero: {
get: function() {
return perfTimeZero;
}
},
time: {
get: function() {
return jazz.Time();
}
}
};
//loads the Jazz plugin by creating an <object>
function loadPlugin(id, classid) {
var plugin,
msg = 'Failed to initialize. Maybe missing Jazz plugin? http://jazz-soft.net/',
elemId = '_Jazz' + Math.random(),
objElem = document.createElement('object'),
fallbackObj = objElem.cloneNode();
objElem.id = elemId + 'ie';
objElem.classid = 'CLSID:1ACE1618-1C7D-4561-AEE1-34842AA85E90';
fallbackObj.id = elemId;
fallbackObj.type = 'audio/x-jazz';
objElem.appendChild(fallbackObj);
document.documentElement.appendChild(objElem);
plugin = (fallbackObj.isJazz === true) ? fallbackObj : objElem;
if (!plugin instanceof window.HTMLObjectElement || !(plugin.isJazz)) {
window.console.error(msg);
return null;
}
return plugin;
}
Object.defineProperties(this, interfaces);
jazzInstances.push(jazz);
}
/**
interface MIDIPort : EventListener {
readonly attribute DOMString id;
readonly attribute DOMString? manufacturer;
readonly attribute DOMString? name;
readonly attribute MIDIPortType type;
readonly attribute DOMString? version;
attribute EventHandler onmessage;
}
*/
function MIDIPort(jazz, type) {
var dispatcher = document.createElement('x-eventDispatcher'),
id,
manufacturer = null,
version = null,
interfaces = {
id: {
get: function() {
return id;
}
},
type: {
get: function() {
return type;
}
},
version: {
get: function() {
return version;
}
},
//EventListener
addEventListener: {
value: function(type, listener, useCapture) {
dispatcher.addEventListener(type, listener, useCapture);
}
},
removeEventListener: {
value: function(type, listener, useCapture) {
dispatcher.removeEventListener(type, listener, useCapture);
}
},
dispatchEvent: {
value: function(evt) {
dispatcher.dispatchEvent(evt);
}
}
};
Object.defineProperties(this, interfaces);
}
function MIDIAccess(successCallback, errorCallback) {
var jazz = new JazzInstance(),
interfaces = {
enumerateInputs: {
value: function() {
return enumerateList(this, jazz, 'input');
}
},
enumerateOutputs: {
value: function() {
return enumerateList(this, jazz, 'output');
}
},
getInput: {
value: function(target) {
return getInput(this, target);
}
},
getOutput: {
value: function(target) {
getOutput(this, target);
}
},
toString: {
value: function() {
toString.call(this);
}
},
send: {
value: function(data, timestamp) {
send(data, timestamp, jazz);
}
}
};
Object.defineProperties(this, interfaces);
function enumerateList(midiAccess, jazz, list, type) {
for (var items = [], i = 0, l = list.length; i < l; i++) {
items[i] = new MIDIPort(midiAccess, list[i], i, type);
}
return items;
}
function getInput(midiAccess, target) {
return (!! target) ? null : new MIDIInput(midiAccess, target);
}
function getOutput(midiAccess, target) {
return (!! target) ? null : new MIDIOutput(midiAccess, target);
}
function toString(midiAccess) {
var info = 'type: ' + midiAccess.type + "name: '" + midiAccess.name + "' manufacturer: '" + midiAccess.manufacturer + "' version: " + midiAccess.version + " fingerprint: '" + midiAccess.fingerprint + "'";
return info;
}
function mideProc(jazz, timestamp, data) {
var evt = new global.CustomEvent('message'),
t = timestamp - jazz._timeZero;
evt.timestamp = parseFloat(timestamp.toString()) + jazz.perfTimeZero;
evt.data = new Uint8Array(data);
dispatcher.dispatchEvent(evt);
}
function send(data, timestamp, jazz) {
var delayBeforeSend = (timestamp) ? Math.floor(timestamp - perf.now()) : 0;
if (!! (data) || data.length === 0) {
return false;
}
if (timestamp && (delayBeforeSend > 1)) {
window.setTimeout(send(data, timestamp, jazz), delayBeforeSend);
} else {
jazz.MidiOutLong(data);
}
return true;
}
}
}(window, window.navigator, window.performance));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment