move ever close to working master/slave logic, this time with audio testing
This commit is contained in:
parent
202ddba9e2
commit
69250b64ea
|
@ -1228,7 +1228,7 @@ RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
|
|||
if (r->mute_control()->muted_by_self ()) {
|
||||
/* full mute */
|
||||
return Gtkmm2ext::ExplicitActive;
|
||||
} else if (r->muted_by_others_soloing () || r->muted_by_others()) {
|
||||
} else if (r->muted_by_others_soloing () || r->muted_by_masters ()) {
|
||||
/* this will reflect both solo mutes AND master mutes */
|
||||
return Gtkmm2ext::ImplicitActive;
|
||||
} else {
|
||||
|
@ -1241,7 +1241,7 @@ RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
|
|||
if (r->mute_control()->muted_by_self()) {
|
||||
/* full mute */
|
||||
return Gtkmm2ext::ExplicitActive;
|
||||
} else if (r->muted_by_others()) {
|
||||
} else if (r->muted_by_masters ()) {
|
||||
/* this shows only master mutes, not mute-by-others-soloing */
|
||||
return Gtkmm2ext::ImplicitActive;
|
||||
} else {
|
||||
|
|
|
@ -237,10 +237,9 @@ VCAMasterStrip::set_solo_text ()
|
|||
void
|
||||
VCAMasterStrip::mute_changed ()
|
||||
{
|
||||
std::cerr << "Mute changed for " << _vca->number() << std::endl;
|
||||
if (_vca->mute_control()->muted_by_self()) {
|
||||
mute_button.set_active_state (ExplicitActive);
|
||||
} else if (_vca->mute_control()->muted_by_others()) {
|
||||
} else if (_vca->mute_control()->muted_by_masters ()) {
|
||||
mute_button.set_active_state (ImplicitActive);
|
||||
} else {
|
||||
mute_button.set_active_state (Gtkmm2ext::Off);
|
||||
|
|
|
@ -56,9 +56,12 @@ class LIBARDOUR_API MuteControl : public SlavableAutomationControl
|
|||
|
||||
bool muted () const;
|
||||
bool muted_by_self () const;
|
||||
bool muted_by_masters () const;
|
||||
bool muted_by_self_or_masters () const {
|
||||
return muted_by_self() || muted_by_masters ();
|
||||
}
|
||||
|
||||
bool muted_by_others_soloing () const;
|
||||
bool muted_by_others () const;
|
||||
|
||||
void set_mute_points (MuteMaster::MutePoint);
|
||||
MuteMaster::MutePoint mute_points () const;
|
||||
|
|
|
@ -52,7 +52,9 @@ class LIBARDOUR_API MuteMaster : public SessionHandleRef, public PBD::Stateful
|
|||
|
||||
bool muted_by_self () const { return _muted_by_self && (_mute_point != MutePoint (0)); }
|
||||
bool muted_by_self_at (MutePoint mp) const { return _muted_by_self && (_mute_point & mp); }
|
||||
bool muted_by_others_at (MutePoint mp) const;
|
||||
bool muted_by_others_soloing_at (MutePoint mp) const;
|
||||
bool muted_by_masters () const { return _muted_by_masters && (_mute_point != MutePoint (0)); }
|
||||
bool muted_by_masters_at (MutePoint mp) const { return _muted_by_masters && (_mute_point & mp); }
|
||||
|
||||
gain_t mute_gain_at (MutePoint) const;
|
||||
|
||||
|
@ -69,7 +71,7 @@ class LIBARDOUR_API MuteMaster : public SessionHandleRef, public PBD::Stateful
|
|||
void set_soloed_by_others (bool yn) { _soloed_by_others = yn; }
|
||||
void set_solo_ignore (bool yn) { _solo_ignore = yn; }
|
||||
|
||||
void set_muted_by_others (bool);
|
||||
void set_muted_by_masters (bool);
|
||||
|
||||
PBD::Signal0<void> MutePointChanged;
|
||||
|
||||
|
@ -83,7 +85,7 @@ class LIBARDOUR_API MuteMaster : public SessionHandleRef, public PBD::Stateful
|
|||
bool _soloed_by_self;
|
||||
bool _soloed_by_others;
|
||||
bool _solo_ignore;
|
||||
bool _muted_by_others;
|
||||
bool _muted_by_masters;
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
|
|
@ -460,7 +460,7 @@ public:
|
|||
|
||||
bool can_be_muted_by_others () const { return !is_master(); }
|
||||
bool muted () const { return _mute_control->muted(); }
|
||||
bool muted_by_others () const { return _mute_control->muted_by_others(); }
|
||||
bool muted_by_masters () const { return _mute_control->muted_by_masters(); }
|
||||
bool muted_by_self () const { return _mute_control->muted_by_self(); }
|
||||
bool muted_by_others_soloing () const;
|
||||
|
||||
|
|
|
@ -45,6 +45,11 @@ class SlavableAutomationControl : public AutomationControl
|
|||
return get_masters_value_locked ();
|
||||
}
|
||||
|
||||
/* for toggled/boolean controls, returns a count of the number of
|
||||
masters currently enabled. For other controls, returns zero.
|
||||
*/
|
||||
int32_t get_boolean_masters () const;
|
||||
|
||||
std::vector<PBD::ID> masters () const;
|
||||
|
||||
PBD::Signal0<void> MasterStatusChange;
|
||||
|
@ -96,7 +101,6 @@ class SlavableAutomationControl : public AutomationControl
|
|||
double get_value_locked() const;
|
||||
void actually_set_value (double val, PBD::Controllable::GroupControlDisposition group_override);
|
||||
void update_boolean_masters_records (boost::shared_ptr<AutomationControl>);
|
||||
int32_t get_boolean_masters () const;
|
||||
|
||||
virtual void master_changed (bool from_self, GroupControlDisposition gcd, boost::shared_ptr<AutomationControl>);
|
||||
virtual void recompute_masters_ratios (double val) { /* do nothing by default */}
|
||||
|
|
|
@ -74,6 +74,14 @@ class LIBARDOUR_API SoloControl : public SlavableAutomationControl
|
|||
}
|
||||
bool soloed() const { return self_soloed() || soloed_by_others(); }
|
||||
|
||||
/* The session object needs to respond to solo
|
||||
changes, but to do so accurately it needs to know if we transition
|
||||
into or out of solo. The normal Changed signal doesn't make that
|
||||
possible.
|
||||
*/
|
||||
|
||||
int32_t transitioned_into_solo () const { return _transition_into_solo; }
|
||||
|
||||
void clear_all_solo_state ();
|
||||
|
||||
int set_state (XMLNode const&, int);
|
||||
|
@ -86,11 +94,12 @@ class LIBARDOUR_API SoloControl : public SlavableAutomationControl
|
|||
void post_add_master (boost::shared_ptr<AutomationControl>);
|
||||
|
||||
private:
|
||||
Soloable& _soloable;
|
||||
Muteable& _muteable;
|
||||
bool _self_solo;
|
||||
uint32_t _soloed_by_others_upstream;
|
||||
uint32_t _soloed_by_others_downstream;
|
||||
Soloable& _soloable;
|
||||
Muteable& _muteable;
|
||||
bool _self_solo;
|
||||
uint32_t _soloed_by_others_upstream;
|
||||
uint32_t _soloed_by_others_downstream;
|
||||
int32_t _transition_into_solo;
|
||||
|
||||
void set_self_solo (bool yn);
|
||||
void set_mute_master_solo ();
|
||||
|
|
|
@ -140,7 +140,6 @@ class Stripable : public SessionObject {
|
|||
virtual boost::shared_ptr<AutomationControl> master_send_enable_controllable () const = 0;
|
||||
|
||||
virtual bool muted_by_others_soloing () const = 0;
|
||||
virtual bool muted_by_others () const = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -57,10 +57,8 @@ class LIBARDOUR_API VCA : public Stripable, public Soloable, public Muteable, pu
|
|||
bool can_solo() const { return true; }
|
||||
bool is_safe () const { return false; }
|
||||
|
||||
bool muted () const;
|
||||
bool can_be_muted_by_others () const { return true; }
|
||||
bool muted_by_others_soloing() const { return false; }
|
||||
bool muted_by_others() const { return false; }
|
||||
|
||||
static std::string default_name_template ();
|
||||
static int next_vca_number ();
|
||||
|
|
|
@ -920,7 +920,7 @@ MidiTrack::act_on_mute ()
|
|||
return;
|
||||
}
|
||||
|
||||
if (muted() || _mute_master->muted_by_others_at(MuteMaster::AllPoints)) {
|
||||
if (muted() || _mute_master->muted_by_others_soloing_at (MuteMaster::AllPoints)) {
|
||||
/* only send messages for channels we are using */
|
||||
|
||||
uint16_t mask = _playback_filter.get_channel_mask();
|
||||
|
@ -947,7 +947,7 @@ void
|
|||
MidiTrack::monitoring_changed (bool self, Controllable::GroupControlDisposition gcd)
|
||||
{
|
||||
Track::monitoring_changed (self, gcd);
|
||||
|
||||
|
||||
/* monitoring state changed, so flush out any on notes at the
|
||||
* port level.
|
||||
*/
|
||||
|
|
|
@ -51,6 +51,7 @@ MuteControl::post_add_master (boost::shared_ptr<AutomationControl> m)
|
|||
*/
|
||||
|
||||
if (!muted_by_self() && !get_boolean_masters()) {
|
||||
_muteable.mute_master()->set_muted_by_masters (true);
|
||||
Changed (false, Controllable::NoGroup);
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +62,7 @@ MuteControl::pre_remove_master (boost::shared_ptr<AutomationControl> m)
|
|||
{
|
||||
if (!m) {
|
||||
/* null control ptr means we're removing all masters */
|
||||
_muteable.mute_master()->set_muted_by_others (false);
|
||||
_muteable.mute_master()->set_muted_by_masters (false);
|
||||
/* Changed will be emitted in SlavableAutomationControl::clear_masters() */
|
||||
return;
|
||||
}
|
||||
|
@ -92,16 +93,18 @@ void
|
|||
MuteControl::master_changed (bool self_change, Controllable::GroupControlDisposition gcd, boost::shared_ptr<AutomationControl> m)
|
||||
{
|
||||
bool send_signal = false;
|
||||
const double changed_master_value = m->get_value();
|
||||
boost::shared_ptr<MuteControl> mc = boost::dynamic_pointer_cast<MuteControl> (m);
|
||||
|
||||
if (changed_master_value) {
|
||||
if (m->get_value()) {
|
||||
/* this master is now enabled */
|
||||
if (!muted_by_self() && get_boolean_masters() == 0) {
|
||||
_muteable.mute_master()->set_muted_by_masters (true);
|
||||
send_signal = true;
|
||||
}
|
||||
} else {
|
||||
/* this master is disabled and there was only 1 enabled before */
|
||||
if (!muted_by_self() && get_boolean_masters() == 1) {
|
||||
_muteable.mute_master()->set_muted_by_masters (false);
|
||||
send_signal = true;
|
||||
}
|
||||
}
|
||||
|
@ -117,8 +120,7 @@ double
|
|||
MuteControl::get_value () const
|
||||
{
|
||||
if (slaved ()) {
|
||||
Glib::Threads::RWLock::ReaderLock lm (master_lock);
|
||||
return get_masters_value_locked ();
|
||||
return get_masters_value ();
|
||||
}
|
||||
|
||||
if (_list && boost::dynamic_pointer_cast<AutomationList>(_list)->automation_playback()) {
|
||||
|
@ -149,7 +151,11 @@ MuteControl::mute_points () const
|
|||
bool
|
||||
MuteControl::muted () const
|
||||
{
|
||||
return muted_by_self() || muted_by_others();
|
||||
/* have to get (self-muted) value from somewhere. could be our own
|
||||
Control, or the Muteable that we sort-of proxy for. Since this
|
||||
method is called by ::get_value(), use the latter to avoid recursion.
|
||||
*/
|
||||
return _muteable.mute_master()->muted_by_self() || get_masters_value ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -159,7 +165,8 @@ MuteControl::muted_by_self () const
|
|||
}
|
||||
|
||||
bool
|
||||
MuteControl::muted_by_others () const
|
||||
MuteControl::muted_by_masters () const
|
||||
{
|
||||
return get_masters_value ();
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ MuteMaster::MuteMaster (Session& s, const std::string&)
|
|||
, _soloed_by_self (false)
|
||||
, _soloed_by_others (false)
|
||||
, _solo_ignore (false)
|
||||
, _muted_by_others (0)
|
||||
, _muted_by_masters (0)
|
||||
{
|
||||
|
||||
if (Config->get_mute_affects_pre_fader ()) {
|
||||
|
@ -89,22 +89,22 @@ MuteMaster::mute_gain_at (MutePoint mp) const
|
|||
if (Config->get_solo_mute_override()) {
|
||||
if (_soloed_by_self) {
|
||||
gain = GAIN_COEFF_UNITY;
|
||||
} else if (muted_by_self_at (mp)) {
|
||||
} else if (muted_by_self_at (mp) || muted_by_masters_at (mp)) {
|
||||
gain = GAIN_COEFF_ZERO;
|
||||
} else {
|
||||
if (muted_by_others_at (mp) && !_soloed_by_others) {
|
||||
if (!_soloed_by_others && muted_by_others_soloing_at (mp)) {
|
||||
gain = Config->get_solo_mute_gain ();
|
||||
} else {
|
||||
gain = GAIN_COEFF_UNITY;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (muted_by_self_at (mp)) {
|
||||
if (muted_by_self_at (mp) || muted_by_masters_at (mp)) {
|
||||
gain = GAIN_COEFF_ZERO;
|
||||
} else if (_soloed_by_self || _soloed_by_others) {
|
||||
gain = GAIN_COEFF_UNITY;
|
||||
} else {
|
||||
if (muted_by_others_at (mp)) {
|
||||
if (muted_by_others_soloing_at (mp)) {
|
||||
gain = Config->get_solo_mute_gain ();
|
||||
} else {
|
||||
gain = GAIN_COEFF_UNITY;
|
||||
|
@ -164,14 +164,16 @@ MuteMaster::get_state()
|
|||
}
|
||||
|
||||
bool
|
||||
MuteMaster::muted_by_others_at (MutePoint mp) const
|
||||
MuteMaster::muted_by_others_soloing_at (MutePoint mp) const
|
||||
{
|
||||
return (!_solo_ignore && (_muted_by_others || _session.soloing()) && (_mute_point & mp));
|
||||
/* note: this is currently called with the assumption that the owner is
|
||||
not soloed. it does not test for this condition.
|
||||
*/
|
||||
return (!_solo_ignore && _session.soloing()) && (_mute_point & mp);
|
||||
}
|
||||
|
||||
void
|
||||
MuteMaster::set_muted_by_others (bool yn)
|
||||
MuteMaster::set_muted_by_masters (bool yn)
|
||||
{
|
||||
_muted_by_others = yn;
|
||||
std::cerr << this << " set muted by others to " << yn << std::endl;
|
||||
_muted_by_masters = yn;
|
||||
}
|
||||
|
|
|
@ -5485,8 +5485,6 @@ Route::muted_by_others_soloing () const
|
|||
return false;
|
||||
}
|
||||
|
||||
/* XXX something needed here re: mute-overrides-solo */
|
||||
|
||||
return _session.soloing() && !_solo_control->soloed() && !_solo_isolate_control->solo_isolated();
|
||||
}
|
||||
|
||||
|
|
|
@ -3406,7 +3406,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
|
|||
boost::weak_ptr<Route> wpr (*x);
|
||||
boost::shared_ptr<Route> r (*x);
|
||||
|
||||
r->solo_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
|
||||
r->solo_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2,wpr));
|
||||
r->solo_isolate_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
|
||||
r->mute_control()->Changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
|
||||
|
||||
|
@ -3772,9 +3772,9 @@ Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
|
|||
}
|
||||
|
||||
void
|
||||
Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
|
||||
Session::route_solo_changed (bool self_solo_changed, Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
|
||||
{
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_changed));
|
||||
|
||||
boost::shared_ptr<Route> route (wpr.lock());
|
||||
|
||||
|
@ -3787,20 +3787,27 @@ Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDi
|
|||
return;
|
||||
}
|
||||
|
||||
if (!self_solo_change) {
|
||||
// session doesn't care about changes to soloed-by-others
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: self %2 masters %3 transition %4\n", route->name(), route->self_soloed(), route->solo_control()->get_masters_value(), route->solo_control()->transitioned_into_solo()));
|
||||
|
||||
if (route->solo_control()->transitioned_into_solo() == 0) {
|
||||
/* route solo changed by upstream/downstream; not interesting
|
||||
to Session.
|
||||
*/
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 not self-soloed nor soloed by master (%2), ignoring\n", route->name(), route->solo_control()->get_masters_value()));
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
int32_t delta;
|
||||
|
||||
if (route->self_soloed()) {
|
||||
delta = 1;
|
||||
} else {
|
||||
delta = -1;
|
||||
if (route->solo_control()->transitioned_into_solo() == 0) {
|
||||
/* reason for being soloed changed (e.g. master went away, we
|
||||
* took over the master state), but actual status did
|
||||
* not. nothing to do.
|
||||
*/
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: solo change was change in reason, not status\n", route->name()));
|
||||
}
|
||||
|
||||
boost::shared_ptr<RouteList> r = routes.reader ();
|
||||
int32_t delta = route->solo_control()->transitioned_into_solo ();
|
||||
|
||||
/* the route may be a member of a group that has shared-solo
|
||||
* semantics. If so, then all members of that group should follow the
|
||||
* solo of the changed route. But ... this is optional, controlled by a
|
||||
|
@ -3907,11 +3914,11 @@ Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDi
|
|||
sends are involved.
|
||||
*/
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 feeds %2 via sends only %3 sboD %4 sboU %5\n",
|
||||
route->name(),
|
||||
(*i)->name(),
|
||||
via_sends_only,
|
||||
route->soloed_by_others_downstream(),
|
||||
route->soloed_by_others_upstream()));
|
||||
route->name(),
|
||||
(*i)->name(),
|
||||
via_sends_only,
|
||||
route->soloed_by_others_downstream(),
|
||||
route->soloed_by_others_upstream()));
|
||||
if (!via_sends_only) {
|
||||
//NB. Triggers Invert Push, which handles soloed by downstream
|
||||
DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
|
||||
|
@ -3964,13 +3971,13 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
|
|||
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
|
||||
if ((*i)->can_solo()) {
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
if ((*i)->self_soloed()) {
|
||||
if ((*i)->self_soloed() || (*i)->solo_control()->get_masters_value()) {
|
||||
listeners++;
|
||||
something_listening = true;
|
||||
}
|
||||
} else {
|
||||
(*i)->set_listen (false);
|
||||
if ((*i)->can_solo() && (*i)->self_soloed()) {
|
||||
if ((*i)->can_solo() && ((*i)->self_soloed() || (*i)->solo_control()->get_masters_value())) {
|
||||
something_soloed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ SlavableAutomationControl::update_boolean_masters_records (boost::shared_ptr<Aut
|
|||
really) which have more than a simple scalar
|
||||
value. For example, the master may be a mute control
|
||||
which can be muted_by_self() and/or
|
||||
muted_by_others(). When either of those two
|
||||
muted_by_masters(). When either of those two
|
||||
conditions changes, Changed() will be emitted, even
|
||||
though ::get_value() will return the same value each
|
||||
time (1.0 if either are true, 0.0 if neither is).
|
||||
|
|
|
@ -36,6 +36,7 @@ SoloControl::SoloControl (Session& session, std::string const & name, Soloable&
|
|||
, _self_solo (false)
|
||||
, _soloed_by_others_upstream (0)
|
||||
, _soloed_by_others_downstream (0)
|
||||
, _transition_into_solo (false)
|
||||
{
|
||||
_list->set_interpolation (Evoral::ControlList::Discrete);
|
||||
/* solo changes must be synchronized by the process cycle */
|
||||
|
@ -48,17 +49,29 @@ SoloControl::set_self_solo (bool yn)
|
|||
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: set SELF solo => %2\n", name(), yn));
|
||||
_self_solo = yn;
|
||||
set_mute_master_solo ();
|
||||
|
||||
_transition_into_solo = 0;
|
||||
|
||||
if (yn) {
|
||||
if (get_masters_value() == 0) {
|
||||
_transition_into_solo = 1;
|
||||
}
|
||||
} else {
|
||||
if (get_masters_value() == 0) {
|
||||
_transition_into_solo = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SoloControl::set_mute_master_solo ()
|
||||
{
|
||||
_muteable.mute_master()->set_soloed_by_self (self_soloed());
|
||||
_muteable.mute_master()->set_soloed_by_self (self_soloed() || get_masters_value());
|
||||
|
||||
if (Config->get_solo_control_is_listen_control()) {
|
||||
_muteable.mute_master()->set_soloed_by_others (false);
|
||||
} else {
|
||||
_muteable.mute_master()->set_soloed_by_others (soloed_by_others_downstream() || soloed_by_others_upstream());
|
||||
_muteable.mute_master()->set_soloed_by_others (soloed_by_others_downstream() || soloed_by_others_upstream() || get_masters_value());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,6 +98,7 @@ SoloControl::mod_solo_by_others_downstream (int32_t delta)
|
|||
DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream));
|
||||
|
||||
set_mute_master_solo ();
|
||||
_transition_into_solo = 0;
|
||||
Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
|
@ -139,6 +153,7 @@ SoloControl::mod_solo_by_others_upstream (int32_t delta)
|
|||
}
|
||||
|
||||
set_mute_master_solo ();
|
||||
_transition_into_solo = 0;
|
||||
Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
|
@ -194,7 +209,7 @@ SoloControl::clear_all_solo_state ()
|
|||
_soloed_by_others_downstream = 0;
|
||||
|
||||
set_self_solo (false);
|
||||
|
||||
_transition_into_solo = 0; /* Session does not need to propagate */
|
||||
Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
|
||||
}
|
||||
|
||||
|
@ -239,15 +254,18 @@ void
|
|||
SoloControl::master_changed (bool /*from self*/, GroupControlDisposition, boost::shared_ptr<AutomationControl> m)
|
||||
{
|
||||
bool send_signal = false;
|
||||
const double changed_master_value = m->get_value();
|
||||
|
||||
if (changed_master_value) {
|
||||
_transition_into_solo = 0;
|
||||
|
||||
if (m->get_value()) {
|
||||
/* this master is now enabled */
|
||||
if (!self_soloed() && get_boolean_masters() == 0) {
|
||||
send_signal = true;
|
||||
_transition_into_solo = 1;
|
||||
}
|
||||
} else {
|
||||
if (!self_soloed() && get_boolean_masters() == 1) {
|
||||
_transition_into_solo = -1;
|
||||
send_signal = true;
|
||||
}
|
||||
}
|
||||
|
@ -255,8 +273,10 @@ SoloControl::master_changed (bool /*from self*/, GroupControlDisposition, boost:
|
|||
update_boolean_masters_records (m);
|
||||
|
||||
if (send_signal) {
|
||||
Changed (false, Controllable::NoGroup);
|
||||
set_mute_master_solo ();
|
||||
Changed (false, Controllable::UseGroup);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -271,6 +291,7 @@ SoloControl::post_add_master (boost::shared_ptr<AutomationControl> m)
|
|||
*/
|
||||
|
||||
if (!self_soloed() && !get_boolean_masters()) {
|
||||
_transition_into_solo = 1;
|
||||
Changed (false, Controllable::NoGroup);
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +310,21 @@ SoloControl::pre_remove_master (boost::shared_ptr<AutomationControl> m)
|
|||
|
||||
if (m->get_value()) {
|
||||
if (!self_soloed() && (get_boolean_masters() == 1)) {
|
||||
Changed (false, Controllable::NoGroup);
|
||||
/* we're not self-soloed, this master is, and we're
|
||||
removing
|
||||
it. SlavableAutomationControl::remove_master() will
|
||||
ensure that we reset our own value after actually
|
||||
removing the master, so that our state does not
|
||||
change (this is a precondition of the
|
||||
SlavableAutomationControl API). This will emit
|
||||
Changed(), and we need to make sure that any
|
||||
listener knows that there has been no transition.
|
||||
*/
|
||||
_transition_into_solo = 0;
|
||||
} else {
|
||||
_transition_into_solo = 1;
|
||||
}
|
||||
} else {
|
||||
_transition_into_solo = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,5 +146,3 @@ VCA::set_state (XMLNode const& node, int version)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1227,7 +1227,7 @@ FaderPort::map_mute ()
|
|||
if (_current_route->muted()) {
|
||||
stop_blinking (Mute);
|
||||
get_button (Mute).set_led_state (_output_port, true);
|
||||
} else if (_current_route->mute_control()->muted_by_others()) {
|
||||
} else if (_current_route->muted_by_others_soloing () || _current_route->muted_by_masters()) {
|
||||
start_blinking (Mute);
|
||||
} else {
|
||||
stop_blinking (Mute);
|
||||
|
|
Loading…
Reference in New Issue