rearrange AutomationControl and RouteAutomationControl to get more shared logic and consistent master/slave behaviour

This commit is contained in:
Paul Davis 2016-03-09 10:26:09 -05:00
parent 91f8c0be54
commit 8eb45c518d
5 changed files with 91 additions and 37 deletions

View File

@ -158,6 +158,7 @@ public:
void master_going_away (boost::weak_ptr<AutomationControl>);
virtual void recompute_masters_ratios (double val) { /* do nothing by default */}
virtual double get_masters_value_locked () const;
double get_value_locked() const;
};

View File

@ -477,6 +477,18 @@ public:
boost::weak_ptr<Route> _route;
};
class BooleanRouteAutomationControl : public RouteAutomationControl {
public:
BooleanRouteAutomationControl (const std::string& name,
AutomationType atype,
boost::shared_ptr<AutomationList> alist,
boost::shared_ptr<Route> route)
: RouteAutomationControl (name, atype, alist, route) {}
protected:
double get_masters_value_locked() const;
};
class GainControllable : public GainControl {
public:
GainControllable (Session& session,
@ -501,7 +513,7 @@ public:
boost::weak_ptr<Route> _route;
};
class SoloControllable : public RouteAutomationControl {
class SoloControllable : public BooleanRouteAutomationControl {
public:
SoloControllable (std::string name, boost::shared_ptr<Route>);
void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@ -511,7 +523,7 @@ public:
void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
};
struct MuteControllable : public RouteAutomationControl {
struct MuteControllable : public BooleanRouteAutomationControl {
public:
MuteControllable (std::string name, boost::shared_ptr<Route>);
void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@ -526,7 +538,7 @@ public:
void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
};
class LIBARDOUR_API PhaseControllable : public RouteAutomationControl {
class LIBARDOUR_API PhaseControllable : public BooleanRouteAutomationControl {
public:
PhaseControllable (std::string name, boost::shared_ptr<Route>);
void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@ -539,7 +551,7 @@ public:
void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
};
class LIBARDOUR_API SoloIsolateControllable : public RouteAutomationControl {
class LIBARDOUR_API SoloIsolateControllable : public BooleanRouteAutomationControl {
public:
SoloIsolateControllable (std::string name, boost::shared_ptr<Route>);
void set_value (double, PBD::Controllable::GroupControlDisposition group_override);
@ -549,7 +561,7 @@ public:
void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
};
class LIBARDOUR_API SoloSafeControllable : public RouteAutomationControl {
class LIBARDOUR_API SoloSafeControllable : public BooleanRouteAutomationControl {
public:
SoloSafeControllable (std::string name, boost::shared_ptr<Route>);
void set_value (double, PBD::Controllable::GroupControlDisposition group_override);

View File

@ -69,6 +69,31 @@ AutomationControl::writable() const
return true;
}
double
AutomationControl::get_masters_value_locked () const
{
gain_t v = 1.0;
for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
/* get current master value, scale by our current ratio with that master */
v *= mr->second.master()->get_value () * mr->second.ratio();
}
return min (_desc.upper, v);
}
double
AutomationControl::get_value_locked() const
{
/* read or write masters lock must be held */
if (_masters.empty()) {
return Control::get_double (false, _session.transport_frame());
}
return get_masters_value_locked ();
}
/** Get the current effective `user' value based on automation state */
double
AutomationControl::get_value() const
@ -83,27 +108,6 @@ AutomationControl::get_value() const
}
}
double
AutomationControl::get_value_locked() const
{
/* read or write masters lock must be held */
if (_masters.empty()) {
return Control::get_double (false, _session.transport_frame());
}
gain_t v = 1.0;
for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
/* get current master value, scale by our current ratio with that master */
v *= mr->second.master()->get_value () * mr->second.ratio();
}
return min (_desc.upper, v);
}
/** Set the value and do the right thing based on automation state
* (e.g. record if necessary, etc.)
* @param value `user' value
@ -358,4 +362,3 @@ AutomationControl::slaved () const
Glib::Threads::RWLock::ReaderLock lm (master_lock);
return !_masters.empty();
}

View File

@ -5899,8 +5899,8 @@ void
Route::vca_assign (boost::shared_ptr<VCA> vca)
{
_gain_control->add_master (vca->gain_control());
vca->add_solo_target (shared_from_this());
vca->add_mute_target (shared_from_this());
_solo_control->add_master (vca->solo_control());
_mute_control->add_master (vca->mute_control());
}
void
@ -5909,10 +5909,12 @@ Route::vca_unassign (boost::shared_ptr<VCA> vca)
if (!vca) {
/* unassign from all */
_gain_control->clear_masters ();
/* XXXX need to remove from solo/mute target lists */
_solo_control->clear_masters ();
_mute_control->clear_masters ();
} else {
_gain_control->remove_master (vca->gain_control());
vca->remove_solo_target (shared_from_this());
vca->remove_mute_target (shared_from_this());
_solo_control->remove_master (vca->solo_control());
_mute_control->remove_master (vca->mute_control());
}
}

View File

@ -94,6 +94,26 @@ Route::RouteAutomationControl::RouteAutomationControl (const std::string& name,
{
}
double
Route::BooleanRouteAutomationControl::get_masters_value_locked () const
{
/* masters (read/write) lock must be held */
/* if any master is enabled (val > 0.0) then we consider the master
value to be 1.0
*/
for (Masters::const_iterator mr = _masters.begin(); mr != _masters.end(); ++mr) {
if (mr->second.master()->get_value()) {
return 1.0;
}
}
return 0.0;
}
Route::GainControllable::GainControllable (Session& s, AutomationType atype, boost::shared_ptr<Route> r)
: GainControl (s, Evoral::Parameter(atype))
, _route (r)
@ -102,7 +122,7 @@ Route::GainControllable::GainControllable (Session& s, AutomationType atype, boo
}
Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
: RouteAutomationControl (name, SoloAutomation, boost::shared_ptr<AutomationList>(), r)
: BooleanRouteAutomationControl (name, SoloAutomation, boost::shared_ptr<AutomationList>(), r)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloAutomation)));
gl->set_interpolation(Evoral::ControlList::Discrete);
@ -138,7 +158,18 @@ Route::SoloControllable::set_value_unchecked (double val)
double
Route::SoloControllable::get_value () const
{
if (slaved()) {
Glib::Threads::RWLock::ReaderLock lm (master_lock);
return get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
}
if (_list && ((AutomationList*)_list.get())->automation_playback()) {
// Playing back automation, get the value from the list
return AutomationControl::get_value();
}
boost::shared_ptr<Route> r = _route.lock ();
if (!r) {
return 0;
}
@ -151,7 +182,7 @@ Route::SoloControllable::get_value () const
}
Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr<Route> r)
: RouteAutomationControl (name, MuteAutomation, boost::shared_ptr<AutomationList>(), r)
: BooleanRouteAutomationControl (name, MuteAutomation, boost::shared_ptr<AutomationList>(), r)
, _route (r)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(MuteAutomation)));
@ -221,6 +252,11 @@ Route::MuteControllable::_set_value (double val, Controllable::GroupControlDispo
double
Route::MuteControllable::get_value () const
{
if (slaved()) {
Glib::Threads::RWLock::ReaderLock lm (master_lock);
return get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
}
if (_list && ((AutomationList*)_list.get())->automation_playback()) {
// Playing back automation, get the value from the list
return AutomationControl::get_value();
@ -232,7 +268,7 @@ Route::MuteControllable::get_value () const
}
Route::PhaseControllable::PhaseControllable (std::string name, boost::shared_ptr<Route> r)
: RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr<AutomationList>(), r)
: BooleanRouteAutomationControl (name, PhaseAutomation, boost::shared_ptr<AutomationList>(), r)
, _current_phase (0)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(PhaseAutomation)));
@ -276,7 +312,7 @@ Route::PhaseControllable::channel () const
}
Route::SoloIsolateControllable::SoloIsolateControllable (std::string name, boost::shared_ptr<Route> r)
: RouteAutomationControl (name, SoloIsolateAutomation, boost::shared_ptr<AutomationList>(), r)
: BooleanRouteAutomationControl (name, SoloIsolateAutomation, boost::shared_ptr<AutomationList>(), r)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloIsolateAutomation)));
gl->set_interpolation(Evoral::ControlList::Discrete);
@ -314,7 +350,7 @@ Route::SoloIsolateControllable::_set_value (double val, PBD::Controllable::Group
}
Route::SoloSafeControllable::SoloSafeControllable (std::string name, boost::shared_ptr<Route> r)
: RouteAutomationControl (name, SoloSafeAutomation, boost::shared_ptr<AutomationList>(), r)
: BooleanRouteAutomationControl (name, SoloSafeAutomation, boost::shared_ptr<AutomationList>(), r)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(SoloSafeAutomation)));
gl->set_interpolation(Evoral::ControlList::Discrete);