+
+ BeatsFramesConverter converter(_session.tempo_map(), source_start);
+
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("MidiSource::midi-read() %5 sstart %1 start %2 cnt %3 tracker %4\n",
+ source_start, start, cnt, tracker, name()));
+
+ if (_model) {
+ Evoral::Sequence<double>::const_iterator& i = _model_iter;
+
+ // If the cached iterator is invalid, search for the first event past start
+ if (_last_read_end == 0 || start != _last_read_end || !_model_iter_valid) {
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("*** %1 search for relevant iterator for %1 / %2\n", _name, source_start, start));
+ for (i = _model->begin(0, false, filtered); i != _model->end(); ++i) {
+ if (converter.to(i->time()) >= start) {
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("***\tstop iterator search @ %1\n", i->time()));
+ break;
+ }
+ }
+ _model_iter_valid = true;
+ } else {
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("*** %1 use cachediterator for %1 / %2\n", _name, source_start, start));
+ }
+
+ _last_read_end = start + cnt;
+
+ // Read events up to end
+ for (; i != _model->end(); ++i) {
+ const framecnt_t time_frames = converter.to(i->time());
+ if (time_frames < start + cnt) {
+ /* convert event times to session frames by adding on the source start position in session frames */
+ dst.write (time_frames + source_start, i->event_type(), i->size(), i->buffer());
+
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: add event @ %2 type %3 size = %4\n",
+ _name, time_frames + source_start, i->event_type(), i->size()));
+
+ if (tracker) {
+ Evoral::MIDIEvent<Evoral::MusicalTime>& ev (*(Evoral::MIDIEvent<Evoral::MusicalTime>*) (&(*i)));
+ if (ev.is_note_on()) {
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("\t%1 track note on %2 @ %3 velocity %4\n", _name, (int) ev.note(), time_frames, (int) ev.velocity()));
+ tracker->add (ev.note(), ev.channel());
+ } else if (ev.is_note_off()) {
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("\t%1 track note off %2 @ %3\n", _name, (int) ev.note(), time_frames));
+ tracker->remove (ev.note(), ev.channel());
+ }
+ }
+ } else {
+ DEBUG_TRACE (DEBUG::MidiSourceIO, string_compose ("%1: reached end with event @ %2 vs. %3\n",
+ _name, time_frames, start+cnt));
+ break;
+ }
+ }
+ return cnt;
+ } else {
+ return read_unlocked (dst, source_start, start, cnt, tracker);
+ }