fix up marshall/unmarshall of note data for MidiModel::DiffCommand
[ardour.git] / libs / ardour / midi_diskstream.cc
index 108dcb21a52b557f4ebe232dbc7cd7cc7d7eb9b0..9c8c9e8620101683593ec0583b14fc899c7a46be 100644 (file)
 #include <sys/stat.h>
 #include <sys/mman.h>
 
-#include <pbd/error.h>
-#include <pbd/basename.h>
+#include "pbd/error.h"
+#include "pbd/basename.h"
 #include <glibmm/thread.h>
-#include <pbd/xml++.h>
-#include <pbd/memento_command.h>
-#include <pbd/enumwriter.h>
-
-#include <ardour/ardour.h>
-#include <ardour/audioengine.h>
-#include <ardour/configuration.h>
-#include <ardour/cycle_timer.h>
-#include <ardour/io.h>
-#include <ardour/midi_diskstream.h>
-#include <ardour/midi_playlist.h>
-#include <ardour/midi_port.h>
-#include <ardour/midi_region.h>
-#include <ardour/playlist_factory.h>
-#include <ardour/region_factory.h>
-#include <ardour/send.h>
-#include <ardour/session.h>
-#include <ardour/smf_source.h>
-#include <ardour/utils.h>
+#include "pbd/xml++.h"
+#include "pbd/memento_command.h"
+#include "pbd/enumwriter.h"
+
+#include "ardour/ardour.h"
+#include "ardour/audioengine.h"
+#include "ardour/configuration.h"
+#include "ardour/cycle_timer.h"
+#include "ardour/io.h"
+#include "ardour/midi_diskstream.h"
+#include "ardour/midi_playlist.h"
+#include "ardour/midi_port.h"
+#include "ardour/midi_region.h"
+#include "ardour/playlist_factory.h"
+#include "ardour/region_factory.h"
+#include "ardour/send.h"
+#include "ardour/session.h"
+#include "ardour/smf_source.h"
+#include "ardour/utils.h"
+
+#include "midi++/types.h"
 
 #include "i18n.h"
 #include <locale.h>
@@ -122,8 +124,8 @@ MidiDiskstream::init (Diskstream::Flag f)
        allocate_temporary_buffers ();
 
        const size_t size = _session.midi_diskstream_buffer_size();
-       _playback_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size);
-       _capture_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size);
+       _playback_buf = new MidiRingBuffer<nframes_t>(size);
+       _capture_buf = new MidiRingBuffer<nframes_t>(size);
        
        _n_channels = ChanCount(DataType::MIDI, 1);
 
@@ -139,8 +141,9 @@ MidiDiskstream::~MidiDiskstream ()
 void
 MidiDiskstream::non_realtime_locate (nframes_t position)
 {
-       assert(_write_source);
-       _write_source->set_timeline_position (position);
+       if (_write_source) {
+               _write_source->set_timeline_position (position);
+       }
        seek(position, false);
 }
 
@@ -156,7 +159,10 @@ MidiDiskstream::non_realtime_input_change ()
                }
 
                if (input_change_pending & ConfigurationChanged) {
-                       assert(_io->n_inputs() == _n_channels);
+                       if (_io->n_ports().n_midi() != _n_channels.n_midi()) {
+                               error << "Can not feed IO " << _io->n_ports()
+                                       << " with diskstream " << _n_channels << endl;
+                       }
                } 
 
                get_input_sources ();
@@ -193,7 +199,7 @@ MidiDiskstream::non_realtime_input_change ()
 void
 MidiDiskstream::get_input_sources ()
 {
-       uint32_t ni = _io->n_inputs().n_midi();
+       uint32_t ni = _io->n_ports().n_midi();
 
        if (ni == 0) {
                return;
@@ -202,7 +208,7 @@ MidiDiskstream::get_input_sources ()
        // This is all we do for now at least
        assert(ni == 1);
 
-       _source_port = _io->midi_input(0);
+       _source_port = _io->midi(0);
 
        // do... stuff?
 }              
@@ -308,7 +314,7 @@ MidiDiskstream::set_note_mode (NoteMode m)
 }
 
 void
-MidiDiskstream::check_record_status (nframes_t transport_frame, 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)
        
@@ -361,7 +367,7 @@ MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframe
                        if (_alignment_style == ExistingMaterial) {
 
 
-                               if (!Config->get_punch_in()) {
+                               if (!_session.config.get_punch_in()) {
 
                                        /* manual punch in happens at the correct transport frame
                                           because the user hit a button. but to get alignment correct 
@@ -390,7 +396,7 @@ MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframe
 
                        } else {
 
-                               if (Config->get_punch_in()) {
+                               if (_session.config.get_punch_in()) {
                                        first_recordable_frame += _roll_delay;
                                } else {
                                        capture_start_frame -= _roll_delay;
@@ -415,8 +421,177 @@ MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframe
        last_possibly_recording = possibly_recording;
 }
 
+#if 0
+static void
+trace_midi (ostream& o, MIDI::byte *msg, size_t len)
+{
+       using namespace MIDI;
+       eventType type;
+       const char trace_prefix = ':';
+       
+       type = (eventType) (msg[0]&0xF0);
+
+       switch (type) {
+       case off:
+               o << trace_prefix
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  << " NoteOff NoteNum "
+                  << (int) msg[1]
+                  << " Vel "
+                  << (int) msg[2]
+                  << endl;
+               break;
+               
+       case on:
+               o << trace_prefix
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  << " NoteOn NoteNum "
+                  << (int) msg[1]
+                  << " Vel "
+                  << (int) msg[2]
+                  << endl;
+               break;
+           
+       case polypress:
+               o << trace_prefix
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  << " PolyPressure"
+                  << (int) msg[1]
+                  << endl;
+               break;
+           
+       case MIDI::controller:
+               o << trace_prefix
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  << " Controller "
+                  << (int) msg[1]
+                  << " Value "
+                  << (int) msg[2]
+                  << endl;
+               break;
+               
+       case program:
+               o << trace_prefix 
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  <<  " Program Change ProgNum "
+                  << (int) msg[1]
+                  << endl;
+               break;
+               
+       case chanpress:
+               o << trace_prefix 
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  << " Channel Pressure "
+                  << (int) msg[1]
+                  << endl;
+               break;
+           
+       case MIDI::pitchbend:
+               o << trace_prefix
+                  << "Channel "
+                  << (msg[0]&0xF)+1
+                  << " Pitch Bend "
+                  << ((msg[2]<<7)|msg[1])
+                  << endl;
+               break;
+           
+       case MIDI::sysex:
+               if (len == 1) {
+                       switch (msg[0]) {
+                       case 0xf8:
+                               o << trace_prefix
+                                  << "Clock"
+                                  << endl;
+                               break;
+                       case 0xfa:
+                               o << trace_prefix
+                                  << "Start"
+                                  << endl;
+                               break;
+                       case 0xfb:
+                               o << trace_prefix
+                                  << "Continue"
+                                  << endl;
+                               break;
+                       case 0xfc:
+                               o << trace_prefix
+                                  << "Stop"
+                                  << endl;
+                               break;
+                       case 0xfe:
+                               o << trace_prefix
+                                  << "Active Sense"
+                                  << endl;
+                               break;
+                       case 0xff:
+                               o << trace_prefix
+                                  << "System Reset"
+                                  << endl;
+                               break;
+                       default:
+                               o << trace_prefix
+                                  << "System Exclusive (1 byte : " << hex << (int) *msg << dec << ')'
+                                  << endl;             
+                               break;
+                       } 
+               } else {
+                       o << trace_prefix
+                          << "System Exclusive (" << len << ") = [ " << hex;
+                       for (unsigned int i = 0; i < len; ++i) {
+                               o << (int) msg[i] << ' ';
+                       }
+                       o << dec << ']' << endl;
+                       
+               }
+               break;
+           
+       case MIDI::song:
+               o << trace_prefix << "Song" << endl;
+               break;
+           
+       case MIDI::tune:
+               o << trace_prefix << "Tune" << endl;
+               break;
+           
+       case MIDI::eox:
+               o << trace_prefix << "End-of-System Exclusive" << endl;
+               break;
+           
+       case MIDI::timing:
+               o << trace_prefix << "Timing" << endl;
+               break;
+           
+       case MIDI::start:
+               o << trace_prefix << "Start" << endl;
+               break;
+           
+       case MIDI::stop:
+               o << trace_prefix << "Stop" << endl;
+               break;
+           
+       case MIDI::contineu:
+               o << trace_prefix << "Continue" << endl;
+               break;
+           
+       case active:
+               o << trace_prefix << "Active Sense" << endl;
+               break;
+           
+       default:
+               o << trace_prefix << "Unrecognized MIDI message" << endl;
+               break;
+       }
+}
+#endif
+
 int
-MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t offset, bool can_record, bool rec_monitors_input)
+MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input)
 {
        // FIXME: waay too much code to duplicate (AudioDiskstream::process)
        int       ret = -1;
@@ -424,7 +599,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
        nframes_t rec_nframes = 0;
        bool      nominally_recording;
        bool      re = record_enabled ();
-       bool      collect_playback = false;
+       bool      collect_playback = true;
 
        /* if we've already processed the frames corresponding to this call,
           just return. this allows multiple routes that are taking input
@@ -461,7 +636,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
        commit_should_unlock = true;
        adjust_capture_position = 0;
 
-       if (nominally_recording || (_session.get_record_enabled() && Config->get_punch_in())) {
+       if (nominally_recording || (_session.get_record_enabled() && _session.config.get_punch_in())) {
                OverlapType ot;
 
                ot = coverage (first_recordable_frame, last_recordable_frame, transport_frame, transport_frame + nframes);
@@ -520,7 +695,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
        if (nominally_recording || rec_nframes) {
 
                // Pump entire port buffer into the ring buffer (FIXME: split cycles?)
-               MidiBuffer& buf = _source_port->get_midi_buffer(nframes, offset);
+               MidiBuffer& buf = _source_port->get_midi_buffer(nframes);
                for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
                        const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
                        assert(ev.buffer());
@@ -537,16 +712,10 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
 
        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;
@@ -556,10 +725,8 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
                /* can't do actual capture yet - waiting for latency effects to finish before we start*/
 
                playback_distance = nframes;
+               collect_playback = false;
 
-       } else {
-
-               collect_playback = true;
        }
 
        if (collect_playback) {
@@ -576,10 +743,13 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
                        necessary_samples = nframes;
                }
 
-               // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
-               // Write into playback buffer here, and whatnot?
-               //cerr << "MDS FIXME: collect playback" << endl;
-
+               // Pump entire port buffer into playback buffer (FIXME: split cycles?)
+               MidiBuffer& buf = _source_port->get_midi_buffer(nframes);
+               for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
+                       const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
+                       assert(ev.buffer());
+                       _playback_buf->write(ev.time() + transport_frame, ev.type(), ev.size(), ev.buffer());
+               }
        }
 
        ret = 0;
@@ -615,20 +785,15 @@ MidiDiskstream::commit (nframes_t nframes)
                adjust_capture_position = 0;
        }
 
-       /* what audio does:
-        * can't do this with midi: write space is in bytes, chunk_frames is in frames
-       if (_slaved) {
-               need_butler = _playback_buf->write_space() >= _playback_buf->capacity() / 2;
-       } else {
-               need_butler = _playback_buf->write_space() >= disk_io_chunk_frames
-                       || _capture_buf->read_space() >= disk_io_chunk_frames;
-       }*/
-       
-       // Use The Counters To calculate how much time the Ringbuffer holds.
        uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
        uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
-       if ((frames_written - frames_read) <= midi_readahead)
+       if ((frames_written - frames_read) + nframes < midi_readahead) {
                need_butler = true;
+       }
+
+       /*cerr << "MDS written: " << frames_written << " - read: " << frames_read <<
+               " = " << frames_written - frames_read
+               << " + " << nframes << " < " << midi_readahead << " = " << need_butler << ")" << endl;*/
        
        if (commit_should_unlock) {
                state_lock.unlock();
@@ -685,13 +850,9 @@ MidiDiskstream::seek (nframes_t frame, bool complete_refill)
 int
 MidiDiskstream::can_internal_playback_seek (nframes_t distance)
 {
-       uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
+       uint32_t frames_read    = g_atomic_int_get(&_frames_read_from_ringbuffer);
        uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
-       if ((frames_written-frames_read) < distance) {
-               return false;
-       } else {
-               return true;
-       }
+       return ((frames_written - frames_read) < distance);
 }
 
 int
@@ -763,11 +924,13 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
                this_read = min(dur,this_read);
 
                if (midi_playlist()->read (*_playback_buf, start, this_read) != this_read) {
-                       error << string_compose(_("MidiDiskstream %1: cannot read %2 from playlist at frame %3"), _id, this_read, 
-                                        start) << endmsg;
+                       error << string_compose(
+                                       _("MidiDiskstream %1: cannot read %2 from playlist at frame %3"),
+                                       _id, this_read, start) << endmsg;
                        return -1;
                }
-               //cout << "this write " << this_read << "start= " << start << endl;
+               
+               //cout << "MDS this read " << this_read << " start = " << start << endl;
                g_atomic_int_add(&_frames_written_to_ringbuffer, this_read);
 
                _read_data_count = _playlist->read_data_count();
@@ -775,7 +938,7 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
                if (reversed) {
 
                        // Swap note ons with note offs here.  etc?
-                       // Fully reversing MIDI required look-ahead (well, behind) to find previous
+                       // Fully reversing MIDI requires look-ahead (well, behind) to find previous
                        // CC values etc.  hard.
 
                } else {
@@ -786,8 +949,8 @@ MidiDiskstream::read (nframes_t& start, nframes_t dur, bool reversed)
                                // Synthesize LoopEvent here, because the next events
                                // written will have non-monotonic timestamps.
                                _playback_buf->write(loop_end - 1, LoopEventType, 0, 0);
-                               //cout << "Pushing LoopEvent ts=" << loop_end-1 
-                               //     << " start+this_read " << start+this_read << endl;
+                               cout << "Pushing LoopEvent ts=" << loop_end-1 
+                                    << " start+this_read " << start+this_read << endl;
 
                                start = loop_start;
                        } else {
@@ -836,14 +999,15 @@ MidiDiskstream::do_refill ()
        // and lets write as much as we need to get this to be midi_readahead;
        uint32_t frames_read = g_atomic_int_get(&_frames_read_from_ringbuffer);
        uint32_t frames_written = g_atomic_int_get(&_frames_written_to_ringbuffer);
-       if ((frames_written-frames_read) >= midi_readahead) {
-               //cout << "Nothing to do. all fine" << endl;
+       if ((frames_written - frames_read) >= midi_readahead) {
+               //cout << "MDS Nothing to do. all fine" << endl;
                return 0;
        }
 
        nframes_t to_read = midi_readahead - (frames_written - frames_read);
 
-       //cout << "read for midi_readahead " << to_read << "  rb_contains: " << frames_written-frames_read << endl;
+       //cout << "MDS read for midi_readahead " << to_read << "  rb_contains: "
+       //      << frames_written - frames_read << endl;
 
        to_read = min(to_read, (max_frames - file_frame));
        
@@ -865,7 +1029,7 @@ MidiDiskstream::do_refill ()
  * written at all unless @a force_flush is true.
  */
 int
-MidiDiskstream::do_flush (RunContext context, bool force_flush)
+MidiDiskstream::do_flush (RunContext /*context*/, bool force_flush)
 {
        uint32_t to_write;
        int32_t ret = 0;
@@ -873,14 +1037,15 @@ MidiDiskstream::do_flush (RunContext context, bool force_flush)
 
        _write_data_count = 0;
 
+       total = _session.transport_frame() - _last_flush_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;
-
-       if (total == 0 || (_capture_buf->read_space() == 0  && _session.transport_speed() == 0) || (total < disk_io_chunk_frames && !force_flush && was_recording)) {
+       if (total == 0 || _capture_buf->read_space() == 0
+                       || (!force_flush && (total < disk_io_chunk_frames && was_recording))) {
                goto out;
        }
 
@@ -903,8 +1068,10 @@ MidiDiskstream::do_flush (RunContext context, bool force_flush)
 
        assert(!destructive());
 
-       if (record_enabled() && _session.transport_frame() - _last_flush_frame > disk_io_chunk_frames) {
-               if ((!_write_source) || _write_source->midi_write (*_capture_buf, to_write) != to_write) {
+       if (record_enabled()
+                       && (   (_session.transport_frame() - _last_flush_frame > disk_io_chunk_frames)
+                               || force_flush)) {
+               if ((!_write_source) || _write_source->midi_write (*_capture_buf, capture_start_frame, to_write) != to_write) {
                        error << string_compose(_("MidiDiskstream %1: cannot write to disk"), _id) << endmsg;
                        return -1;
                } else {
@@ -917,7 +1084,7 @@ out:
 }
 
 void
-MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_capture)
+MidiDiskstream::transport_stopped (struct tm& /*when*/, time_t /*twhen*/, bool abort_capture)
 {
        uint32_t buffer_position;
        bool more_work = true;
@@ -990,9 +1157,9 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                   */
 
                try {
-                       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)));
+                       boost::shared_ptr<Region> rx (RegionFactory::create (srcs, 0,
+                                       total_capture, whole_file_region_name, 0,
+                                       Region::Flag (Region::DefaultFlags|Region::Automatic|Region::WholeFile)));
 
                        region = boost::dynamic_pointer_cast<MidiRegion> (rx);
                        region->special_set_position (capture_info.front()->start);
@@ -1011,7 +1178,7 @@ MidiDiskstream::transport_stopped (struct tm& when, time_t twhen, bool abort_cap
                XMLNode &before = _playlist->get_state();
                _playlist->freeze ();
 
-               for (buffer_position = _write_source->last_capture_start_frame(), ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
+               for (buffer_position = 0, ci = capture_info.begin(); ci != capture_info.end(); ++ci) {
 
                        string region_name;
 
@@ -1090,7 +1257,7 @@ MidiDiskstream::transport_looped (nframes_t transport_frame)
 }
 
 void
-MidiDiskstream::finish_capture (bool rec_monitors_input)
+MidiDiskstream::finish_capture (bool /*rec_monitors_input*/)
 {
        was_recording = false;
        
@@ -1160,7 +1327,7 @@ MidiDiskstream::engage_record_enable ()
        g_atomic_int_set (&_record_enabled, 1);
        
        if (_source_port && Config->get_monitoring_model() == HardwareMonitoring) {
-               _source_port->request_monitor_input (!(Config->get_auto_input() && rolling));
+               _source_port->request_monitor_input (!(_session.config.get_auto_input() && rolling));
        }
 
        // FIXME: Why is this necessary?  Isn't needed for AudioDiskstream...
@@ -1222,8 +1389,8 @@ MidiDiskstream::get_state ()
 
                Location* pi;
 
-               if (Config->get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
-                       snprintf (buf, sizeof (buf), "%" PRIu32, pi->start());
+               if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
+                       snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
                } else {
                        snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
                }
@@ -1380,7 +1547,7 @@ MidiDiskstream::use_new_write_source (uint32_t n)
 }
 
 void
-MidiDiskstream::reset_write_sources (bool mark_write_complete, bool force)
+MidiDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
 {
        if (!recordable()) {
                return;
@@ -1408,7 +1575,7 @@ MidiDiskstream::rename_write_sources ()
 }
 
 void
-MidiDiskstream::set_block_size (nframes_t nframes)
+MidiDiskstream::set_block_size (nframes_t /*nframes*/)
 {
 }
 
@@ -1421,9 +1588,7 @@ void
 MidiDiskstream::monitor_input (bool yn)
 {
        if (_source_port)
-               _source_port->request_monitor_input (yn);
-       else
-               cerr << "MidiDiskstream NO SOURCE PORT TO MONITOR\n";
+               _source_port->ensure_monitor_input (yn);
 }
 
 void
@@ -1464,7 +1629,7 @@ MidiDiskstream::capture_buffer_load () const
 }
 
 int
-MidiDiskstream::use_pending_capture_data (XMLNode& node)
+MidiDiskstream::use_pending_capture_data (XMLNode& /*node*/)
 {
        return 0;
 }
@@ -1473,34 +1638,28 @@ MidiDiskstream::use_pending_capture_data (XMLNode& node)
  * so that an event at \a start has time = 0
  */
 void
-MidiDiskstream::get_playback(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset)
+MidiDiskstream::get_playback (MidiBuffer& dst, nframes_t start, nframes_t end)
 {
-       if (offset == 0) {
-               dst.clear();
-               assert(dst.size() == 0);
-       }
+       dst.clear();
+       assert(dst.size() == 0);
        
        // Reverse.  ... We just don't do reverse, ok?  Back off.
        if (end <= start) {
                return;
        }
 
-       // Check only events added this offset cycle
-       MidiBuffer::iterator this_cycle_start = dst.end();
-       
-       // Translates stamps to be relative to start, but add offset.
-       const size_t events_read = _playback_buf->read(dst, start, end, offset);
+       // Translates stamps to be relative to start
 
-       gint32 frames_read = end-start;
-       cout << "frames read = " << frames_read << " events read = " << events_read << " end=" << end << " start=" << start << " offset= " << offset
-               << " readspace " << _playback_buf->read_space() << " writespace " << _playback_buf->write_space() << endl;
-       g_atomic_int_add(&_frames_read_from_ringbuffer, frames_read);
+       _playback_buf->read(dst, start, end);
+#if 0
+       const size_t events_read = _playback_buf->read(dst, start, end);
+       cout << _name << ": MDS events read = " << events_read
+            << " start = " << start << " end = " << end
+            << " readspace " << _playback_buf->read_space()
+            << " writespace " << _playback_buf->write_space() << endl;
+#endif
        
-       // Now feed the data through the MidiStateTracker.
-       // In case it detects a LoopEvent it will add necessary note
-       // offs.
-
-       if (_midistate_tracker.track(this_cycle_start, dst.end())) {
-               _midistate_tracker.resolve_notes(dst, end-start - 1 + offset);
-       }
+       gint32 frames_read = end - start;
+       g_atomic_int_add(&_frames_read_from_ringbuffer, frames_read);
 }
+