From 1fd56c5476a4628dcf25d64c2950811c395bcfac Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 21 Jul 2010 02:17:57 +0000 Subject: [PATCH] Sort tracks in the port matrix according to editor order. Fixes #2966. git-svn-id: svn://localhost/ardour2/branches/3.0@7458 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/port_group.cc | 56 +++++++++++++++++++++++++----------- gtk2_ardour/port_group.h | 3 +- gtk2_ardour/port_matrix.cc | 4 ++- libs/ardour/ardour/route.h | 1 + libs/ardour/ardour/session.h | 4 +++ libs/ardour/route.cc | 34 +++++++++++++++++++--- libs/ardour/session.cc | 8 ++++++ 7 files changed, 87 insertions(+), 23 deletions(-) diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc index 7990eded89..0af3c24ed9 100644 --- a/gtk2_ardour/port_group.cc +++ b/gtk2_ardour/port_group.cc @@ -272,7 +272,7 @@ PortGroupList::~PortGroupList() void PortGroupList::maybe_add_processor_to_list ( - boost::weak_ptr wp, list >* route_bundles, bool inputs, set >& used_io + boost::weak_ptr wp, list >* route_ios, bool inputs, set >& used_io ) { boost::shared_ptr p (wp.lock()); @@ -288,12 +288,28 @@ PortGroupList::maybe_add_processor_to_list ( boost::shared_ptr io = inputs ? iop->input() : iop->output(); if (io && used_io.find (io) == used_io.end()) { - route_bundles->push_back (io->bundle ()); + route_ios->push_back (io); used_io.insert (io); } } } +struct RouteIOs { + RouteIOs (boost::shared_ptr r, boost::shared_ptr i) { + route = r; + ios.push_back (i); + } + + boost::shared_ptr route; + std::list > ios; +}; + +class RouteIOsComparator { +public: + bool operator() (RouteIOs const & a, RouteIOs const & b) { + return a.route->order_key (X_("editor")) < b.route->order_key (X_("editor")); + } +}; /** Gather bundles from around the system and put them in this PortGroupList. * @param type Type of bundles to collect, or NIL for all types. @@ -313,16 +329,16 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp boost::shared_ptr ardour (new PortGroup (_("Ardour"))); boost::shared_ptr other (new PortGroup (_("Other"))); - /* Find the bundles for routes. We use the RouteBundle class to join - the route's input/output and processor bundles together so that they - are presented as one bundle in the matrix. */ + /* Find the IOs which have bundles for routes and their processors. We store + these IOs in a RouteIOs class so that we can then sort the results by route + order key. + */ boost::shared_ptr routes = session->get_routes (); + list route_ios; for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) { - list > route_bundles; - /* keep track of IOs that we have taken bundles from, so that we can avoid taking the same IO from both Route::output() and the main_outs Delivery */ @@ -331,24 +347,32 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp boost::shared_ptr io = inputs ? (*i)->input() : (*i)->output(); used_io.insert (io); - route_bundles.push_back (io->bundle ()); + RouteIOs rb (*i, io); + (*i)->foreach_processor (boost::bind (&PortGroupList::maybe_add_processor_to_list, this, _1, &rb.ios, inputs, used_io)); - (*i)->foreach_processor (boost::bind (&PortGroupList::maybe_add_processor_to_list, this, _1, &route_bundles, inputs, used_io)); + route_ios.push_back (rb); + } - /* Work out which group to put these bundles in */ + /* Sort RouteIOs by the routes' editor order keys */ + route_ios.sort (RouteIOsComparator ()); + + /* Now put the bundles that belong to these sorted RouteIOs into the PortGroup */ + for (list::iterator i = route_ios.begin(); i != route_ios.end(); ++i) { + TimeAxisView* tv = PublicEditor::instance().axis_view_from_route (i->route); + + /* Work out which group to put these IOs' bundles in */ boost::shared_ptr g; - if (boost::dynamic_pointer_cast (*i)) { + if (boost::dynamic_pointer_cast (i->route)) { g = track; } else { g = bus; } - - TimeAxisView* tv = PublicEditor::instance().axis_view_from_route (*i); - for (list >::iterator i = route_bundles.begin(); i != route_bundles.end(); ++i) { + + for (list >::iterator j = i->ios.begin(); j != i->ios.end(); ++j) { if (tv) { - g->add_bundle (*i, io, tv->color ()); + g->add_bundle ((*j)->bundle(), *j, tv->color ()); } else { - g->add_bundle (*i, io); + g->add_bundle ((*j)->bundle(), *j); } } } diff --git a/gtk2_ardour/port_group.h b/gtk2_ardour/port_group.h index f8955337a2..5f66c8cd81 100644 --- a/gtk2_ardour/port_group.h +++ b/gtk2_ardour/port_group.h @@ -40,7 +40,6 @@ namespace ARDOUR { } class PortMatrix; -class RouteBundle; class PublicEditor; /** A list of bundles grouped by some aspect of their type e.g. busses, tracks, system. @@ -145,7 +144,7 @@ class PortGroupList : public sigc::trackable void emit_bundle_changed (ARDOUR::Bundle::Change); boost::shared_ptr make_bundle_from_ports (std::vector const &, ARDOUR::DataType, bool) const; void maybe_add_processor_to_list ( - boost::weak_ptr, std::list > *, bool, std::set > & + boost::weak_ptr, std::list > *, bool, std::set > & ); mutable PortGroup::BundleList _bundles; diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc index 4486cfb30d..6113412df9 100644 --- a/gtk2_ardour/port_matrix.cc +++ b/gtk2_ardour/port_matrix.cc @@ -151,6 +151,8 @@ PortMatrix::init () /* and also ports */ _session->engine().PortRegisteredOrUnregistered.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context()); + /* watch for route order keys changing, which changes the order of things in our global ports list(s) */ + _session->RouteOrderKeyChanged.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports, this), gui_context()); /* Part 3: other stuff */ @@ -201,7 +203,7 @@ PortMatrix::setup () { /* this needs to be done first, as the visible_ports() method uses the notebook state to decide which ports are being shown */ - + setup_notebooks (); _body->setup (); diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index a9ebd65338..ab04520443 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -257,6 +257,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, PBD::Signal0 meter_change; PBD::Signal0 signal_latency_changed; PBD::Signal0 initial_delay_changed; + PBD::Signal0 order_key_changed; /* gui's call this for their own purposes. */ diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 7f2fbc0a09..ac528081ff 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -774,6 +774,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void send_mmc_locate (nframes64_t); int send_full_time_code (nframes64_t); + PBD::Signal0 RouteOrderKeyChanged; + protected: friend class AudioEngine; void set_block_size (nframes_t nframes); @@ -1416,6 +1418,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void setup_midi_machine_control (); void cleanup_stubfiles (); + + void route_order_key_changed (); }; } // namespace ARDOUR diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index e8ddf678c9..daabf8a56f 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -227,15 +227,32 @@ Route::order_key (std::string const & name) const void Route::set_order_key (std::string const & name, long n) { - order_keys[name] = n; + bool changed = false; + + /* This method looks more complicated than it should, but + it's important that we don't emit order_key_changed unless + it actually has, as expensive things happen on receipt of that + signal. + */ + + if (order_keys.find(name) == order_keys.end() || order_keys[name] != n) { + order_keys[name] = n; + changed = true; + } if (Config->get_sync_all_route_ordering()) { for (OrderKeys::iterator x = order_keys.begin(); x != order_keys.end(); ++x) { - x->second = n; + if (x->second != n) { + x->second = n; + changed = true; + } } } - _session.set_dirty (); + if (changed) { + order_key_changed (); /* EMIT SIGNAL */ + _session.set_dirty (); + } } /** Set all order keys to be the same as that for `base', if such a key @@ -263,8 +280,17 @@ Route::sync_order_keys (std::string const & base) i = order_keys.begin(); } + bool changed = false; + for (; i != order_keys.end(); ++i) { - i->second = key; + if (i->second != key) { + i->second = key; + changed = true; + } + } + + if (changed) { + order_key_changed (); /* EMIT SIGNAL */ } } diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 7e849d028f..d294898443 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -1911,6 +1911,7 @@ Session::add_routes (RouteList& new_routes, bool save) r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1)); 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)); + r->order_key_changed.connect_same_thread (*this, boost::bind (&Session::route_order_key_changed, this)); if (r->is_master()) { _master_out = r; @@ -3898,3 +3899,10 @@ Session::add_session_range_location (nframes_t start, nframes_t end) _session_range_location = new Location (start, end, _("session"), Location::IsSessionRange); _locations.add (_session_range_location); } + +/** Called when one of our routes' order keys has changed */ +void +Session::route_order_key_changed () +{ + RouteOrderKeyChanged (); /* EMIT SIGNAL */ +}