X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fmidi_source.cc;h=ea0bd15b0c3a78caa3b059bff3565dfe79ddfc7d;hb=2b320d51dd080909a0e305116f1396dd1356200b;hp=b8afba6b3f0804d0770dbffbe7f946fd3ed8d310;hpb=17ace643e4edbec1e5bd7b446d039f8c94beef75;p=ardour.git diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index b8afba6b3f..ea0bd15b0c 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -40,14 +40,16 @@ #include "ardour/debug.h" #include "ardour/file_source.h" #include "ardour/midi_channel_filter.h" +#include "ardour/midi_cursor.h" #include "ardour/midi_model.h" #include "ardour/midi_source.h" #include "ardour/midi_state_tracker.h" #include "ardour/session.h" #include "ardour/session_directory.h" #include "ardour/source_factory.h" +#include "ardour/tempo.h" -#include "i18n.h" +#include "pbd/i18n.h" namespace ARDOUR { template class MidiRingBuffer; } @@ -55,14 +57,10 @@ using namespace std; using namespace ARDOUR; using namespace PBD; -PBD::Signal1 MidiSource::MidiSourceCreated; - MidiSource::MidiSource (Session& s, string name, Source::Flag flags) : Source(s, DataType::MIDI, name, flags) , _writing(false) - , _model_iter_valid(false) , _length_beats(0.0) - , _last_read_end(0) , _capture_length(0) , _capture_loop_length(0) { @@ -71,9 +69,7 @@ MidiSource::MidiSource (Session& s, string name, Source::Flag flags) MidiSource::MidiSource (Session& s, const XMLNode& node) : Source(s, node) , _writing(false) - , _model_iter_valid(false) , _length_beats(0.0) - , _last_read_end(0) , _capture_length(0) , _capture_loop_length(0) { @@ -84,6 +80,8 @@ MidiSource::MidiSource (Session& s, const XMLNode& node) MidiSource::~MidiSource () { + /* invalidate any existing iterators */ + Invalidated (false); } XMLNode& @@ -92,19 +90,19 @@ MidiSource::get_state () XMLNode& node (Source::get_state()); if (_captured_for.length()) { - node.add_property ("captured-for", _captured_for); + node.set_property ("captured-for", _captured_for); } for (InterpolationStyleMap::const_iterator i = _interpolation_style.begin(); i != _interpolation_style.end(); ++i) { XMLNode* child = node.add_child (X_("InterpolationStyle")); - child->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first)); - child->add_property (X_("style"), enum_2_string (i->second)); + child->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first)); + child->set_property (X_("style"), enum_2_string (i->second)); } for (AutomationStateMap::const_iterator i = _automation_state.begin(); i != _automation_state.end(); ++i) { XMLNode* child = node.add_child (X_("AutomationState")); - child->add_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first)); - child->add_property (X_("state"), enum_2_string (i->second)); + child->set_property (X_("parameter"), EventTypeMap::instance().to_symbol (i->first)); + child->set_property (X_("state"), enum_2_string (i->second)); } return node; @@ -113,40 +111,38 @@ MidiSource::get_state () int MidiSource::set_state (const XMLNode& node, int /*version*/) { - XMLProperty const * prop; - if ((prop = node.property ("captured-for")) != 0) { - _captured_for = prop->value(); - } + node.get_property ("captured-for", _captured_for); + std::string str; XMLNodeList children = node.children (); for (XMLNodeConstIterator i = children.begin(); i != children.end(); ++i) { if ((*i)->name() == X_("InterpolationStyle")) { - if ((prop = (*i)->property (X_("parameter"))) == 0) { + if (!(*i)->get_property (X_("parameter"), str)) { error << _("Missing parameter property on InterpolationStyle") << endmsg; return -1; } - Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value()); + Evoral::Parameter p = EventTypeMap::instance().from_symbol (str); - if ((prop = (*i)->property (X_("style"))) == 0) { + if (!(*i)->get_property (X_("style"), str)) { error << _("Missing style property on InterpolationStyle") << endmsg; return -1; } - Evoral::ControlList::InterpolationStyle s = static_cast( - string_2_enum (prop->value(), s)); + Evoral::ControlList::InterpolationStyle s = + static_cast(string_2_enum (str, s)); set_interpolation_of (p, s); } else if ((*i)->name() == X_("AutomationState")) { - if ((prop = (*i)->property (X_("parameter"))) == 0) { + if (!(*i)->get_property (X_("parameter"), str)) { error << _("Missing parameter property on AutomationState") << endmsg; return -1; } - Evoral::Parameter p = EventTypeMap::instance().from_symbol (prop->value()); + Evoral::Parameter p = EventTypeMap::instance().from_symbol (str); - if ((prop = (*i)->property (X_("state"))) == 0) { + if (!(*i)->get_property (X_("state"), str)) { error << _("Missing state property on AutomationState") << endmsg; return -1; } - AutoState s = static_cast (string_2_enum (prop->value(), s)); + AutoState s = static_cast(string_2_enum (str, s)); set_automation_state_of (p, s); } } @@ -178,10 +174,9 @@ MidiSource::update_length (framecnt_t) } void -MidiSource::invalidate (const Lock& lock, std::set::WeakNotePtr>* notes) +MidiSource::invalidate (const Lock& lock) { - _model_iter_valid = false; - _model_iter.invalidate(notes); + Invalidated(_session.transport_rolling()); } framecnt_t @@ -190,106 +185,113 @@ MidiSource::midi_read (const Lock& lm, framepos_t source_start, framepos_t start, framecnt_t cnt, + Evoral::Range* loop_range, + MidiCursor& cursor, MidiStateTracker* tracker, MidiChannelFilter* filter, - const std::set& filtered) const + const std::set& filtered, + const double pos_beats, + const double start_beats) const { BeatsFramesConverter converter(_session.tempo_map(), source_start); + const double start_qn = pos_beats - start_beats; + 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) { - // Find appropriate model iterator - 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, - 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