do not allow smf_source's reads to stomp on cached read_end position in parent class...
[ardour.git] / libs / ardour / smf_source.cc
index b3a6784d1339a13dd2eb549cae73cd227d55ed7b..7fbc8b0287d29296fc5106c292dc8dc03c92e567 100644 (file)
@@ -55,6 +55,7 @@ SMFSource::SMFSource (Session& s, const ustring& path, bool embedded, Source::Fl
        , Evoral::SMF()
        , _last_ev_time_beats(0.0)
        , _last_ev_time_frames(0)
+       , _smf_last_read_end (0)
 {
        if (init(_name, false)) {
                throw failed_constructor ();
@@ -72,6 +73,7 @@ SMFSource::SMFSource (Session& s, const XMLNode& node, bool must_exist)
        , FileSource(s, node, must_exist)
        , _last_ev_time_beats(0.0)
        , _last_ev_time_frames(0)
+       , _smf_last_read_end (0)
 {
        if (set_state(node)) {
                throw failed_constructor ();
@@ -95,7 +97,7 @@ SMFSource::~SMFSource ()
 
 /** All stamps in audio frames */
 nframes_t
-SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t position,
+SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t source_start,
                sframes_t start, nframes_t duration,
                sframes_t stamp_offset, sframes_t negative_stamp_offset) const
 {
@@ -112,24 +114,24 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t posi
 
        size_t scratch_size = 0; // keep track of scratch to minimize reallocs
        
-       BeatsFramesConverter converter(_session, position);
+       BeatsFramesConverter converter(_session, source_start);
 
        const uint64_t start_ticks = (uint64_t)(converter.from(start) * ppqn());
 
-       if (_last_read_end == 0 || start != _last_read_end) {
-               cerr << "SMFSource::read_unlocked seeking to " << start << endl;
+       if (_smf_last_read_end == 0 || start != _smf_last_read_end) {
+               //cerr << "SMFSource::read_unlocked seeking to " << start << endl;
                Evoral::SMF::seek_to_start();
                while (time < start_ticks) {
                        ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
                        if (ret == -1) { // EOF
-                               _last_read_end = start + duration;
+                               _smf_last_read_end = start + duration;
                                return duration;
                        }
                        time += ev_delta_t; // accumulate delta time
                }
        }
        
-       _last_read_end = start + duration;
+       _smf_last_read_end = start + duration;
 
        while (true) {
                ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
@@ -171,9 +173,9 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& source, sframes_t position
 {
        _write_data_count = 0;
                
-       nframes_t         event_time;
-       Evoral::EventType event_type;
-       uint32_t          event_size;
+       nframes_t         time;
+       Evoral::EventType type;
+       uint32_t          size;
 
        size_t   buf_capacity = 4;
        uint8_t* buf          = (uint8_t*)malloc(buf_capacity);
@@ -185,36 +187,32 @@ SMFSource::write_unlocked (MidiRingBuffer<nframes_t>& source, sframes_t position
        Evoral::MIDIEvent<nframes_t> ev;
 
        while (true) {
-               bool ret = source.peek_time(&event_time);
-               g_debug ("event_time: %u, last_write_end: %lu, duration: %u", event_time, _last_write_end, duration);
-               if (!ret || event_time > _last_write_end + duration) {
-                       if (!ret) g_debug ("peek failed");
-                       if (event_time > _last_write_end + duration) g_debug ("event_time: %u > last_write_end: %lu + duration: %u", event_time, _last_write_end, duration);
+               bool ret = source.peek_time(&time);
+               if (!ret || time > _last_write_end + duration) {
                        break;
                }
 
-               ret = source.read_prefix(&event_time, &event_type, &event_size);
+               ret = source.read_prefix(&time, &type, &size);
                if (!ret) {
                        cerr << "ERROR: Unable to read event prefix, corrupt MIDI ring buffer" << endl;
                        break;
                }
 
-               if (event_size > buf_capacity) {
-                       buf_capacity = event_size;
-                       buf = (uint8_t*)realloc(buf, event_size);
+               if (size > buf_capacity) {
+                       buf_capacity = size;
+                       buf = (uint8_t*)realloc(buf, size);
                }
 
-               ret = source.read_contents(event_size, buf);
+               ret = source.read_contents(size, buf);
                if (!ret) {
-                       cerr << "ERROR: Read event time/size but not buffer, corrupt MIDI ring buffer" << endl;
+                       cerr << "ERROR: Read time/size but not buffer, corrupt MIDI ring buffer" << endl;
                        break;
                }
                
-               assert(event_time >= position);
-               event_time -= position;
+               assert(time >= position);
+               time -= position;
                
-               ev.set(buf, event_size, event_time);
+               ev.set(buf, size, time);
                ev.set_event_type(EventTypeMap::instance().midi_event_type(ev.buffer()[0]));
                if (!(ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex())) {
                        cerr << "SMFSource: WARNING: caller tried to write non SMF-Event of type "
@@ -260,7 +258,7 @@ SMFSource::append_event_unlocked_beats (const Evoral::Event<double>& ev)
        
        const double delta_time_beats   = ev.time() - _last_ev_time_beats;
        const uint32_t delta_time_ticks = (uint32_t)lrint(delta_time_beats * (double)ppqn());
-
+       
        Evoral::SMF::append_event_delta(delta_time_ticks, ev.size(), ev.buffer());
        _last_ev_time_beats = ev.time();
 
@@ -378,10 +376,10 @@ SMFSource::load_model (bool lock, bool force_reload)
 
        if (! _model) {
                _model = boost::shared_ptr<MidiModel>(new MidiModel(this));
-               cerr << _name << " loaded new model " << _model.get() << endl;
+               //cerr << _name << " loaded new model " << _model.get() << endl;
        } else {
-               cerr << _name << " reloading model " << _model.get()
-                       << " (" << _model->n_notes() << " notes)" <<endl;
+               /*cerr << _name << " reloading model " << _model.get()
+                       << " (" << _model->n_notes() << " notes)" << endl;*/
                _model->clear();
        }
 
@@ -400,7 +398,7 @@ SMFSource::load_model (bool lock, bool force_reload)
        while ((ret = read_event(&delta_t, &size, &buf)) >= 0) {
                time += delta_t;
                ev.set(buf, size, time / (double)ppqn());
-               
+
                if (ret > 0) { // didn't skip (meta) event
                        ev.set_event_type(EventTypeMap::instance().midi_event_type(buf[0]));
                        _model->append(ev);