diff options
Diffstat (limited to 'gtk2_ardour')
-rw-r--r-- | gtk2_ardour/ardour_ui.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/au_pluginui.mm | 7 | ||||
-rw-r--r-- | gtk2_ardour/editor.cc | 7 | ||||
-rw-r--r-- | gtk2_ardour/editor.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_group_tabs.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/editor_routes.cc | 304 | ||||
-rw-r--r-- | gtk2_ardour/editor_routes.h | 12 | ||||
-rw-r--r-- | gtk2_ardour/mixer_group_tabs.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/mixer_ui.cc | 414 | ||||
-rw-r--r-- | gtk2_ardour/mixer_ui.h | 10 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix.cc | 16 | ||||
-rw-r--r-- | gtk2_ardour/port_matrix.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/route_ui.cc | 7 |
13 files changed, 438 insertions, 349 deletions
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc index 8b90b2d5b8..96e309ed01 100644 --- a/gtk2_ardour/ardour_ui.cc +++ b/gtk2_ardour/ardour_ui.cc @@ -3142,8 +3142,6 @@ ARDOUR_UI::add_route (Gtk::Window* float_window) output_chan = input_chan; } - cerr << "ARD said " << input_chan << " and " << output_chan << endl; - /* XXX do something with name template */ switch (add_route_dialog->type_wanted()) { diff --git a/gtk2_ardour/au_pluginui.mm b/gtk2_ardour/au_pluginui.mm index 359b32478a..0433d2502d 100644 --- a/gtk2_ardour/au_pluginui.mm +++ b/gtk2_ardour/au_pluginui.mm @@ -568,12 +568,13 @@ AUPluginUI::parent_carbon_window () int packing_extra = 6; // this is the total vertical packing in our top level window - MoveWindow (carbon_window, x, y + titlebar_height + top_box.get_height() + packing_extra, false); - ShowWindow (carbon_window); - // create the cocoa window for the carbon one and make it visible cocoa_parent = [[NSWindow alloc] initWithWindowRef: carbon_window]; + PositionWindow (carbon_window, [cocoa_parent windowRef], kWindowCascadeStartAtParentWindowScreen); + MoveWindow (carbon_window, x, y + titlebar_height + top_box.get_height() + packing_extra, false); + ShowWindow (carbon_window); + SetWindowActivationScope (carbon_window, kWindowActivationScopeNone); _notify = [ [NotificationObject alloc] initWithPluginUI:this andCocoaParent:cocoa_parent andTopLevelParent:win ]; diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc index 9daf72c589..f33dda2dac 100644 --- a/gtk2_ardour/editor.cc +++ b/gtk2_ardour/editor.cc @@ -1271,7 +1271,7 @@ Editor::set_session (Session *t) _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context()); _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context()); _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context()); - _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::handle_new_route, this, _1), gui_context()); + _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context()); _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context()); _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context()); _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context()); @@ -4785,9 +4785,8 @@ Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const return t; } - void -Editor::handle_new_route (RouteList& routes) +Editor::add_routes (RouteList& routes) { ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes) @@ -4797,7 +4796,7 @@ Editor::handle_new_route (RouteList& routes) for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr<Route> route = (*x); - if (route->is_hidden() || route->is_monitor()) { + if (route->is_hidden()) { continue; } diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 23da8d7c6d..9408b27f8f 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -704,7 +704,7 @@ class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARD void popup_control_point_context_menu (ArdourCanvas::Item *, GdkEvent *); Gtk::Menu _control_point_context_menu; - void handle_new_route (ARDOUR::RouteList&); + void add_routes (ARDOUR::RouteList&); void timeaxisview_deleted (TimeAxisView *); Gtk::HBox global_hpacker; diff --git a/gtk2_ardour/editor_group_tabs.cc b/gtk2_ardour/editor_group_tabs.cc index 5a1e9c8aaa..cb85544669 100644 --- a/gtk2_ardour/editor_group_tabs.cc +++ b/gtk2_ardour/editor_group_tabs.cc @@ -201,5 +201,5 @@ EditorGroupTabs::selected_routes () const void EditorGroupTabs::sync_order_keys () { - _editor->_routes->sync_order_keys (UndefinedSort); + _editor->_routes->sync_order_keys_from_model (); } 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; +} diff --git a/gtk2_ardour/editor_routes.h b/gtk2_ardour/editor_routes.h index 00631d914a..cbe9825cb5 100644 --- a/gtk2_ardour/editor_routes.h +++ b/gtk2_ardour/editor_routes.h @@ -42,6 +42,10 @@ public: _no_redisplay = true; } + void allow_redisplay () { + _no_redisplay = false; + } + void resume_redisplay () { _no_redisplay = false; redisplay (); @@ -55,8 +59,8 @@ public: std::list<TimeAxisView*> views () const; void hide_all_tracks (bool); void clear (); - void sync_order_keys (ARDOUR::RouteSortOrderKey); - + uint32_t count_displayed_non_special_routes () const; + void sync_order_keys_from_model (); private: void initial_display (); @@ -68,6 +72,7 @@ private: void on_tv_solo_safe_toggled (std::string const &); void build_menu (); void show_menu (); + void sync_model_from_order_keys (ARDOUR::RouteSortOrderKey); void route_deleted (Gtk::TreeModel::Path const &); void visible_changed (std::string const &); void active_changed (std::string const &); @@ -98,7 +103,6 @@ private: Glib::RefPtr<Gdk::DragContext> const &, gint, gint, Gtk::SelectionData const &, guint, guint ); - void track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const & iter, int* new_order); bool selection_filter (Glib::RefPtr<Gtk::TreeModel> const &, Gtk::TreeModel::Path const &, bool); void name_edit (std::string const &, std::string const &); void solo_changed_so_update_mute (); @@ -150,8 +154,6 @@ private: bool _ignore_reorder; bool _no_redisplay; - bool _redisplay_does_not_sync_order_keys; - bool _redisplay_does_not_reset_order_keys; Gtk::Menu* _menu; Gtk::Widget* old_focus; diff --git a/gtk2_ardour/mixer_group_tabs.cc b/gtk2_ardour/mixer_group_tabs.cc index 60a625c96d..f3121a5ca9 100644 --- a/gtk2_ardour/mixer_group_tabs.cc +++ b/gtk2_ardour/mixer_group_tabs.cc @@ -192,5 +192,5 @@ MixerGroupTabs::selected_routes () const void MixerGroupTabs::sync_order_keys () { - _mixer->sync_order_keys (UndefinedSort); + _mixer->sync_order_keys_from_model (); } diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index 5034243680..17d37fa5fb 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -29,6 +29,8 @@ #include "pbd/convert.h" #include "pbd/stacktrace.h" +#include "pbd/unwind.h" + #include <glibmm/thread.h> #include <gtkmm2ext/gtk_ui.h> @@ -36,6 +38,7 @@ #include <gtkmm2ext/tearoff.h> #include <gtkmm2ext/window_title.h> +#include "ardour/debug.h" #include "ardour/plugin_manager.h" #include "ardour/route_group.h" #include "ardour/session.h" @@ -63,6 +66,7 @@ using namespace Gtkmm2ext; using namespace std; using PBD::atoi; +using PBD::Unwinder; Mixer_UI* Mixer_UI::_instance = 0; @@ -78,22 +82,19 @@ Mixer_UI::instance () Mixer_UI::Mixer_UI () : Window (Gtk::WINDOW_TOPLEVEL) + , _visible (false) + , no_track_list_redisplay (false) + , in_group_row_change (false) + , track_menu (0) + , _monitor_section (0) + , _strip_width (Config->get_default_narrow_ms() ? Narrow : Wide) + , ignore_reorder (false) , _following_editor_selection (false) { /* allow this window to become the key focus window */ set_flags (CAN_FOCUS); - _strip_width = Config->get_default_narrow_ms() ? Narrow : Wide; - track_menu = 0; - _monitor_section = 0; - no_track_list_redisplay = false; - in_group_row_change = false; - _visible = false; - strip_redisplay_does_not_reset_order_keys = false; - strip_redisplay_does_not_sync_order_keys = false; - ignore_sync = false; - - Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_order_keys, this, _1), gui_context()); + Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_model_from_order_keys, this, _1), gui_context()); scroller_base.set_flags (Gtk::CAN_FOCUS); scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); @@ -305,70 +306,68 @@ Mixer_UI::hide_window (GdkEventAny *ev) void -Mixer_UI::add_strip (RouteList& routes) +Mixer_UI::add_strips (RouteList& routes) { MixerStrip* strip; - no_track_list_redisplay = true; - strip_redisplay_does_not_sync_order_keys = true; - - for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { - boost::shared_ptr<Route> route = (*x); - - if (route->is_hidden()) { - continue; - } - - if (route->is_monitor()) { - - if (!_monitor_section) { - _monitor_section = new MonitorSection (_session); + { + Unwinder<bool> uw (no_track_list_redisplay, true); + + for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { + boost::shared_ptr<Route> route = (*x); + + if (route->is_hidden()) { + continue; + } + + if (route->is_monitor()) { - XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section")); - if (mnode) { - _monitor_section->tearoff().set_state (*mnode); - } - } - - out_packer.pack_end (_monitor_section->tearoff(), false, false); - _monitor_section->set_session (_session); - _monitor_section->tearoff().show_all (); - - route->DropReferences.connect (*this, invalidator(*this), boost::bind (&Mixer_UI::monitor_section_going_away, this), gui_context()); - - /* no regular strip shown for control out */ - - continue; - } - - strip = new MixerStrip (*this, _session, route); - strips.push_back (strip); - - Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide; - - if (strip->width_owner() != strip) { - strip->set_width_enum (_strip_width, this); + if (!_monitor_section) { + _monitor_section = new MonitorSection (_session); + + XMLNode* mnode = ARDOUR_UI::instance()->tearoff_settings (X_("monitor-section")); + if (mnode) { + _monitor_section->tearoff().set_state (*mnode); + } + } + + out_packer.pack_end (_monitor_section->tearoff(), false, false); + _monitor_section->set_session (_session); + _monitor_section->tearoff().show_all (); + + route->DropReferences.connect (*this, invalidator(*this), boost::bind (&Mixer_UI::monitor_section_going_away, this), gui_context()); + + /* no regular strip shown for control out */ + + continue; + } + + strip = new MixerStrip (*this, _session, route); + strips.push_back (strip); + + Config->get_default_narrow_ms() ? _strip_width = Narrow : _strip_width = Wide; + + if (strip->width_owner() != strip) { + strip->set_width_enum (_strip_width, this); + } + + show_strip (strip); + + TreeModel::Row row = *(track_model->append()); + row[track_columns.text] = route->name(); + row[track_columns.visible] = strip->route()->is_master() ? true : strip->marked_for_display(); + row[track_columns.route] = route; + row[track_columns.strip] = strip; + + route->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::strip_property_changed, this, _1, strip), gui_context()); + + strip->WidthChanged.connect (sigc::mem_fun(*this, &Mixer_UI::strip_width_changed)); + strip->signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::strip_button_release_event), strip)); } - - show_strip (strip); - - TreeModel::Row row = *(track_model->append()); - row[track_columns.text] = route->name(); - row[track_columns.visible] = strip->route()->is_master() ? true : strip->marked_for_display(); - row[track_columns.route] = route; - row[track_columns.strip] = strip; - - route->PropertyChanged.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::strip_property_changed, this, _1, strip), gui_context()); - - strip->WidthChanged.connect (sigc::mem_fun(*this, &Mixer_UI::strip_width_changed)); - strip->signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &Mixer_UI::strip_button_release_event), strip)); } - no_track_list_redisplay = false; - + sync_order_keys_from_model (); redisplay_track_list (); - - strip_redisplay_does_not_sync_order_keys = false; } void @@ -387,62 +386,117 @@ Mixer_UI::remove_strip (MixerStrip* strip) strips.erase (i); } - strip_redisplay_does_not_sync_order_keys = true; - for (ri = rows.begin(); ri != rows.end(); ++ri) { if ((*ri)[track_columns.strip] == strip) { track_model->erase (ri); break; } } - - strip_redisplay_does_not_sync_order_keys = false; } void -Mixer_UI::sync_order_keys (RouteSortOrderKey src) +Mixer_UI::sync_order_keys_from_model () { - TreeModel::Children rows = track_model->children(); - TreeModel::Children::iterator ri; + if (ignore_reorder || !_session || _session->deletion_in_progress()) { + return; + } - if (src == MixerSort || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) { + TreeModel::Children rows = track_model->children(); + + if (rows.empty()) { return; } - std::map<int,int> keys; + DEBUG_TRACE (DEBUG::OrderKeys, "mixer sync order keys from model\n"); + TreeModel::Children::iterator ri; bool changed = false; + uint32_t order = 0; - unsigned order = 0; - for (ri = rows.begin(); ri != rows.end(); ++ri, ++order) { + for (ri = rows.begin(); ri != rows.end(); ++ri) { boost::shared_ptr<Route> route = (*ri)[track_columns.route]; - unsigned int old_key = order; - unsigned int new_key = route->order_key (MixerSort); + bool visible = (*ri)[track_columns.visible]; + + uint32_t old_key = route->order_key (MixerSort); + uint32_t new_key; - keys[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 (MixerSort, new_key); changed = true; } + + order++; + } + + if (changed) { + /* tell everyone that we changed the mixer sort keys */ + _session->sync_order_keys (MixerSort); } +} - if (keys.size() != rows.size()) { - PBD::stacktrace (cerr, 20); +void +Mixer_UI::sync_model_from_order_keys (RouteSortOrderKey src) +{ + if (!_session || _session->deletion_in_progress()) { + return; } - assert(keys.size() == rows.size()); - // Remove any gaps in keys caused by automation children tracks + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("mixer sync model from order keys, src = %1\n", enum_2_string (src))); + + if (src == EditorSort) { + + if (!Config->get_sync_all_route_ordering()) { + /* editor sort keys changed - we don't care */ + return; + } + + DEBUG_TRACE (DEBUG::OrderKeys, "reset mixer order key to match editor\n"); + + /* editor sort keys were changed, update the mixer 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; - for (std::map<int,int>::const_iterator i = keys.begin(); i != keys.end(); ++i) { - neworder.push_back(i->second); + TreeModel::Children rows = track_model->children(); + uint32_t n = 0; + + if (rows.empty()) { + return; } - assert(neworder.size() == rows.size()); - if (changed) { - strip_redisplay_does_not_reset_order_keys = true; + neworder.assign (rows.size(), 0); + + for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++n) { + boost::shared_ptr<Route> route = (*ri)[track_columns.route]; + neworder[route->order_key (MixerSort)] = n; + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("mixer change order for %1 to %2\n", + route->name(), route->order_key (MixerSort))); + } + + { + Unwinder<bool> uw (ignore_reorder, true); track_model->reorder (neworder); - strip_redisplay_does_not_reset_order_keys = false; } + + redisplay_track_list (); } void @@ -573,7 +627,7 @@ Mixer_UI::set_session (Session* sess) initial_track_display (); - _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::add_strip, this, _1), gui_context()); + _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::add_strips, this, _1), gui_context()); _session->route_group_added.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::add_route_group, this, _1), gui_context()); _session->route_group_removed.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::route_groups_changed, this), gui_context()); _session->route_groups_reordered.connect (_session_connections, invalidator (*this), boost::bind (&Mixer_UI::route_groups_changed, this), gui_context()); @@ -690,25 +744,26 @@ Mixer_UI::set_all_strips_visibility (bool yn) TreeModel::Children rows = track_model->children(); TreeModel::Children::iterator i; - no_track_list_redisplay = true; - - for (i = rows.begin(); i != rows.end(); ++i) { - - TreeModel::Row row = (*i); - MixerStrip* strip = row[track_columns.strip]; - - if (strip == 0) { - continue; - } - - if (strip->route()->is_master() || strip->route()->is_monitor()) { - continue; + { + Unwinder<bool> uw (no_track_list_redisplay, true); + + for (i = rows.begin(); i != rows.end(); ++i) { + + TreeModel::Row row = (*i); + MixerStrip* strip = row[track_columns.strip]; + + if (strip == 0) { + continue; + } + + if (strip->route()->is_master() || strip->route()->is_monitor()) { + continue; + } + + (*i)[track_columns.visible] = yn; } - - (*i)[track_columns.visible] = yn; } - no_track_list_redisplay = false; redisplay_track_list (); } @@ -719,42 +774,43 @@ Mixer_UI::set_all_audio_visibility (int tracks, bool yn) TreeModel::Children rows = track_model->children(); TreeModel::Children::iterator i; - no_track_list_redisplay = true; - - for (i = rows.begin(); i != rows.end(); ++i) { - TreeModel::Row row = (*i); - MixerStrip* strip = row[track_columns.strip]; - - if (strip == 0) { - continue; - } - - if (strip->route()->is_master() || strip->route()->is_monitor()) { - continue; - } - - boost::shared_ptr<AudioTrack> at = strip->audio_track(); - - switch (tracks) { - case 0: - (*i)[track_columns.visible] = yn; - break; - - case 1: - if (at) { /* track */ - (*i)[track_columns.visible] = yn; + { + Unwinder<bool> uw (no_track_list_redisplay, true); + + for (i = rows.begin(); i != rows.end(); ++i) { + TreeModel::Row row = (*i); + MixerStrip* strip = row[track_columns.strip]; + + if (strip == 0) { + continue; } - break; - - case 2: - if (!at) { /* bus */ + + if (strip->route()->is_master() || strip->route()->is_monitor()) { + continue; + } + + boost::shared_ptr<AudioTrack> at = strip->audio_track(); + + switch (tracks) { + case 0: (*i)[track_columns.visible] = yn; + break; + + case 1: + if (at) { /* track */ + (*i)[track_columns.visible] = yn; + } + break; + + case 2: + if (!at) { /* bus */ + (*i)[track_columns.visible] = yn; + } + break; } - break; } } - no_track_list_redisplay = false; redisplay_track_list (); } @@ -795,27 +851,18 @@ Mixer_UI::hide_all_audiotracks () void Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/) { - strip_redisplay_does_not_sync_order_keys = true; - redisplay_track_list (); - strip_redisplay_does_not_sync_order_keys = false; -} - -void -Mixer_UI::track_list_change (const Gtk::TreeModel::Path&, const Gtk::TreeModel::iterator&) -{ - // never reset order keys because of a property change - strip_redisplay_does_not_reset_order_keys = true; - redisplay_track_list (); - strip_redisplay_does_not_reset_order_keys = false; + DEBUG_TRACE (DEBUG::OrderKeys, "mixer UI treeview reordered\n"); + sync_order_keys_from_model (); } void Mixer_UI::track_list_delete (const Gtk::TreeModel::Path&) { - /* this could require an order sync */ - if (_session && !_session->deletion_in_progress()) { - redisplay_track_list (); - } + /* 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, "mixer UI treeview row deleted\n"); + sync_order_keys_from_model (); } void @@ -823,8 +870,6 @@ Mixer_UI::redisplay_track_list () { TreeModel::Children rows = track_model->children(); TreeModel::Children::iterator i; - long regular_order = 0; - long hidden_order = 999999; // arbitary high number if (no_track_list_redisplay) { return; @@ -848,41 +893,17 @@ Mixer_UI::redisplay_track_list () if (strip->route()->is_master() || strip->route()->is_monitor()) { out_packer.reorder_child (*strip, -1); - - if (!strip_redisplay_does_not_reset_order_keys) { - if (strip->route()->is_master()) { - strip->route()->set_order_key (MixerSort, Route::MasterBusRemoteControlID); - } else { - strip->route()->set_order_key (MixerSort, Route::MonitorBusRemoteControlID); - } - } } else { strip_packer.reorder_child (*strip, -1); /* put at end */ - - if (!strip_redisplay_does_not_reset_order_keys) { - strip->route()->set_order_key (MixerSort, regular_order++); - } - } } else { if (strip->route()->is_master() || strip->route()->is_monitor()) { out_packer.pack_start (*strip, false, false); - if (!strip_redisplay_does_not_reset_order_keys) { - if (strip->route()->is_master()) { - strip->route()->set_order_key (MixerSort, Route::MasterBusRemoteControlID); - } else { - strip->route()->set_order_key (MixerSort, Route::MonitorBusRemoteControlID); - } - } } else { strip_packer.pack_start (*strip, false, false); - - if (!strip_redisplay_does_not_reset_order_keys) { - strip->route()->set_order_key (MixerSort, regular_order++); - } } strip->set_packed (true); } @@ -898,18 +919,10 @@ Mixer_UI::redisplay_track_list () strip_packer.remove (*strip); strip->set_packed (false); } - - if (!strip_redisplay_does_not_reset_order_keys) { - strip->route()->set_order_key (MixerSort, hidden_order++); - } } } } - if (!strip_redisplay_does_not_reset_order_keys && !strip_redisplay_does_not_sync_order_keys) { - _session->sync_order_keys (MixerSort); - } - _group_tabs->set_dirty (); } @@ -942,7 +955,17 @@ Mixer_UI::strip_width_changed () struct SignalOrderRouteSorter { bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) { + if (a->is_master() || a->is_monitor()) { + /* "a" is a special route (master, monitor, etc), and comes + * last in the mixer ordering + */ + return false; + } else if (b->is_master() || b->is_monitor()) { + /* everything comes before b */ + return true; + } return a->order_key (MixerSort) < b->order_key (MixerSort); + } }; @@ -955,13 +978,13 @@ Mixer_UI::initial_track_display () copy.sort (sorter); - no_track_list_redisplay = true; - - track_model->clear (); - - add_strip (copy); + { + Unwinder<bool> uw1 (no_track_list_redisplay, true); + Unwinder<bool> uw2 (ignore_reorder, true); - no_track_list_redisplay = false; + track_model->clear (); + add_strips (copy); + } redisplay_track_list (); } @@ -1675,7 +1698,6 @@ Mixer_UI::setup_track_display () track_display.set_headers_visible (true); track_model->signal_row_deleted().connect (sigc::mem_fun (*this, &Mixer_UI::track_list_delete)); - track_model->signal_row_changed().connect (sigc::mem_fun (*this, &Mixer_UI::track_list_change)); track_model->signal_rows_reordered().connect (sigc::mem_fun (*this, &Mixer_UI::track_list_reorder)); CellRendererToggle* track_list_visible_cell = dynamic_cast<CellRendererToggle*>(track_display.get_column_cell_renderer (1)); diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h index f3d7845461..ab0223aa4d 100644 --- a/gtk2_ardour/mixer_ui.h +++ b/gtk2_ardour/mixer_ui.h @@ -130,7 +130,7 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR void scroll_left (); void scroll_right (); - void add_strip (ARDOUR::RouteList&); + void add_strips (ARDOUR::RouteList&); void remove_strip (MixerStrip *); MixerStrip* strip_by_route (boost::shared_ptr<ARDOUR::Route>); @@ -161,7 +161,6 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR bool track_display_button_press (GdkEventButton*); void strip_width_changed (); - void track_list_change (const Gtk::TreeModel::Path&,const Gtk::TreeModel::iterator&); void track_list_delete (const Gtk::TreeModel::Path&); void track_list_reorder (const Gtk::TreeModel::Path& path, const Gtk::TreeModel::iterator& iter, int* new_order); @@ -245,10 +244,9 @@ class Mixer_UI : public Gtk::Window, public PBD::ScopedConnectionList, public AR Width _strip_width; - void sync_order_keys (ARDOUR::RouteSortOrderKey); - bool strip_redisplay_does_not_reset_order_keys; - bool strip_redisplay_does_not_sync_order_keys; - bool ignore_sync; + void sync_order_keys_from_model (); + void sync_model_from_order_keys (ARDOUR::RouteSortOrderKey); + bool ignore_reorder; void parameter_changed (std::string const &); void set_route_group_activation (ARDOUR::RouteGroup *, bool); diff --git a/gtk2_ardour/port_matrix.cc b/gtk2_ardour/port_matrix.cc index 40c48b2345..8db2dad475 100644 --- a/gtk2_ardour/port_matrix.cc +++ b/gtk2_ardour/port_matrix.cc @@ -157,7 +157,7 @@ PortMatrix::init () _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_proxy, this), gui_context()); + Route::SyncOrderKeys.connect (_session_connections, invalidator (*this), boost::bind (&PortMatrix::setup_global_ports_proxy, this, _1), gui_context()); /* Part 3: other stuff */ @@ -598,13 +598,15 @@ PortMatrix::setup_global_ports () } void -PortMatrix::setup_global_ports_proxy () +PortMatrix::setup_global_ports_proxy (RouteSortOrderKey sk) { - /* Avoid a deadlock by calling this in an idle handler: see IOSelector::io_changed_proxy - for a discussion. - */ - - Glib::signal_idle().connect_once (sigc::mem_fun (*this, &PortMatrix::setup_global_ports)); + if (sk == EditorSort) { + /* Avoid a deadlock by calling this in an idle handler: see IOSelector::io_changed_proxy + for a discussion. + */ + + Glib::signal_idle().connect_once (sigc::mem_fun (*this, &PortMatrix::setup_global_ports)); + } } void diff --git a/gtk2_ardour/port_matrix.h b/gtk2_ardour/port_matrix.h index 76ead4bee9..2b5e9ce31d 100644 --- a/gtk2_ardour/port_matrix.h +++ b/gtk2_ardour/port_matrix.h @@ -188,7 +188,7 @@ private: void disassociate_all_on_channel (boost::weak_ptr<ARDOUR::Bundle>, uint32_t, int); void disassociate_all_on_bundle (boost::weak_ptr<ARDOUR::Bundle>, int); void setup_global_ports (); - void setup_global_ports_proxy (); + void setup_global_ports_proxy (ARDOUR::RouteSortOrderKey); void toggle_show_only_bundles (); bool on_scroll_event (GdkEventScroll *); boost::shared_ptr<ARDOUR::IO> io_from_bundle (boost::shared_ptr<ARDOUR::Bundle>) const; diff --git a/gtk2_ardour/route_ui.cc b/gtk2_ardour/route_ui.cc index b6c81717a2..536b4f110b 100644 --- a/gtk2_ardour/route_ui.cc +++ b/gtk2_ardour/route_ui.cc @@ -1738,9 +1738,12 @@ RouteUI::open_remote_control_id_dialog () dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT); } else { Label* l = manage (new Label()); - l->set_markup (string_compose (_("Remote Control IDs are currently determined by track/bus ordering in %1\n\n\n" + l->set_markup (string_compose (_("Remote Control IDs are currently determined by track/bus ordering in %1\n\n" + "This %2 has remote control ID %3\n\n\n" "<span size=\"small\" style=\"italic\">Use the User Interaction tab of the Preferences window if you want to change this</span>"), - (Config->get_remote_model() == MixerOrdered ? _("the mixer") : ("the editor")))); + (Config->get_remote_model() == MixerOrdered ? _("the mixer") : ("the editor")), + (is_track() ? _("track") : _("bus")), + _route->remote_control_id())); dialog.get_vbox()->pack_start (*l); dialog.add_button (Stock::OK, RESPONSE_CANCEL); } |