From f49d11d5e306c8f053856e7c4bf85d1e320adcf4 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Mon, 18 Nov 2019 15:06:59 +0100 Subject: [PATCH] Automation event lookup when rolling backwards When rolling backwards we need to be able to find the *next* event before "start". --- libs/ardour/ardour/automatable.h | 1 + libs/ardour/automatable.cc | 45 +++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/libs/ardour/ardour/automatable.h b/libs/ardour/ardour/automatable.h index 46160c60b0..a9756ebfb4 100644 --- a/libs/ardour/ardour/automatable.h +++ b/libs/ardour/ardour/automatable.h @@ -129,6 +129,7 @@ protected: private: inline void find_next_ac_event (boost::shared_ptr, double start, double end, Evoral::ControlEvent& ev) const; + inline void find_prev_ac_event (boost::shared_ptr, double start, double end, Evoral::ControlEvent& ev) const; PBD::ScopedConnectionList _control_connections; ///< connections to our controls' signals }; diff --git a/libs/ardour/automatable.cc b/libs/ardour/automatable.cc index c146aa9757..47945326ff 100644 --- a/libs/ardour/automatable.cc +++ b/libs/ardour/automatable.cc @@ -620,13 +620,17 @@ Automatable::clear_controls () bool Automatable::find_next_event (double start, double end, Evoral::ControlEvent& next_event, bool only_active) const { - next_event.when = std::numeric_limits::max(); + next_event.when = start <= end ? std::numeric_limits::max() : 0; if (only_active) { boost::shared_ptr cl = _automated_controls.reader (); for (ControlList::const_iterator ci = cl->begin(); ci != cl->end(); ++ci) { if ((*ci)->automation_playback()) { - find_next_ac_event (*ci, start, end, next_event); + if (start <= end) { + find_next_ac_event (*ci, start, end, next_event); + } else { + find_prev_ac_event (*ci, start, end, next_event); + } } } } else { @@ -634,16 +638,22 @@ Automatable::find_next_event (double start, double end, Evoral::ControlEvent& ne boost::shared_ptr c = boost::dynamic_pointer_cast(li->second); if (c) { - find_next_ac_event (c, start, end, next_event); + if (start <= end) { + find_next_ac_event (c, start, end, next_event); + } else { + find_prev_ac_event (c, start, end, next_event); + } } } } - return next_event.when != std::numeric_limits::max(); + return next_event.when != (start <= end ? std::numeric_limits::max() : 0); } void Automatable::find_next_ac_event (boost::shared_ptr c, double start, double end, Evoral::ControlEvent& next_event) const { + assert (start <= end); + boost::shared_ptr sc = boost::dynamic_pointer_cast(c); @@ -670,3 +680,30 @@ Automatable::find_next_ac_event (boost::shared_ptr c, double } } } + +void +Automatable::find_prev_ac_event (boost::shared_ptr c, double start, double end, Evoral::ControlEvent& next_event) const +{ + assert (start > end); + boost::shared_ptr sc + = boost::dynamic_pointer_cast(c); + + if (sc) { + sc->find_next_event (start, end, next_event); + } + + boost::shared_ptr alist (c->list()); + if (!alist) { + return; + } + + Evoral::ControlEvent cp (end, 0.0f); + Evoral::ControlList::const_iterator i = upper_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator); + + while (i != alist->end() && (*i)->when < start) { + if ((*i)->when > next_event.when) { + next_event.when = (*i)->when; + } + ++i; + } +}