Route now calls back into Session when solo/mute/listen state changes. All other interested
parties must use the Route::{solo,mute,...}_control()->Changed() to be notified of changes.
The Session requires more information than the Changed signal can provide, in order to
propagate solo/mute changes across the entire Session correctly.
Note that this uses an experimental use of CRTP to isolate a public API within Session
framecnt_t signal_latency() const { return _signal_latency; }
PBD::Signal0<void> active_changed;
- PBD::Signal0<void> phase_invert_changed;
PBD::Signal0<void> denormal_protection_changed;
- PBD::Signal1<void,PBD::Controllable::GroupControlDisposition> listen_changed;
- PBD::Signal2<void,bool,PBD::Controllable::GroupControlDisposition> solo_changed;
- PBD::Signal0<void> solo_safe_changed;
- PBD::Signal0<void> solo_isolated_changed;
PBD::Signal0<void> comment_changed;
- PBD::Signal0<void> mute_changed;
PBD::Signal0<void> mute_points_changed;
/** track numbers - assigned by session
#include "ardour/rc_configuration.h"
#include "ardour/session_configuration.h"
#include "ardour/session_event.h"
+#include "ardour/session_solo_notifications.h"
#include "ardour/interpolation.h"
#include "ardour/plugin.h"
#include "ardour/route.h"
};
/** Ardour Session */
-class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
+class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager, public SessionSoloNotifications<Session>
{
public:
enum RecordState {
void reassign_track_numbers ();
uint32_t _track_number_decimals;
- /* mixer stuff */
+ /* solo/mute/notifications (see SessionSoloNotifications object) */
+
+ friend class SessionSoloNotifications;
+ void _route_listen_changed (PBD::Controllable::GroupControlDisposition, boost::shared_ptr<Route>);
+ void _route_mute_changed ();
+ void _route_solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition group_override, boost::shared_ptr<Route>);
+ void _route_solo_isolated_changed (boost::shared_ptr<Route>);
- void route_listen_changed (PBD::Controllable::GroupControlDisposition, boost::weak_ptr<Route>);
- void route_mute_changed ();
- void route_solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route>);
- void route_solo_isolated_changed (boost::weak_ptr<Route>);
void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
void listen_position_changed ();
--- /dev/null
+/*
+ Copyright (C) 2016 Paul Davis
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef __libardour_session_solo_notifications_h__
+#define __libardour_session_solo_notifications_h__
+
+#include <boost/shared_ptr.hpp>
+#include "pbd/controllable.h"
+
+namespace ARDOUR {
+
+class Route;
+
+template<typename T>
+class SessionSoloNotifications
+{
+ public:
+ void solo_changed (bool self_solo_change, PBD::Controllable::GroupControlDisposition gcd, boost::shared_ptr<Route> route) {
+ static_cast<T*>(this)->_route_solo_changed (self_solo_change, gcd, route);
+ }
+
+ void listen_changed (PBD::Controllable::GroupControlDisposition gcd, boost::shared_ptr<Route> route) {
+ static_cast<T*>(this)->_route_listen_changed (gcd, route);
+ }
+
+ void mute_changed () {
+ static_cast<T*>(this)->_route_mute_changed ();
+ }
+
+ void solo_isolated_changed (boost::shared_ptr<Route> route) {
+ static_cast<T*>(this)->_route_solo_isolated_changed (route);
+ }
+};
+
+} /* namespace */
+
+#endif /* __libardour_session_solo_notifications_h__ */
}
_mute_master->set_soloed_by_others (false);
- listen_changed (group_override); /* EMIT SIGNAL */
+ _session.listen_changed (group_override, shared_from_this());
+ _solo_control->Changed(); /* EMIT SIGNAL */
}
}
}
{
if (_solo_safe != yn) {
_solo_safe = yn;
- solo_safe_changed (); /* EMIT SIGNAL */
_solo_safe_control->Changed(); /* EMIT SIGNAL */
}
}
if (emit_changed) {
set_mute_master_solo ();
- solo_changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
+ _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
+ _solo_control->Changed (); /* EMIT SIGNAL */
}
}
if (self_soloed() != yn) {
set_self_solo (yn);
- solo_changed (true, group_override); /* EMIT SIGNAL */
+ _session.solo_changed (true, group_override, shared_from_this());
_solo_control->Changed (); /* EMIT SIGNAL */
}
}
set_mute_master_solo ();
- solo_changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
+ _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
+ _solo_control->Changed (); /* EMIT SIGNAL */
}
void
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, Controllable::UseGroup); /* EMIT SIGNAL */
+ _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
+ _solo_control->Changed (); /* EMIT SIGNAL */
}
void
if (solo_isolated() != old) {
/* solo isolated status changed */
_mute_master->set_solo_ignore (solo_isolated());
- solo_isolated_changed (); /* EMIT SIGNAL */
+ _session.solo_isolated_changed (shared_from_this());
+ _solo_isolate_control->Changed(); /* EMIT SIGNAL */
}
}
/* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
- solo_isolated_changed (); /* EMIT SIGNAL */
+ _session.solo_isolated_changed (shared_from_this());
_solo_isolate_control->Changed(); /* EMIT SIGNAL */
}
mute_points_changed (); /* EMIT SIGNAL */
if (_mute_master->muted_by_self()) {
- mute_changed (); /* EMIT SIGNAL */
+ _session.mute_changed ();
_mute_control->Changed (); /* EMIT SIGNAL */
}
}
*/
act_on_mute ();
/* tell everyone else */
- mute_changed (); /* EMIT SIGNAL */
+ _session.mute_changed ();
_mute_control->Changed (); /* EMIT SIGNAL */
}
}
{
if (_phase_invert[c] != yn) {
_phase_invert[c] = yn;
- phase_invert_changed (); /* EMIT SIGNAL */
_phase_control->Changed(); /* EMIT SIGNAL */
_session.set_dirty ();
}
{
if (_phase_invert != p) {
_phase_invert = p;
- phase_invert_changed (); /* EMIT SIGNAL */
+ _phase_control->Changed (); /* EMIT SIGNAL */
_session.set_dirty ();
}
}
boost::weak_ptr<Route> wpr (*x);
boost::shared_ptr<Route> r (*x);
- r->listen_changed.connect_same_thread (*this, boost::bind (&Session::route_listen_changed, this, _1, wpr));
- r->solo_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_changed, this, _1, _2, wpr));
- r->solo_isolated_changed.connect_same_thread (*this, boost::bind (&Session::route_solo_isolated_changed, this, wpr));
- r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this));
+ /* we don't connect to control Changed signals for
+ * solo/mute/listen. The Route calls back to use, via
+ * the SessionSoloNotifications API, passing us more
+ * information than would be available from a control Changed signal.
+ */
+
r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
}
void
-Session::route_mute_changed ()
+Session::_route_mute_changed ()
{
set_dirty ();
}
void
-Session::route_listen_changed (Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
+Session::_route_listen_changed (Controllable::GroupControlDisposition group_override, boost::shared_ptr<Route> route)
{
- boost::shared_ptr<Route> route = wpr.lock();
- if (!route) {
- error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_listen_changed")) << endmsg;
- return;
- }
-
if (route->listening_via_monitor ()) {
if (Config->get_exclusive_solo()) {
update_route_solo_state ();
}
+
void
-Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
+Session::_route_solo_isolated_changed (boost::shared_ptr<Route> route)
{
- boost::shared_ptr<Route> route = wpr.lock ();
-
- if (!route) {
- /* should not happen */
- error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_isolated_changed")) << endmsg;
- return;
- }
-
bool send_changed = false;
if (route->solo_isolated()) {
}
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_change, Controllable::GroupControlDisposition group_override, boost::shared_ptr<Route> route)
{
DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
return;
}
- boost::shared_ptr<Route> route = wpr.lock ();
- assert (route);
-
boost::shared_ptr<RouteList> r = routes.reader ();
int32_t delta;
for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1, which neither feeds or is fed by %2\n", (*i)->name(), route->name()));
(*i)->act_on_mute ();
- (*i)->mute_changed ();
+ (*i)->mute_control()->Changed (); /* EMIT SIGNAL */
}
SoloChanged (); /* EMIT SIGNAL */