summaryrefslogtreecommitdiff
path: root/gtk2_ardour/mixer_ui.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/mixer_ui.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/mixer_ui.cc')
-rw-r--r--gtk2_ardour/mixer_ui.cc414
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));