X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_source.cc;h=0314a92c235901178fb3cf532e009554933886a7;hb=6739b6a1e31f943f039b3c1678190af4fe0f8d16;hp=0f3df97f9b1216c8587988544013cbfb90ae393b;hpb=1693e57e0ee37c6cd74f2feadb3af6249ac6c29d;p=ardour.git diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 0f3df97f9b..0314a92c23 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -34,13 +34,15 @@ #include "pbd/pthread_utils.h" #include "pbd/basename.h" +#include "evoral/Control.hpp" #include "evoral/EventSink.hpp" #include "ardour/debug.h" +#include "ardour/file_source.h" +#include "ardour/midi_channel_filter.h" #include "ardour/midi_model.h" -#include "ardour/midi_state_tracker.h" #include "ardour/midi_source.h" -#include "ardour/file_source.h" +#include "ardour/midi_state_tracker.h" #include "ardour/session.h" #include "ardour/session_directory.h" #include "ardour/source_factory.h" @@ -123,7 +125,7 @@ MidiSource::set_state (const XMLNode& node, int /*version*/) error << _("Missing parameter property on InterpolationStyle") << endmsg; return -1; } - Evoral::Parameter p = EventTypeMap::instance().new_parameter (prop->value()); + Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value()); if ((prop = (*i)->property (X_("style"))) == 0) { error << _("Missing style property on InterpolationStyle") << endmsg; @@ -138,7 +140,7 @@ MidiSource::set_state (const XMLNode& node, int /*version*/) error << _("Missing parameter property on AutomationState") << endmsg; return -1; } - Evoral::Parameter p = EventTypeMap::instance().new_parameter (prop->value()); + Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value()); if ((prop = (*i)->property (X_("state"))) == 0) { error << _("Missing state property on AutomationState") << endmsg; @@ -176,22 +178,22 @@ MidiSource::update_length (framecnt_t) } void -MidiSource::invalidate () +MidiSource::invalidate (const Lock& lock, std::set::WeakNotePtr>* notes) { _model_iter_valid = false; - _model_iter.invalidate(); + _model_iter.invalidate(notes); } framecnt_t -MidiSource::midi_read (Evoral::EventSink& dst, +MidiSource::midi_read (const Lock& lm, + Evoral::EventSink& dst, framepos_t source_start, framepos_t start, framecnt_t cnt, MidiStateTracker* tracker, + MidiChannelFilter* filter, const std::set& filtered) const { - Glib::Threads::Mutex::Lock lm (_lock); - BeatsFramesConverter converter(_session.tempo_map(), source_start); DEBUG_TRACE (DEBUG::MidiSourceIO, @@ -200,11 +202,58 @@ MidiSource::midi_read (Evoral::EventSink& dst, if (_model) { // Find appropriate model iterator - Evoral::Sequence::const_iterator& i = _model_iter; - if (_last_read_end == 0 || start != _last_read_end || !_model_iter_valid) { + Evoral::Sequence::const_iterator& i = _model_iter; + const bool linear_read = _last_read_end != 0 && start == _last_read_end; + if (!linear_read || !_model_iter_valid) { +#if 0 // Cached iterator is invalid, search for the first event past start - i = _model->begin(converter.from(start), false, filtered); + i = _model->begin(converter.from(start), false, filtered, + linear_read ? &_model->active_notes() : NULL); + _model_iter_valid = true; + if (!linear_read) { + _model->active_notes().clear(); + } +#else + /* hot-fix http://tracker.ardour.org/view.php?id=6541 + * "parallel playback of linked midi regions -> no note-offs" + * + * A midi source can be used by multiple tracks simultaneously, + * in which case midi_read() may be called from different tracks for + * overlapping time-ranges. + * + * However there is only a single iterator for a given midi-source. + * This results in every midi_read() performing a seek. + * + * If seeking is performed with + * _model->begin(converter.from(start),...) + * the model is used for seeking. That method seeks to the first + * *note-on* event after 'start'. + * + * _model->begin(converter.from( ) ,..) eventually calls + * Sequence