X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Feditor_routes.cc;h=b05e4617282849ca75337aa6952307f16c1920da;hb=6acdfc69b785841ac10a324484ddd0208612a213;hp=015d42b3858ac5f24929abb61bb9055fc99ea2b6;hpb=aef4f9fb078225f06bba457d88082d7108965bff;p=ardour.git diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc index 015d42b385..b05e461728 100644 --- a/gtk2_ardour/editor_routes.cc +++ b/gtk2_ardour/editor_routes.cc @@ -24,8 +24,18 @@ #include #include +#include "pbd/unknown_type.h" +#include "pbd/unwind.h" + +#include "ardour/debug.h" +#include "ardour/route.h" +#include "ardour/midi_track.h" #include "ardour/session.h" +#include "gtkmm2ext/cell_renderer_pixbuf_multi.h" +#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h" +#include "gtkmm2ext/treeutils.h" + #include "editor.h" #include "keyboard.h" #include "ardour_ui.h" @@ -35,18 +45,10 @@ #include "gui_thread.h" #include "actions.h" #include "utils.h" +#include "route_sorter.h" #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; @@ -57,13 +59,18 @@ using namespace Gtkmm2ext; using namespace Glib; using Gtkmm2ext::Keyboard; +struct ColumnInfo { + int index; + const char* label; + const char* tooltip; +}; + 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) + , _adding_routes (false) + , _menu (0) , old_focus (0) , selection_countdown (0) , name_editable (0) @@ -115,9 +122,9 @@ EditorRoutes::EditorRoutes (Editor* e) // Mute enable toggle CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti()); - mute_col_renderer->set_pixbuf (ActiveState(0), ::get_icon("mute-disabled")); - mute_col_renderer->set_pixbuf (Mid, ::get_icon("muted-by-others")); - mute_col_renderer->set_pixbuf (Active, ::get_icon("mute-enabled")); + mute_col_renderer->set_pixbuf (Gtkmm2ext::Off, ::get_icon("mute-disabled")); + mute_col_renderer->set_pixbuf (Gtkmm2ext::ImplicitActive, ::get_icon("muted-by-others")); + mute_col_renderer->set_pixbuf (Gtkmm2ext::ExplicitActive, ::get_icon("mute-enabled")); mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled)); TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer)); @@ -131,14 +138,15 @@ EditorRoutes::EditorRoutes (Editor* e) // Solo enable toggle CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti()); - solo_col_renderer->set_pixbuf (ActiveState(0), ::get_icon("solo-disabled")); - solo_col_renderer->set_pixbuf (Active, ::get_icon("solo-enabled")); - solo_col_renderer->set_pixbuf (Mid, ::get_icon("soloed-by-others")); + solo_col_renderer->set_pixbuf (Gtkmm2ext::Off, ::get_icon("solo-disabled")); + solo_col_renderer->set_pixbuf (Gtkmm2ext::ExplicitActive, ::get_icon("solo-enabled")); + solo_col_renderer->set_pixbuf (Gtkmm2ext::ImplicitActive, ::get_icon("soloed-by-others")); solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled)); TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer)); solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state); + solo_state_column->add_attribute(solo_col_renderer->property_visible(), _columns.solo_visible); solo_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_state_column->set_alignment(ALIGN_CENTER); solo_state_column->set_expand(false); @@ -154,6 +162,7 @@ EditorRoutes::EditorRoutes (Editor* e) TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("SI", *solo_iso_renderer)); solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state); + solo_isolate_state_column->add_attribute(solo_iso_renderer->property_visible(), _columns.solo_visible); solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_isolate_state_column->set_alignment(ALIGN_CENTER); solo_isolate_state_column->set_expand(false); @@ -168,11 +177,16 @@ EditorRoutes::EditorRoutes (Editor* e) TreeViewColumn* solo_safe_state_column = manage (new TreeViewColumn(_("SS"), *solo_safe_renderer)); solo_safe_state_column->add_attribute(solo_safe_renderer->property_state(), _columns.solo_safe_state); + solo_safe_state_column->add_attribute(solo_safe_renderer->property_visible(), _columns.solo_visible); solo_safe_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED); solo_safe_state_column->set_alignment(ALIGN_CENTER); solo_safe_state_column->set_expand(false); solo_safe_state_column->set_fixed_width(column_width); + _name_column = _display.append_column ("", _columns.text) - 1; + _visible_column = _display.append_column ("", _columns.visible) - 1; + _active_column = _display.append_column ("", _columns.active) - 1; + _display.append_column (*input_active_column); _display.append_column (*rec_state_column); _display.append_column (*mute_state_column); @@ -180,15 +194,36 @@ EditorRoutes::EditorRoutes (Editor* e) _display.append_column (*solo_isolate_state_column); _display.append_column (*solo_safe_state_column); - _name_column = _display.append_column (_("Name"), _columns.text) - 1; - _visible_column = _display.append_column (_("V"), _columns.visible) - 1; - _active_column = _display.append_column (_("A"), _columns.active) - 1; + + TreeViewColumn* col; + Gtk::Label* l; + + ColumnInfo ci[] = { + { 0, _("Name"), _("Track/Bus Name") }, + { 1, _("V"), _("Track/Bus visible ?") }, + { 2, _("A"), _("Track/Bus active ?") }, + { 3, _("I"), _("MIDI input enabled") }, + { 4, _("R"), _("Record enabled") }, + { 5, _("M"), _("Muted") }, + { 6, _("S"), _("Soloed") }, + { 7, _("SI"), _("Solo Isolated") }, + { 8, _("SS"), _("Solo Safe (Locked)") }, + { -1, 0, 0 } + }; + + for (int i = 0; ci[i].index >= 0; ++i) { + col = _display.get_column (ci[i].index); + l = manage (new Label (ci[i].label)); + ARDOUR_UI::instance()->set_tip (*l, ci[i].tooltip); + col->set_widget (*l); + l->show (); + } _display.set_headers_visible (true); - _display.set_name ("TrackListDisplay"); _display.get_selection()->set_mode (SELECTION_SINGLE); _display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter)); _display.set_reorderable (true); + _display.set_name (X_("EditGroupList")); _display.set_rules_hint (true); _display.set_size_request (100, -1); _display.add_object_drag (_columns.route.index(), "routes"); @@ -249,7 +284,7 @@ EditorRoutes::EditorRoutes (Editor* e) _display.set_enable_search (false); - Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::sync_order_keys, this, _1), gui_context()); + Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this), gui_context()); } bool @@ -456,7 +491,7 @@ EditorRoutes::show_menu () void EditorRoutes::redisplay () { - if (_no_redisplay || !_session) { + if (_no_redisplay || !_session || _session->deletion_in_progress()) { return; } @@ -469,12 +504,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 = (*i)[_columns.route]; @@ -483,25 +513,17 @@ EditorRoutes::redisplay () continue; } - if (!_redisplay_does_not_reset_order_keys) { - /* this reorder is caused by user action, so reassign sort order keys - to tracks. - */ - route->set_order_key (N_ ("editor"), order_key); - } - bool visible = tv->marked_for_display (); /* show or hide the TimeAxisView */ if (visible) { position += tv->show_at (position, n, &_editor->edit_controls_vbox); - tv->clip_to_viewport (); + // SHOWTRACKS } else { tv->hide (); } n++; - order_key++; } /* whenever we go idle, update the track view list to reflect the new order. @@ -512,34 +534,32 @@ EditorRoutes::redisplay () _editor->reset_controls_layout_height (position); _editor->reset_controls_layout_width (); - _editor->full_canvas_height = position + _editor->canvas_timebars_vsize; - _editor->vertical_adjustment.set_upper (_editor->full_canvas_height); + _editor->_full_canvas_height = position; - if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) { + if ((_editor->vertical_adjustment.get_value() + _editor->_visible_canvas_height) > _editor->vertical_adjustment.get_upper()) { /* We're increasing the size of the canvas while the bottom is visible. We scroll down to keep in step with the controls layout. */ - _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 (N_ ("editor")); + _editor->vertical_adjustment.set_value (_editor->_full_canvas_height - _editor->_visible_canvas_height); } } 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_treeview (); +} - /* this could require an order reset & sync */ - _session->set_remote_control_ids(); - _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_treeview (); } void @@ -557,11 +577,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; - _session->set_remote_control_ids(); update_visibility (); - redisplay (); - _redisplay_does_not_reset_order_keys = false; } } } @@ -583,16 +599,33 @@ EditorRoutes::active_changed (std::string const & path) void EditorRoutes::routes_added (list routes) { - TreeModel::Row row; + PBD::Unwinder at (_adding_routes, true); + + bool from_scratch = (_model->children().size() == 0); + Gtk::TreeModel::Children::iterator insert_iter = _model->children().end(); + + for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) { + boost::shared_ptr r = (*it)[_columns.route]; + + if (r->order_key() == (routes.front()->route()->order_key() + routes.size())) { + insert_iter = it; + break; + } + } + + if(!from_scratch) { + _editor->selection->tracks.clear(); + } - _redisplay_does_not_sync_order_keys = true; suspend_redisplay (); + _display.set_model (Glib::RefPtr()); + for (list::iterator x = routes.begin(); x != routes.end(); ++x) { boost::shared_ptr midi_trk = boost::dynamic_pointer_cast ((*x)->route()); - row = *(_model->append ()); + TreeModel::Row row = *(_model->insert (insert_iter)); row[_columns.text] = (*x)->route()->name(); row[_columns.visible] = (*x)->marked_for_display(); @@ -609,25 +642,21 @@ EditorRoutes::routes_added (list routes) row[_columns.is_midi] = false; } - row[_columns.mute_state] = (*x)->route()->muted() ? Active : ActiveState (0); + row[_columns.mute_state] = (*x)->route()->muted() ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off; row[_columns.solo_state] = RouteUI::solo_active_state ((*x)->route()); + row[_columns.solo_visible] = !(*x)->route()->is_master (); row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated(); row[_columns.solo_safe_state] = (*x)->route()->solo_safe(); row[_columns.name_editable] = true; - _ignore_reorder = true; - - /* added a new fresh one at the end */ - if ((*x)->route()->order_key (N_ ("editor")) == -1) { - (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1); + if (!from_scratch) { + _editor->selection->add(*x); } - _ignore_reorder = false; - boost::weak_ptr wr ((*x)->route()); - (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context()); - (*x)->route()->PropertyChanged.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::route_property_changed, this, _1, wr), gui_context()); + (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context()); + (*x)->route()->PropertyChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::route_property_changed, this, _1, wr), gui_context()); if ((*x)->is_track()) { boost::shared_ptr t = boost::dynamic_pointer_cast ((*x)->route()); @@ -641,11 +670,12 @@ EditorRoutes::routes_added (list routes) } (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context()); - (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::update_solo_display, this, _1), gui_context()); - (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::update_solo_display, this, _1), gui_context()); + (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context()); + (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context()); (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context()); (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context()); (*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ()); + } update_rec_display (); @@ -655,20 +685,26 @@ EditorRoutes::routes_added (list routes) update_solo_safe_display (); update_input_active_display (); update_active_display (); + resume_redisplay (); - _redisplay_does_not_sync_order_keys = false; + _display.set_model (_model); + + /* now update route order keys from the treeview/track display order */ + + sync_order_keys_from_treeview (); } void EditorRoutes::handle_gui_changes (string const & what, void*) { - ENSURE_GUI_THREAD (*this, &EditorRoutes::handle_gui_changes, what, src) + if (_adding_routes) { + return; + } if (what == "track_height") { /* Optional :make tracks change height while it happens, instead of on first-idle */ - //update_canvas_now (); redisplay (); } @@ -685,12 +721,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); @@ -698,7 +728,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 @@ -753,6 +785,11 @@ EditorRoutes::update_visibility () (*i)[_columns.visible] = tv->marked_for_display (); } + /* force route order keys catch up with visibility changes + */ + + sync_order_keys_from_treeview (); + resume_redisplay (); } @@ -790,57 +827,180 @@ EditorRoutes::show_track_in_display (TimeAxisView& tv) } void -EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/) +EditorRoutes::reset_remote_control_ids () { - redisplay (); + if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) { + return; + } + + TreeModel::Children rows = _model->children(); + + if (rows.empty()) { + return; + } + + + DEBUG_TRACE (DEBUG::OrderKeys, "editor reset remote control ids\n"); + + TreeModel::Children::iterator ri; + bool rid_change = false; + uint32_t rid = 1; + uint32_t invisible_key = UINT32_MAX; + + for (ri = rows.begin(); ri != rows.end(); ++ri) { + + boost::shared_ptr route = (*ri)[_columns.route]; + bool visible = (*ri)[_columns.visible]; + + + 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 (rid_change) { + /* tell the world that we changed the remote control IDs */ + _session->notify_remote_id_change (); + } } -/** 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 (string const & src) +EditorRoutes::sync_order_keys_from_treeview () { - map new_order; - TreeModel::Children rows = _model->children(); - TreeModel::Children::iterator ri; + if (_ignore_reorder || !_session || _session->deletion_in_progress()) { + return; + } - if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) { + TreeModel::Children rows = _model->children(); + + if (rows.empty()) { return; } + + DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from treeview\n"); + + TreeModel::Children::iterator ri; bool changed = false; - int order; + bool rid_change = false; + uint32_t order = 0; + uint32_t rid = 1; + uint32_t invisible_key = UINT32_MAX; + + for (ri = rows.begin(); ri != rows.end(); ++ri) { - for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) { boost::shared_ptr route = (*ri)[_columns.route]; + bool visible = (*ri)[_columns.visible]; - int const old_key = order; - int const new_key = route->order_key (N_ ("editor")); + uint32_t old_key = route->order_key (); - new_order[new_key] = old_key; + if (order != old_key) { + route->set_order_key (order); - if (new_key != old_key) { changed = true; } - } - if (changed) { - _redisplay_does_not_reset_order_keys = true; + if ((Config->get_remote_model() == MixerOrdered) && !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++; + } - /* `compact' new_order into a vector */ - vector co; - for (map::const_iterator i = new_order.begin(); i != new_order.end(); ++i) { - co.push_back (i->second); } - assert (co.size() == _model->children().size ()); + ++order; + } + + if (changed) { + /* tell the world that we changed the editor sort keys */ + _session->sync_order_keys (); + } - _model->reorder (co); - _redisplay_does_not_reset_order_keys = false; + if (rid_change) { + /* tell the world that we changed the remote control IDs */ + _session->notify_remote_id_change (); } } +void +EditorRoutes::sync_treeview_from_order_keys () +{ + /* Some route order key(s) have been changed, make sure that + we update out tree/list model and GUI to reflect the change. + */ + + if (_ignore_reorder || !_session || _session->deletion_in_progress()) { + return; + } + + DEBUG_TRACE (DEBUG::OrderKeys, "editor 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. + */ + + vector neworder; + TreeModel::Children rows = _model->children(); + uint32_t old_order = 0; + bool changed = false; + + if (rows.empty()) { + return; + } + + OrderKeySortedRoutes sorted_routes; + + for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) { + boost::shared_ptr route = (*ri)[_columns.route]; + 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[n] = sr->old_display_order; + + if (sr->old_display_order != n) { + changed = true; + } + + DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("EDITOR change order for %1 from %2 to %3\n", + sr->route->name(), sr->old_display_order, n)); + } + + if (changed) { + Unwinder uw (_ignore_reorder, true); + _model->reorder (neworder); + } + + redisplay (); +} void EditorRoutes::hide_all_tracks (bool /*with_select*/) @@ -863,12 +1023,6 @@ EditorRoutes::hide_all_tracks (bool /*with_select*/) } resume_redisplay (); - - /* XXX this seems like a hack and half, but its not clear where to put this - otherwise. - */ - - //reset_scrolling_region (); } void @@ -888,9 +1042,15 @@ EditorRoutes::set_all_tracks_visibility (bool yn) continue; } + tv->set_marked_for_display (yn); (*i)[_columns.visible] = yn; } + /* force route order keys catch up with visibility changes + */ + + sync_order_keys_from_treeview (); + resume_redisplay (); } @@ -948,6 +1108,11 @@ EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn) } } + /* force route order keys catch up with visibility changes + */ + + sync_order_keys_from_treeview (); + resume_redisplay (); } @@ -1033,10 +1198,12 @@ EditorRoutes::key_press (GdkEventKey* ev) break; case 's': - if (Config->get_solo_control_is_listen_control()) { - _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup); - } else { - _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup); + if (get_relevant_routes (rl)) { + if (Config->get_solo_control_is_listen_control()) { + _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup); + } else { + _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup); + } } return true; break; @@ -1105,15 +1272,21 @@ EditorRoutes::button_press (GdkEventButton* ev) return true; } - //Scroll editor canvas to selected track - if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { + TreeModel::Path path; + TreeViewColumn *tvc; + int cell_x; + int cell_y; - TreeModel::Path path; - TreeViewColumn *tvc; - int cell_x; - int cell_y; + if (!_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y)) { + /* cancel selection */ + _display.get_selection()->unselect_all (); + /* end any editing by grabbing focus */ + _display.grab_focus (); + return true; + } - _display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y); + //Scroll editor canvas to selected track + if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) { // Get the model row. Gtk::TreeModel::Row row = *_model->get_iter (path); @@ -1123,8 +1296,8 @@ EditorRoutes::button_press (GdkEventButton* ev) int y_pos = tv->y_position(); //Clamp the y pos so that we do not extend beyond the canvas full height. - if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){ - y_pos = _editor->full_canvas_height - _editor->_canvas_height; + if (_editor->_full_canvas_height - y_pos < _editor->_visible_canvas_height){ + y_pos = _editor->_full_canvas_height - _editor->_visible_canvas_height; } //Only scroll to if the track is visible @@ -1152,8 +1325,14 @@ EditorRoutes::selection_filter (Glib::RefPtr const &, TreeModel::Path struct EditorOrderRouteSorter { bool operator() (boost::shared_ptr a, boost::shared_ptr b) { - /* use of ">" forces the correct sort order */ - return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor")); + 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 () < b->order_key (); } }; @@ -1169,49 +1348,32 @@ EditorRoutes::initial_display () } boost::shared_ptr 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(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; - _session->set_remote_control_ids(); - redisplay (); - _redisplay_does_not_sync_order_keys = false; -} - void EditorRoutes::display_drag_data_received (const RefPtr& context, int x, int y, @@ -1330,18 +1492,26 @@ EditorRoutes::move_selected_tracks (bool up) } for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) { - neworder.push_back (leading->second->order_key (N_ ("editor"))); + uint32_t order = leading->second->order_key (); + neworder.push_back (order); } #ifndef NDEBUG + DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n"); for (vector::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::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 (N_ ("editor")); } void @@ -1520,3 +1690,4 @@ EditorRoutes::show_tracks_with_regions_at_playhead () resume_redisplay (); } +