diff options
Diffstat (limited to 'gtk2_ardour/mixer_ui.cc')
-rw-r--r-- | gtk2_ardour/mixer_ui.cc | 414 |
1 files changed, 218 insertions, 196 deletions
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)); |