STILL OUTSTANDING
=================

* Sconstruct doesn't support jackdmp & Jack MIDI.  Only supports
  "classic" jack (e.g. 0.109.2).  Need to either add support for
  jackdmp versions, or drop support for anything not conforming
  to the 0.105.0 API.
  (gabe 2/19/09)

* Merging r594 (lookahead code) -- make sure we didn't
  introduce a regression.  TEST! TEST! TEST!
  We didn't.  THE WHOLE BRANCH IS A REGRESSION!!
  Need to fix MIDI record on the jack MIDI branch.
  (gabe 2/19/09)

* There's a fix for jack_output.cpp that tests if the
  'client' variable is NULL.  I don't think this got
  ported over in the latest merge.  It needs to be.
  (gabe 2/19/09)

* Need to do some sample-accuracy tests.

COMPLETED (KEEP UNTIL MERGED INTO TRUNK)
========================================

* Get MIDI working in a sample-perfect mode....
  [DONE]

* Solve the exit-segfault problem.
  [DONE, I think]

* Kill the JACK client whenever the drivers are restarted.
  [DONE]

* Create a JackDriver (or JackClass) superclass to manage Jack's
  client* pointer for both the MIDI and audio ports.
  [DONE]

* Add the public method MidiInput::process(nframes) and give it a
  default implementation of doing nothing.
  [DONE]

* Add a call to MidiInput::process() from
  audio_Engine_updateNoteQueue() (hydrogen.cpp:1004).  Doing this and
  the two above elim. the need for JackMidiDriver to have it's own
  jack client* handle and jack process callback... but still puts us
  in the process graph.
  [DONE]

* Find a way to use Jack's frame information to put better
  "timestamps" into m_midiNoteQueue.  Maybe this can be done by adding
  an optional parameter to MidiInput::handleMidiMessage() that is the
  frame number given by jack.  Then, add an optional paramter to
  addRealtimeNote() that will pass along this parameter.  When the
  notes get inserted in the note queue (addRealtimeNote), their tick
  position will consider the jack-returned sample where it happened.
  (hmmm.... messy.)
  [DONE]

  How a note gets added:

  MidiInput::handleNoteOnMessage()
    Hydrogen::addRealtimeNote()
      position = getTickPosition() [quantized]
      realcolumn = getRealtimeTickPosition() (??)
        getRealtimeTickPosition() returns
        (m_nRealtimeFrames + eps) / transport->m_nTickSize
        [eps is an estimate of the time elapsed since m_nRealtimeFrames.]
	It's getTickPosition() if we're recording the note.
        It's getRealtimeTickPosition() if we're just playing it.
      currentPattern.note_map.insert(..., Note(.., position,..)) // only if recording
      Hydrogen::midi_noteOn(Note(.., realcolumn, ..))
        audioEngine_noteOn(note)
          m_midiNoteQueue.push_back(note)

  Once in the note queue, the sound will happen at the right time.
  So, the way I would want this to happen is this:

  MidiInput::handleNoteOnMessage(frame) // offset from current process cycle
    Hydrogen::addRealtimeNote(frame)
      tick = (m_nRealtimeFrames + frame) / transport->m_nTickSize
      position = quantized version of tick
      realcolumn = tick
      if recording: currentPattern.note_map.insert(.. Note(.. position ..) ..)
      Hydrogen::midi_noteOn(.. Note(.. realcolumn ..) ..)

  Ways to implement:

  o Add a frame number to MidiMessage and a flag on whether or not it
    should be referred to.  This keeps from being hyper-invasive to
    the classes that currently implement the MidiInput class.

  o Create a version of addRealtimeNote() that has the frame parameter and a
    bool for whether or not it should be used.

  o Redo the current addRealtimeNote to be an interface to the new one
    (return addRealtimeNote(..., false, 0);)

  Complicateion:

  o audioEngine_process() is private to hydrogen.cpp.  Currently, the
    callback is passed to JackOutput's constructor.  I can't just
    flippantly pass the same callback to JackMidiDriver... because if
    Jack isn't processing audio, then audioEngine_process() will get
    called twice:  once by Jack's MIDI thread, and once by whatever
    thread is processing audio.
    WHat do I do???
 
