diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 915618037f..cf7ec90fd1 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -160,6 +160,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou void set_solo (bool yn, void *src); bool soloed () const { return self_soloed () || soloed_by_others (); } + void clear_all_solo_state (); bool soloed_by_others () const { return _soloed_by_others_upstream||_soloed_by_others_downstream; } bool soloed_by_others_upstream () const { return _soloed_by_others_upstream; } diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index c627998913..144b3c8670 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -736,6 +736,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop static const SessionEvent::RTeventCallback rt_cleanup; void set_solo (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); + void clear_all_solo_state (boost::shared_ptr); void set_just_one_solo (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup); void set_mute (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_listen (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); @@ -1774,6 +1775,7 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop } void rt_set_solo (boost::shared_ptr, bool yn, bool group_override); + void rt_clear_all_solo_state (boost::shared_ptr, bool yn, bool group_override); void rt_set_just_one_solo (boost::shared_ptr, bool yn, bool /* ignored*/ ); void rt_set_mute (boost::shared_ptr, bool yn, bool group_override); void rt_set_listen (boost::shared_ptr, bool yn, bool group_override); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index aa7a7ee9f8..7f21a6fdc3 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -815,6 +815,42 @@ Route::solo_safe() const return _solo_safe; } +void +Route::clear_all_solo_state () +{ + // ideally this function will never do anything, it only exists to forestall Murphy + bool emit_changed = false; + bool old_safe = _solo_safe; + +#ifndef NDEBUG + // these are really debug messages, but of possible interest. + if (_self_solo) { + PBD::info << string_compose (_("Cleared Explicit solo: %1\n"), name()); + } + if (_soloed_by_others_upstream || _soloed_by_others_downstream) { + PBD::info << string_compose (_("Cleared Implicit solo: %1 up:%2 down:%3\n"), + name(), _soloed_by_others_upstream, _soloed_by_others_downstream); + } +#endif + + if (!_self_solo && (_soloed_by_others_upstream || _soloed_by_others_downstream)) { + // if self-soled, set_solo() will do signal emission + emit_changed = true; + } + + _soloed_by_others_upstream = 0; + _soloed_by_others_downstream = 0; + + _solo_safe = false; // allow set_solo() to do its job; + set_solo (false, this); + _solo_safe = old_safe; + + if (emit_changed) { + set_mute_master_solo (); + solo_changed (false, this); /* EMIT SIGNAL */ + } +} + void Route::set_solo (bool yn, void *src) { @@ -916,7 +952,7 @@ Route::mod_solo_by_others_upstream (int32_t delta) } set_mute_master_solo (); - solo_changed (false, this); + solo_changed (false, this); /* EMIT SIGNAL */ } void @@ -938,7 +974,7 @@ Route::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 (); - solo_changed (false, this); + solo_changed (false, this); /* EMIT SIGNAL */ } void @@ -968,7 +1004,7 @@ Route::mod_solo_isolated_by_upstream (bool yn, void* src) if (solo_isolated() != old) { /* solo isolated status changed */ _mute_master->set_solo_ignore (solo_isolated()); - solo_isolated_changed (src); + solo_isolated_changed (src); /* EMIT SIGNAL */ } } @@ -1024,7 +1060,7 @@ Route::set_solo_isolated (bool yn, void *src) /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */ - solo_isolated_changed (src); + solo_isolated_changed (src); /* EMIT SIGNAL */ } bool diff --git a/libs/ardour/session_rtevents.cc b/libs/ardour/session_rtevents.cc index 189385e2ee..d001b239ba 100644 --- a/libs/ardour/session_rtevents.cc +++ b/libs/ardour/session_rtevents.cc @@ -53,12 +53,31 @@ Session::rt_set_monitoring (boost::shared_ptr rl, MonitorChoice mc, b set_dirty(); } +void +Session::clear_all_solo_state (boost::shared_ptr rl) +{ + queue_event (get_rt_event (rl, false, rt_cleanup, false, &Session::rt_clear_all_solo_state)); +} + +void +Session::rt_clear_all_solo_state (boost::shared_ptr rl, bool /* yn */, bool /* group_override */) +{ + for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) { + if ((*i)->is_auditioner()) { + continue; + } + (*i)->clear_all_solo_state(); + } + set_dirty(); +} + void Session::set_solo (boost::shared_ptr rl, bool yn, SessionEvent::RTeventCallback after, bool group_override) { queue_event (get_rt_event (rl, yn, after, group_override, &Session::rt_set_solo)); } + void Session::rt_set_solo (boost::shared_ptr rl, bool yn, bool /* group_override */) {