add missing file
[ardour.git] / libs / ardour / midi_diskstream.cc
index b11e3f30625bf7f04ec2da5fa3c7b79217923e63..2b8f70a307c6e1b6d9437e87ac1e08f4c076b3ef 100644 (file)
@@ -42,7 +42,6 @@
 #include <ardour/utils.h>
 #include <ardour/configuration.h>
 #include <ardour/smf_source.h>
-#include <ardour/destructive_filesource.h>
 #include <ardour/send.h>
 #include <ardour/region_factory.h>
 #include <ardour/midi_playlist.h>
@@ -69,6 +68,7 @@ MidiDiskstream::MidiDiskstream (Session &sess, const string &name, Diskstream::F
        , _source_port(0)
        , _capture_transition_buf(0)
        , _last_flush_frame(0)
+       , _note_mode(Sustained)
 {
        /* prevent any write sources from being created */
 
@@ -93,6 +93,7 @@ MidiDiskstream::MidiDiskstream (Session& sess, const XMLNode& node)
        , _source_port(0)
        , _capture_transition_buf(0)
        , _last_flush_frame(0)
+       , _note_mode(Sustained)
 {
        in_set_state = true;
        init (Recordable);
@@ -122,8 +123,6 @@ MidiDiskstream::init (Diskstream::Flag f)
        set_block_size (_session.get_block_size());
        allocate_temporary_buffers ();
 
-       //_playback_wrap_buffer = new RawMidi[wrap_buffer_size];
-       //_capture_wrap_buffer = new RawMidi[wrap_buffer_size];
        _playback_buf = new MidiRingBuffer (_session.diskstream_buffer_size());
        _capture_buf = new MidiRingBuffer (_session.diskstream_buffer_size());
        _capture_transition_buf = new RingBufferNPT<CaptureTransition> (128);
@@ -138,6 +137,14 @@ MidiDiskstream::~MidiDiskstream ()
        Glib::Mutex::Lock lm (state_lock);
 }
 
+       
+void
+MidiDiskstream::non_realtime_locate (nframes_t position)
+{
+       _write_source->set_timeline_position (position);
+}
+
+
 void
 MidiDiskstream::non_realtime_input_change ()
 {
@@ -149,7 +156,6 @@ MidiDiskstream::non_realtime_input_change ()
                }
 
                if (input_change_pending & ConfigurationChanged) {
-
                        assert(_io->n_inputs() == _n_channels);
                } 
 
@@ -164,6 +170,8 @@ MidiDiskstream::non_realtime_input_change ()
                }
 
                input_change_pending = NoChange;
+               
+               /* implicit unlock */
        }
 
        /* reset capture files */
@@ -173,7 +181,7 @@ MidiDiskstream::non_realtime_input_change ()
        /* now refill channel buffers */
 
        if (speed() != 1.0f || speed() != -1.0f) {
-               seek ((jack_nframes_t) (_session.transport_frame() * (double) speed()));
+               seek ((nframes_t) (_session.transport_frame() * (double) speed()));
        }
        else {
                seek (_session.transport_frame());
@@ -185,7 +193,7 @@ MidiDiskstream::non_realtime_input_change ()
 void
 MidiDiskstream::get_input_sources ()
 {
-       uint32_t ni = _io->n_inputs().get(DataType::MIDI);
+       uint32_t ni = _io->n_inputs().n_midi();
 
        if (ni == 0) {
                return;
@@ -223,7 +231,7 @@ MidiDiskstream::find_and_use_playlist (const string& name)
        boost::shared_ptr<MidiPlaylist> playlist;
                
        if ((playlist = boost::dynamic_pointer_cast<MidiPlaylist> (_session.playlist_by_name (name))) == 0) {
-               playlist = boost::dynamic_pointer_cast<MidiPlaylist> (PlaylistFactory::create (_session, name));
+               playlist = boost::dynamic_pointer_cast<MidiPlaylist> (PlaylistFactory::create (DataType::MIDI, _session, name));
        }
 
        if (!playlist) {
@@ -307,9 +315,18 @@ MidiDiskstream::set_destructive (bool yn)
        assert( ! yn);
        return -1;
 }
+       
+void
+MidiDiskstream::set_note_mode (NoteMode m)
+{
+       _note_mode = m;
+       midi_playlist()->set_note_mode(m);
+       if (_write_source && _write_source->model())
+               _write_source->model()->set_note_mode(m);
+}
 
 void
-MidiDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframes_t nframes, bool can_record)
+MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframes, bool can_record)
 {
        // FIXME: waaay too much code to duplicate (AudioDiskstream)
        
@@ -354,7 +371,7 @@ MidiDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframe
                        } else {
                                first_recordable_frame += _roll_delay;
                        }
-
+               
                } else {
 
                        /* was rolling, but record state changed */
@@ -432,18 +449,15 @@ MidiDiskstream::check_record_status (jack_nframes_t transport_frame, jack_nframe
 }
 
 int
-MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes, jack_nframes_t offset, bool can_record, bool rec_monitors_input)
+MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t offset, bool can_record, bool rec_monitors_input)
 {
        // FIXME: waay too much code to duplicate (AudioDiskstream::process)
-       int            ret = -1;
-       jack_nframes_t rec_offset = 0;
-       jack_nframes_t rec_nframes = 0;
-       bool           nominally_recording;
-       bool           re = record_enabled ();
-       bool           collect_playback = false;
-
-       /*_current_capture_buffer = 0;
-         _current_playback_buffer = 0;*/
+       int       ret = -1;
+       nframes_t rec_offset = 0;
+       nframes_t rec_nframes = 0;
+       bool      nominally_recording;
+       bool      re = record_enabled ();
+       bool      collect_playback = false;
 
        /* if we've already processed the frames corresponding to this call,
           just return. this allows multiple routes that are taking input
@@ -456,6 +470,8 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes,
        if (_processed) {
                return 0;
        }
+       
+       commit_should_unlock = false;
 
        check_record_status (transport_frame, nframes, can_record);
 
@@ -475,7 +491,7 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes,
        if (!state_lock.trylock()) {
                return 1;
        }
-
+       commit_should_unlock = true;
        adjust_capture_position = 0;
 
        if (nominally_recording || (_session.get_record_enabled() && Config->get_punch_in())) {
@@ -538,19 +554,19 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes,
 
                assert(_source_port);
 
-               // Pump entire port buffer into the ring buffer (FIXME!)
-               _capture_buf->write(_source_port->get_midi_buffer(), transport_frame);
+               // Pump entire port buffer into the ring buffer (FIXME: split cycles?)
+               //_capture_buf->write(_source_port->get_midi_buffer(), transport_frame);
+               size_t num_events = _source_port->get_midi_buffer().size();
+               size_t to_write = std::min(_capture_buf->write_space(), num_events);
 
-               // FIXME: hackitty hack, don't come back
-               //_write_source->ViewDataRangeReady (_write_source->length(), rec_nframes); /* EMIT SIGNAL */
-               /*
-                  for (size_t i=0; i < _source_port->size(); ++i) {
-                  cerr << "DISKSTREAM GOT EVENT(1) " << i << "!!\n";
-                  }
+               MidiBuffer::iterator port_iter = _source_port->get_midi_buffer().begin();
 
-                  if (_source_port->size() == 0)
-                  cerr << "No events :/ (1)\n";
-                  */
+               for (size_t i=0; i < to_write; ++i) {
+                       const MidiEvent& ev = *port_iter;
+                       _capture_buf->write(ev.time() + transport_frame, ev.size(), ev.buffer());
+                       ++port_iter;
+               }
+       
        } else {
 
                if (was_recording) {
@@ -562,16 +578,23 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes,
        if (rec_nframes) {
 
                /* XXX XXX XXX XXX XXX XXX XXX XXX */
+               
                /* data will be written to disk */
 
+               if (rec_nframes == nframes && rec_offset == 0) {
+
+                       playback_distance = nframes;
+               } else {
+               
+                       collect_playback = true;
+               }
+
                adjust_capture_position = rec_nframes;
 
        } else if (nominally_recording) {
 
                /* can't do actual capture yet - waiting for latency effects to finish before we start*/
 
-               // Ummm.. well, I suppose we'll just hang out for a bit?
-
                playback_distance = nframes;
 
        } else {
@@ -583,18 +606,19 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes,
 
                /* we're doing playback */
 
-               jack_nframes_t necessary_samples;
+               nframes_t necessary_samples;
 
                /* no varispeed playback if we're recording, because the output .... TBD */
 
                if (rec_nframes == 0 && _actual_speed != 1.0f) {
-                       necessary_samples = (jack_nframes_t) floor ((nframes * fabs (_actual_speed))) + 1;
+                       necessary_samples = (nframes_t) floor ((nframes * fabs (_actual_speed))) + 1;
                } else {
                        necessary_samples = nframes;
                }
 
                // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
-               // Write into playback buffer here, and whatnot
+               // Write into playback buffer here, and whatnot?
+               //cerr << "MDS FIXME: collect playback" << endl;
 
        }
 
@@ -608,18 +632,15 @@ MidiDiskstream::process (jack_nframes_t transport_frame, jack_nframes_t nframes,
                   be called. unlock the state lock.
                   */
 
+               commit_should_unlock = false;
                state_lock.unlock();
        } 
 
        return ret;
-
-       _processed = true;
-
-       return 0;
 }
 
 bool
-MidiDiskstream::commit (jack_nframes_t nframes)
+MidiDiskstream::commit (nframes_t nframes)
 {
        bool need_butler = false;
 
@@ -629,15 +650,6 @@ MidiDiskstream::commit (jack_nframes_t nframes)
                playback_sample += playback_distance;
        }
 
-       /* XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX */
-
-       /*
-       _playback_buf->increment_read_ptr (playback_distance);
-
-       if (adjust_capture_position) {
-               _capture_buf->increment_write_ptr (adjust_capture_position);
-       }
-*/
        if (adjust_capture_position != 0) {
                capture_captured += adjust_capture_position;
                adjust_capture_position = 0;
@@ -650,7 +662,9 @@ MidiDiskstream::commit (jack_nframes_t nframes)
                        || _capture_buf->read_space() >= disk_io_chunk_frames;
        }
        
-       state_lock.unlock();
+       if (commit_should_unlock) {
+               state_lock.unlock();
+       }
 
        _processed = false;
 
@@ -675,7 +689,7 @@ MidiDiskstream::overwrite_existing_buffers ()
 }
 
 int
-MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill)
+MidiDiskstream::seek (nframes_t frame, bool complete_refill)
 {
        Glib::Mutex::Lock lm (state_lock);
        int ret = -1;
@@ -685,7 +699,6 @@ MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill)
 
        playback_sample = frame;
        file_frame = frame;
-       _last_flush_frame = frame;
 
        if (complete_refill) {
                while ((ret = do_refill_with_alloc ()) > 0) ;
@@ -697,7 +710,7 @@ MidiDiskstream::seek (jack_nframes_t frame, bool complete_refill)
 }
 
 int
-MidiDiskstream::can_internal_playback_seek (jack_nframes_t distance)
+MidiDiskstream::can_internal_playback_seek (nframes_t distance)
 {
        if (_playback_buf->read_space() < distance) {
                return false;
@@ -707,7 +720,7 @@ MidiDiskstream::can_internal_playback_seek (jack_nframes_t distance)
 }
 
 int
-MidiDiskstream::internal_playback_seek (jack_nframes_t distance)
+MidiDiskstream::internal_playback_seek (nframes_t distance)
 {
        first_recordable_frame += distance;
        playback_sample += distance;
@@ -717,13 +730,13 @@ MidiDiskstream::internal_playback_seek (jack_nframes_t distance)
 
 /** @a start is set to the new frame position (TIME) read up to */
 int
-MidiDiskstream::read (jack_nframes_t& start, jack_nframes_t dur, bool reversed)
+MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
 {      
-       jack_nframes_t this_read = 0;
+       nframes_t this_read = 0;
        bool reloop = false;
-       jack_nframes_t loop_end = 0;
-       jack_nframes_t loop_start = 0;
-       jack_nframes_t loop_length = 0;
+       nframes_t loop_end = 0;
+       nframes_t loop_start = 0;
+       nframes_t loop_length = 0;
        Location *loc = 0;
 
        if (!reversed) {
@@ -782,8 +795,9 @@ MidiDiskstream::read (jack_nframes_t& start, jack_nframes_t dur, bool reversed)
                
                if (reversed) {
 
-                       cerr << "Reversed MIDI.. that's just crazy talk." << endl;
-                       // Swap note ons with note offs here
+                       // Swap note ons with note offs here.  etc?
+                       // Fully reversing MIDI required look-ahead (well, behind) to find previous
+                       // CC values etc.  hard.
 
                } else {
                        
@@ -797,6 +811,7 @@ MidiDiskstream::read (jack_nframes_t& start, jack_nframes_t dur, bool reversed)
                } 
 
                dur -= this_read;
+               //offset += this_read;
        }
 
        return 0;
@@ -820,16 +835,6 @@ MidiDiskstream::do_refill ()
                return 0;
        }
 
-       /* if there are 2+ chunks of disk i/o possible for
-          this track, let the caller know so that it can arrange
-          for us to be called again, ASAP.
-          */
-
-       // FIXME: using disk_io_chunk_frames as an event count, not good
-       if (_playback_buf->write_space() >= (_slaved?3:2) * disk_io_chunk_frames) {
-               ret = 1;
-       }
-
        /* if we're running close to normal speed and there isn't enough 
           space to do disk_io_chunk_frames of I/O, then don't bother.  
 
@@ -838,7 +843,7 @@ MidiDiskstream::do_refill ()
           */
 
        if ((write_space < disk_io_chunk_frames) && fabs (_actual_speed) < 2.0f) {
-               cerr << "No refill 1\n";
+               //cerr << "No refill 1\n";
                return 0;
        }
 
@@ -848,12 +853,12 @@ MidiDiskstream::do_refill ()
           */
 
        if (_slaved && write_space < (_playback_buf->capacity() / 2)) {
-               cerr << "No refill 2\n";
+               //cerr << "No refill 2\n";
                return 0;
        }
 
        if (reversed) {
-               cerr << "No refill 3 (reverse)\n";
+               //cerr << "No refill 3 (reverse)\n";
                return 0;
        }
 
@@ -865,28 +870,12 @@ MidiDiskstream::do_refill ()
                return 0;
        }
 
-#if 0
-       // or this
-       if (file_frame > max_frames - total_space) {
-
-               /* to close to the end: read what we can, and zero fill the rest */
-
-               zero_fill = total_space - (max_frames - file_frame);
-               total_space = max_frames - file_frame;
-
-       } else {
-               zero_fill = 0;
-       }
-#endif
-
-       // At this point we:
+       // At this point we...
        assert(_playback_buf->write_space() > 0); // ... have something to write to, and
        assert(file_frame <= max_frames); // ... something to write
 
-       // So (read it, then) write it:
-       
-       jack_nframes_t file_frame_tmp = file_frame;
-       jack_nframes_t to_read = min(disk_io_chunk_frames, (max_frames - file_frame));
+       nframes_t file_frame_tmp = file_frame;
+       nframes_t to_read = min(disk_io_chunk_frames, (max_frames - file_frame));
        
        // FIXME: read count?
        if (read (file_frame_tmp, to_read, reversed)) {
@@ -918,20 +907,18 @@ MidiDiskstream::do_flush (Session::RunContext context, bool force_flush)
        int32_t ret = 0;
        // FIXME: I'd be lying if I said I knew what this thing was
        //RingBufferNPT<CaptureTransition>::rw_vector transvec;
-       jack_nframes_t total;
+       nframes_t total;
 
        _write_data_count = 0;
 
-       if (_last_flush_frame > _session.transport_frame()) {
+       if (_last_flush_frame > _session.transport_frame()
+                       || _last_flush_frame < capture_start_frame) {
                _last_flush_frame = _session.transport_frame();
        }
 
        total = _session.transport_frame() - _last_flush_frame;
 
-
-       // FIXME: put this condition back in! (removed for testing)
-       if (total == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
-               //cerr << "MDS - no flush 1\n";
+       if (total == 0 || _capture_buf->read_space() == 0  && _session.transport_speed() == 0 || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
                goto out;
        }
 
@@ -950,25 +937,23 @@ MidiDiskstream::do_flush (Session::RunContext context, bool force_flush)
                ret = 1;
        } 
 
-       //to_write = min (disk_io_chunk_frames, (jack_nframes_t) vector.len[0]);
+       //to_write = min (disk_io_chunk_frames, (nframes_t) vector.len[0]);
        to_write = disk_io_chunk_frames;
 
        assert(!destructive());
 
-       if ((!_write_source) || _write_source->write (*_capture_buf, to_write) != to_write) {
-               //cerr << "MDS - no flush 2\n";
-               error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
-               return -1;
-       } else {
-               _last_flush_frame = _session.transport_frame();
-               //cerr << "MDS - flushed\n";
+       if (record_enabled() && _session.transport_frame() - _last_flush_frame > disk_io_chunk_frames) {
+               if ((!_write_source) || _write_source->write (*_capture_buf, to_write) != to_write) {
+                       error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
+                       return -1;
+               } else {
+                       _last_flush_frame = _session.transport_frame();
+               }
        }
 
-       //(*chan).curr_capture_cnt += to_write;
-
 out:
        //return ret;
-       return 0;
+       return 0; // FIXME: everything's fine!  always!  honest!
 }
 
 void
@@ -978,7 +963,7 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
        bool more_work = true;
        int err = 0;
        boost::shared_ptr<MidiRegion> region;
-       jack_nframes_t total_capture;
+       nframes_t total_capture;
        MidiRegion::SourceList srcs;
        MidiRegion::SourceList::iterator src;
        vector<CaptureInfo*>::iterator ci;
@@ -1030,30 +1015,21 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                }
 
                /* figure out the name for this take */
-
-               boost::shared_ptr<SMFSource> s = _write_source;
-
-               if (s) {
-
-                       srcs.push_back (s);
-
-                       cerr << "MidiDiskstream: updating source after capture\n";
-                       s->update_header (capture_info.front()->start, when, twhen);
-
-                       s->set_captured_for (_name);
-
-               }
+       
+               srcs.push_back (_write_source);
+               _write_source->set_timeline_position (capture_info.front()->start);
+               _write_source->set_captured_for (_name);
 
                string whole_file_region_name;
                whole_file_region_name = region_name_from_path (_write_source->name(), true);
+
                /* Register a new region with the Session that
                   describes the entire source. Do this first
                   so that any sub-regions will obviously be
                   children of this one (later!)
                   */
+
                try {
-                       assert(_write_source);
-                       
                        boost::shared_ptr<Region> rx (RegionFactory::create (srcs, _write_source->last_capture_start_frame(), total_capture, 
                                                                             whole_file_region_name, 
                                                                             0, Region::Flag (Region::DefaultFlags|Region::Automatic|Region::WholeFile)));
@@ -1078,6 +1054,7 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                for (buffer_position = _write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
 
                        string region_name;
+
                        _session.region_name (region_name, _write_source->name(), false);
 
                        // cerr << _name << ": based on ci of " << (*ci)->start << " for " << (*ci)->frames << " add a region\n";
@@ -1091,6 +1068,8 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                                error << _("MidiDiskstream: could not create region for captured midi!") << endmsg;
                                continue; /* XXX is this OK? */
                        }
+                       
+                       region->GoingAway.connect (bind (mem_fun (*this, &Diskstream::remove_region_from_last_capture), boost::weak_ptr<Region>(region)));
 
                        _last_capture_regions.push_back (region);
 
@@ -1107,11 +1086,11 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                XMLNode &after = _playlist->get_state();
                _session.add_command (new MementoCommand<Playlist>(*_playlist, &before, &after));
 
-               mark_write_completed = true;
+       }
 
-               reset_write_sources (mark_write_completed);
+       mark_write_completed = true;
 
-       }
+       reset_write_sources (mark_write_completed);
 
        for (ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
                delete *ci;
@@ -1121,6 +1100,35 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
        capture_start_frame = 0;
 }
 
+void
+MidiDiskstream::transport_looped (nframes_t transport_frame)
+{
+       if (was_recording) {
+
+               // adjust the capture length knowing that the data will be recorded to disk
+               // only necessary after the first loop where we're recording
+               if (capture_info.size() == 0) {
+                       capture_captured += _capture_offset;
+
+                       if (_alignment_style == ExistingMaterial) {
+                               capture_captured += _session.worst_output_latency();
+                       } else {
+                               capture_captured += _roll_delay;
+                       }
+               }
+
+               finish_capture (true);
+
+               // the next region will start recording via the normal mechanism
+               // we'll set the start position to the current transport pos
+               // no latency adjustment or capture offset needs to be made, as that already happened the first time
+               capture_start_frame = transport_frame;
+               first_recordable_frame = transport_frame; // mild lie
+               last_recordable_frame = max_frames;
+               was_recording = true;
+       }
+}
+
 void
 MidiDiskstream::finish_capture (bool rec_monitors_input)
 {
@@ -1195,6 +1203,8 @@ MidiDiskstream::engage_record_enable ()
                _source_port->request_monitor_input (!(Config->get_auto_input() && rolling));
        }
 
+       _write_source->mark_streaming_midi_write_started (_note_mode, _session.transport_frame());
+
        RecordEnableChanged (); /* EMIT SIGNAL */
 }
 
@@ -1359,7 +1369,7 @@ MidiDiskstream::use_new_write_source (uint32_t n)
 
        if (_write_source) {
 
-               if (SMFSource::is_empty (_write_source->path())) {
+               if (_write_source->is_empty ()) {
                        _write_source->mark_for_remove ();
                        _write_source.reset();
                } else {
@@ -1395,9 +1405,10 @@ MidiDiskstream::reset_write_sources (bool mark_write_complete, bool force)
        if (_write_source && mark_write_complete) {
                _write_source->mark_streaming_write_completed ();
        }
-
-       if (!_write_source) {
-               use_new_write_source ();
+       use_new_write_source (0);
+                       
+       if (record_enabled()) {
+               //_capturing_sources.push_back (_write_source);
        }
 }
 
@@ -1405,14 +1416,14 @@ int
 MidiDiskstream::rename_write_sources ()
 {
        if (_write_source != 0) {
-               _write_source->set_name (_name, destructive());
+               _write_source->set_source_name (_name, destructive());
                /* XXX what to do if this fails ? */
        }
        return 0;
 }
 
 void
-MidiDiskstream::set_block_size (jack_nframes_t nframes)
+MidiDiskstream::set_block_size (nframes_t nframes)
 {
 }
 
@@ -1474,55 +1485,20 @@ MidiDiskstream::use_pending_capture_data (XMLNode& node)
        return 0;
 }
 
-/** Writes playback events in the given range to dst, translating time stamps
- * so that an event at start has time = 0
+/** Writes playback events in the given range to \a dst, translating time stamps
+ * so that an event at \a start has time = 0
  */
 void
-MidiDiskstream::get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end)
+MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end)
 {
        dst.clear();
        assert(dst.size() == 0);
        
-       // I think this happens with reverse varispeed?  maybe?
+       // Reverse.  ... We just don't do reverse, ok?  Back off.
        if (end <= start) {
                return;
        }
 
-/*
-       cerr << "MIDI Diskstream pretending to read" << endl;
-
-       MidiEvent ev;
-       RawMidi data[4];
-
-       const char note = rand()%30 + 30;
-       
-       ev.buffer = data;
-       ev.time = 0;
-       ev.size = 3;
-
-       data[0] = 0x90;
-       data[1] = note;
-       data[2] = 120;
-
-       dst.push_back(ev);
-       
-       ev.buffer = data;
-       ev.time = (end - start) / 2;
-       ev.size = 3;
-
-       data[0] = 0x80;
-       data[1] = note;
-       data[2] = 64;
-*/
+       // Translates stamps to be relative to start
        _playback_buf->read(dst, start, end);
-
-       // Translate time stamps to be relative to the start of this cycle
-       for (size_t i=0; i < dst.size(); ++i) {
-               assert(dst[i].time >= start);
-               assert(dst[i].time <= end);
-               //cerr << "Translating event stamp " << dst[i].time << " to ";
-               dst[i].time -= start;
-               //cerr << dst[i].time << endl;
-
-       }
 }