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; bool masters_curve_multiply (framepos_t, framepos_t, float*, framecnt_t) const;
virtual double reduce_by_masters_locked (double val, bool) 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 handle_master_change (boost::shared_ptr<AutomationControl>);
virtual bool boolean_automation_run_locked (framepos_t start, pframes_t len); 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 void
SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m) SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
{ {
@ -323,17 +332,20 @@ SlavableAutomationControl::remove_master (boost::shared_ptr<AutomationControl> m
} }
pre_remove_master (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); Glib::Threads::RWLock::WriterLock lm (master_lock);
Masters::const_iterator mi = _masters.find (m->id ()); Masters::const_iterator mi = _masters.find (m->id ());
/* when un-assigning we apply the master-value permanently */
if (mi != _masters.end()) { if (mi != _masters.end()) {
new_val *= mi->second.master_ratio (); master_ratio = mi->second.master_ratio ();
update_value = true;
} }
if (!_masters.erase (m->id())) { if (!_masters.erase (m->id())) {
@ -341,10 +353,21 @@ 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;
if (old_val != new_val) { if (old_val != new_val) {
AutomationControl::set_double (new_val, Controllable::NoGroup); 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 */ MasterStatusChange (); /* EMIT SIGNAL */
/* no need to update boolean masters records, since the MR will have /* no need to update boolean masters records, since the MR will have
@ -360,8 +383,10 @@ SlavableAutomationControl::clear_masters ()
return; return;
} }
double new_val = AutomationControl::get_double(); const double old_val = AutomationControl::get_double();
const double old_val = new_val;
bool update_value = false;
double master_ratio = 0;
/* null ptr means "all masters */ /* null ptr means "all masters */
pre_remove_master (boost::shared_ptr<AutomationControl>()); pre_remove_master (boost::shared_ptr<AutomationControl>());
@ -371,15 +396,26 @@ SlavableAutomationControl::clear_masters ()
if (_masters.empty()) { if (_masters.empty()) {
return; return;
} }
/* permanently apply masters value */ master_ratio = get_masters_value_locked ();
new_val *= get_masters_value_locked (); update_value = true;
_masters.clear (); _masters.clear ();
} }
if (update_value) {
/* permanently apply masters value */
double new_val = old_val * master_ratio;
if (old_val != new_val) { if (old_val != new_val) {
AutomationControl::set_double (new_val, Controllable::NoGroup); 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 */ MasterStatusChange (); /* EMIT SIGNAL */
/* no need to update boolean masters records, since all MRs will have /* 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 slide (iterator before, double distance);
void shift (double before, double distance); void shift (double before, double distance);
void y_transform (boost::function<double(double)> callback);
/** add automation events /** add automation events
* @param when absolute time in samples * @param when absolute time in samples
* @param value parameter value * @param value parameter value

View File

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