#endif
#include "ardour/automation_control.h"
+#include "ardour/parameter_descriptor.h"
#include "ardour/route.h"
#include "ardour/session.h"
case GainAutomation:
/* route must mediate group control */
set_gain (val, group_override);
- return;
break;
case TrimAutomation:
/* route must mediate group control */
set_trim (val, group_override);
- return;
break;
case RecEnableAutomation:
rl.reset (new RouteList);
rl->push_back (shared_from_this());
_session.set_record_enabled (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
- return;
break;
case SoloAutomation:
if (Config->get_solo_control_is_listen_control()) {
_session.set_listen (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
} else {
- _session.set_solo (rl, val >= 0.5 ? true : false);
+ _session.set_solo (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
}
-
- return;
break;
case MuteAutomation:
/* session must mediate group control */
rl.reset (new RouteList);
rl->push_back (shared_from_this());
- _session.set_mute (rl, !muted(), Session::rt_cleanup, group_override);
+ _session.set_mute (rl, val >= 0.5 ? true : false, Session::rt_cleanup, group_override);
return;
break;
{
}
+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)
}
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);
set_list (gl);
}
+void
+Route::SoloControllable::master_changed (bool from_self, PBD::Controllable::GroupControlDisposition gcd)
+{
+ boost::shared_ptr<Route> r = _route.lock ();
+
+ if (!r) {
+ return;
+ }
+
+ bool master_soloed;
+
+ {
+ Glib::Threads::RWLock::ReaderLock lm (master_lock);
+ master_soloed = (bool) get_masters_value_locked ();
+ }
+
+ /* Master is considered equivalent to an upstream solo control, not
+ * direct control over self-soloed.
+ */
+
+ r->mod_solo_by_others_upstream (master_soloed ? 1 : -1);
+
+ AutomationControl::master_changed (false, gcd);
+}
+
void
Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
{
void
Route::SoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
{
- const bool bval = ((val >= 0.5) ? true : false);
-
- boost::shared_ptr<RouteList> rl (new RouteList);
-
boost::shared_ptr<Route> r = _route.lock ();
if (!r) {
return;
}
-
- rl->push_back (r);
-
- if (Config->get_solo_control_is_listen_control()) {
- _session.set_listen (rl, bval, Session::rt_cleanup, group_override);
- } else {
- _session.set_solo (rl, bval, Session::rt_cleanup, group_override);
- }
+ r->set_control (SoloAutomation, val, group_override);
}
void
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;
}
}
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)));
const bool to_list = _list && ((AutomationList*)_list.get ())->automation_write ();
const double where = _session.audible_frame ();
+
if (to_list) {
/* Note that we really need this:
* if (as == Touch && _list->in_new_write_pass ()) {
Control::set_double (muted, where, to_list);
}
+void
+Route::MuteControllable::master_changed (bool from_self, PBD::Controllable::GroupControlDisposition gcd)
+{
+ bool master_muted;
+
+ {
+ Glib::Threads::RWLock::ReaderLock lm (master_lock);
+ master_muted = (bool) get_masters_value_locked ();
+ }
+
+ boost::shared_ptr<Route> r (_route.lock());
+ if (r) {
+ r->mute_master()->mod_muted_by_others (master_muted ? 1 : -1);
+ }
+
+ AutomationControl::master_changed (false, gcd);
+}
+
void
Route::MuteControllable::set_value (double val, PBD::Controllable::GroupControlDisposition group_override)
{
void
Route::MuteControllable::_set_value (double val, Controllable::GroupControlDisposition group_override)
{
- const bool bval = ((val >= 0.5) ? true : false);
-
boost::shared_ptr<Route> r = _route.lock ();
+
if (!r) {
return;
}
if (_list && ((AutomationList*)_list.get())->automation_playback()) {
// Set superficial/automation value to drive controller (and possibly record)
+ const bool bval = ((val >= 0.5) ? true : false);
set_superficial_value (bval);
// Playing back automation, set route mute directly
r->set_mute (bval, Controllable::NoGroup);
} else {
- // Set from user, queue mute event
- boost::shared_ptr<RouteList> rl (new RouteList);
- rl->push_back (r);
- _session.set_mute (rl, bval, Session::rt_cleanup, group_override);
+ r->set_control (MuteAutomation, val, group_override);
}
}
double
Route::MuteControllable::get_value () const
{
+ if (slaved()) {
+ Glib::Threads::RWLock::ReaderLock lm (master_lock);
+ return get_masters_value_locked () ? 1.0 : 0.0;
+ }
+
if (_list && ((AutomationList*)_list.get())->automation_playback()) {
// Playing back automation, get the value from the list
return AutomationControl::get_value();
// Not playing back automation, get the actual route mute value
boost::shared_ptr<Route> r = _route.lock ();
- return (r && r->muted()) ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+ return (r && r->muted()) ? 1.0 : 0.0;
}
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)));
gl->set_interpolation(Evoral::ControlList::Discrete);
Route::PhaseControllable::get_value () const
{
boost::shared_ptr<Route> r = _route.lock ();
+ if (!r) {
+ return 0.0;
+ }
return (double) r->phase_invert (_current_phase);
}
return _current_phase;
}
+Route::SoloIsolateControllable::SoloIsolateControllable (std::string name, boost::shared_ptr<Route> 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);
+ set_list (gl);
+}
+
+
+double
+Route::SoloIsolateControllable::get_value () const
+{
+ boost::shared_ptr<Route> r = _route.lock ();
+ if (!r) {
+ return 0.0; /* "false" */
+ }
+
+ return r->solo_isolated() ? 1.0 : 0.0;
+}
+
+void
+Route::SoloIsolateControllable::set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
+{
+ _set_value (val, gcd);
+}
+
+void
+Route::SoloIsolateControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition)
+{
+ boost::shared_ptr<Route> r = _route.lock ();
+ if (!r) {
+ return;
+ }
+
+ /* no group semantics yet */
+ r->set_solo_isolated (val >= 0.5 ? true : false);
+}
+
+Route::SoloSafeControllable::SoloSafeControllable (std::string name, boost::shared_ptr<Route> 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);
+ set_list (gl);
+}
+
+void
+Route::SoloSafeControllable::set_value (double val, PBD::Controllable::GroupControlDisposition gcd)
+{
+ _set_value (val, gcd);
+}
+
+void
+Route::SoloSafeControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition)
+{
+ boost::shared_ptr<Route> r = _route.lock ();
+ if (!r) {
+ return;
+ }
+
+ /* no group semantics yet */
+ r->set_solo_safe (val >= 0.5 ? true : false);
+}
+
+double
+Route::SoloSafeControllable::get_value () const
+{
+ boost::shared_ptr<Route> r = _route.lock ();
+ if (!r) {
+ return 0.0; /* "false" */
+ }
+
+ return r->solo_safe() ? 1.0 : 0.0;
+}