summaryrefslogtreecommitdiff
path: root/gtk2_ardour/editor_routes.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2012-06-27 22:57:06 +0000
committerPaul Davis <paul@linuxaudiosystems.com>2012-06-27 22:57:06 +0000
commit11415b49be02f16495c95d6286c485ac8afc5189 (patch)
tree8541101b792c6659994aedbd1ac19714e7ef4c2e /gtk2_ardour/editor_routes.cc
parent5ba1996fd70f05362c70b54e68261b955659f291 (diff)
first pass at the big rethink of managing sort order keys for editor and mixer. this appears to work, but remote control IDs are not yet correct (frequently off by one because of the presence of the master bus in the editor)
git-svn-id: svn://localhost/ardour2/branches/3.0@12953 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'gtk2_ardour/editor_routes.cc')
-rw-r--r--gtk2_ardour/editor_routes.cc304
1 files changed, 184 insertions, 120 deletions
diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc
index 3faeba183f..d8aec33007 100644
--- a/gtk2_ardour/editor_routes.cc
+++ b/gtk2_ardour/editor_routes.cc
@@ -24,6 +24,16 @@
#include <cmath>
#include <cassert>
+#include "pbd/unknown_type.h"
+#include "pbd/unwind.h"
+
+#include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
+#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
+#include "gtkmm2ext/treeutils.h"
+
+#include "ardour/debug.h"
+#include "ardour/route.h"
+#include "ardour/midi_track.h"
#include "ardour/session.h"
#include "editor.h"
@@ -38,15 +48,6 @@
#include "editor_group_tabs.h"
#include "editor_routes.h"
-#include "pbd/unknown_type.h"
-
-#include "ardour/route.h"
-#include "ardour/midi_track.h"
-
-#include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
-#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
-#include "gtkmm2ext/treeutils.h"
-
#include "i18n.h"
using namespace std;
@@ -67,9 +68,7 @@ EditorRoutes::EditorRoutes (Editor* e)
: EditorComponent (e)
, _ignore_reorder (false)
, _no_redisplay (false)
- , _redisplay_does_not_sync_order_keys (false)
- , _redisplay_does_not_reset_order_keys (false)
- ,_menu (0)
+ , _menu (0)
, old_focus (0)
, selection_countdown (0)
, name_editable (0)
@@ -282,7 +281,7 @@ EditorRoutes::EditorRoutes (Editor* e)
_display.set_enable_search (false);
- Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_order_keys, this, _1), gui_context());
+ Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_model_from_order_keys, this, _1), gui_context());
}
bool
@@ -502,12 +501,7 @@ EditorRoutes::redisplay ()
*/
int n;
- /* Order keys must not take children into account, so use a separate counter
- for that.
- */
- int order_key;
-
- for (n = 0, order_key = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
+ for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
TimeAxisView *tv = (*i)[_columns.tv];
boost::shared_ptr<Route> route = (*i)[_columns.route];
@@ -516,20 +510,6 @@ EditorRoutes::redisplay ()
continue;
}
- if (!_redisplay_does_not_reset_order_keys) {
- /* this reorder is caused by user action, so reassign sort order keys
- to tracks.
- */
-
- if (route->is_master()) {
- route->set_order_key (EditorSort, Route::MasterBusRemoteControlID);
- } else if (route->is_monitor()) {
- route->set_order_key (EditorSort, Route::MonitorBusRemoteControlID);
- } else {
- route->set_order_key (EditorSort, order_key++);
- }
- }
-
bool visible = tv->marked_for_display ();
/* show or hide the TimeAxisView */
@@ -561,23 +541,23 @@ EditorRoutes::redisplay ()
*/
_editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
}
-
- if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
- _session->sync_order_keys (EditorSort);
- }
}
void
EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
{
- if (!_session || _session->deletion_in_progress()) {
- return;
- }
+ /* this happens as the second step of a DnD within the treeview as well
+ as when a row/route is actually deleted.
+ */
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
+ sync_order_keys_from_model ();
+}
- /* this could require an order reset & sync */
- _ignore_reorder = true;
- redisplay ();
- _ignore_reorder = false;
+void
+EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
+{
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
+ sync_order_keys_from_model ();
}
void
@@ -595,10 +575,7 @@ EditorRoutes::visible_changed (std::string const & path)
bool visible = (*iter)[_columns.visible];
if (tv->set_marked_for_display (!visible)) {
- _redisplay_does_not_reset_order_keys = true;
update_visibility ();
- redisplay ();
- _redisplay_does_not_reset_order_keys = false;
}
}
}
@@ -622,7 +599,6 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
{
TreeModel::Row row;
- _redisplay_does_not_sync_order_keys = true;
suspend_redisplay ();
for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
@@ -685,7 +661,10 @@ EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
update_input_active_display ();
update_active_display ();
resume_redisplay ();
- _redisplay_does_not_sync_order_keys = false;
+
+ /* now update route order keys from the treeview/track display order */
+
+ sync_order_keys_from_model ();
}
void
@@ -714,12 +693,6 @@ EditorRoutes::route_removed (TimeAxisView *tv)
TreeModel::Children rows = _model->children();
TreeModel::Children::iterator ri;
- /* the core model has changed, there is no need to sync
- view orders.
- */
-
- _redisplay_does_not_sync_order_keys = true;
-
for (ri = rows.begin(); ri != rows.end(); ++ri) {
if ((*ri)[_columns.tv] == tv) {
_model->erase (ri);
@@ -727,7 +700,9 @@ EditorRoutes::route_removed (TimeAxisView *tv)
}
}
- _redisplay_does_not_sync_order_keys = false;
+ /* the deleted signal for the treeview/model will take
+ care of any updates.
+ */
}
void
@@ -782,6 +757,11 @@ EditorRoutes::update_visibility ()
(*i)[_columns.visible] = tv->marked_for_display ();
}
+ /* force route order keys catch up with visibility changes
+ */
+
+ sync_order_keys_from_model ();
+
resume_redisplay ();
}
@@ -819,57 +799,109 @@ EditorRoutes::show_track_in_display (TimeAxisView& tv)
}
void
-EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
+EditorRoutes::sync_order_keys_from_model ()
{
- redisplay ();
-}
+ if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
+ return;
+ }
-/** If src != "editor", take editor order keys from each route and use them to rearrange the
- * route list so that the visual arrangement of routes matches the order keys from the routes.
- */
-void
-EditorRoutes::sync_order_keys (RouteSortOrderKey src)
-{
- map<int, int> new_order;
TreeModel::Children rows = _model->children();
- TreeModel::Children::iterator ri;
-
- if (src == EditorSort || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
+
+ if (rows.empty()) {
return;
}
+ DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from model\n");
+
+ TreeModel::Children::iterator ri;
bool changed = false;
- int order;
+ uint32_t order = 0;
- for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
+ for (ri = rows.begin(); ri != rows.end(); ++ri) {
boost::shared_ptr<Route> route = (*ri)[_columns.route];
+ bool visible = (*ri)[_columns.visible];
- int const old_key = order;
- int const new_key = route->order_key (EditorSort);
+ uint32_t old_key = route->order_key (EditorSort);
+ uint32_t new_key;
- new_order[new_key] = old_key;
+ if (!visible) {
+ new_key = UINT_MAX;
+ } else {
+ new_key = order;
+ }
- if (new_key != old_key) {
+ if (old_key != new_key) {
+ route->set_order_key (EditorSort, new_key);
changed = true;
}
- }
+ order++;
+ }
+
if (changed) {
- _redisplay_does_not_reset_order_keys = true;
+ /* tell the world that we changed the editor sort keys */
+ _session->sync_order_keys (EditorSort);
+ }
+}
+
+void
+EditorRoutes::sync_model_from_order_keys (RouteSortOrderKey src)
+{
+ if (!_session || _session->deletion_in_progress()) {
+ return;
+ }
- /* `compact' new_order into a vector */
- vector<int> co;
- for (map<int, int>::const_iterator i = new_order.begin(); i != new_order.end(); ++i) {
- co.push_back (i->second);
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor sync model from order keys, src = %1\n", enum_2_string (src)));
+
+ if (src == MixerSort) {
+
+ if (!Config->get_sync_all_route_ordering()) {
+ /* mixer sort keys changed - we don't care */
+ return;
}
- assert (co.size() == _model->children().size ());
+ DEBUG_TRACE (DEBUG::OrderKeys, "reset editor order key to match mixer\n");
- _model->reorder (co);
- _redisplay_does_not_reset_order_keys = false;
+ /* mixer sort keys were changed, update the editor sort
+ * keys since "sync mixer+editor order" is enabled.
+ */
+
+ boost::shared_ptr<RouteList> r = _session->get_routes ();
+
+ for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+ (*i)->sync_order_keys (src);
+ }
}
-}
+ /* we could get here after either a change in the Mixer or Editor sort
+ * order, but either way, the mixer order keys reflect the intended
+ * order for the GUI, so reorder the treeview model to match it.
+ */
+
+ vector<int> neworder;
+ TreeModel::Children rows = _model->children();
+ uint32_t n = 0;
+
+ if (rows.empty()) {
+ return;
+ }
+
+ neworder.assign (rows.size(), 0);
+
+ for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++n) {
+ boost::shared_ptr<Route> 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)));
+ }
+
+ {
+ Unwinder<bool> uw (_ignore_reorder, true);
+ _model->reorder (neworder);
+ }
+
+ redisplay ();
+}
void
EditorRoutes::hide_all_tracks (bool /*with_select*/)
@@ -920,6 +952,11 @@ EditorRoutes::set_all_tracks_visibility (bool yn)
(*i)[_columns.visible] = yn;
}
+ /* force route order keys catch up with visibility changes
+ */
+
+ sync_order_keys_from_model ();
+
resume_redisplay ();
}
@@ -977,6 +1014,11 @@ EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
}
}
+ /* force route order keys catch up with visibility changes
+ */
+
+ sync_order_keys_from_model ();
+
resume_redisplay ();
}
@@ -1187,7 +1229,13 @@ EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path
struct EditorOrderRouteSorter {
bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
- /* use of ">" forces the correct sort order */
+ if (a->is_master()) {
+ /* master before everything else */
+ return true;
+ } else if (b->is_master()) {
+ /* everything else before master */
+ return false;
+ }
return a->order_key (EditorSort) < b->order_key (EditorSort);
}
};
@@ -1204,49 +1252,33 @@ EditorRoutes::initial_display ()
}
boost::shared_ptr<RouteList> routes = _session->get_routes();
- RouteList r (*routes);
- EditorOrderRouteSorter sorter;
-
- r.sort (sorter);
- _editor->handle_new_route (r);
-
- /* don't show master bus in a new session */
if (ARDOUR_UI::instance()->session_is_new ()) {
- TreeModel::Children rows = _model->children();
- TreeModel::Children::iterator i;
-
- _no_redisplay = true;
-
- for (i = rows.begin(); i != rows.end(); ++i) {
+ /* new session: stamp all routes with the right editor order
+ * key
+ */
- TimeAxisView *tv = (*i)[_columns.tv];
- RouteTimeAxisView *rtv;
+ _editor->add_routes (*(routes.get()));
+
+ } else {
- if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
- if (rtv->route()->is_master()) {
- _display.get_selection()->unselect (i);
- }
- }
- }
+ /* existing session: sort a copy of the route list by
+ * editor-order and add its contents to the display.
+ */
- _no_redisplay = false;
- redisplay ();
+ RouteList r (*routes);
+ EditorOrderRouteSorter sorter;
+
+ r.sort (sorter);
+ _editor->add_routes (r);
+
}
resume_redisplay ();
}
void
-EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
-{
- _redisplay_does_not_sync_order_keys = true;
- redisplay ();
- _redisplay_does_not_sync_order_keys = false;
-}
-
-void
EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
int x, int y,
const SelectionData& data,
@@ -1364,18 +1396,26 @@ EditorRoutes::move_selected_tracks (bool up)
}
for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
- neworder.push_back (leading->second->order_key (EditorSort));
+ uint32_t order = leading->second->order_key (EditorSort);
+ neworder.push_back (order);
}
#ifndef NDEBUG
+ DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n");
for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
+ DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("\t%1\n", *i));
+ }
+ DEBUG_TRACE (DEBUG::OrderKeys, "-------\n");
+
+ for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
+ if (*i >= (int) neworder.size()) {
+ cerr << "Trying to move something to " << *i << " of " << neworder.size() << endl;
+ }
assert (*i < (int) neworder.size ());
}
#endif
_model->reorder (neworder);
-
- _session->sync_order_keys (EditorSort);
}
void
@@ -1554,3 +1594,27 @@ EditorRoutes::show_tracks_with_regions_at_playhead ()
resume_redisplay ();
}
+
+uint32_t
+EditorRoutes::count_displayed_non_special_routes () const
+{
+ if (!_model) {
+ return 0;
+ }
+ uint32_t cnt = 0;
+ TreeModel::Children rows = _model->children ();
+ for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
+ bool visible = (*i)[_columns.visible];
+ if (visible) {
+ boost::shared_ptr<Route> route = (*i)[_columns.route];
+ if (route) {
+ if (route->is_master() || route->is_monitor()) {
+ continue;
+ }
+ cnt++;
+ }
+ }
+ }
+
+ return cnt;
+}