Prepare for automation control master
authorRobin Gareus <robin@gareus.org>
Tue, 30 May 2017 13:13:37 +0000 (15:13 +0200)
committerRobin Gareus <robin@gareus.org>
Tue, 30 May 2017 13:13:37 +0000 (15:13 +0200)
Basic infrastructure to allow VCA automation and Trim automation:
look up events during automation playback.

libs/ardour/ardour/slavable_automation_control.h
libs/ardour/automatable.cc
libs/ardour/slavable_automation_control.cc

index f1a78891e4ec196570e3c7afdd125cb1cf83c6ae..8827b29f6b0f89f5e67fb1f403c7353281ccc950 100644 (file)
@@ -64,6 +64,8 @@ class LIBARDOUR_API SlavableAutomationControl : public AutomationControl
        int set_state (XMLNode const&, int);
        XMLNode& get_state();
 
+       bool find_next_event (double now, double end, Evoral::ControlEvent& next_event) const;
+
     protected:
 
        class MasterRecord {
index 00dcdec8f06338758a8e9911b075575d03763f49..462f4f29748065fcce4bcfb4ecb39237e86245f9 100644 (file)
@@ -563,6 +563,13 @@ Automatable::find_next_event (double now, double end, Evoral::ControlEvent& next
                        continue;
                }
 
+               boost::shared_ptr<SlavableAutomationControl> sc
+                       = boost::dynamic_pointer_cast<SlavableAutomationControl>(li->second);
+
+               if (sc) {
+                       sc->find_next_event (now, end, next_event);
+               }
+
                Evoral::ControlList::const_iterator i;
                boost::shared_ptr<const Evoral::ControlList> alist (li->second->list());
                Evoral::ControlEvent cp (now, 0.0f);
index c06d8db7a5ca02143daf0dce5c8c32f2790ca322..51b2d30004eb8a9d3d58a8291f32c502f1f61625 100644 (file)
@@ -344,6 +344,54 @@ SlavableAutomationControl::clear_masters ()
         */
 }
 
+bool
+SlavableAutomationControl::find_next_event (double now, double end, Evoral::ControlEvent& next_event) const
+{
+       Glib::Threads::RWLock::ReaderLock lm (master_lock);
+       if (_masters.empty()) {
+               return false;
+       }
+       bool rv = false;
+       /* iterate over all masters check their automation lists
+        * for any event between "now" and "end" which is earlier than
+        * next_event.when. If found, set next_event.when and return true.
+        * (see also Automatable::find_next_event)
+        */
+       for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
+               boost::shared_ptr<AutomationControl> ac (mr->second.master());
+
+               boost::shared_ptr<SlavableAutomationControl> sc
+                       = boost::dynamic_pointer_cast<SlavableAutomationControl>(ac);
+
+               if (sc && sc->find_next_event (now, end, next_event)) {
+                       rv = true;
+               }
+
+               Evoral::ControlList::const_iterator i;
+               boost::shared_ptr<const Evoral::ControlList> alist (ac->list());
+               Evoral::ControlEvent cp (now, 0.0f);
+               if (!alist) {
+                       continue;
+               }
+
+               for (i = lower_bound (alist->begin(), alist->end(), &cp, Evoral::ControlList::time_comparator);
+                    i != alist->end() && (*i)->when < end; ++i) {
+                       if ((*i)->when > now) {
+                               break;
+                       }
+               }
+
+               if (i != alist->end() && (*i)->when < end) {
+                       if ((*i)->when < next_event.when) {
+                               next_event.when = (*i)->when;
+                               rv = true;
+                       }
+               }
+       }
+
+       return rv;
+}
+
 bool
 SlavableAutomationControl::slaved_to (boost::shared_ptr<AutomationControl> m) const
 {