diff options
-rw-r--r-- | gtk2_ardour/route_ui.cc | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/io.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/mute_master.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/port.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/route.h | 24 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 7 | ||||
-rw-r--r-- | libs/ardour/delivery.cc | 1 | ||||
-rw-r--r-- | libs/ardour/io.cc | 12 | ||||
-rw-r--r-- | libs/ardour/mute_master.cc | 27 | ||||
-rw-r--r-- | libs/ardour/port.cc | 26 | ||||
-rw-r--r-- | libs/ardour/route.cc | 100 | ||||
-rw-r--r-- | libs/ardour/session.cc | 111 |
13 files changed, 273 insertions, 53 deletions
diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index 010f0714b9..e6c8fbf574 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -838,7 +838,7 @@ RouteUI::mute_visual_state (Session* s, boost::shared_ptr<Route> r) if (r->self_muted ()) { /* full mute */ return 2; - } else if (r->muted_by_others()) { + } else if (r->muted_by_others() || r->path_muted_by_others()) { return 1; } else { /* no mute at all */ diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index a7ba3a23a9..72815c17cc 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -108,7 +108,8 @@ class IO : public SessionObject, public Latent int disconnect (void *src); bool connected_to (boost::shared_ptr<const IO>) const; bool connected () const; - + bool physically_connected () const; + nframes_t signal_latency() const { return _own_latency; } nframes_t latency() const; void set_port_latency (nframes_t); diff --git a/libs/ardour/ardour/mute_master.h b/libs/ardour/ardour/mute_master.h index 4ddb7075da..a0207f9817 100644 --- a/libs/ardour/ardour/mute_master.h +++ b/libs/ardour/ardour/mute_master.h @@ -25,11 +25,13 @@ #include "pbd/stateful.h" #include <string> +#include "ardour/session_handle.h" + namespace ARDOUR { class Session; -class MuteMaster : public PBD::Stateful +class MuteMaster : public SessionHandleRef, public PBD::Stateful { public: enum MutePoint { @@ -69,7 +71,7 @@ class MuteMaster : public PBD::Stateful void set_mute_points (MutePoint); MutePoint mute_points() const { return _mute_point; } - void set_solo_level (int32_t); + void set_solo_level (SoloLevel); PBD::Signal0<void> MutePointChanged; @@ -80,7 +82,7 @@ class MuteMaster : public PBD::Stateful volatile MutePoint _mute_point; volatile bool _self_muted; volatile uint32_t _muted_by_others; - volatile int32_t _solo_level; + volatile SoloLevel _solo_level; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h index ce4b88f8f2..cc37bf0821 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -116,6 +116,8 @@ public: } virtual void transport_stopped () {} + bool physically_connected () const; + static void set_engine (AudioEngine *); PBD::Signal1<void,bool> MonitorInputChanged; @@ -128,7 +130,7 @@ protected: static nframes_t _port_offset; static nframes_t _buffer_size; - + static AudioEngine* _engine; ///< the AudioEngine private: diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 5efb9c111b..b4a392c23b 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -129,6 +129,9 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou bool self_muted () const; bool muted_by_others () const; + bool path_muted_by_others() const { return _path_muted_by_others > 0; } + void mod_path_muted_by_others (int delta); + void set_mute (bool yn, void* src); void mod_muted_by_others (int delta); @@ -138,7 +141,9 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou void set_solo (bool yn, void *src); bool soloed () const { return self_soloed () || soloed_by_others (); } - bool soloed_by_others () const { return !_solo_isolated && _soloed_by_others; } + 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; } + bool soloed_by_others_downstream () const { return _soloed_by_others_downstream; } bool self_soloed () const { return _self_solo; } void set_solo_isolated (bool yn, void *src); @@ -372,8 +377,15 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou protected: friend class Session; + void set_graph_level (int32_t); + int32_t graph_level() const { return _graph_level; } + void check_physical_connections (); + // this functions may ONLY be called during a route resort + bool physically_connected () const { return _physically_connected; } + void catch_up_on_solo_mute_override (); - void mod_solo_by_others (int32_t); + void mod_solo_by_others_upstream (int32_t); + void mod_solo_by_others_downstream (int32_t); bool has_external_redirects() const; void curve_reallocate (); void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes); @@ -411,7 +423,8 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou MeterPoint _meter_point; uint32_t _phase_invert; bool _self_solo; - uint32_t _soloed_by_others; + uint32_t _soloed_by_others_upstream; + uint32_t _soloed_by_others_downstream; uint32_t _solo_isolated; bool _denormal_protection; @@ -424,9 +437,12 @@ class Route : public SessionObject, public AutomatableControls, public RouteGrou boost::shared_ptr<MuteControllable> _mute_control; boost::shared_ptr<MuteMaster> _mute_master; MuteMaster::MutePoint _mute_points; - + volatile uint32_t _path_muted_by_others; + std::string _comment; bool _have_internal_generator; + bool _physically_connected; // valid ONLY during a route resort + int32_t _graph_level; bool _solo_safe; DataType _default_type; FedBy _fed_by; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 014b49b318..b399745187 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -415,6 +415,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void remove_route (boost::shared_ptr<Route>); void resort_routes (); void resort_routes_using (boost::shared_ptr<RouteList>); + void find_route_levels (boost::shared_ptr<RouteList>); void set_remote_control_ids(); diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 25a6ea4c98..2bd08cbcdf 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -306,6 +306,13 @@ namespace ARDOUR { PreFaderListen }; + enum SoloLevel { + NotSoloed, + DownstreamSoloed, + UpstreamSoloed, + SelfSoloed + }; + enum AutoConnectOption { ManualConnect = 0x0, AutoConnectPhysical = 0x1, diff --git a/libs/ardour/delivery.cc b/libs/ardour/delivery.cc index e2928c1f5b..5861e5ea2c 100644 --- a/libs/ardour/delivery.cc +++ b/libs/ardour/delivery.cc @@ -500,6 +500,7 @@ Delivery::target_gain () break; } + // cerr << name() << ' '; desired_gain = _mute_master->mute_gain_at (mp); if (_role == Listen && _session.monitor_out() && !_session.listening()) { diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index a41003cf89..8b52bfaea5 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -1553,3 +1553,15 @@ IO::port_by_name (const std::string& str) const return 0; } + +bool +IO::physically_connected () const +{ + for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { + if (i->physically_connected()) { + return true; + } + } + + return false; +} diff --git a/libs/ardour/mute_master.cc b/libs/ardour/mute_master.cc index 0182e205d0..df9a66ef7f 100644 --- a/libs/ardour/mute_master.cc +++ b/libs/ardour/mute_master.cc @@ -23,7 +23,7 @@ #include "ardour/types.h" #include "ardour/mute_master.h" -#include "ardour/rc_configuration.h" +#include "ardour/session.h" #include "i18n.h" @@ -35,8 +35,9 @@ const MuteMaster::MutePoint MuteMaster::AllPoints = MutePoint (MuteMaster::PreFa MuteMaster::Listen| MuteMaster::Main); -MuteMaster::MuteMaster (Session&, const std::string&) - : _mute_point (AllPoints) +MuteMaster::MuteMaster (Session& s, const std::string&) + : SessionHandleRef (s) + , _mute_point (AllPoints) , _self_muted (false) , _muted_by_others (0) { @@ -83,7 +84,7 @@ MuteMaster::mod_muted_by_others (int32_t delta) } void -MuteMaster::set_solo_level (int32_t l) +MuteMaster::set_solo_level (SoloLevel l) { _solo_level = l; } @@ -92,14 +93,16 @@ gain_t MuteMaster::mute_gain_at (MutePoint mp) const { gain_t gain; - int32_t l = _solo_level; + const SoloLevel l = _solo_level; + // cerr << "solo level = " << _solo_level << " selfmuted " << self_muted_at (mp) << " omute " << muted_by_others_at (mp) << endl; + if (Config->get_solo_mute_override()) { - if (l == 2) { // self-soloed + if ((l == SelfSoloed) || (l == DownstreamSoloed)) { gain = 1.0; } else if (self_muted_at (mp)) { // self-muted gain = Config->get_solo_mute_gain (); - } else if (l == 1) { // soloed by others + } else if (l == UpstreamSoloed) { gain = 1.0; } else if (muted_by_others_at (mp)) { // muted by others gain = Config->get_solo_mute_gain (); @@ -109,17 +112,19 @@ MuteMaster::mute_gain_at (MutePoint mp) const } else { if (self_muted_at (mp)) { // self-muted gain = Config->get_solo_mute_gain (); - } else if (l == 2) { // self-soloed + } else if ((l == SelfSoloed) || (l == DownstreamSoloed)) { gain = 1.0; } else if (muted_by_others_at (mp)) { // muted by others gain = Config->get_solo_mute_gain (); - } else if (l == 1) { // soloed by others + } else if (l == UpstreamSoloed) { // soloed by others gain = 1.0; } else { gain = 1.0; } } + // cerr << "\tgain = " << gain << endl; + return gain; } @@ -130,7 +135,7 @@ MuteMaster::set_mute_points (const std::string& mute_point) _mute_point = (MutePoint) string_2_enum (mute_point, _mute_point); cerr << "Mute point set from string, now " << _mute_point << endl; - + if (old != _mute_point) { MutePointChanged(); /* EMIT SIGNAL */ } @@ -152,7 +157,7 @@ MuteMaster::set_state (const XMLNode& node, int /*version*/) const XMLProperty* prop; if ((prop = node.property ("mute-point")) != 0) { - //_mute_point = (MutePoint) string_2_enum (prop->value(), _mute_point); + _mute_point = (MutePoint) string_2_enum (prop->value(), _mute_point); cerr << "Mute point set from STATE string, now " << _mute_point << endl; } diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index 5897015b27..9cbdd14172 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -99,7 +99,8 @@ Port::get_connections (std::vector<std::string> & c) const c.push_back (jc[i]); ++n; } - free (jc); + + jack_free (jc); } return n; @@ -148,7 +149,7 @@ Port::disconnect (std::string const & other) _connections.erase (other); } -return r; + return r; } @@ -290,3 +291,24 @@ Port::set_latency (nframes_t n) jack_port_set_latency (_jack_port, n); } +bool +Port::physically_connected () const +{ + const char** jc = jack_port_get_connections (_jack_port); + + if (jc) { + for (int i = 0; jc[i]; ++i) { + + jack_port_t* port = jack_port_by_name (_engine->jack(), jc[i]); + + if (port && (jack_port_flags (port) & JackPortIsPhysical)) { + jack_free (jc); + return true; + } + } + + jack_free (jc); + } + + return false; +} diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 392ac7b0ca..ddb227c6bb 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -80,7 +80,8 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _meter_point (MeterPostFader) , _phase_invert (0) , _self_solo (false) - , _soloed_by_others (0) + , _soloed_by_others_upstream (0) + , _soloed_by_others_downstream (0) , _solo_isolated (0) , _denormal_protection (false) , _recordable (true) @@ -90,7 +91,10 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type) , _mute_control (new MuteControllable (X_("mute"), *this)) , _mute_master (new MuteMaster (sess, name)) , _mute_points (MuteMaster::AllPoints) + , _path_muted_by_others (false) , _have_internal_generator (false) + , _physically_connected (false) + , _graph_level (-1) , _solo_safe (false) , _default_type (default_type) , _remote_control_id (0) @@ -447,6 +451,10 @@ Route::process_output_buffers (BufferSet& bufs, Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK); if (rm.locked()) { + //cerr << name() << " upstream solo " << _soloed_by_others_upstream + // << " downstream solo " << _soloed_by_others_downstream + // << " self " << _self_solo + //<< endl; for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) { if (bufs.count() != (*i)->input_streams()) { @@ -589,20 +597,41 @@ Route::set_self_solo (bool yn) } void -Route::mod_solo_by_others (int32_t delta) +Route::mod_solo_by_others_upstream (int32_t delta) { if (_solo_safe) { return; } if (delta < 0) { - if (_soloed_by_others >= (uint32_t) abs (delta)) { - _soloed_by_others += delta; + if (_soloed_by_others_upstream >= (uint32_t) abs (delta)) { + _soloed_by_others_upstream += delta; } else { - _soloed_by_others = 0; + _soloed_by_others_upstream = 0; } } else { - _soloed_by_others += delta; + _soloed_by_others_upstream += delta; + } + + set_mute_master_solo (); + solo_changed (false, this); +} + +void +Route::mod_solo_by_others_downstream (int32_t delta) +{ + if (_solo_safe) { + return; + } + + 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; } set_mute_master_solo (); @@ -612,14 +641,16 @@ Route::mod_solo_by_others (int32_t delta) void Route::set_mute_master_solo () { - int32_t level; + SoloLevel level; if (self_soloed()) { - level = 2; - } else if (soloed_by_others()) { - level = 1; + level = SelfSoloed; + } else if (soloed_by_others_upstream()) { + level = UpstreamSoloed; + } else if (soloed_by_others_downstream()) { + level = DownstreamSoloed; } else { - level = 0; + level = NotSoloed; } _mute_master->set_solo_level (level); @@ -722,19 +753,31 @@ Route::muted_by_others() const void Route::mod_muted_by_others (int delta) { - bool old = muted (); - if (_solo_isolated) { return; } + bool old = muted (); _mute_master->mod_muted_by_others (delta); - if (old != muted()) { mute_changed (this); } } +void +Route::mod_path_muted_by_others (int32_t delta) +{ + if (delta < 0) { + if (_path_muted_by_others >= (uint32_t) abs (delta)) { + _path_muted_by_others += delta; + } else { + _path_muted_by_others = 0; + } + } else { + _path_muted_by_others += delta; + } +} + #if 0 static void dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs) @@ -1683,8 +1726,10 @@ Route::state(bool full_state) } node->add_property ("order-keys", order_string); node->add_property ("self-solo", (_self_solo ? "yes" : "no")); - snprintf (buf, sizeof (buf), "%d", _soloed_by_others); - node->add_property ("soloed-by-others", buf); + 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_child_nocopy (_input->state (full_state)); node->add_child_nocopy (_output->state (full_state)); @@ -1782,9 +1827,14 @@ Route::_set_state (const XMLNode& node, int version, bool /*call_base*/) set_self_solo (string_is_affirmative (prop->value())); } - if ((prop = node.property ("soloed-by-others")) != 0) { - _soloed_by_others = 0; // needed for mod_solo_by_others () to work - mod_solo_by_others (atoi (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) { @@ -2532,6 +2582,12 @@ Route::direct_feeds (boost::shared_ptr<Route> other, bool* only_send) } void +Route::check_physical_connections () +{ + _physically_connected = _output->physically_connected (); +} + +void Route::handle_transport_stopped (bool /*abort_ignored*/, bool did_locate, bool can_flush_processors) { nframes_t now = _session.transport_frame(); @@ -3301,3 +3357,9 @@ Route::has_io_processor_named (const string& name) return false; } + +void +Route::set_graph_level (int32_t l) +{ + _graph_level = l; +} diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 4ba092dd91..2da383b810 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -17,6 +17,9 @@ */ +#define __STDC_LIMIT_MACROS +#include <stdint.h> + #include <algorithm> #include <string> #include <vector> @@ -1351,6 +1354,10 @@ Session::resort_routes_using (shared_ptr<RouteList> r) RouteList::iterator i, j; for (i = r->begin(); i != r->end(); ++i) { + (*i)->check_physical_connections (); + } + + for (i = r->begin(); i != r->end(); ++i) { (*i)->clear_fed_by (); @@ -1381,15 +1388,102 @@ Session::resort_routes_using (shared_ptr<RouteList> r) RouteSorter cmp; r->sort (cmp); + find_route_levels (r); + #ifndef NDEBUG DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n"); for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n", (*i)->name(), (*i)->order_key ("signal"))); + DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2 level %3\n", + (*i)->name(), (*i)->order_key ("signal"), + (*i)->graph_level())); } #endif } +void +Session::find_route_levels (shared_ptr<RouteList> rl) +{ + uint32_t setcnt = 0; + uint32_t limit = rl->size(); + RouteList last_level; + RouteList this_level; + + for (RouteList::iterator r = rl->begin(); r != rl->end(); ++r) { + + /* find routes with direct physical connections, + or routes with no connections at all. Mark them + with "special" level values, and push them into + the "last_level" set. + + All other routes get marked with a graph level + of -1, which indicates that it needs to be set. + + */ + + if ((*r)->physically_connected()) { + last_level.push_back (*r); + (*r)->set_graph_level (0); + setcnt++; + } else if (!(*r)->output()->connected()) { + last_level.push_back (*r); + (*r)->set_graph_level (INT32_MAX/2); + setcnt++; + } else { + (*r)->set_graph_level (-1); + } + } + + // until we've set the graph level for every route ... + + while (setcnt < limit) { + + for (RouteList::reverse_iterator r = rl->rbegin(); r != rl->rend(); ++r) { + + int32_t l = INT32_MAX; + bool found = false; + + if ((*r)->graph_level() != -1) { + // we already have the graph level for this route + continue; + } + + /* check if this route (r) has a direction connection to anything in + the set of routes we processed last time. On the first pass + through this, last_level will contain routes with either + no connections or direct "physical" connections. If there is + at least 1 connection, store the lowest graph level of whatever + r is connected to. + */ + + for (RouteList::iterator o = last_level.begin(); o != last_level.end(); ++o) { + bool sends_only; + if ((*r)->direct_feeds (*o, &sends_only)) { + if (!sends_only) { + l = min (l, (*o)->graph_level()); + found = true; + } + } + } + + /* if we found any connections, then mark the graph level of r, and push + it into the "this_level" set that will become "last_level" next time + around the while() loop. + */ + + if (found) { + (*r)->set_graph_level (l + 1); + this_level.push_back (*r); + setcnt++; + } + } + + last_level = this_level; + this_level.clear (); + } +} + + /** Find the route name starting with \a base with the lowest \a id. * * Names are constructed like e.g. "Audio 3" for base="Audio" and id=3. @@ -2185,13 +2279,14 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { bool via_sends_only; - bool in_signal_flow; if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) { continue; } - in_signal_flow = false; + if ((*i)->graph_level () == route->graph_level()) { + (*i)->mod_muted_by_others (delta); + } /* feed-backwards (other route to solo change route): @@ -2204,8 +2299,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p if ((*i)->feeds (route, &via_sends_only)) { if (!via_sends_only) { - (*i)->mod_solo_by_others (delta); - in_signal_flow = true; + (*i)->mod_solo_by_others_upstream (delta); } } @@ -2218,12 +2312,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p */ if (route->feeds (*i, &via_sends_only)) { - (*i)->mod_solo_by_others (delta); - in_signal_flow = true; - } - - if (!in_signal_flow) { - (*i)->mod_muted_by_others (delta); + (*i)->mod_solo_by_others_downstream (delta); } } |