From 8e6f71b8c190d2311e5547e349c4cc1fc37f131f Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Tue, 13 Jun 2017 20:57:01 +0200 Subject: Apply master-value to automation on disconnect. --- libs/ardour/ardour/slavable_automation_control.h | 1 + libs/ardour/slavable_automation_control.cc | 62 +++++++++++++++++++----- libs/evoral/evoral/ControlList.hpp | 2 + libs/evoral/src/ControlList.cpp | 13 +++++ 4 files changed, 65 insertions(+), 13 deletions(-) (limited to 'libs') diff --git a/libs/ardour/ardour/slavable_automation_control.h b/libs/ardour/ardour/slavable_automation_control.h index 3cfc22405c..88114d24c6 100644 --- a/libs/ardour/ardour/slavable_automation_control.h +++ b/libs/ardour/ardour/slavable_automation_control.h @@ -138,6 +138,7 @@ protected: bool masters_curve_multiply (framepos_t, framepos_t, float*, framecnt_t) const; virtual double reduce_by_masters_locked (double val, bool) const; + virtual double scale_automation_callback (double val, double ratio) const; virtual bool handle_master_change (boost::shared_ptr); virtual bool boolean_automation_run_locked (framepos_t start, pframes_t len); diff --git a/libs/ardour/slavable_automation_control.cc b/libs/ardour/slavable_automation_control.cc index 53808c862a..a1fd18571a 100644 --- a/libs/ardour/slavable_automation_control.cc +++ b/libs/ardour/slavable_automation_control.cc @@ -314,6 +314,15 @@ SlavableAutomationControl::master_going_away (boost::weak_ptr } } +double +SlavableAutomationControl::scale_automation_callback (double value, double ratio) const +{ + /* derived classes can override this and e.g. add/subtract. */ + value *= ratio; + value = std::max (lower(), std::min(upper(), value)); + return value; +} + void SlavableAutomationControl::remove_master (boost::shared_ptr m) { @@ -323,17 +332,20 @@ SlavableAutomationControl::remove_master (boost::shared_ptr m } pre_remove_master (m); - double new_val = AutomationControl::get_double(); - const double old_val = new_val; + + const double old_val = AutomationControl::get_double(); + + bool update_value = false; + double master_ratio = 0; { Glib::Threads::RWLock::WriterLock lm (master_lock); Masters::const_iterator mi = _masters.find (m->id ()); - /* when un-assigning we apply the master-value permanently */ if (mi != _masters.end()) { - new_val *= mi->second.master_ratio (); + master_ratio = mi->second.master_ratio (); + update_value = true; } if (!_masters.erase (m->id())) { @@ -341,8 +353,19 @@ SlavableAutomationControl::remove_master (boost::shared_ptr m } } - if (old_val != new_val) { - AutomationControl::set_double (new_val, Controllable::NoGroup); + if (update_value) { + /* when un-assigning we apply the master-value permanently */ + double new_val = old_val * master_ratio; + + if (old_val != new_val) { + AutomationControl::set_double (new_val, Controllable::NoGroup); + } + + /* ..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)); + } } MasterStatusChange (); /* EMIT SIGNAL */ @@ -360,8 +383,10 @@ SlavableAutomationControl::clear_masters () return; } - double new_val = AutomationControl::get_double(); - const double old_val = new_val; + const double old_val = AutomationControl::get_double(); + + bool update_value = false; + double master_ratio = 0; /* null ptr means "all masters */ pre_remove_master (boost::shared_ptr()); @@ -371,15 +396,26 @@ SlavableAutomationControl::clear_masters () if (_masters.empty()) { return; } - /* permanently apply masters value */ - new_val *= get_masters_value_locked (); - + master_ratio = get_masters_value_locked (); + update_value = true; _masters.clear (); } - if (old_val != new_val) { - AutomationControl::set_double (new_val, Controllable::NoGroup); + if (update_value) { + /* permanently apply masters value */ + double new_val = old_val * master_ratio; + + if (old_val != new_val) { + AutomationControl::set_double (new_val, Controllable::NoGroup); + } + + /* ..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)); + } } + MasterStatusChange (); /* EMIT SIGNAL */ /* no need to update boolean masters records, since all MRs will have diff --git a/libs/evoral/evoral/ControlList.hpp b/libs/evoral/evoral/ControlList.hpp index 2a80ad5bd4..515067de04 100644 --- a/libs/evoral/evoral/ControlList.hpp +++ b/libs/evoral/evoral/ControlList.hpp @@ -123,6 +123,8 @@ public: void slide (iterator before, double distance); void shift (double before, double distance); + void y_transform (boost::function callback); + /** add automation events * @param when absolute time in samples * @param value parameter value diff --git a/libs/evoral/src/ControlList.cpp b/libs/evoral/src/ControlList.cpp index ce8ea89fc9..92234a6ea7 100644 --- a/libs/evoral/src/ControlList.cpp +++ b/libs/evoral/src/ControlList.cpp @@ -250,6 +250,19 @@ ControlList::extend_to (double when) return true; } +void +ControlList::y_transform (boost::function callback) +{ + { + Glib::Threads::RWLock::WriterLock lm (_lock); + for (iterator i = _events.begin(); i != _events.end(); ++i) { + (*i)->value = callback ((*i)->value); + } + mark_dirty (); + } + maybe_signal_changed (); +} + void ControlList::_x_scale (double factor) { -- cgit v1.2.3