13
0

Apply master-value to automation on disconnect.

This commit is contained in:
Robin Gareus 2017-06-13 20:57:01 +02:00
parent c1912b6d51
commit 8e6f71b8c1
4 changed files with 65 additions and 13 deletions

View File

@ -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<AutomationControl>);
virtual bool boolean_automation_run_locked (framepos_t start, pframes_t len);

View File

@ -314,6 +314,15 @@ SlavableAutomationControl::master_going_away (boost::weak_ptr<AutomationControl>
}
}
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<AutomationControl> m)
{
@ -323,17 +332,20 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> 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<AutomationControl> 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<AutomationControl>());
@ -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

View File

@ -123,6 +123,8 @@ public:
void slide (iterator before, double distance);
void shift (double before, double distance);
void y_transform (boost::function<double(double)> callback);
/** add automation events
* @param when absolute time in samples
* @param value parameter value

View File

@ -250,6 +250,19 @@ ControlList::extend_to (double when)
return true;
}
void
ControlList::y_transform (boost::function<double(double)> 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)
{