Merge event control lists when disconnecting a master-ctrl
authorRobin Gareus <robin@gareus.org>
Wed, 14 Jun 2017 00:39:15 +0000 (02:39 +0200)
committerRobin Gareus <robin@gareus.org>
Wed, 14 Jun 2017 00:40:09 +0000 (02:40 +0200)
libs/ardour/ardour/slavable_automation_control.h
libs/ardour/slavable_automation_control.cc

index 88114d24c60356f364438ad840e6ba7e10c9c4b7..4a3c990147dbe5117a9028ed11dd2810aa5eb068 100644 (file)
@@ -99,6 +99,7 @@ protected:
 
                double val_ctrl () const { return _val_ctrl; }
                double val_master () const { return _val_master; }
+               double val_master_inv () const { return _val_master == 0 ? 1.0 : 1.0 / _val_master; }
 
                double master_ratio () const { return _val_master == 0 ? master()->get_value() : master()->get_value() / _val_master; }
 
index a1fd18571ae08b7b2e607ab7d0d128279af62bc5..46b86c7cf5068310f74b0c036e952ed12f060e74 100644 (file)
@@ -166,7 +166,7 @@ SlavableAutomationControl::reduce_by_masters_locked (double value, bool ignore_a
                        /* need to scale given value by current master's scaling */
                        const double masters_value = get_masters_value_locked();
                        if (masters_value == 0.0) {
-                               value = 0.0;
+                               value = 0.0; // XXX 1.0, see master_ratio(), val_master_inv()
                        } else {
                                value /= masters_value;
                                value = std::max (lower(), std::min(upper(), value));
@@ -337,6 +337,9 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
 
        bool update_value = false;
        double master_ratio = 0;
+       double list_ratio = 1;
+
+       boost::shared_ptr<AutomationControl> master;
 
        {
                Glib::Threads::RWLock::WriterLock lm (master_lock);
@@ -346,6 +349,8 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
                if (mi != _masters.end()) {
                        master_ratio = mi->second.master_ratio ();
                        update_value = true;
+                       master = mi->second.master();
+                       list_ratio *= mi->second.val_master_inv ();
                }
 
                if (!_masters.erase (m->id())) {
@@ -355,17 +360,22 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
 
        if (update_value) {
                /* when un-assigning we apply the master-value permanently */
-                       double new_val = old_val * master_ratio;
+               double new_val = old_val * master_ratio;
 
-                       if (old_val != new_val) {
-                               AutomationControl::set_double (new_val, Controllable::NoGroup);
-                       }
+               if (old_val != new_val) {
+                       AutomationControl::set_double (new_val, Controllable::NoGroup);
+               }
 
-                       /* ..and update automation */
-                       if (_list) {
+               /* ..and update automation */
+               if (_list) {
+                       if (master->automation_playback () && master->list()) {
+                               _list->list_merge (*master->list().get(), boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, _2));
+                               _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, list_ratio));
+                       } else {
                                // do we need to freeze/thaw the list? probably no: iterators & positions don't change
                                _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
                        }
+               }
        }
 
        MasterStatusChange (); /* EMIT SIGNAL */
@@ -385,8 +395,10 @@ SlavableAutomationControl::clear_masters ()
 
        const double old_val = AutomationControl::get_double();
 
+       ControlList masters;
        bool update_value = false;
        double master_ratio = 0;
+       double list_ratio = 1;
 
        /* null ptr means "all masters */
        pre_remove_master (boost::shared_ptr<AutomationControl>());
@@ -396,6 +408,17 @@ SlavableAutomationControl::clear_masters ()
                if (_masters.empty()) {
                        return;
                }
+
+               for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
+                       boost::shared_ptr<AutomationControl> master = mr->second.master();
+                       if (master->automation_playback () && master->list()) {
+                               masters.push_back (mr->second.master());
+                               list_ratio *= mr->second.val_master_inv ();
+                       } else {
+                               list_ratio *= mr->second.master_ratio ();
+                       }
+               }
+
                master_ratio = get_masters_value_locked ();
                update_value = true;
                _masters.clear ();
@@ -411,8 +434,14 @@ SlavableAutomationControl::clear_masters ()
 
                        /* ..and update automation */
                        if (_list) {
-                               // do we need to freeze/thaw the list? probably no: iterators & positions don't change
-                               _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
+                               if (!masters.empty()) {
+                                       for (ControlList::const_iterator m = masters.begin(); m != masters.end(); ++m) {
+                                               _list->list_merge (*(*m)->list().get(), boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, _2));
+                                       }
+                                       _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, list_ratio));
+                               } else {
+                                       _list->y_transform (boost::bind (&SlavableAutomationControl::scale_automation_callback, this, _1, master_ratio));
+                               }
                        }
        }