2 Copyright (C) 2000-2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #include "pbd/unknown_type.h"
28 #include "pbd/unwind.h"
30 #include "ardour/debug.h"
31 #include "ardour/route.h"
32 #include "ardour/midi_track.h"
33 #include "ardour/session.h"
35 #include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
36 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
37 #include "gtkmm2ext/treeutils.h"
41 #include "ardour_ui.h"
42 #include "audio_time_axis.h"
43 #include "midi_time_axis.h"
44 #include "mixer_strip.h"
45 #include "gui_thread.h"
48 #include "route_sorter.h"
49 #include "editor_group_tabs.h"
50 #include "editor_routes.h"
55 using namespace ARDOUR;
56 using namespace ARDOUR_UI_UTILS;
59 using namespace Gtkmm2ext;
61 using Gtkmm2ext::Keyboard;
69 EditorRoutes::EditorRoutes (Editor* e)
71 , _ignore_reorder (false)
72 , _no_redisplay (false)
73 , _adding_routes (false)
74 , _route_deletion_in_progress (false)
77 , selection_countdown (0)
80 static const int column_width = 22;
82 _scroller.add (_display);
83 _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
85 _model = ListStore::create (_columns);
86 _display.set_model (_model);
88 // Record enable toggle
89 CellRendererPixbufMulti* rec_col_renderer = manage (new CellRendererPixbufMulti());
91 rec_col_renderer->set_pixbuf (0, ::get_icon("record-normal-disabled"));
92 rec_col_renderer->set_pixbuf (1, ::get_icon("record-normal-in-progress"));
93 rec_col_renderer->set_pixbuf (2, ::get_icon("record-normal-enabled"));
94 rec_col_renderer->set_pixbuf (3, ::get_icon("record-step"));
95 rec_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_rec_enable_changed));
97 TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer));
99 rec_state_column->add_attribute(rec_col_renderer->property_state(), _columns.rec_state);
100 rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
102 rec_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
103 rec_state_column->set_alignment(ALIGN_CENTER);
104 rec_state_column->set_expand(false);
105 rec_state_column->set_fixed_width(column_width);
109 CellRendererPixbufMulti* input_active_col_renderer = manage (new CellRendererPixbufMulti());
110 input_active_col_renderer->set_pixbuf (0, ::get_icon("midi-input-inactive"));
111 input_active_col_renderer->set_pixbuf (1, ::get_icon("midi-input-active"));
112 input_active_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_input_active_changed));
114 TreeViewColumn* input_active_column = manage (new TreeViewColumn ("I", *input_active_col_renderer));
116 input_active_column->add_attribute(input_active_col_renderer->property_state(), _columns.is_input_active);
117 input_active_column->add_attribute (input_active_col_renderer->property_visible(), _columns.is_midi);
119 input_active_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
120 input_active_column->set_alignment(ALIGN_CENTER);
121 input_active_column->set_expand(false);
122 input_active_column->set_fixed_width(column_width);
124 // Mute enable toggle
125 CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
127 mute_col_renderer->set_pixbuf (Gtkmm2ext::Off, ::get_icon("mute-disabled"));
128 mute_col_renderer->set_pixbuf (Gtkmm2ext::ImplicitActive, ::get_icon("muted-by-others"));
129 mute_col_renderer->set_pixbuf (Gtkmm2ext::ExplicitActive, ::get_icon("mute-enabled"));
130 mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
132 TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
134 mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
135 mute_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
136 mute_state_column->set_alignment(ALIGN_CENTER);
137 mute_state_column->set_expand(false);
138 mute_state_column->set_fixed_width(15);
140 // Solo enable toggle
141 CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
143 solo_col_renderer->set_pixbuf (Gtkmm2ext::Off, ::get_icon("solo-disabled"));
144 solo_col_renderer->set_pixbuf (Gtkmm2ext::ExplicitActive, ::get_icon("solo-enabled"));
145 solo_col_renderer->set_pixbuf (Gtkmm2ext::ImplicitActive, ::get_icon("soloed-by-others"));
146 solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
148 TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
150 solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
151 solo_state_column->add_attribute(solo_col_renderer->property_visible(), _columns.solo_visible);
152 solo_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
153 solo_state_column->set_alignment(ALIGN_CENTER);
154 solo_state_column->set_expand(false);
155 solo_state_column->set_fixed_width(column_width);
157 // Solo isolate toggle
158 CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti());
160 solo_iso_renderer->set_pixbuf (0, ::get_icon("solo-isolate-disabled"));
161 solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolate-enabled"));
162 solo_iso_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled));
164 TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("SI", *solo_iso_renderer));
166 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state);
167 solo_isolate_state_column->add_attribute(solo_iso_renderer->property_visible(), _columns.solo_visible);
168 solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
169 solo_isolate_state_column->set_alignment(ALIGN_CENTER);
170 solo_isolate_state_column->set_expand(false);
171 solo_isolate_state_column->set_fixed_width(column_width);
174 CellRendererPixbufMulti* solo_safe_renderer = manage (new CellRendererPixbufMulti ());
176 solo_safe_renderer->set_pixbuf (0, ::get_icon("solo-safe-disabled"));
177 solo_safe_renderer->set_pixbuf (1, ::get_icon("solo-safe-enabled"));
178 solo_safe_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_safe_toggled));
180 TreeViewColumn* solo_safe_state_column = manage (new TreeViewColumn(_("SS"), *solo_safe_renderer));
181 solo_safe_state_column->add_attribute(solo_safe_renderer->property_state(), _columns.solo_safe_state);
182 solo_safe_state_column->add_attribute(solo_safe_renderer->property_visible(), _columns.solo_visible);
183 solo_safe_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
184 solo_safe_state_column->set_alignment(ALIGN_CENTER);
185 solo_safe_state_column->set_expand(false);
186 solo_safe_state_column->set_fixed_width(column_width);
188 _name_column = _display.append_column ("", _columns.text) - 1;
189 _visible_column = _display.append_column ("", _columns.visible) - 1;
190 _active_column = _display.append_column ("", _columns.active) - 1;
192 _display.append_column (*input_active_column);
193 _display.append_column (*rec_state_column);
194 _display.append_column (*mute_state_column);
195 _display.append_column (*solo_state_column);
196 _display.append_column (*solo_isolate_state_column);
197 _display.append_column (*solo_safe_state_column);
204 { 0, _("Name"), _("Track/Bus Name") },
205 { 1, _("V"), _("Track/Bus visible ?") },
206 { 2, _("A"), _("Track/Bus active ?") },
207 { 3, _("I"), _("MIDI input enabled") },
208 { 4, _("R"), _("Record enabled") },
209 { 5, _("M"), _("Muted") },
210 { 6, _("S"), _("Soloed") },
211 { 7, _("SI"), _("Solo Isolated") },
212 { 8, _("SS"), _("Solo Safe (Locked)") },
216 for (int i = 0; ci[i].index >= 0; ++i) {
217 col = _display.get_column (ci[i].index);
218 l = manage (new Label (ci[i].label));
219 ARDOUR_UI::instance()->set_tip (*l, ci[i].tooltip);
220 col->set_widget (*l);
224 _display.set_headers_visible (true);
225 _display.get_selection()->set_mode (SELECTION_SINGLE);
226 _display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
227 _display.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::selection_changed));
228 _display.set_reorderable (true);
229 _display.set_name (X_("EditGroupList"));
230 _display.set_rules_hint (true);
231 _display.set_size_request (100, -1);
232 _display.add_object_drag (_columns.route.index(), "routes");
234 CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (_name_column));
237 name_cell->signal_editing_started().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit_started));
239 TreeViewColumn* name_column = _display.get_column (_name_column);
241 assert (name_column);
243 name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
244 name_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
245 name_column->set_expand(true);
246 name_column->set_min_width(50);
248 name_cell->property_editable() = true;
249 name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit));
251 // Set the visible column cell renderer to radio toggle
252 CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (_visible_column));
254 visible_cell->property_activatable() = true;
255 visible_cell->property_radio() = false;
256 visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::visible_changed));
258 TreeViewColumn* visible_col = dynamic_cast<TreeViewColumn*> (_display.get_column (_visible_column));
259 visible_col->set_expand(false);
260 visible_col->set_sizing(TREE_VIEW_COLUMN_FIXED);
261 visible_col->set_fixed_width(30);
262 visible_col->set_alignment(ALIGN_CENTER);
264 CellRendererToggle* active_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (_active_column));
266 active_cell->property_activatable() = true;
267 active_cell->property_radio() = false;
268 active_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::active_changed));
270 TreeViewColumn* active_col = dynamic_cast<TreeViewColumn*> (_display.get_column (_active_column));
271 active_col->set_expand (false);
272 active_col->set_sizing (TREE_VIEW_COLUMN_FIXED);
273 active_col->set_fixed_width (30);
274 active_col->set_alignment (ALIGN_CENTER);
276 _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::row_deleted));
277 _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered));
279 _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false);
280 _scroller.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorRoutes::key_press), false);
282 _scroller.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditorRoutes::focus_in), false);
283 _scroller.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditorRoutes::focus_out));
285 _display.signal_enter_notify_event().connect (sigc::mem_fun (*this, &EditorRoutes::enter_notify), false);
286 _display.signal_leave_notify_event().connect (sigc::mem_fun (*this, &EditorRoutes::leave_notify), false);
288 _display.set_enable_search (false);
290 Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::sync_treeview_from_order_keys, this), gui_context());
294 EditorRoutes::focus_in (GdkEventFocus*)
296 Window* win = dynamic_cast<Window*> (_scroller.get_toplevel ());
299 old_focus = win->get_focus ();
306 /* try to do nothing on focus in (doesn't work, hence selection_count nonsense) */
311 EditorRoutes::focus_out (GdkEventFocus*)
314 old_focus->grab_focus ();
322 EditorRoutes::enter_notify (GdkEventCrossing*)
328 /* arm counter so that ::selection_filter() will deny selecting anything for the
329 next two attempts to change selection status.
331 selection_countdown = 2;
332 _scroller.grab_focus ();
333 Keyboard::magic_widget_grab_focus ();
338 EditorRoutes::leave_notify (GdkEventCrossing*)
340 selection_countdown = 0;
343 old_focus->grab_focus ();
347 Keyboard::magic_widget_drop_focus ();
352 EditorRoutes::set_session (Session* s)
354 SessionHandlePtr::set_session (s);
359 _session->SoloChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::solo_changed_so_update_mute, this), gui_context());
360 _session->RecordStateChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
365 EditorRoutes::on_input_active_changed (std::string const & path_string)
367 // Get the model row that has been toggled.
368 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
370 TimeAxisView* tv = row[_columns.tv];
371 RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
374 boost::shared_ptr<MidiTrack> mt;
375 mt = rtv->midi_track();
377 mt->set_input_active (!mt->input_active());
383 EditorRoutes::on_tv_rec_enable_changed (std::string const & path_string)
385 // Get the model row that has been toggled.
386 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
388 TimeAxisView* tv = row[_columns.tv];
389 RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
391 if (rtv && rtv->track()) {
392 boost::shared_ptr<RouteList> rl (new RouteList);
393 rl->push_back (rtv->route());
394 _session->set_record_enabled (rl, !rtv->track()->record_enabled(), Session::rt_cleanup);
399 EditorRoutes::on_tv_mute_enable_toggled (std::string const & path_string)
401 // Get the model row that has been toggled.
402 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
404 TimeAxisView *tv = row[_columns.tv];
405 RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
408 boost::shared_ptr<RouteList> rl (new RouteList);
409 rl->push_back (rtv->route());
410 _session->set_mute (rl, !rtv->route()->muted(), Session::rt_cleanup);
415 EditorRoutes::on_tv_solo_enable_toggled (std::string const & path_string)
417 // Get the model row that has been toggled.
418 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
420 TimeAxisView *tv = row[_columns.tv];
421 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
424 boost::shared_ptr<RouteList> rl (new RouteList);
425 rl->push_back (rtv->route());
426 if (Config->get_solo_control_is_listen_control()) {
427 _session->set_listen (rl, !rtv->route()->listening_via_monitor(), Session::rt_cleanup);
429 _session->set_solo (rl, !rtv->route()->self_soloed(), Session::rt_cleanup);
435 EditorRoutes::on_tv_solo_isolate_toggled (std::string const & path_string)
437 // Get the model row that has been toggled.
438 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
440 TimeAxisView *tv = row[_columns.tv];
441 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
444 rtv->route()->set_solo_isolated (!rtv->route()->solo_isolated(), this);
449 EditorRoutes::on_tv_solo_safe_toggled (std::string const & path_string)
451 // Get the model row that has been toggled.
452 Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
454 TimeAxisView *tv = row[_columns.tv];
455 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
458 rtv->route()->set_solo_safe (!rtv->route()->solo_safe(), this);
463 EditorRoutes::build_menu ()
465 using namespace Menu_Helpers;
470 MenuList& items = _menu->items();
471 _menu->set_name ("ArdourContextMenu");
473 items.push_back (MenuElem (_("Show All"), sigc::mem_fun (*this, &EditorRoutes::show_all_routes)));
474 items.push_back (MenuElem (_("Hide All"), sigc::mem_fun (*this, &EditorRoutes::hide_all_routes)));
475 items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
476 items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
477 items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus)));
478 items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
479 items.push_back (MenuElem (_("Show All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_miditracks)));
480 items.push_back (MenuElem (_("Hide All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_miditracks)));
481 items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
485 EditorRoutes::show_menu ()
491 _menu->popup (1, gtk_get_current_event_time());
495 EditorRoutes::redisplay ()
497 if (_no_redisplay || !_session || _session->deletion_in_progress()) {
501 TreeModel::Children rows = _model->children();
502 TreeModel::Children::iterator i;
505 /* n will be the count of tracks plus children (updated by TimeAxisView::show_at),
506 so we will use that to know where to put things.
510 for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
511 TimeAxisView *tv = (*i)[_columns.tv];
512 boost::shared_ptr<Route> route = (*i)[_columns.route];
515 // just a "title" row
519 bool visible = tv->marked_for_display ();
521 /* show or hide the TimeAxisView */
523 position += tv->show_at (position, n, &_editor->edit_controls_vbox);
531 /* whenever we go idle, update the track view list to reflect the new order.
532 we can't do this here, because we could mess up something that is traversing
533 the track order and has caused a redisplay of the list.
535 Glib::signal_idle().connect (sigc::mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
537 _editor->reset_controls_layout_height (position);
538 _editor->reset_controls_layout_width ();
539 _editor->_full_canvas_height = position;
541 if ((_editor->vertical_adjustment.get_value() + _editor->_visible_canvas_height) > _editor->vertical_adjustment.get_upper()) {
543 We're increasing the size of the canvas while the bottom is visible.
544 We scroll down to keep in step with the controls layout.
546 _editor->vertical_adjustment.set_value (_editor->_full_canvas_height - _editor->_visible_canvas_height);
551 EditorRoutes::row_deleted (Gtk::TreeModel::Path const &)
553 /* this happens as the second step of a DnD within the treeview, and
554 when a route is actually removed. we don't differentiate between
557 note that the sync_orders_keys() step may not actually change any
558 RID's (e.g. the last track may be removed, so all other tracks keep
559 the same RID), which means that no redisplay would happen. so we
560 have to force a redisplay.
563 DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
566 sync_order_keys_from_treeview ();
570 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
572 /* reordering implies that RID's will change, so sync_order_keys() will
576 DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
577 sync_order_keys_from_treeview ();
581 EditorRoutes::visible_changed (std::string const & path)
583 if (_session && _session->deletion_in_progress()) {
590 if ((iter = _model->get_iter (path))) {
591 TimeAxisView* tv = (*iter)[_columns.tv];
593 bool visible = (*iter)[_columns.visible];
595 if (tv->set_marked_for_display (!visible)) {
596 update_visibility ();
603 EditorRoutes::active_changed (std::string const & path)
605 if (_session && _session->deletion_in_progress ()) {
609 Gtk::TreeModel::Row row = *_model->get_iter (path);
610 boost::shared_ptr<Route> route = row[_columns.route];
611 bool const active = row[_columns.active];
612 route->set_active (!active, this);
616 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
618 PBD::Unwinder<bool> at (_adding_routes, true);
620 bool from_scratch = (_model->children().size() == 0);
621 Gtk::TreeModel::Children::iterator insert_iter = _model->children().end();
623 for (Gtk::TreeModel::Children::iterator it = _model->children().begin(); it != _model->children().end(); ++it) {
624 boost::shared_ptr<Route> r = (*it)[_columns.route];
626 if (r->order_key() == (routes.front()->route()->order_key() + routes.size())) {
633 _editor->selection->tracks.clear();
638 _display.set_model (Glib::RefPtr<ListStore>());
640 for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
642 boost::shared_ptr<MidiTrack> midi_trk = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
644 TreeModel::Row row = *(_model->insert (insert_iter));
646 row[_columns.text] = (*x)->route()->name();
647 row[_columns.visible] = (*x)->marked_for_display();
648 row[_columns.active] = (*x)->route()->active ();
649 row[_columns.tv] = *x;
650 row[_columns.route] = (*x)->route ();
651 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
654 row[_columns.is_input_active] = midi_trk->input_active ();
655 row[_columns.is_midi] = true;
657 row[_columns.is_input_active] = false;
658 row[_columns.is_midi] = false;
661 row[_columns.mute_state] = (*x)->route()->muted() ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off;
662 row[_columns.solo_state] = RouteUI::solo_active_state ((*x)->route());
663 row[_columns.solo_visible] = !(*x)->route()->is_master ();
664 row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated();
665 row[_columns.solo_safe_state] = (*x)->route()->solo_safe();
666 row[_columns.name_editable] = true;
669 _editor->selection->add(*x);
672 boost::weak_ptr<Route> wr ((*x)->route());
674 (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
675 (*x)->route()->PropertyChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::route_property_changed, this, _1, wr), gui_context());
677 if ((*x)->is_track()) {
678 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
679 t->RecordEnableChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
682 if ((*x)->is_midi_track()) {
683 boost::shared_ptr<MidiTrack> t = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
684 t->StepEditStatusChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
685 t->InputActiveChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_input_active_display, this), gui_context());
688 (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
689 (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
690 (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
691 (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
692 (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context());
693 (*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ());
697 update_rec_display ();
698 update_mute_display ();
699 update_solo_display (true);
700 update_solo_isolate_display ();
701 update_solo_safe_display ();
702 update_input_active_display ();
703 update_active_display ();
705 _display.set_model (_model);
707 /* now update route order keys from the treeview/track display order */
709 sync_order_keys_from_treeview ();
713 EditorRoutes::handle_gui_changes (string const & what, void*)
715 if (_adding_routes) {
719 if (what == "track_height") {
720 /* Optional :make tracks change height while it happens, instead
726 if (what == "visible_tracks") {
732 EditorRoutes::route_removed (TimeAxisView *tv)
734 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
736 TreeModel::Children rows = _model->children();
737 TreeModel::Children::iterator ri;
739 for (ri = rows.begin(); ri != rows.end(); ++ri) {
740 if ((*ri)[_columns.tv] == tv) {
741 PBD::Unwinder<bool> uw (_route_deletion_in_progress, true);
747 /* the deleted signal for the treeview/model will take
753 EditorRoutes::route_property_changed (const PropertyChange& what_changed, boost::weak_ptr<Route> r)
755 if (!what_changed.contains (ARDOUR::Properties::name)) {
759 ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
761 boost::shared_ptr<Route> route = r.lock ();
767 TreeModel::Children rows = _model->children();
768 TreeModel::Children::iterator i;
770 for (i = rows.begin(); i != rows.end(); ++i) {
771 boost::shared_ptr<Route> t = (*i)[_columns.route];
773 (*i)[_columns.text] = route->name();
780 EditorRoutes::update_active_display ()
782 TreeModel::Children rows = _model->children();
783 TreeModel::Children::iterator i;
785 for (i = rows.begin(); i != rows.end(); ++i) {
786 boost::shared_ptr<Route> route = (*i)[_columns.route];
787 (*i)[_columns.active] = route->active ();
792 EditorRoutes::update_visibility ()
794 TreeModel::Children rows = _model->children();
795 TreeModel::Children::iterator i;
797 DisplaySuspender ds ();
799 for (i = rows.begin(); i != rows.end(); ++i) {
800 TimeAxisView *tv = (*i)[_columns.tv];
801 (*i)[_columns.visible] = tv->marked_for_display ();
804 /* force route order keys catch up with visibility changes
807 sync_order_keys_from_treeview ();
811 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
813 TreeModel::Children rows = _model->children();
814 TreeModel::Children::iterator i;
816 for (i = rows.begin(); i != rows.end(); ++i) {
817 if ((*i)[_columns.tv] == &tv) {
818 tv.set_marked_for_display (false);
819 (*i)[_columns.visible] = false;
827 EditorRoutes::show_track_in_display (TimeAxisView& tv)
829 TreeModel::Children rows = _model->children();
830 TreeModel::Children::iterator i;
833 for (i = rows.begin(); i != rows.end(); ++i) {
834 if ((*i)[_columns.tv] == &tv) {
835 tv.set_marked_for_display (true);
836 (*i)[_columns.visible] = true;
844 EditorRoutes::reset_remote_control_ids ()
846 if (Config->get_remote_model() == UserOrdered || !_session || _session->deletion_in_progress()) {
850 TreeModel::Children rows = _model->children();
857 DEBUG_TRACE (DEBUG::OrderKeys, "editor reset remote control ids\n");
859 TreeModel::Children::iterator ri;
860 bool rid_change = false;
862 uint32_t invisible_key = UINT32_MAX;
864 for (ri = rows.begin(); ri != rows.end(); ++ri) {
866 boost::shared_ptr<Route> route = (*ri)[_columns.route];
867 bool visible = (*ri)[_columns.visible];
870 if (!route->is_master() && !route->is_monitor()) {
872 uint32_t new_rid = (visible ? rid : invisible_key--);
874 if (new_rid != route->remote_control_id()) {
875 route->set_remote_control_id_explicit (new_rid);
887 /* tell the world that we changed the remote control IDs */
888 _session->notify_remote_id_change ();
894 EditorRoutes::sync_order_keys_from_treeview ()
896 if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
900 TreeModel::Children rows = _model->children();
907 DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from treeview\n");
909 TreeModel::Children::iterator ri;
910 bool changed = false;
911 bool rid_change = false;
914 uint32_t invisible_key = UINT32_MAX;
916 for (ri = rows.begin(); ri != rows.end(); ++ri) {
918 boost::shared_ptr<Route> route = (*ri)[_columns.route];
919 bool visible = (*ri)[_columns.visible];
921 uint32_t old_key = route->order_key ();
923 if (order != old_key) {
924 route->set_order_key (order);
929 if ((Config->get_remote_model() == MixerOrdered) && !route->is_master() && !route->is_monitor()) {
931 uint32_t new_rid = (visible ? rid : invisible_key--);
933 if (new_rid != route->remote_control_id()) {
934 route->set_remote_control_id_explicit (new_rid);
948 /* tell the world that we changed the editor sort keys */
949 _session->sync_order_keys ();
953 /* tell the world that we changed the remote control IDs */
954 _session->notify_remote_id_change ();
959 EditorRoutes::sync_treeview_from_order_keys ()
961 /* Some route order key(s) have been changed, make sure that
962 we update out tree/list model and GUI to reflect the change.
965 if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
969 DEBUG_TRACE (DEBUG::OrderKeys, "editor sync model from order keys.\n");
971 /* we could get here after either a change in the Mixer or Editor sort
972 * order, but either way, the mixer order keys reflect the intended
973 * order for the GUI, so reorder the treeview model to match it.
976 vector<int> neworder;
977 TreeModel::Children rows = _model->children();
978 uint32_t old_order = 0;
979 bool changed = false;
985 OrderKeySortedRoutes sorted_routes;
987 for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
988 boost::shared_ptr<Route> route = (*ri)[_columns.route];
989 sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key ()));
992 SortByNewDisplayOrder cmp;
994 sort (sorted_routes.begin(), sorted_routes.end(), cmp);
995 neworder.assign (sorted_routes.size(), 0);
999 for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) {
1001 neworder[n] = sr->old_display_order;
1003 if (sr->old_display_order != n) {
1007 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("EDITOR change order for %1 from %2 to %3\n",
1008 sr->route->name(), sr->old_display_order, n));
1012 Unwinder<bool> uw (_ignore_reorder, true);
1013 _model->reorder (neworder);
1020 EditorRoutes::hide_all_tracks (bool /*with_select*/)
1022 TreeModel::Children rows = _model->children();
1023 TreeModel::Children::iterator i;
1025 DisplaySuspender ds;
1027 for (i = rows.begin(); i != rows.end(); ++i) {
1029 TreeModel::Row row = (*i);
1030 TimeAxisView *tv = row[_columns.tv];
1036 row[_columns.visible] = false;
1041 EditorRoutes::set_all_tracks_visibility (bool yn)
1043 TreeModel::Children rows = _model->children();
1044 TreeModel::Children::iterator i;
1046 DisplaySuspender ds;
1048 for (i = rows.begin(); i != rows.end(); ++i) {
1050 TreeModel::Row row = (*i);
1051 TimeAxisView* tv = row[_columns.tv];
1057 tv->set_marked_for_display (yn);
1058 (*i)[_columns.visible] = yn;
1061 /* force route order keys catch up with visibility changes
1064 sync_order_keys_from_treeview ();
1068 EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
1070 TreeModel::Children rows = _model->children();
1071 TreeModel::Children::iterator i;
1073 DisplaySuspender ds;
1075 for (i = rows.begin(); i != rows.end(); ++i) {
1077 TreeModel::Row row = (*i);
1078 TimeAxisView* tv = row[_columns.tv];
1080 AudioTimeAxisView* atv;
1081 MidiTimeAxisView* mtv;
1087 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1090 (*i)[_columns.visible] = yn;
1094 if (atv->is_audio_track()) {
1095 (*i)[_columns.visible] = yn;
1100 if (!atv->is_audio_track()) {
1101 (*i)[_columns.visible] = yn;
1106 else if ((mtv = dynamic_cast<MidiTimeAxisView*>(tv)) != 0) {
1109 (*i)[_columns.visible] = yn;
1113 if (mtv->is_midi_track()) {
1114 (*i)[_columns.visible] = yn;
1121 /* force route order keys catch up with visibility changes
1124 sync_order_keys_from_treeview ();
1128 EditorRoutes::hide_all_routes ()
1130 set_all_tracks_visibility (false);
1134 EditorRoutes::show_all_routes ()
1136 set_all_tracks_visibility (true);
1140 EditorRoutes::show_all_audiotracks()
1142 set_all_audio_midi_visibility (1, true);
1145 EditorRoutes::hide_all_audiotracks ()
1147 set_all_audio_midi_visibility (1, false);
1151 EditorRoutes::show_all_audiobus ()
1153 set_all_audio_midi_visibility (2, true);
1156 EditorRoutes::hide_all_audiobus ()
1158 set_all_audio_midi_visibility (2, false);
1162 EditorRoutes::show_all_miditracks()
1164 set_all_audio_midi_visibility (3, true);
1167 EditorRoutes::hide_all_miditracks ()
1169 set_all_audio_midi_visibility (3, false);
1173 EditorRoutes::key_press (GdkEventKey* ev)
1175 TreeViewColumn *col;
1176 boost::shared_ptr<RouteList> rl (new RouteList);
1179 switch (ev->keyval) {
1181 case GDK_ISO_Left_Tab:
1183 /* If we appear to be editing something, leave that cleanly and appropriately.
1185 if (name_editable) {
1186 name_editable->editing_done ();
1190 col = _display.get_column (_name_column); // select&focus on name column
1192 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1193 treeview_select_previous (_display, _model, col);
1195 treeview_select_next (_display, _model, col);
1202 if (get_relevant_routes (rl)) {
1203 _session->set_mute (rl, !rl->front()->muted(), Session::rt_cleanup);
1209 if (get_relevant_routes (rl)) {
1210 if (Config->get_solo_control_is_listen_control()) {
1211 _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
1213 _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
1220 if (get_relevant_routes (rl)) {
1221 _session->set_record_enabled (rl, !rl->front()->record_enabled(), Session::rt_cleanup);
1233 EditorRoutes::get_relevant_routes (boost::shared_ptr<RouteList> rl)
1236 RouteTimeAxisView* rtv;
1237 RefPtr<TreeSelection> selection = _display.get_selection();
1241 if (selection->count_selected_rows() != 0) {
1245 RefPtr<TreeModel> tm = RefPtr<TreeModel>::cast_dynamic (_model);
1246 iter = selection->get_selected (tm);
1249 /* use mouse pointer */
1254 _display.get_pointer (x, y);
1255 _display.convert_widget_to_bin_window_coords (x, y, bx, by);
1257 if (_display.get_path_at_pos (bx, by, path)) {
1258 iter = _model->get_iter (path);
1263 tv = (*iter)[_columns.tv];
1265 rtv = dynamic_cast<RouteTimeAxisView*>(tv);
1267 rl->push_back (rtv->route());
1272 return !rl->empty();
1276 EditorRoutes::button_press (GdkEventButton* ev)
1278 if (Keyboard::is_context_menu_event (ev)) {
1283 TreeModel::Path path;
1284 TreeViewColumn *tvc;
1288 if (!_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y)) {
1289 /* cancel selection */
1290 _display.get_selection()->unselect_all ();
1291 /* end any editing by grabbing focus */
1292 _display.grab_focus ();
1296 //Scroll editor canvas to selected track
1297 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1299 Gtk::TreeModel::Row row = *_model->get_iter (path);
1300 TimeAxisView *tv = row[_columns.tv];
1303 _editor->ensure_time_axis_view_is_visible (*tv, true);
1311 EditorRoutes::selection_changed ()
1313 if (_display.get_selection()->count_selected_rows() > 0) {
1316 TreeView::Selection::ListHandle_Path rows = _display.get_selection()->get_selected_rows ();
1317 TrackViewList selected;
1319 _editor->get_selection().clear_regions ();
1321 for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
1323 if ((iter = _model->get_iter (*i))) {
1325 TimeAxisView* tv = (*iter)[_columns.tv];
1326 selected.push_back (tv);
1331 _editor->get_selection().set (selected);
1332 _editor->ensure_time_axis_view_is_visible (*(selected.front()), true);
1335 _editor->get_selection().clear_tracks ();
1340 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
1342 if (selection_countdown) {
1343 if (--selection_countdown == 0) {
1346 /* no selection yet ... */
1353 struct EditorOrderRouteSorter {
1354 bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
1355 if (a->is_master()) {
1356 /* master before everything else */
1358 } else if (b->is_master()) {
1359 /* everything else before master */
1362 return a->order_key () < b->order_key ();
1367 EditorRoutes::initial_display ()
1369 DisplaySuspender ds;
1376 boost::shared_ptr<RouteList> routes = _session->get_routes();
1378 if (ARDOUR_UI::instance()->session_is_new ()) {
1380 /* new session: stamp all routes with the right editor order
1384 _editor->add_routes (*(routes.get()));
1388 /* existing session: sort a copy of the route list by
1389 * editor-order and add its contents to the display.
1392 RouteList r (*routes);
1393 EditorOrderRouteSorter sorter;
1396 _editor->add_routes (r);
1402 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
1404 const SelectionData& data,
1405 guint info, guint time)
1407 if (data.get_target() == "GTK_TREE_MODEL_ROW") {
1408 _display.on_drag_data_received (context, x, y, data, info, time);
1412 context->drag_finish (true, false, time);
1416 EditorRoutes::move_selected_tracks (bool up)
1418 if (_editor->selection->tracks.empty()) {
1422 typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
1423 std::list<ViewRoute> view_routes;
1424 std::vector<int> neworder;
1425 TreeModel::Children rows = _model->children();
1426 TreeModel::Children::iterator ri;
1428 for (ri = rows.begin(); ri != rows.end(); ++ri) {
1429 TimeAxisView* tv = (*ri)[_columns.tv];
1430 boost::shared_ptr<Route> route = (*ri)[_columns.route];
1432 view_routes.push_back (ViewRoute (tv, route));
1435 list<ViewRoute>::iterator trailing;
1436 list<ViewRoute>::iterator leading;
1440 trailing = view_routes.begin();
1441 leading = view_routes.begin();
1445 while (leading != view_routes.end()) {
1446 if (_editor->selection->selected (leading->first)) {
1447 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
1448 leading = view_routes.erase (leading);
1457 /* if we could use reverse_iterator in list::insert, this code
1458 would be a beautiful reflection of the code above. but we can't
1459 and so it looks like a bit of a mess.
1462 trailing = view_routes.end();
1463 leading = view_routes.end();
1465 --leading; if (leading == view_routes.begin()) { return; }
1471 if (_editor->selection->selected (leading->first)) {
1472 list<ViewRoute>::iterator tmp;
1474 /* need to insert *after* trailing, not *before* it,
1475 which is what insert (iter, val) normally does.
1481 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
1483 /* can't use iter = cont.erase (iter); form here, because
1484 we need iter to move backwards.
1492 if (leading == view_routes.begin()) {
1493 /* the one we've just inserted somewhere else
1494 was the first in the list. erase this copy,
1495 and then break, because we're done.
1500 view_routes.erase (leading);
1509 if (leading == view_routes.begin()) {
1518 for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
1519 uint32_t order = leading->second->order_key ();
1520 neworder.push_back (order);
1524 DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n");
1525 for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1526 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("\t%1\n", *i));
1528 DEBUG_TRACE (DEBUG::OrderKeys, "-------\n");
1530 for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1531 if (*i >= (int) neworder.size()) {
1532 cerr << "Trying to move something to " << *i << " of " << neworder.size() << endl;
1534 assert (*i < (int) neworder.size ());
1538 _model->reorder (neworder);
1542 EditorRoutes::update_input_active_display ()
1544 TreeModel::Children rows = _model->children();
1545 TreeModel::Children::iterator i;
1547 for (i = rows.begin(); i != rows.end(); ++i) {
1548 boost::shared_ptr<Route> route = (*i)[_columns.route];
1550 if (boost::dynamic_pointer_cast<Track> (route)) {
1551 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1554 (*i)[_columns.is_input_active] = mt->input_active();
1561 EditorRoutes::update_rec_display ()
1563 TreeModel::Children rows = _model->children();
1564 TreeModel::Children::iterator i;
1566 for (i = rows.begin(); i != rows.end(); ++i) {
1567 boost::shared_ptr<Route> route = (*i)[_columns.route];
1569 if (boost::dynamic_pointer_cast<Track> (route)) {
1570 boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1572 if (route->record_enabled()) {
1573 if (_session->record_status() == Session::Recording) {
1574 (*i)[_columns.rec_state] = 1;
1576 (*i)[_columns.rec_state] = 2;
1578 } else if (mt && mt->step_editing()) {
1579 (*i)[_columns.rec_state] = 3;
1581 (*i)[_columns.rec_state] = 0;
1584 (*i)[_columns.name_editable] = !route->record_enabled ();
1590 EditorRoutes::update_mute_display ()
1592 TreeModel::Children rows = _model->children();
1593 TreeModel::Children::iterator i;
1595 for (i = rows.begin(); i != rows.end(); ++i) {
1596 boost::shared_ptr<Route> route = (*i)[_columns.route];
1597 (*i)[_columns.mute_state] = RouteUI::mute_active_state (_session, route);
1602 EditorRoutes::update_solo_display (bool /* selfsoloed */)
1604 TreeModel::Children rows = _model->children();
1605 TreeModel::Children::iterator i;
1607 for (i = rows.begin(); i != rows.end(); ++i) {
1608 boost::shared_ptr<Route> route = (*i)[_columns.route];
1609 (*i)[_columns.solo_state] = RouteUI::solo_active_state (route);
1614 EditorRoutes::update_solo_isolate_display ()
1616 TreeModel::Children rows = _model->children();
1617 TreeModel::Children::iterator i;
1619 for (i = rows.begin(); i != rows.end(); ++i) {
1620 boost::shared_ptr<Route> route = (*i)[_columns.route];
1621 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_active_state (route) ? 1 : 0;
1626 EditorRoutes::update_solo_safe_display ()
1628 TreeModel::Children rows = _model->children();
1629 TreeModel::Children::iterator i;
1631 for (i = rows.begin(); i != rows.end(); ++i) {
1632 boost::shared_ptr<Route> route = (*i)[_columns.route];
1633 (*i)[_columns.solo_safe_state] = RouteUI::solo_safe_active_state (route) ? 1 : 0;
1638 EditorRoutes::views () const
1640 list<TimeAxisView*> v;
1641 for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1642 v.push_back ((*i)[_columns.tv]);
1649 EditorRoutes::clear ()
1651 _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1653 _display.set_model (_model);
1657 EditorRoutes::name_edit_started (CellEditable* ce, const Glib::ustring&)
1661 /* give it a special name */
1663 Gtk::Entry *e = dynamic_cast<Gtk::Entry*> (ce);
1666 e->set_name (X_("RouteNameEditorEntry"));
1671 EditorRoutes::name_edit (std::string const & path, std::string const & new_text)
1675 TreeIter iter = _model->get_iter (path);
1681 boost::shared_ptr<Route> route = (*iter)[_columns.route];
1683 if (route && route->name() != new_text) {
1684 route->set_name (new_text);
1689 EditorRoutes::solo_changed_so_update_mute ()
1691 update_mute_display ();
1695 EditorRoutes::show_tracks_with_regions_at_playhead ()
1697 boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1699 set<TimeAxisView*> show;
1700 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1701 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1707 DisplaySuspender ds;
1709 TreeModel::Children rows = _model->children ();
1710 for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1711 TimeAxisView* tv = (*i)[_columns.tv];
1712 (*i)[_columns.visible] = (show.find (tv) != show.end());