X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fmixer_ui.cc;h=12cf87d7931a7f31341b7ea8296bf895e3e74b2f;hb=a18db90264a91a5fe80b5993511c960329964742;hp=e301bbcc79af3a285d298abe6631136e2aea93ca;hpb=7db500301d1f02e9cb98eb5c744ae68456fac75b;p=ardour.git diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc index e301bbcc79..12cf87d793 100644 --- a/gtk2_ardour/mixer_ui.cc +++ b/gtk2_ardour/mixer_ui.cc @@ -28,10 +28,9 @@ #include #include "pbd/convert.h" -#include "pbd/stacktrace.h" #include "pbd/unwind.h" -#include +#include #include #include @@ -39,6 +38,7 @@ #include #include "ardour/debug.h" +#include "ardour/midi_track.h" #include "ardour/plugin_manager.h" #include "ardour/route_group.h" #include "ardour/session.h" @@ -52,6 +52,7 @@ #include "ardour_ui.h" #include "prompter.h" #include "utils.h" +#include "route_sorter.h" #include "actions.h" #include "gui_thread.h" #include "mixer_group_tabs.h" @@ -82,6 +83,7 @@ Mixer_UI::instance () Mixer_UI::Mixer_UI () : Window (Gtk::WINDOW_TOPLEVEL) + , VisibilityTracker (*((Gtk::Window*) this)) , _visible (false) , no_track_list_redisplay (false) , in_group_row_change (false) @@ -94,7 +96,10 @@ Mixer_UI::Mixer_UI () /* allow this window to become the key focus window */ set_flags (CAN_FOCUS); - Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_model_from_order_keys, this, _1), gui_context()); + Route::SyncOrderKeys.connect (*this, invalidator (*this), boost::bind (&Mixer_UI::sync_treeview_from_order_keys, this), gui_context()); + + scroller.set_can_default (true); + set_default (scroller); scroller_base.set_flags (Gtk::CAN_FOCUS); scroller_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK); @@ -122,7 +127,7 @@ Mixer_UI::Mixer_UI () group_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); group_display.get_column (0)->set_expand(true); group_display.get_column (1)->set_expand(false); - group_display.set_name ("MixerGroupList"); + group_display.set_name ("EditGroupList"); group_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE); group_display.set_reorderable (true); group_display.set_headers_visible (true); @@ -308,15 +313,32 @@ Mixer_UI::hide_window (GdkEventAny *ev) void Mixer_UI::add_strips (RouteList& routes) { + bool from_scratch = track_model->children().size() == 0; + Gtk::TreeModel::Children::iterator insert_iter = track_model->children().end(); + + for (Gtk::TreeModel::Children::iterator it = track_model->children().begin(); it != track_model->children().end(); ++it) { + boost::shared_ptr r = (*it)[track_columns.route]; + + if (r->order_key() == (routes.front()->order_key() + routes.size())) { + insert_iter = it; + break; + } + } + + if(!from_scratch) { + _selection.clear_routes (); + } + MixerStrip* strip; - { - Unwinder uw (no_track_list_redisplay, true); - + try { + no_track_list_redisplay = true; + track_display.set_model (Glib::RefPtr()); + for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr route = (*x); - if (route->is_hidden()) { + if (route->is_auditioner()) { continue; } @@ -344,7 +366,7 @@ Mixer_UI::add_strips (RouteList& routes) 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) { @@ -353,20 +375,29 @@ Mixer_UI::add_strips (RouteList& routes) show_strip (strip); - TreeModel::Row row = *(track_model->append()); + TreeModel::Row row = *(track_model->insert(insert_iter)); 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; + + if (!from_scratch) { + _selection.add (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)); } + + } catch (...) { } - sync_order_keys_from_model (); + no_track_list_redisplay = false; + track_display.set_model (track_model); + + sync_order_keys_from_treeview (); redisplay_track_list (); } @@ -395,9 +426,9 @@ Mixer_UI::remove_strip (MixerStrip* strip) } void -Mixer_UI::sync_order_keys_from_model () +Mixer_UI::reset_remote_control_ids () { - if (ignore_reorder || !_session || _session->deletion_in_progress()) { + if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) { return; } @@ -407,57 +438,109 @@ Mixer_UI::sync_order_keys_from_model () return; } - DEBUG_TRACE (DEBUG::OrderKeys, "mixer sync order keys from model\n"); + DEBUG_TRACE (DEBUG::OrderKeys, "mixer resets remote control ids after remote model change\n"); TreeModel::Children::iterator ri; - bool changed = false; - uint32_t order = 0; + bool rid_change = false; + uint32_t rid = 1; + uint32_t invisible_key = UINT32_MAX; - for (ri = rows.begin(); ri != rows.end(); ++ri, ++order) { + for (ri = rows.begin(); ri != rows.end(); ++ri) { boost::shared_ptr route = (*ri)[track_columns.route]; - uint32_t old_key = route->order_key (MixerSort); + bool visible = (*ri)[track_columns.visible]; - if (old_key != order) { - route->set_order_key (MixerSort, order); - changed = true; + if (!route->is_master() && !route->is_monitor()) { + + uint32_t new_rid = (visible ? rid : invisible_key--); + + if (new_rid != route->remote_control_id()) { + route->set_remote_control_id_explicit (new_rid); + rid_change = true; + } + + if (visible) { + rid++; + } } } - - if (changed) { - /* tell everyone that we changed the mixer sort keys */ - _session->sync_order_keys (MixerSort); + + if (rid_change) { + /* tell the world that we changed the remote control IDs */ + _session->notify_remote_id_change (); } } void -Mixer_UI::sync_model_from_order_keys (RouteSortOrderKey src) +Mixer_UI::sync_order_keys_from_treeview () { - if (!_session || _session->deletion_in_progress()) { + if (ignore_reorder || !_session || _session->deletion_in_progress()) { return; } - DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("mixer sync model from order keys, src = %1\n", enum_2_string (src))); + TreeModel::Children rows = track_model->children(); + + if (rows.empty()) { + return; + } + + DEBUG_TRACE (DEBUG::OrderKeys, "mixer sync order keys from model\n"); - if (src == EditorSort) { + TreeModel::Children::iterator ri; + bool changed = false; + bool rid_change = false; + uint32_t order = 0; + uint32_t rid = 1; + uint32_t invisible_key = UINT32_MAX; - if (!Config->get_sync_all_route_ordering()) { - /* editor sort keys changed - we don't care */ - return; + for (ri = rows.begin(); ri != rows.end(); ++ri) { + boost::shared_ptr route = (*ri)[track_columns.route]; + bool visible = (*ri)[track_columns.visible]; + + uint32_t old_key = route->order_key (); + + if (order != old_key) { + route->set_order_key (order); + changed = true; } - DEBUG_TRACE (DEBUG::OrderKeys, "reset mixer order key to match editor\n"); + if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) { - /* editor sort keys were changed, update the mixer sort - * keys since "sync mixer+editor order" is enabled. - */ + uint32_t new_rid = (visible ? rid : invisible_key--); + + if (new_rid != route->remote_control_id()) { + route->set_remote_control_id_explicit (new_rid); + rid_change = true; + } + + if (visible) { + rid++; + } - boost::shared_ptr r = _session->get_routes (); - - for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { - (*i)->sync_order_keys (src); } + + ++order; + } + + if (changed) { + /* tell everyone that we changed the mixer sort keys */ + _session->sync_order_keys (); } + if (rid_change) { + /* tell the world that we changed the remote control IDs */ + _session->notify_remote_id_change (); + } +} + +void +Mixer_UI::sync_treeview_from_order_keys () +{ + if (!_session || _session->deletion_in_progress()) { + return; + } + + DEBUG_TRACE (DEBUG::OrderKeys, "mixer sync model from order keys.\n"); + /* 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. @@ -465,27 +548,37 @@ Mixer_UI::sync_model_from_order_keys (RouteSortOrderKey src) vector neworder; TreeModel::Children rows = track_model->children(); - uint32_t n = 0; + uint32_t old_order = 0; bool changed = false; if (rows.empty()) { return; } - neworder.assign (rows.size(), 0); - - for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++n) { + OrderKeySortedRoutes sorted_routes; + + for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) { boost::shared_ptr route = (*ri)[track_columns.route]; - uint32_t o = route->order_key (MixerSort); + sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key ())); + } + + SortByNewDisplayOrder cmp; + + sort (sorted_routes.begin(), sorted_routes.end(), cmp); + neworder.assign (sorted_routes.size(), 0); + + uint32_t n = 0; + + for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) { - neworder[o] = n; + neworder[n] = sr->old_display_order; - if (o != n) { + if (sr->old_display_order != n) { changed = true; } - DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("mixer change order for %1 to %2\n", - route->name(), route->order_key (MixerSort))); + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("MIXER change order for %1 from %2 to %3\n", + sr->route->name(), sr->old_display_order, n)); } if (changed) { @@ -679,6 +772,50 @@ Mixer_UI::session_going_away () update_title (); } +void +Mixer_UI::track_visibility_changed (std::string const & path) +{ + if (_session && _session->deletion_in_progress()) { + return; + } + + TreeIter iter; + + if ((iter = track_model->get_iter (path))) { + MixerStrip* strip = (*iter)[track_columns.strip]; + if (strip) { + bool visible = (*iter)[track_columns.visible]; + + if (strip->set_marked_for_display (!visible)) { + update_track_visibility (); + } + } + } +} + +void +Mixer_UI::update_track_visibility () +{ + TreeModel::Children rows = track_model->children(); + TreeModel::Children::iterator i; + + { + Unwinder uw (no_track_list_redisplay, true); + + for (i = rows.begin(); i != rows.end(); ++i) { + MixerStrip *strip = (*i)[track_columns.strip]; + (*i)[track_columns.visible] = strip->marked_for_display (); + } + + /* force route order keys catch up with visibility changes + */ + + sync_order_keys_from_treeview (); + } + + redisplay_track_list (); +} + void Mixer_UI::show_strip (MixerStrip* ms) { @@ -690,6 +827,7 @@ Mixer_UI::show_strip (MixerStrip* ms) MixerStrip* strip = (*i)[track_columns.strip]; if (strip == ms) { (*i)[track_columns.visible] = true; + redisplay_track_list (); break; } } @@ -706,6 +844,7 @@ Mixer_UI::hide_strip (MixerStrip* ms) MixerStrip* strip = (*i)[track_columns.strip]; if (strip == ms) { (*i)[track_columns.visible] = false; + redisplay_track_list (); break; } } @@ -849,7 +988,7 @@ void Mixer_UI::track_list_reorder (const TreeModel::Path&, const TreeModel::iterator&, int* /*new_order*/) { DEBUG_TRACE (DEBUG::OrderKeys, "mixer UI treeview reordered\n"); - sync_order_keys_from_model (); + sync_order_keys_from_treeview (); } void @@ -859,7 +998,7 @@ Mixer_UI::track_list_delete (const Gtk::TreeModel::Path&) as when a row/route is actually deleted. */ DEBUG_TRACE (DEBUG::OrderKeys, "mixer UI treeview row deleted\n"); - sync_order_keys_from_model (); + sync_order_keys_from_treeview (); } void @@ -961,7 +1100,7 @@ struct SignalOrderRouteSorter { /* everything comes before b */ return true; } - return a->order_key (MixerSort) < b->order_key (MixerSort); + return a->order_key () < b->order_key (); } }; @@ -983,7 +1122,7 @@ Mixer_UI::initial_track_display () add_strips (copy); } - _session->sync_order_keys (MixerSort); + _session->sync_order_keys (); redisplay_track_list (); } @@ -1006,46 +1145,9 @@ Mixer_UI::track_display_button_press (GdkEventButton* ev) return true; } - TreeIter iter; - TreeModel::Path path; - TreeViewColumn* column; - int cellx; - int celly; - - if (!track_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) { - return false; - } - - switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) { - case 0: - /* allow normal processing to occur */ - return false; - - case 1: /* visibility */ - - if ((iter = track_model->get_iter (path))) { - MixerStrip* strip = (*iter)[track_columns.strip]; - if (strip) { - - if (!strip->route()->is_master() && !strip->route()->is_monitor()) { - bool visible = (*iter)[track_columns.visible]; - (*iter)[track_columns.visible] = !visible; - } -#ifdef GTKOSX - track_display.queue_draw(); -#endif - } - } - return true; - - default: - break; - } - return false; } - void Mixer_UI::build_track_menu () { @@ -1375,12 +1477,12 @@ Mixer_UI::strip_scroller_button_release (GdkEventButton* ev) } void -Mixer_UI::set_strip_width (Width w) +Mixer_UI::set_strip_width (Width w, bool save) { _strip_width = w; for (list::iterator i = strips.begin(); i != strips.end(); ++i) { - (*i)->set_width_enum (w, this); + (*i)->set_width_enum (w, save ? (*i)->width_owner() : this); } } @@ -1564,6 +1666,7 @@ Mixer_UI::pane_allocation_handler (Allocation&, Gtk::Paned* which) void Mixer_UI::scroll_left () { + if (!scroller.get_hscrollbar()) return; Adjustment* adj = scroller.get_hscrollbar()->get_adjustment(); /* stupid GTK: can't rely on clamping across versions */ scroller.get_hscrollbar()->set_value (max (adj->get_lower(), adj->get_value() - adj->get_step_increment())); @@ -1572,6 +1675,7 @@ Mixer_UI::scroll_left () void Mixer_UI::scroll_right () { + if (!scroller.get_hscrollbar()) return; Adjustment* adj = scroller.get_hscrollbar()->get_adjustment(); /* stupid GTK: can't rely on clamping across versions */ scroller.get_hscrollbar()->set_value (min (adj->get_upper(), adj->get_value() + adj->get_step_increment())); @@ -1660,6 +1764,8 @@ Mixer_UI::parameter_changed (string const & p) for (list::iterator i = strips.begin(); i != strips.end(); ++i) { (*i)->set_width_enum (s ? Narrow : Wide, this); } + } else if (p == "remote-model") { + reset_remote_control_ids (); } } @@ -1691,7 +1797,7 @@ Mixer_UI::setup_track_display () track_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1)); track_display.get_column (0)->set_expand(true); track_display.get_column (1)->set_expand(false); - track_display.set_name (X_("MixerTrackDisplayList")); + track_display.set_name (X_("EditGroupList")); track_display.get_selection()->set_mode (Gtk::SELECTION_NONE); track_display.set_reorderable (true); track_display.set_headers_visible (true); @@ -1702,6 +1808,7 @@ Mixer_UI::setup_track_display () CellRendererToggle* track_list_visible_cell = dynamic_cast(track_display.get_column_cell_renderer (1)); track_list_visible_cell->property_activatable() = true; track_list_visible_cell->property_radio() = false; + track_list_visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &Mixer_UI::track_visibility_changed)); track_display.signal_button_press_event().connect (sigc::mem_fun (*this, &Mixer_UI::track_display_button_press), false); @@ -1794,7 +1901,7 @@ Mixer_UI::set_route_targets_for_operation () return; } - /* try to get mixer strip at mouse */ + /* nothing selected ... try to get mixer strip at mouse */ int x, y; get_pointer (x, y); @@ -1814,3 +1921,24 @@ Mixer_UI::monitor_section_going_away () _monitor_section->set_session (0); } } + +void +Mixer_UI::toggle_midi_input_active (bool flip_others) +{ + boost::shared_ptr rl (new RouteList); + bool onoff = false; + + set_route_targets_for_operation (); + + for (RouteUISelection::iterator r = _route_targets.begin(); r != _route_targets.end(); ++r) { + boost::shared_ptr mt = (*r)->midi_track(); + + if (mt) { + rl->push_back ((*r)->route()); + onoff = !mt->input_active(); + } + } + + _session->set_exclusive_input_active (rl, onoff, flip_others); +} +