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
This commit is contained in:
Carl Hetherington 2010-07-21 02:17:57 +00:00
parent f58a810af8
commit 1fd56c5476
7 changed files with 87 additions and 23 deletions

View File

@ -272,7 +272,7 @@ PortGroupList::~PortGroupList()
void
PortGroupList::maybe_add_processor_to_list (
boost::weak_ptr<Processor> wp, list<boost::shared_ptr<Bundle> >* route_bundles, bool inputs, set<boost::shared_ptr<IO> >& used_io
boost::weak_ptr<Processor> wp, list<boost::shared_ptr<IO> >* route_ios, bool inputs, set<boost::shared_ptr<IO> >& used_io
)
{
boost::shared_ptr<Processor> p (wp.lock());
@ -288,12 +288,28 @@ PortGroupList::maybe_add_processor_to_list (
boost::shared_ptr<IO> 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<Route> r, boost::shared_ptr<IO> i) {
route = r;
ios.push_back (i);
}
boost::shared_ptr<Route> route;
std::list<boost::shared_ptr<IO> > 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<PortGroup> ardour (new PortGroup (_("Ardour")));
boost::shared_ptr<PortGroup> 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<RouteList> routes = session->get_routes ();
list<RouteIOs> route_ios;
for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
list<boost::shared_ptr<Bundle> > 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> 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<RouteIOs>::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<PortGroup> g;
if (boost::dynamic_pointer_cast<Track> (*i)) {
if (boost::dynamic_pointer_cast<Track> (i->route)) {
g = track;
} else {
g = bus;
}
TimeAxisView* tv = PublicEditor::instance().axis_view_from_route (*i);
for (list<boost::shared_ptr<Bundle> >::iterator i = route_bundles.begin(); i != route_bundles.end(); ++i) {
for (list<boost::shared_ptr<IO> >::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);
}
}
}

View File

@ -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<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, ARDOUR::DataType, bool) const;
void maybe_add_processor_to_list (
boost::weak_ptr<ARDOUR::Processor>, std::list<boost::shared_ptr<ARDOUR::Bundle> > *, bool, std::set<boost::shared_ptr<ARDOUR::IO> > &
boost::weak_ptr<ARDOUR::Processor>, std::list<boost::shared_ptr<ARDOUR::IO> > *, bool, std::set<boost::shared_ptr<ARDOUR::IO> > &
);
mutable PortGroup::BundleList _bundles;

View File

@ -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 ();

View File

@ -257,6 +257,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember,
PBD::Signal0<void> meter_change;
PBD::Signal0<void> signal_latency_changed;
PBD::Signal0<void> initial_delay_changed;
PBD::Signal0<void> order_key_changed;
/* gui's call this for their own purposes. */

View File

@ -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<void> 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

View File

@ -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 */
}
}

View File

@ -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 */
}