X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Froute_controls.cc;h=ad5408d06d416765628c4b0fe47e1097b36019a0;hb=c107f1ab56270f4485ca2a787d575c2b5b53cfcf;hp=71e44ef91c13431ae3444282715cb6c471bb7ac0;hpb=e2a085190f02cfba8ddbf06a31e37e38c40fafc4;p=ardour.git diff --git a/libs/ardour/route_controls.cc b/libs/ardour/route_controls.cc index 71e44ef91c..ad5408d06d 100644 --- a/libs/ardour/route_controls.cc +++ b/libs/ardour/route_controls.cc @@ -22,6 +22,7 @@ #endif #include "ardour/automation_control.h" +#include "ardour/parameter_descriptor.h" #include "ardour/route.h" #include "ardour/session.h" @@ -40,13 +41,11 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon 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: @@ -54,7 +53,6 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon 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: @@ -64,17 +62,15 @@ Route::set_control (AutomationType type, double val, PBD::Controllable::GroupCon 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; @@ -98,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 r) : GainControl (s, Evoral::Parameter(atype)) , _route (r) @@ -106,13 +122,38 @@ Route::GainControllable::GainControllable (Session& s, AutomationType atype, boo } Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr r) - : RouteAutomationControl (name, SoloAutomation, boost::shared_ptr(), r) + : BooleanRouteAutomationControl (name, SoloAutomation, boost::shared_ptr(), r) { boost::shared_ptr 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 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) { @@ -124,22 +165,11 @@ Route::SoloControllable::set_value (double val, PBD::Controllable::GroupControlD void Route::SoloControllable::_set_value (double val, PBD::Controllable::GroupControlDisposition group_override) { - const bool bval = ((val >= 0.5) ? true : false); - - boost::shared_ptr rl (new RouteList); - boost::shared_ptr 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 @@ -153,7 +183,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 r = _route.lock (); + if (!r) { return 0; } @@ -166,7 +207,7 @@ Route::SoloControllable::get_value () const } Route::MuteControllable::MuteControllable (std::string name, boost::shared_ptr r) - : RouteAutomationControl (name, MuteAutomation, boost::shared_ptr(), r) + : BooleanRouteAutomationControl (name, MuteAutomation, boost::shared_ptr(), r) , _route (r) { boost::shared_ptr gl(new AutomationList(Evoral::Parameter(MuteAutomation))); @@ -182,6 +223,7 @@ Route::MuteControllable::set_superficial_value(bool muted) 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 ()) { @@ -198,6 +240,24 @@ Route::MuteControllable::set_superficial_value(bool muted) 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 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) { @@ -216,29 +276,31 @@ Route::MuteControllable::set_value_unchecked (double val) void Route::MuteControllable::_set_value (double val, Controllable::GroupControlDisposition group_override) { - const bool bval = ((val >= 0.5) ? true : false); - boost::shared_ptr 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 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(); @@ -246,11 +308,12 @@ Route::MuteControllable::get_value () const // Not playing back automation, get the actual route mute value boost::shared_ptr 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 r) - : RouteAutomationControl (name, PhaseAutomation, boost::shared_ptr(), r) + : BooleanRouteAutomationControl (name, PhaseAutomation, boost::shared_ptr(), r) + , _current_phase (0) { boost::shared_ptr gl(new AutomationList(Evoral::Parameter(PhaseAutomation))); gl->set_interpolation(Evoral::ControlList::Discrete); @@ -274,6 +337,9 @@ double Route::PhaseControllable::get_value () const { boost::shared_ptr r = _route.lock (); + if (!r) { + return 0.0; + } return (double) r->phase_invert (_current_phase); } @@ -289,3 +355,77 @@ Route::PhaseControllable::channel () const return _current_phase; } +Route::SoloIsolateControllable::SoloIsolateControllable (std::string name, boost::shared_ptr r) + : BooleanRouteAutomationControl (name, SoloIsolateAutomation, boost::shared_ptr(), r) +{ + boost::shared_ptr gl(new AutomationList(Evoral::Parameter(SoloIsolateAutomation))); + gl->set_interpolation(Evoral::ControlList::Discrete); + set_list (gl); +} + + +double +Route::SoloIsolateControllable::get_value () const +{ + boost::shared_ptr 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 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 r) + : BooleanRouteAutomationControl (name, SoloSafeAutomation, boost::shared_ptr(), r) +{ + boost::shared_ptr 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 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 r = _route.lock (); + if (!r) { + return 0.0; /* "false" */ + } + + return r->solo_safe() ? 1.0 : 0.0; +}