diff options
Diffstat (limited to 'libs/ardour/route.cc')
-rw-r--r-- | libs/ardour/route.cc | 665 |
1 files changed, 119 insertions, 546 deletions
diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 8207176729..7a3d37d2a7 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -58,6 +58,7 @@ #include "ardour/panner.h" #include "ardour/panner_shell.h" #include "ardour/parameter_descriptor.h" +#include "ardour/phase_control.h" #include "ardour/plugin_insert.h" #include "ardour/port.h" #include "ardour/port_insert.h" @@ -67,6 +68,8 @@ #include "ardour/route_group.h" #include "ardour/send.h" #include "ardour/session.h" +#include "ardour/solo_control.h" +#include "ardour/solo_isolate_control.h" #include "ardour/unknown_processor.h" #include "ardour/utils.h" #include "ardour/vca.h" @@ -84,6 +87,7 @@ PBD::Signal3<int,boost::shared_ptr<Route>, boost::shared_ptr<PluginInsert>, Rout /** Base class for all routable/mixable objects (tracks and busses) */ Route::Route (Session& sess, string name, Flag flg, DataType default_type) : Stripable (sess, name) + , Muteable (sess, name) , Automatable (sess) , GraphNode (sess._process_graph) , _active (true) @@ -99,18 +103,11 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _meter_point (MeterPostFader) , _pending_meter_point (MeterPostFader) , _meter_type (MeterPeak) - , _self_solo (false) - , _soloed_by_others_upstream (0) - , _soloed_by_others_downstream (0) - , _solo_isolated (false) - , _solo_isolated_by_upstream (0) , _denormal_protection (false) , _recordable (true) , _silent (false) , _declickable (false) - , _mute_master (new MuteMaster (sess, name)) , _have_internal_generator (false) - , _solo_safe (false) , _default_type (default_type) , _order_key (0) , _has_order_key (false) @@ -141,21 +138,30 @@ Route::init () /* add standard controls */ - _solo_control.reset (new SoloControllable (X_("solo"), shared_from_this ())); - _mute_control.reset (new MuteControllable (X_("mute"), shared_from_this ())); - _phase_control.reset (new PhaseControllable (X_("phase"), shared_from_this ())); + _gain_control.reset (new GainControl (_session, GainAutomation)); + add_control (_gain_control); - _solo_isolate_control.reset (new SoloIsolateControllable (X_("solo-iso"), shared_from_this ())); - _solo_safe_control.reset (new SoloSafeControllable (X_("solo-safe"), shared_from_this ())); + _trim_control.reset (new GainControl (_session, TrimAutomation)); + add_control (_trim_control); + _solo_control.reset (new SoloControl (_session, X_("solo"), *this, *this)); _solo_control->set_flags (Controllable::Flag (_solo_control->flags() | Controllable::Toggle)); - _mute_control->set_flags (Controllable::Flag (_mute_control->flags() | Controllable::Toggle)); - _phase_control->set_flags (Controllable::Flag (_phase_control->flags() | Controllable::Toggle)); - add_control (_solo_control); + _solo_control->Changed.connect_same_thread (*this, boost::bind (&Route::solo_control_changed, this, _1, _2)); + + _mute_control.reset (new MuteControl (_session, X_("mute"), *this)); + _mute_control->set_flags (Controllable::Flag (_mute_control->flags() | Controllable::Toggle)); add_control (_mute_control); + + _phase_control.reset (new PhaseControl (_session, X_("phase"))); add_control (_phase_control); + _solo_isolate_control.reset (new SoloIsolateControl (_session, X_("solo-iso"), *this, *this)); + add_control (_solo_isolate_control); + + _solo_safe_control.reset (new SoloSafeControl (_session, X_("solo-safe"))); + add_control (_solo_safe_control); + /* panning */ if (!(_flags & Route::MonitorOut)) { @@ -177,9 +183,6 @@ Route::init () * it should be the first processor to be added on every route. */ - _gain_control = boost::shared_ptr<GainControllable> (new GainControllable (_session, GainAutomation, shared_from_this ())); - add_control (_gain_control); - _amp.reset (new Amp (_session, X_("Fader"), _gain_control, true)); add_processor (_amp, PostFader); @@ -196,9 +199,6 @@ Route::init () /* and input trim */ - _trim_control = boost::shared_ptr<GainControllable> (new GainControllable (_session, TrimAutomation, shared_from_this ())); - add_control (_trim_control); - _trim.reset (new Amp (_session, X_("Trim"), _trim_control, false)); _trim->set_display_to_user (false); @@ -399,82 +399,10 @@ Route::ensure_track_or_route_name(string name, Session &session) } void -Route::inc_gain (gain_t factor) -{ - /* To be used ONLY when doing group-relative gain adjustment, from - * ::set_gain() - */ - - float desired_gain = _gain_control->user_double(); - - if (fabsf (desired_gain) < GAIN_COEFF_SMALL) { - // really?! what's the idea here? - _gain_control->route_set_value (0.000001f + (0.000001f * factor)); - } else { - _gain_control->route_set_value (desired_gain + (desired_gain * factor)); - } -} - -void -Route::set_gain (gain_t val, Controllable::GroupControlDisposition gcd) -{ - if (use_group (gcd, &RouteGroup::is_gain)) { - - if (_route_group->is_relative()) { - - gain_t usable_gain = _gain_control->get_value(); - if (usable_gain < 0.000001f) { - usable_gain = 0.000001f; - } - - gain_t delta = val; - if (delta < 0.000001f) { - delta = 0.000001f; - } - - delta -= usable_gain; - - if (delta == 0.0f) - return; - - gain_t factor = delta / usable_gain; - - if (factor > 0.0f) { - factor = _route_group->get_max_factor(factor); - if (factor == 0.0f) { - _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 (true, gcd); /* EMIT SIGNAL */ - return; - } - } - - _route_group->foreach_route (boost::bind (&Route::inc_gain, _1, factor)); - - } else { - - _route_group->foreach_route (boost::bind (&Route::set_gain, _1, val, Controllable::NoGroup)); - } - - return; - } - - if (val == _gain_control->get_value()) { - return; - } - - _gain_control->route_set_value (val); -} - -void Route::set_trim (gain_t val, Controllable::GroupControlDisposition /* group override */) { // TODO route group, see set_gain() - _trim_control->route_set_value (val); + // _trim_control->route_set_value (val); } void @@ -551,7 +479,7 @@ Route::process_output_buffers (BufferSet& bufs, DENORMAL CONTROL/PHASE INVERT ----------------------------------------------------------------------------------------- */ - if (_phase_invert.any ()) { + if (!_phase_control->none()) { int chn = 0; @@ -560,7 +488,7 @@ Route::process_output_buffers (BufferSet& bufs, for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) { Sample* const sp = i->data(); - if (_phase_invert[chn]) { + if (_phase_control->inverted (chn)) { for (pframes_t nx = 0; nx < nframes; ++nx) { sp[nx] = -sp[nx]; sp[nx] += 1.0e-27f; @@ -577,7 +505,7 @@ Route::process_output_buffers (BufferSet& bufs, for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i, ++chn) { Sample* const sp = i->data(); - if (_phase_invert[chn]) { + if (_phase_control->inverted (chn)) { for (pframes_t nx = 0; nx < nframes; ++nx) { sp[nx] = -sp[nx]; } @@ -808,283 +736,46 @@ Route::passthru_silence (framepos_t start_frame, framepos_t end_frame, pframes_t } void -Route::set_listen (bool yn, Controllable::GroupControlDisposition group_override) -{ - if (_solo_safe) { - return; - } - - if (use_group (group_override, &RouteGroup::is_solo)) { - _route_group->foreach_route (boost::bind (&Route::set_listen, _1, yn, Controllable::ForGroup)); - return; - } - - if (_monitor_send) { - if (yn != _monitor_send->active()) { - if (yn) { - _monitor_send->activate (); - _mute_master->set_soloed_by_self (true); - } else { - _monitor_send->deactivate (); - _mute_master->set_soloed_by_self (false); - } - _mute_master->set_soloed_by_others (false); - - /* first argument won't matter because solo <=> listen right now */ - _solo_control->Changed (false, group_override); /* EMIT SIGNAL */ - } - } -} - -bool -Route::listening_via_monitor () const +Route::set_listen (bool yn) { - if (_monitor_send) { - return _monitor_send->active (); + if (yn) { + _monitor_send->activate (); } else { - return false; + _monitor_send->deactivate (); } } void -Route::set_solo_safe (bool yn, Controllable::GroupControlDisposition gcd) +Route::solo_control_changed (bool, Controllable::GroupControlDisposition) { - if (_solo_safe != yn) { - _solo_safe = yn; - _solo_safe_control->Changed (true, gcd); /* EMIT SIGNAL */ - } -} - -bool -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; - -#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; - - { - PBD::Unwinder<bool> uw (_solo_safe, false); - set_solo (false, Controllable::NoGroup); - } - - if (emit_changed) { - set_mute_master_solo (); - _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */ - } -} - -void -Route::set_solo (bool yn, Controllable::GroupControlDisposition group_override) -{ - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1: set solo => %2, grp ? %3 currently self-soloed ? %4\n", - name(), yn, enum_2_string(group_override), self_soloed())); - - if (_solo_safe) { - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 ignore solo change due to solo-safe\n", name())); - return; - } - - if (is_master() || is_monitor() || is_auditioner()) { - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 ignore solo change (master, monitor or auditioner)\n", name())); - return; - } - - if (use_group (group_override, &RouteGroup::is_solo)) { - _route_group->foreach_route (boost::bind (&Route::set_solo, _1, yn, Controllable::ForGroup)); - return; - } - - if (self_soloed() != yn) { - set_self_solo (yn); - _solo_control->Changed (true, group_override); /* EMIT SIGNAL */ - } - - assert (Config->get_solo_control_is_listen_control() || !_monitor_send || !_monitor_send->active()); -} - -void -Route::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 (); -} - -void -Route::mod_solo_by_others_upstream (int32_t delta) -{ - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 mod solo-by-upstream by %2, current up = %3 down = %4\n", - name(), delta, _soloed_by_others_upstream, _soloed_by_others_downstream)); - - uint32_t old_sbu = _soloed_by_others_upstream; - - if (delta < 0) { - if (_soloed_by_others_upstream >= (uint32_t) abs (delta)) { - _soloed_by_others_upstream += delta; - } else { - _soloed_by_others_upstream = 0; - } - } else { - _soloed_by_others_upstream += delta; - } - - DEBUG_TRACE (DEBUG::Solo, string_compose ( - "%1 SbU delta %2 = %3 old = %4 sbd %5 ss %6 exclusive %7\n", - name(), delta, _soloed_by_others_upstream, old_sbu, - _soloed_by_others_downstream, _self_solo, Config->get_exclusive_solo())); - - /* push the inverse solo change to everything that feeds us. - - This is important for solo-within-group. When we solo 1 track out of N that - feed a bus, that track will cause mod_solo_by_upstream (+1) to be called - on the bus. The bus then needs to call mod_solo_by_downstream (-1) on all - tracks that feed it. This will silence them if they were audible because - of a bus solo, but the newly soloed track will still be audible (because - it is self-soloed). - - but .. do this only when we are being told to solo-by-upstream (i.e delta = +1), - not in reverse. + /* nothing to do if we're not using AFL/PFL. But if we are, we need + to alter the active state of the monitor send. */ - if ((_self_solo || _soloed_by_others_downstream) && - ((old_sbu == 0 && _soloed_by_others_upstream > 0) || - (old_sbu > 0 && _soloed_by_others_upstream == 0))) { - - if (delta > 0 || !Config->get_exclusive_solo()) { - DEBUG_TRACE (DEBUG::Solo, string_compose("\t ... INVERT push from %1\n", _name)); - for (FedBy::iterator i = _fed_by.begin(); i != _fed_by.end(); ++i) { - if (i->sends_only) { - continue; - } - boost::shared_ptr<Route> sr = i->r.lock(); - if (sr) { - sr->mod_solo_by_others_downstream (-delta); - } - } - } - } - - set_mute_master_solo (); - cerr << name() << " SC->Changed (false, UseGroup)\n"; - _solo_control->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */ -} - -void -Route::mod_solo_by_others_downstream (int32_t delta) -{ - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 mod solo-by-downstream by %2, current up = %3 down = %4\n", - name(), delta, _soloed_by_others_upstream, _soloed_by_others_downstream)); - - if (delta < 0) { - if (_soloed_by_others_downstream >= (uint32_t) abs (delta)) { - _soloed_by_others_downstream += delta; - } else { - _soloed_by_others_downstream = 0; - } - } else { - _soloed_by_others_downstream += delta; + if (Config->get_solo_control_is_listen_control ()) { + set_listen (_solo_control->self_soloed()); } - - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 SbD delta %2 = %3\n", name(), delta, _soloed_by_others_downstream)); - - set_mute_master_solo (); - _solo_control->Changed (false, Controllable::UseGroup); /* EMIT SIGNAL */ -} - -void -Route::set_mute_master_solo () -{ - _mute_master->set_soloed_by_self (self_soloed()); - _mute_master->set_soloed_by_others (soloed_by_others_downstream() || soloed_by_others_upstream()); } -void -Route::mod_solo_isolated_by_upstream (bool yn) +bool +Route::listening_via_monitor () const { - bool old = solo_isolated (); - DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 mod_solo_isolated_by_upstream cur: %2 d: %3\n", - name(), _solo_isolated_by_upstream, yn ? "+1" : "-1")); - - if (!yn) { - if (_solo_isolated_by_upstream >= 1) { - _solo_isolated_by_upstream--; - } else { - _solo_isolated_by_upstream = 0; - } + if (_monitor_send) { + return _monitor_send->active (); } else { - _solo_isolated_by_upstream++; - } - - if (solo_isolated() != old) { - /* solo isolated status changed */ - _mute_master->set_solo_ignore (solo_isolated()); - _solo_isolate_control->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */ + return false; } } void -Route::set_solo_isolated (bool yn, Controllable::GroupControlDisposition group_override) +Route::push_solo_isolate_upstream (int32_t delta) { - if (is_master() || is_monitor() || is_auditioner()) { - return; - } - - if (use_group (group_override, &RouteGroup::is_solo)) { - _route_group->foreach_route (boost::bind (&Route::set_solo_isolated, _1, yn, Controllable::ForGroup)); - return; - } - - bool changed = false; - - if (yn) { - if (_solo_isolated == false) { - _mute_master->set_solo_ignore (true); - changed = true; - } - _solo_isolated = true; - } else { - if (_solo_isolated == true) { - _solo_isolated = false; - _mute_master->set_solo_ignore (false); - changed = true; - } - } - - - if (!changed) { - return; - } - /* forward propagate solo-isolate status to everything fed by this route, but not those via sends only */ boost::shared_ptr<RouteList> routes = _session.get_routes (); for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { - if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) { + if ((*i).get() == this || !(*i)->can_solo()) { continue; } @@ -1092,87 +783,26 @@ Route::set_solo_isolated (bool yn, Controllable::GroupControlDisposition group_o bool does_feed = feeds (*i, &sends_only); if (does_feed && !sends_only) { - (*i)->mod_solo_isolated_by_upstream (yn); + (*i)->solo_isolate_control()->mod_solo_isolated_by_upstream (delta); } } - - /* XXX should we back-propagate as well? (April 2010: myself and chris goddard think not) */ - - _solo_isolate_control->Changed (true, group_override); /* EMIT SIGNAL */ -} - -bool -Route::solo_isolated () const -{ - return (_solo_isolated == true) || (_solo_isolated_by_upstream > 0); -} - -void -Route::set_mute_points (MuteMaster::MutePoint mp) -{ - _mute_master->set_mute_points (mp); - mute_points_changed (); /* EMIT SIGNAL */ - - if (_mute_master->muted_by_self()) { - _mute_control->Changed (true, Controllable::UseGroup); /* EMIT SIGNAL */ - } } void -Route::set_mute (bool yn, Controllable::GroupControlDisposition group_override) +Route::push_solo_upstream (int delta) { - if (use_group (group_override, &RouteGroup::is_mute)) { - _route_group->foreach_route (boost::bind (&Route::set_mute, _1, yn, Controllable::ForGroup)); - return; - } - - if (muted() != yn) { - _mute_master->set_muted_by_self (yn); - /* allow any derived classes to respond to the mute change - before anybody else knows about it. - */ - act_on_mute (); - /* tell everyone else */ - _mute_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */ + DEBUG_TRACE (DEBUG::Solo, string_compose("\t ... INVERT push from %1\n", _name)); + for (FedBy::iterator i = _fed_by.begin(); i != _fed_by.end(); ++i) { + if (i->sends_only) { + continue; + } + boost::shared_ptr<Route> sr (i->r.lock()); + if (sr) { + sr->solo_control()->mod_solo_by_others_downstream (-delta); + } } } -bool -Route::muted () const -{ - return _mute_master->muted_by_self(); -} - -bool -Route::muted_by_others_soloing () const -{ - // This method is only used by route_ui for display state. - // The real thing is MuteMaster::muted_by_others_at() - - //master is never muted by others - if (is_master()) - return false; - - //now check to see if something is soloed (and I am not) - //see also MuteMaster::mute_gain_at() - return _session.soloing() && !soloed() && !solo_isolated(); -} - -bool -Route::muted_by_others () const -{ - // This method is only used by route_ui for display state. - // The real thing is MuteMaster::muted_by_others_at() - - //master is never muted by others - if (is_master()) - return false; - - //now check to see if something is soloed (and I am not) - //see also MuteMaster::mute_gain_at() - return _mute_master->muted_by_others() || (_session.soloing() && !soloed() && !solo_isolated()); -} - #if 0 static void dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs) @@ -2743,8 +2373,6 @@ Route::state(bool full_state) node->add_property("active", _active?"yes":"no"); string p; - boost::to_string (_phase_invert, p); - node->add_property("phase-invert", p); node->add_property("denormal-protection", _denormal_protection?"yes":"no"); node->add_property("meter-point", enum_2_string (_meter_point)); @@ -2756,18 +2384,9 @@ Route::state(bool full_state) snprintf (buf, sizeof (buf), "%d", _order_key); node->add_property ("order-key", buf); - node->add_property ("self-solo", (_self_solo ? "yes" : "no")); - snprintf (buf, sizeof (buf), "%d", _soloed_by_others_upstream); - node->add_property ("soloed-by-upstream", buf); - snprintf (buf, sizeof (buf), "%d", _soloed_by_others_downstream); - node->add_property ("soloed-by-downstream", buf); - node->add_property ("solo-isolated", solo_isolated() ? "yes" : "no"); - node->add_property ("solo-safe", _solo_safe ? "yes" : "no"); node->add_child_nocopy (_input->state (full_state)); node->add_child_nocopy (_output->state (full_state)); - node->add_child_nocopy (_solo_control->get_state ()); - node->add_child_nocopy (_mute_control->get_state ()); node->add_child_nocopy (_mute_master->get_state ()); if (full_state) { @@ -2866,7 +2485,7 @@ Route::set_state (const XMLNode& node, int version) _strict_io = string_is_affirmative (prop->value()); } - if (is_master() || is_monitor() || is_auditioner()) { + if (!can_solo()) { _mute_master->set_solo_ignore (true); } @@ -2933,31 +2552,10 @@ Route::set_state (const XMLNode& node, int version) // this looks up the internal instrument in processors reset_instrument_info(); - if ((prop = node.property ("self-solo")) != 0) { - set_self_solo (string_is_affirmative (prop->value())); - } - - if ((prop = node.property ("soloed-by-upstream")) != 0) { - _soloed_by_others_upstream = 0; // needed for mod_.... () to work - mod_solo_by_others_upstream (atoi (prop->value())); - } - - if ((prop = node.property ("soloed-by-downstream")) != 0) { - _soloed_by_others_downstream = 0; // needed for mod_.... () to work - mod_solo_by_others_downstream (atoi (prop->value())); - } - - if ((prop = node.property ("solo-isolated")) != 0) { - set_solo_isolated (string_is_affirmative (prop->value()), Controllable::NoGroup); - } - - if ((prop = node.property ("solo-safe")) != 0) { - set_solo_safe (string_is_affirmative (prop->value()), Controllable::NoGroup); - } - - if ((prop = node.property (X_("phase-invert"))) != 0) { - set_phase_invert (boost::dynamic_bitset<> (prop->value ())); - } + _solo_control->set_state (node, version); + _solo_safe_control->set_state (node, version); + _solo_isolate_control->set_state (node, version); + _mute_control->set_state (node, version); if ((prop = node.property (X_("denormal-protection"))) != 0) { set_denormal_protection (string_is_affirmative (prop->value())); @@ -3046,7 +2644,7 @@ Route::set_state (const XMLNode& node, int version) set_remote_control_id_internal (x); } - } else if (child->name() == X_("MuteMaster")) { + } else if (child->name() == MuteMaster::xml_node_name) { _mute_master->set_state (*child, version); } else if (child->name() == Automatable::xml_node_name) { @@ -3089,26 +2687,10 @@ Route::set_state_2X (const XMLNode& node, int version) _mute_master->set_solo_ignore (true); } - if ((prop = node.property (X_("phase-invert"))) != 0) { - boost::dynamic_bitset<> p (_input->n_ports().n_audio ()); - if (string_is_affirmative (prop->value ())) { - p.set (); - } - set_phase_invert (p); - } - if ((prop = node.property (X_("denormal-protection"))) != 0) { set_denormal_protection (string_is_affirmative (prop->value())); } - if ((prop = node.property (X_("soloed"))) != 0) { - bool yn = string_is_affirmative (prop->value()); - - /* XXX force reset of solo status */ - - set_solo (yn); - } - if ((prop = node.property (X_("muted"))) != 0) { bool first = true; @@ -3870,11 +3452,11 @@ Route::input_change_handler (IOChange change, void * /*src*/) contains ConfigurationChanged */ configure_processors (0); - _phase_invert.resize (_input->n_ports().n_audio ()); + _phase_control->resize (_input->n_ports().n_audio ()); io_changed (); /* EMIT SIGNAL */ } - if (_soloed_by_others_upstream || _solo_isolated_by_upstream) { + if (_solo_control->soloed_by_others_upstream() || _solo_isolate_control->solo_isolated_by_upstream()) { int sbou = 0; int ibou = 0; boost::shared_ptr<RouteList> routes = _session.get_routes (); @@ -3889,38 +3471,36 @@ Route::input_change_handler (IOChange change, void * /*src*/) if ((*i)->soloed()) { ++sbou; } - if ((*i)->solo_isolated()) { + if ((*i)->solo_isolate_control()->solo_isolated()) { ++ibou; } } } } - int delta = sbou - _soloed_by_others_upstream; - int idelta = ibou - _solo_isolated_by_upstream; + int delta = sbou - _solo_control->soloed_by_others_upstream(); + int idelta = ibou - _solo_isolate_control->solo_isolated_by_upstream(); if (idelta < -1) { PBD::warning << string_compose ( _("Invalid Solo-Isolate propagation: from:%1 new:%2 - old:%3 = delta:%4"), - _name, ibou, _solo_isolated_by_upstream, idelta) + _name, ibou, _solo_isolate_control->solo_isolated_by_upstream(), idelta) << endmsg; } - if (_soloed_by_others_upstream) { + if (_solo_control->soloed_by_others_upstream()) { // ignore new connections (they're not propagated) if (delta <= 0) { - mod_solo_by_others_upstream (delta); + _solo_control->mod_solo_by_others_upstream (delta); } } - if (_solo_isolated_by_upstream) { + if (_solo_isolate_control->solo_isolated_by_upstream()) { // solo-isolate currently only propagates downstream if (idelta < 0) { - mod_solo_isolated_by_upstream (false); + _solo_isolate_control->mod_solo_isolated_by_upstream (1); } - // TODO think: mod_solo_isolated_by_upstream() does not take delta arg, - // but idelta can't be smaller than -1, can it? //_solo_isolated_by_upstream = ibou; } @@ -3933,11 +3513,11 @@ Route::input_change_handler (IOChange change, void * /*src*/) bool sends_only; bool does_feed = feeds (*i, &sends_only); if (delta <= 0 && does_feed && !sends_only) { - (*i)->mod_solo_by_others_upstream (delta); + (*i)->solo_control()->mod_solo_by_others_upstream (delta); } if (idelta < 0 && does_feed && !sends_only) { - (*i)->mod_solo_isolated_by_upstream (false); + (*i)->solo_isolate_control()->mod_solo_isolated_by_upstream (-1); } } } @@ -3963,7 +3543,7 @@ Route::output_change_handler (IOChange change, void * /*src*/) io_changed (); /* EMIT SIGNAL */ } - if (_soloed_by_others_downstream) { + if (_solo_control->soloed_by_others_downstream()) { int sbod = 0; /* checking all all downstream routes for * explicit of implict solo is a rather drastic measure, @@ -3986,20 +3566,20 @@ Route::output_change_handler (IOChange change, void * /*src*/) } } } - int delta = sbod - _soloed_by_others_downstream; + int delta = sbod - _solo_control->soloed_by_others_downstream(); if (delta <= 0) { // do not allow new connections to change implicit solo (no propagation) - mod_solo_by_others_downstream (delta); + _solo_control->mod_solo_by_others_downstream (delta); // Session::route_solo_changed() does not propagate indirect solo-changes // propagate upstream to tracks for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) { - if ((*i).get() == this || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) { + if ((*i).get() == this || !can_solo()) { continue; } bool sends_only; bool does_feed = (*i)->feeds (shared_from_this(), &sends_only); if (delta != 0 && does_feed && !sends_only) { - (*i)->mod_solo_by_others_downstream (delta); + (*i)->solo_control()->mod_solo_by_others_downstream (delta); } } @@ -4639,41 +4219,6 @@ Route::internal_send_for (boost::shared_ptr<const Route> target) const return boost::shared_ptr<Send>(); } -/** @param c Audio channel index. - * @param yn true to invert phase, otherwise false. - */ -void -Route::set_phase_invert (uint32_t c, bool yn) -{ - if (_phase_invert[c] != yn) { - _phase_invert[c] = yn; - _phase_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */ - _session.set_dirty (); - } -} - -void -Route::set_phase_invert (boost::dynamic_bitset<> p) -{ - if (_phase_invert != p) { - _phase_invert = p; - _phase_control->Changed (true, Controllable::NoGroup); /* EMIT SIGNAL */ - _session.set_dirty (); - } -} - -bool -Route::phase_invert (uint32_t c) const -{ - return _phase_invert[c]; -} - -boost::dynamic_bitset<> -Route::phase_invert () const -{ - return _phase_invert; -} - void Route::set_denormal_protection (bool yn) { @@ -4735,20 +4280,16 @@ Route::gain_control() const return _gain_control; } -boost::shared_ptr<AutomationControl> +boost::shared_ptr<GainControl> Route::trim_control() const { return _trim_control; } -boost::shared_ptr<AutomationControl> +boost::shared_ptr<PhaseControl> Route::phase_control() const { - if (phase_invert().size()) { - return _phase_control; - } else { - return boost::shared_ptr<PhaseControllable>(); - } + return _phase_control; } boost::shared_ptr<AutomationControl> @@ -4841,12 +4382,6 @@ Route::has_io_processor_named (const string& name) return false; } -MuteMaster::MutePoint -Route::mute_points () const -{ - return _mute_master->mute_points (); -} - void Route::set_processor_positions () { @@ -5903,7 +5438,7 @@ Route::vca_assign (boost::shared_ptr<VCA> vca) { _gain_control->add_master (vca->gain_control()); _solo_control->add_master (vca->solo_control()); - _mute_control->add_master (vca->mute_control()); + // _mute_control->add_master (vca->mute_control()); } void @@ -5913,10 +5448,48 @@ Route::vca_unassign (boost::shared_ptr<VCA> vca) /* unassign from all */ _gain_control->clear_masters (); _solo_control->clear_masters (); - _mute_control->clear_masters (); + //_mute_control->clear_masters (); } else { _gain_control->remove_master (vca->gain_control()); _solo_control->remove_master (vca->solo_control()); - _mute_control->remove_master (vca->mute_control()); + //_mute_control->remove_master (vca->mute_control()); + } +} + +bool +Route::muted_by_others_soloing () const +{ + // This method is only used by route_ui for display state. + // The DSP version is MuteMaster::muted_by_others_at() + + if (!can_be_muted_by_others ()) { + return false; + } + + return _session.soloing() && !_solo_control->soloed() && !_solo_isolate_control->solo_isolated(); +} + +bool +Route::muted_by_others () const +{ + // This method is only used by route_ui for display state. + // The DSP version is MuteMaster::muted_by_others_at() + + if (!can_be_muted_by_others()) { + return false; + } + + return _mute_master->muted_by_others(); +} + +void +Route::clear_all_solo_state () +{ + double v = _solo_safe_control->get_value (); + + _solo_control->clear_all_solo_state (); + + if (v != 0.0) { + _solo_safe_control->set_value (v, Controllable::NoGroup); } } |