From 7db500301d1f02e9cb98eb5c744ae68456fac75b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Thu, 28 Jun 2012 22:27:37 +0000 Subject: [PATCH] further efforts at cleaning up the design of the interaction/relationship between route sort order keys and remote control IDs git-svn-id: svn://localhost/ardour2/branches/3.0@12962 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/editor_routes.cc | 42 +++++++------ gtk2_ardour/mixer_ui.cc | 31 +++++----- libs/ardour/ardour/route.h | 3 +- libs/ardour/ardour/session.h | 1 + libs/ardour/route.cc | 114 +++++++++++++++++++++++------------ libs/ardour/session.cc | 60 +++++++++++++++++- libs/ardour/session_state.cc | 27 ++++++++- 7 files changed, 201 insertions(+), 77 deletions(-) diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index eaf0c2500a..39e31f59d4 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -817,25 +817,14 @@ EditorRoutes::sync_order_keys_from_model () bool changed = false; uint32_t order = 0; - for (ri = rows.begin(); ri != rows.end(); ++ri) { + for (ri = rows.begin(); ri != rows.end(); ++ri, ++order) { boost::shared_ptr route = (*ri)[_columns.route]; - bool visible = (*ri)[_columns.visible]; - uint32_t old_key = route->order_key (EditorSort); - uint32_t new_key; - if (!visible) { - new_key = UINT_MAX; - } else { - new_key = order; - } - - if (old_key != new_key) { - route->set_order_key (EditorSort, new_key); + if (order != old_key) { + route->set_order_key (EditorSort, order); changed = true; } - - order++; } if (changed) { @@ -847,6 +836,10 @@ EditorRoutes::sync_order_keys_from_model () void EditorRoutes::sync_model_from_order_keys (RouteSortOrderKey src) { + /* Some route order key(s) for `src' has been changed, make sure that + we update out tree/list model and GUI to reflect the change. + */ + if (!_session || _session->deletion_in_progress()) { return; } @@ -880,7 +873,8 @@ EditorRoutes::sync_model_from_order_keys (RouteSortOrderKey src) vector neworder; TreeModel::Children rows = _model->children(); - uint32_t n = 0; + uint32_t old_order = 0; + bool changed = false; if (rows.empty()) { return; @@ -888,14 +882,22 @@ EditorRoutes::sync_model_from_order_keys (RouteSortOrderKey src) neworder.assign (rows.size(), 0); - for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++n) { + for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) { boost::shared_ptr route = (*ri)[_columns.route]; - neworder[route->order_key (EditorSort)] = n; - DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor change order for %1 to %2\n", - route->name(), route->order_key (MixerSort))); + uint32_t new_order = route->order_key (EditorSort); + + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor change order for %1 from %2 to %3\n", + route->name(), old_order, new_order)); + + neworder[new_order] = old_order; + + if (old_order != new_order) { + changed = true; + } + } - { + if (changed) { Unwinder uw (_ignore_reorder, true); _model->reorder (neworder); } diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 17d37fa5fb..e301bbcc79 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -413,25 +413,14 @@ Mixer_UI::sync_order_keys_from_model () bool changed = false; uint32_t order = 0; - for (ri = rows.begin(); ri != rows.end(); ++ri) { + for (ri = rows.begin(); ri != rows.end(); ++ri, ++order) { boost::shared_ptr route = (*ri)[track_columns.route]; - bool visible = (*ri)[track_columns.visible]; - uint32_t old_key = route->order_key (MixerSort); - uint32_t new_key; - if (!visible) { - new_key = UINT_MAX; - } else { - new_key = order; - } - - if (old_key != new_key) { - route->set_order_key (MixerSort, new_key); + if (old_key != order) { + route->set_order_key (MixerSort, order); changed = true; } - - order++; } if (changed) { @@ -477,6 +466,7 @@ Mixer_UI::sync_model_from_order_keys (RouteSortOrderKey src) vector neworder; TreeModel::Children rows = track_model->children(); uint32_t n = 0; + bool changed = false; if (rows.empty()) { return; @@ -486,12 +476,19 @@ Mixer_UI::sync_model_from_order_keys (RouteSortOrderKey src) for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++n) { boost::shared_ptr route = (*ri)[track_columns.route]; - neworder[route->order_key (MixerSort)] = n; + uint32_t o = route->order_key (MixerSort); + + neworder[o] = n; + + if (o != n) { + changed = true; + } + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("mixer change order for %1 to %2\n", route->name(), route->order_key (MixerSort))); } - { + if (changed) { Unwinder uw (ignore_reorder, true); track_model->reorder (neworder); } @@ -985,6 +982,8 @@ Mixer_UI::initial_track_display () track_model->clear (); add_strips (copy); } + + _session->sync_order_keys (MixerSort); redisplay_track_list (); } diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index 695e151dbb..f6c737d766 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -423,6 +423,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, void set_remote_control_id (uint32_t id, bool notify_class_listeners = true); uint32_t remote_control_id () const; + void set_remote_control_id_from_order_key (RouteSortOrderKey); /* for things concerned about *this* route's RID */ @@ -534,7 +535,7 @@ class Route : public SessionObject, public Automatable, public RouteGroupMember, typedef std::map OrderKeys; OrderKeys order_keys; - uint32_t* _remote_control_id; + uint32_t _remote_control_id; void input_change_handler (IOChange, void *src); void output_change_handler (IOChange, void *src); diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index a132a4a5e8..bc14805074 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -235,6 +235,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi }; void sync_order_keys (RouteSortOrderKey); + void sync_remote_id_from_order_keys (RouteSortOrderKey); template void foreach_route (T *obj, void (T::*func)(Route&)); template void foreach_route (T *obj, void (T::*func)(boost::shared_ptr)); diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 2112336d8b..0c233bfc31 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -195,8 +195,6 @@ Route::~Route () } _processors.clear (); - - delete _remote_control_id; } void @@ -232,11 +230,9 @@ Route::set_remote_control_id (uint32_t id, bool notify_class_listeners) } if (id != remote_control_id()) { - if (!_remote_control_id) { - _remote_control_id = new uint32_t; - } - *_remote_control_id = id; + _remote_control_id = id; RemoteControlIDChanged (); + if (notify_class_listeners) { RemoteControlIDChange (); } @@ -246,16 +242,6 @@ Route::set_remote_control_id (uint32_t id, bool notify_class_listeners) uint32_t Route::remote_control_id() const { - switch (Config->get_remote_model()) { - case UserOrdered: - if (_remote_control_id) { - return *_remote_control_id; - } - break; - default: - break; - } - if (is_master()) { return MasterBusRemoteControlID; } @@ -264,16 +250,7 @@ Route::remote_control_id() const return MonitorBusRemoteControlID; } - /* order keys are zero-based, remote control ID's are one-based - */ - - switch (Config->get_remote_model()) { - case EditorOrdered: - return order_key (EditorSort) + 1; - case MixerOrdered: - default: - return order_key (MixerSort) + 1; - } + return _remote_control_id; } bool @@ -297,6 +274,10 @@ Route::order_key (RouteSortOrderKey key) const void Route::sync_order_keys (RouteSortOrderKey base) { + /* this is called after changes to 1 or more route order keys have been + * made, and we want to sync up. + */ + OrderKeys::iterator i = order_keys.find (base); if (i == order_keys.end()) { @@ -305,27 +286,86 @@ Route::sync_order_keys (RouteSortOrderKey base) for (OrderKeys::iterator k = order_keys.begin(); k != order_keys.end(); ++k) { - if (k->first == MixerSort && (is_master() || is_monitor())) { - /* don't sync the mixer sort keys for master/monitor, + if (is_master() || is_monitor()) { + /* don't sync the sort keys for master/monitor, * since they are not part of the normal ordering. */ - continue; } if (k->first != base) { + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1 set key for %2 to %3 from %4\n", + name(), + enum_2_string (k->first), + i->second, + base)); + k->second = i->second; } } } +void +Route::set_remote_control_id_from_order_key (RouteSortOrderKey key) +{ + if (is_master() || is_monitor() || is_hidden()) { + return; + } + + uint32_t n = order_keys[key]; + + switch (Config->get_remote_model()) { + case UserOrdered: + break; + case EditorOrdered: + if (key == EditorSort) { + boost::shared_ptr master = _session.master_out(); + if (master && n > 0 && n > master->order_key (EditorSort)) { + --n; + } + _remote_control_id = n + 1; + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1: from order key %2, set edit-based RID to %3\n", + name(), n, _remote_control_id)); + RemoteControlIDChanged (); /* EMIT SIGNAL * (per-route) */ + } + break; + + case MixerOrdered: + if (key == MixerSort) { + boost::shared_ptr master = _session.master_out(); + if (master && n > 0 && n > master->order_key (MixerSort)) { + --n; + } + _remote_control_id = n + 1; + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1: from order key %2, set mix-based RID to %3\n", + name(), n, _remote_control_id)); + RemoteControlIDChanged (); /* EMIT SIGNAL (per-route) */ + } + break; + } + + /* don't emit class-level RID signals here, leave that to the entity + that changed the order key, so that we don't get lots + of emissions for no good reasons (e.g. when changing all + route order keys) + */ +} + void Route::set_order_key (RouteSortOrderKey key, uint32_t n) { - if (order_keys.find (key) == order_keys.end() || order_keys[key] != n) { - order_keys[key] = n; - _session.set_dirty (); + OrderKeys::iterator i = order_keys.find (key); + + if (i != order_keys.end() && i->second == n) { + return; } + + order_keys[key] = n; + + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1 order key %2 set to %3 (chk=%4)\n", + name(), enum_2_string (key), n, order_key (key))); + + _session.set_dirty (); } string @@ -1894,12 +1934,10 @@ Route::state(bool full_state) node->add_child_nocopy (_mute_control->get_state ()); node->add_child_nocopy (_mute_master->get_state ()); - if (_remote_control_id) { - XMLNode* remote_control_node = new XMLNode (X_("RemoteControl")); - snprintf (buf, sizeof (buf), "%d", *_remote_control_id); - remote_control_node->add_property (X_("id"), buf); - node->add_child_nocopy (*remote_control_node); - } + XMLNode* remote_control_node = new XMLNode (X_("RemoteControl")); + snprintf (buf, sizeof (buf), "%d", _remote_control_id); + remote_control_node->add_property (X_("id"), buf); + node->add_child_nocopy (*remote_control_node); if (_comment.length()) { XMLNode *cmt = node->add_child ("Comment"); diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 47d76ff150..fab877cf0b 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2205,7 +2205,22 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output } RouteAdded (new_routes); /* EMIT SIGNAL */ - Route::RemoteControlIDChange (); /* EMIT SIGNAL */ + + /* we added at least one new route, and everyone who needs to has now + * handled this event. This means that route order keys are correctly + * set and we can now ensure that remote control IDs are set. + */ + + switch (Config->get_remote_model()) { + case UserOrdered: + break; + case MixerOrdered: + sync_remote_id_from_order_keys (MixerSort); + break; + case EditorOrdered: + sync_remote_id_from_order_keys (EditorSort); + break; + } } void @@ -4714,11 +4729,54 @@ Session::sync_order_keys (RouteSortOrderKey sort_key_changed) /* tell everyone that something has happened to the sort keys and let them sync up with the change(s) + this will give objects that manage the sort order keys the + opportunity to keep them in sync if they wish to. */ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("Sync Order Keys, based on %1\n", enum_2_string (sort_key_changed))); Route::SyncOrderKeys (sort_key_changed); /* EMIT SIGNAL */ + + /* ensure that remote control IDs are in sync with the relevant + order keys. + */ + + sync_remote_id_from_order_keys (sort_key_changed); +} + +void +Session::sync_remote_id_from_order_keys (RouteSortOrderKey sort_key_changed) +{ + /* update remote control IDs if that makes sense */ + + bool do_update = false; + + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("sync RID to order key %1\n", enum_2_string (sort_key_changed))); + + switch (Config->get_remote_model()) { + case UserOrdered: + break; + case EditorOrdered: + if (sort_key_changed == EditorSort) { + do_update = true; + } + break; + case MixerOrdered: + if (sort_key_changed == MixerSort) { + do_update = true; + } + break; + } + + if (do_update) { + DEBUG_TRACE (DEBUG::OrderKeys, "\tactually update + signal\n"); + boost::shared_ptr r = routes.reader(); + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + (*i)->set_remote_control_id_from_order_key (sort_key_changed); + } + + Route::RemoteControlIDChange (); /* EMIT SIGNAL - static */ + } } bool diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc index da6f618c11..a3460dddfb 100644 --- a/libs/ardour/session_state.cc +++ b/libs/ardour/session_state.cc @@ -3506,8 +3506,33 @@ Session::config_changed (std::string p, bool ours) setup_fpu (); } else if (p == "history-depth") { set_history_depth (Config->get_history_depth()); + } else if (p == "remote-model") { + switch (Config->get_remote_model()) { + case UserOrdered: + break; + case MixerOrdered: + sync_remote_id_from_order_keys (MixerSort); + break; + case EditorOrdered: + sync_remote_id_from_order_keys (EditorSort); + break; + } } else if (p == "sync-all-route-ordering") { - /* XXX sync_order_keys (UndefinedSort); */ + + /* sync to editor order unless mixer is used for remote IDs + */ + + switch (Config->get_remote_model()) { + case UserOrdered: + sync_order_keys (EditorSort); + break; + case EditorOrdered: + sync_order_keys (EditorSort); + break; + case MixerOrdered: + sync_order_keys (MixerSort); + } + } else if (p == "initial-program-change") { if (MIDI::Manager::instance()->mmc()->output_port() && Config->get_initial_program_change() >= 0) {