This allows the signal to convey more information, which may be required by some handlers of a control's Changed signal
/* Controllable API */
- void set_value (double v, PBD::Controllable::GroupControlDisposition group_override) {
+ void set_value (double v, PBD::Controllable::GroupControlDisposition gcd) {
T newval = (T) v;
if (newval != _value) {
_value = std::max (_lower, std::min (_upper, newval));
- Changed(); /* EMIT SIGNAL */
+ Changed (true, gcd); /* EMIT SIGNAL */
}
}
MPControl& operator=(const T& v) {
if (v != _value) {
_value = std::max (_lower, std::min (_upper, v));
- Changed (); /* EMIT SIGNAL */
+ Changed (true, PBD::Controllable::UseGroup); /* EMIT SIGNAL */
}
return *this;
}
, _getter (getter)
{}
- void set_value (double v, PBD::Controllable::GroupControlDisposition /*group_override*/) { if (_setter (v)) { Changed(); /* EMIT SIGNAL */ } }
+ void set_value (double v, PBD::Controllable::GroupControlDisposition gcd) { if (_setter (v)) { Changed (true, gcd); /* EMIT SIGNAL */ } }
double get_value () const { return _getter (); }
double internal_to_user (double i) const { return accurate_coefficient_to_dB (i);}
/* Pretend to change value, but do not affect actual route mute. */
void set_superficial_value(bool muted);
-
private:
boost::weak_ptr<Route> _route;
void _set_value (double, PBD::Controllable::GroupControlDisposition group_override);
#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, public SessionSoloNotifications<Session>
+class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
{
public:
enum RecordState {
void reassign_track_numbers ();
uint32_t _track_number_decimals;
- /* solo/mute/notifications (see SessionSoloNotifications object) */
+ /* solo/mute/notifications */
- 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>());
* @param value `user' value
*/
void
-AutomationControl::set_value (double value, PBD::Controllable::GroupControlDisposition /* group_override */)
+AutomationControl::set_value (double value, PBD::Controllable::GroupControlDisposition gcd)
{
bool to_list = _list && ((AutomationList*)_list.get())->automation_write();
Control::set_double (value, _session.transport_frame(), to_list);
- Changed(); /* EMIT SIGNAL */
+ cerr << "AC was set to " << value << endl;
+
+ Changed (true, gcd);
}
void
AutomationControl::set_list (boost::shared_ptr<Evoral::ControlList> list)
{
Control::set_list (list);
- Changed(); /* EMIT SIGNAL */
+ Changed (true, Controllable::NoGroup);
}
void
AutomationControl::add_master (boost::shared_ptr<AutomationControl> m)
{
double current_value;
+ double new_value;
std::pair<Masters::iterator,bool> res;
{
/* Store the connection inside the MasterRecord, so that when we destroy it, the connection is destroyed
and we no longer hear about changes to the AutomationControl.
+
+ Note that we fix the "from_self" argument that will
+ be given to our own Changed signal to "false",
+ because the change came from the master.
*/
- m->Changed.connect_same_thread (res.first->second.connection, boost::bind (&PBD::Signal0<void>::operator(), &Changed));
+
+ m->Changed.connect_same_thread (res.first->second.connection, boost::bind (&PBD::Signal2<void,bool,Controllable::GroupControlDisposition>::operator(), &Changed, false, _2));
}
+
+ new_value = get_value_locked ();
}
if (res.second) {
MasterStatusChange (); /* EMIT SIGNAL */
}
+
+ if (new_value != current_value) {
+ /* effective value changed by master */
+ Changed (false, Controllable::NoGroup);
+ }
+
}
void
AutomationControl::remove_master (boost::shared_ptr<AutomationControl> m)
{
double current_value;
+ double new_value;
Masters::size_type erased = 0;
{
if (erased) {
recompute_masters_ratios (current_value);
}
+ new_value = get_value_locked ();
}
if (erased) {
MasterStatusChange (); /* EMIT SIGNAL */
}
+
+ if (new_value != current_value) {
+ Changed (false, Controllable::NoGroup);
+ }
}
void
AutomationControl::clear_masters ()
{
+ double current_value;
+ double new_value;
bool had_masters = false;
{
Glib::Threads::RWLock::WriterLock lm (master_lock);
+ current_value = get_value_locked ();
if (!_masters.empty()) {
had_masters = true;
}
_masters.clear ();
+ new_value = get_value_locked ();
}
if (had_masters) {
MasterStatusChange (); /* EMIT SIGNAL */
}
+
+ if (new_value != current_value) {
+ Changed (false, Controllable::NoGroup);
+ }
+
}
bool
/* specialize for bool because of set_value() semantics */
namespace ARDOUR {
- template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition /*group_override*/) {
+ template<> void MPControl<bool>::set_value (double v, PBD::Controllable::GroupControlDisposition gcd) {
bool newval = fabs (v) >= 0.5;
if (newval != _value) {
_value = newval;
- Changed(); /* EMIT SIGNAL */
+ Changed (true, gcd); /* EMIT SIGNAL */
}
}
}
}
void
-Route::set_gain (gain_t val, Controllable::GroupControlDisposition group_override)
+Route::set_gain (gain_t val, Controllable::GroupControlDisposition gcd)
{
- if (use_group (group_override, &RouteGroup::is_gain)) {
+ if (use_group (gcd, &RouteGroup::is_gain)) {
if (_route_group->is_relative()) {
if (factor > 0.0f) {
factor = _route_group->get_max_factor(factor);
if (factor == 0.0f) {
- _amp->gain_control()->Changed(); /* EMIT SIGNAL */
+ _amp->gain_control()->Changed (true, gcd); /* EMIT SIGNAL */
return;
}
} else {
factor = _route_group->get_min_factor(factor);
if (factor == 0.0f) {
- _amp->gain_control()->Changed(); /* EMIT SIGNAL */
+ _amp->gain_control()->Changed (true, gcd); /* EMIT SIGNAL */
return;
}
}
}
_mute_master->set_soloed_by_others (false);
- _session.listen_changed (group_override, shared_from_this());
- _solo_control->Changed(); /* EMIT SIGNAL */
+ /* first argument won't matter because solo <=> listen right now */
+ _solo_control->Changed (false, group_override); /* EMIT SIGNAL */
}
}
}
}
void
-Route::set_solo_safe (bool yn, Controllable::GroupControlDisposition /* group_override */)
+Route::set_solo_safe (bool yn, Controllable::GroupControlDisposition gcd)
{
if (_solo_safe != yn) {
_solo_safe = yn;
- _solo_safe_control->Changed(); /* EMIT SIGNAL */
+ _solo_safe_control->Changed (true, gcd); /* EMIT SIGNAL */
}
}
if (emit_changed) {
set_mute_master_solo ();
- _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
- _solo_control->Changed (); /* EMIT SIGNAL */
+ _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
}
}
if (self_soloed() != yn) {
set_self_solo (yn);
- _session.solo_changed (true, group_override, shared_from_this());
- _solo_control->Changed (); /* EMIT SIGNAL */
+ _solo_control->Changed (true, group_override); /* EMIT SIGNAL */
}
assert (Config->get_solo_control_is_listen_control() || !_monitor_send || !_monitor_send->active());
}
set_mute_master_solo ();
- _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
- _solo_control->Changed (); /* EMIT SIGNAL */
+ _solo_control->Changed (false, Controllable::UseGroup); /* 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 ();
- _session.solo_changed (false, Controllable::UseGroup, shared_from_this());
- _solo_control->Changed (); /* EMIT SIGNAL */
+ _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */
}
void
if (solo_isolated() != old) {
/* solo isolated status changed */
_mute_master->set_solo_ignore (solo_isolated());
- _session.solo_isolated_changed (shared_from_this());
- _solo_isolate_control->Changed(); /* EMIT SIGNAL */
+ _solo_isolate_control->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */
}
}
/* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */
- _session.solo_isolated_changed (shared_from_this());
- _solo_isolate_control->Changed(); /* EMIT SIGNAL */
+ _solo_isolate_control->Changed (true, group_override); /* EMIT SIGNAL */
}
bool
mute_points_changed (); /* EMIT SIGNAL */
if (_mute_master->muted_by_self()) {
- _session.mute_changed ();
- _mute_control->Changed (); /* EMIT SIGNAL */
+ _mute_control->Changed (true, Controllable::UseGroup); /* EMIT SIGNAL */
}
}
*/
act_on_mute ();
/* tell everyone else */
- _session.mute_changed ();
- _mute_control->Changed (); /* EMIT SIGNAL */
+ _mute_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */
}
}
{
if (_phase_invert[c] != yn) {
_phase_invert[c] = yn;
- _phase_control->Changed(); /* EMIT SIGNAL */
+ _phase_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */
_session.set_dirty ();
}
}
{
if (_phase_invert != p) {
_phase_invert = p;
- _phase_control->Changed (); /* EMIT SIGNAL */
+ _phase_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */
_session.set_dirty ();
}
}
double
Route::SoloControllable::get_value () const
{
+ std::cerr << "RSC get value\n";
+
if (slaved()) {
+ std::cerr << "slaved solo control, get master value ... ";
Glib::Threads::RWLock::ReaderLock lm (master_lock);
- return get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+ double v = get_masters_value_locked () ? GAIN_COEFF_UNITY : GAIN_COEFF_ZERO;
+ std::cerr << v << std::endl;
}
if (_list && ((AutomationList*)_list.get())->automation_playback()) {
return r->solo_safe() ? 1.0 : 0.0;
}
-
boost::weak_ptr<Route> wpr (*x);
boost::shared_ptr<Route> r (*x);
- /* 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->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));
+
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::shared_ptr<Route> route)
+Session::route_listen_changed (Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
{
+ boost::shared_ptr<Route> route (wpr.lock());
+
+ if (!route) {
+ return;
+ }
+
if (route->listening_via_monitor ()) {
if (Config->get_exclusive_solo()) {
}
void
-Session::_route_solo_isolated_changed (boost::shared_ptr<Route> route)
+Session::route_solo_isolated_changed (boost::weak_ptr<Route> wpr)
{
+ boost::shared_ptr<Route> route (wpr.lock());
+
+ if (!route) {
+ return;
+ }
+
bool send_changed = false;
if (route->solo_isolated()) {
}
void
-Session::_route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override, boost::shared_ptr<Route> route)
+Session::route_solo_changed (bool self_solo_change, Controllable::GroupControlDisposition group_override, boost::weak_ptr<Route> wpr)
{
+ cerr << "route solo change (self ? " << self_solo_change << endl;
+
DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
+ boost::shared_ptr<Route> route (wpr.lock());
+
+ if (!route) {
+ return;
+ }
+
+ if (Config->get_solo_control_is_listen_control()) {
+ route_listen_changed (group_override, wpr);
+ return;
+ }
+
if (!self_solo_change) {
// session doesn't care about changes to soloed-by-others
return;
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_control()->Changed (); /* EMIT SIGNAL */
+ (*i)->mute_control()->Changed (false, Controllable::NoGroup);
}
SoloChanged (); /* EMIT SIGNAL */
} else if (p == "solo-control-is-listen-control") {
solo_control_mode_changed ();
} else if (p == "solo-mute-gain") {
- _solo_cut_control->Changed();
+ _solo_cut_control->Changed (true, Controllable::NoGroup);
} else if (p == "timecode-offset" || p == "timecode-offset-negative") {
last_timecode_valid = false;
} else if (p == "playback-buffer-seconds") {
}
void
-Track::set_record_enabled (bool yn, Controllable::GroupControlDisposition group_override)
+Track::set_record_enabled (bool yn, Controllable::GroupControlDisposition gcd)
{
if (_diskstream->record_safe ()) {
return;
return;
}
- if (use_group (group_override, &RouteGroup::is_recenable)) {
+ if (use_group (gcd, &RouteGroup::is_recenable)) {
_route_group->apply (&Track::set_record_enabled, yn, Controllable::NoGroup);
return;
}
_diskstream->set_record_enabled (yn);
- _rec_enable_control->Changed ();
+ _rec_enable_control->Changed (true, gcd);
}
bool
}
MonitoringChanged (); /* EMIT SIGNAL */
- _monitoring_control->Changed (); /* EMIT SIGNAL */
+ _monitoring_control->Changed (true, gcd);
}
}
static PBD::Signal1<void,Controllable*> Destroyed;
- PBD::Signal0<void> Changed;
+ PBD::Signal2<void,bool,PBD::Controllable::GroupControlDisposition> Changed;
int set_state (const XMLNode&, int version);
XMLNode& get_state ();