// Set a global MIDI variable
var MIDI = false;

/**
 * Template events should be defined here.
 *
 * Docs: http://docs.meteor.com/#template_events
 */
Template.home.events({

  /**
   * Recording
   *   * Determine end time.
   *   * Push midi events to a db record until end time condition is met.
   */
  'click #record': function(event) {
    var mid = Mid.insert({
      notes: [],
      createdAt: Date.now()
    });

    $('#record')
      .removeClass('red')
      .addClass('green');

    // Triggered for every midi input.
    MIDI.onmidimessage = function(message) {
      Mid.update(mid, {$push: {'notes': message}});
    }

    Meteor.setTimeout(function() {
      var mid = null;
      MIDI.onmidimessage = null;
      $('#record')
        .removeClass('green')
        .addClass('red');
    }, 8000);


  }
});

/**
 * Initialize the template here.
 *
 * Docs: http://docs.meteor.com/#template_rendered
 */
Template.home.rendered = function() {
  navigator.requestMIDIAccess().then(function (m) {
    // Web MIDI API changed in Chrome 29 here's a catchall.
    // Chrome < 29:
    if (typeof m.inputs === 'function') {
      MIDI = m.inputs()[0];
    } else {
      // Chrome > 29:
      MIDI = m.inputs.values().next().value;
      console.log(MIDI);
    }
    // If no device
    if (!MIDI) {
      console.log('no midi device.');
      // so disable recording.
      $('#record')
        .attr('disabled', 'disabled')
        .addClass('disabled');
    }
  }, function(err) {
    // Log access failures
    console.log("MIDI Access Failure. Error code: " + err.code );
    // and disable recording.
    $('#record')
      .attr('disabled', 'disabled')
      .addClass('disabled');
  });

};

@@ -40,16 +40,1339 @@
 = false;
+%0Avar tinymusic = Npm.require('tinymusic');%0A%0A// Save the MIDI notes to the database.%0Avar saveNote = function(message) %7B%0A  // Push events to database.%0A  var note = %7B%0A    keys: message.data,%0A    time: message.timestamp%0A  %7D%0A  Mid.update(mid, %7B$push: %7B'notes': note%7D%7D);%0A%0A  // Make it composable with other midi message handlers.%0A  return message;%0A%7D%0A%0A/**%0A * Do a thing as many times as specified.%0A */%0Afunction loop(times, fn) %7B%0A  var t = times;%0A  while (t) %7B%0A    fn(times - t);%0A    t--;%0A  %7D%0A%0A%7D%0A%0A/**%0A * Programatically reconstruct this table%0A * http://computermusicresource.com/midikeys.html%0A *%0A * @return Object Dictionary of keycodes and letter notes.%0A */%0AkeycodeNoteMap = function() %7B%0A  var enharmonics = %5B%0A    'C',%0A    'Db',%0A    'D',%0A    'Eb',%0A    'Fb',%0A    'F',%0A    'Gb',%0A    'G',%0A    'Ab',%0A    'A',%0A    'Bb',%0A    'Cb'%0A  %5D;%0A  var map = %7B%7D;%0A  loop(11, function(i) %7B%0A    var octave = (-2) + i; // this gives us octaves -2 ... 8%0A    enharmonics.forEach(function (note) %7B%0A      var lastKeycode = Number(_.last(_.keys(map)))%0A      if (!lastKeycode && !(lastKeycode %3E -1)) %7B lastKeycode = -1; %7D%0A      map%5BlastKeycode + 1%5D = note + octave;%0A    %7D);%0A  %7D);%0A  return map;%0A%7D%0A%0Avar playNote = function(message) %7B%0A  var note = message.data;%0A  console.log(note);%0A%0A  // Make it composable with other midi message handlers.%0A  return message;%0A%7D
 %0A%0A/**%0A *
@@ -1736,24 +1736,60 @@
 ()%0A    %7D);%0A%0A
+    // Visually indicate recording.%0A
     $('#reco
@@ -1885,16 +1885,17 @@
  input.%0A
+%0A
     MIDI
@@ -1915,86 +1915,38 @@
 e = 
-function(message) %7B%0A      Mid.update(mid, %7B$push: %7B'notes': message%7D%7D);%0A    %7D%0A
+_.compose(playNote, saveNote);
 %0A   
@@ -2026,20 +2026,24 @@
 ssage = 
-null
+playNote
 ;%0A      
@@ -2551,16 +2551,38 @@
 .value;%0A
+    %7D%0A    if (MIDI) %7B%0A
       co
@@ -2602,48 +2602,57 @@
 I);%0A
-    %7D%0A    // If no device%0A    if (!MIDI)
+%0A      MIDI.onmidimessage = playNote;%0A%0A    %7D else
  %7B%0A 

add key to note mapping