diff options
Diffstat (limited to 'gtk2_ardour/editor_routes.cc')
-rw-r--r-- | gtk2_ardour/editor_routes.cc | 304 |
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; +} |