From e0a1c7690acc0c79c070bb23c992ab6b62cbf2c6 Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Wed, 14 Jun 2017 02:39:15 +0200 Subject: Merge event control lists when disconnecting a master-ctrl --- libs/ardour/ardour/slavable_automation_control.h | 1 + libs/ardour/slavable_automation_control.cc | 47 +++++++++++++++++++----- 2 files changed, 39 insertions(+), 9 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/slavable_automation_control.h b/libs/ardour/ardour/slavable_automation_control.h index 88114d24c6..4a3c990147 100644 --- a/libs/ardour/ardour/slavable_automation_control.h +++ b/libs/ardour/ardour/slavable_automation_control.h @@ -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; } diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc index a1fd18571a..46b86c7cf5 100644 --- a/libs/ardour/slavable_automation_control.cc +++ b/libs/ardour/slavable_automation_control.cc @@ -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 m bool update_value = false; double master_ratio = 0; + double list_ratio = 1; + + boost::shared_ptr master; { Glib::Threads::RWLock::WriterLock lm (master_lock); @@ -346,6 +349,8 @@ SlavableAutomationControl::remove_master (boost::shared_ptr 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 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()); @@ -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 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)); + } } } -- cgit v1.2.3