update drobilla's fascistic dir-locals.el to force emacs users into whitespace submis...
[ardour.git] / gtk2_ardour / editor_routes.cc
1 /*
2     Copyright (C) 2000-2009 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include <list>
21 #include <vector>
22 #include <algorithm>
23 #include <cstdlib>
24 #include <cmath>
25 #include <cassert>
26
27 #include "ardour/session.h"
28
29 #include "editor.h"
30 #include "keyboard.h"
31 #include "ardour_ui.h"
32 #include "audio_time_axis.h"
33 #include "midi_time_axis.h"
34 #include "mixer_strip.h"
35 #include "gui_thread.h"
36 #include "actions.h"
37 #include "utils.h"
38 #include "editor_group_tabs.h"
39 #include "editor_routes.h"
40
41 #include "pbd/unknown_type.h"
42
43 #include "ardour/route.h"
44 #include "ardour/midi_track.h"
45
46 #include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
47 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
48 #include "gtkmm2ext/treeutils.h"
49
50 #include "i18n.h"
51
52 using namespace std;
53 using namespace ARDOUR;
54 using namespace PBD;
55 using namespace Gtk;
56 using namespace Gtkmm2ext;
57 using namespace Glib;
58 using Gtkmm2ext::Keyboard;
59
60 EditorRoutes::EditorRoutes (Editor* e)
61         : EditorComponent (e)
62         , _ignore_reorder (false)
63         , _no_redisplay (false)
64         , _redisplay_does_not_sync_order_keys (false)
65         , _redisplay_does_not_reset_order_keys (false)
66         ,_menu (0)
67         , old_focus (0)
68         , selection_countdown (0)
69         , name_editable (0)
70 {
71         _scroller.add (_display);
72         _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
73
74         _model = ListStore::create (_columns);
75         _display.set_model (_model);
76
77         // Record enable toggle
78         CellRendererPixbufMulti* rec_col_renderer = manage (new CellRendererPixbufMulti());
79
80         rec_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
81         rec_col_renderer->set_pixbuf (1, ::get_icon("rec-in-progress"));
82         rec_col_renderer->set_pixbuf (2, ::get_icon("rec-enabled"));
83         rec_col_renderer->set_pixbuf (3, ::get_icon("step-editing"));
84         rec_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_rec_enable_changed));
85
86         TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer));
87
88         rec_state_column->add_attribute(rec_col_renderer->property_state(), _columns.rec_state);
89         rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
90         rec_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
91         rec_state_column->set_alignment(ALIGN_CENTER);
92         rec_state_column->set_expand(false);
93         rec_state_column->set_fixed_width(15);
94
95         // Mute enable toggle
96         CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
97
98         mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
99         mute_col_renderer->set_pixbuf (1, ::get_icon("muted-by-others"));
100         mute_col_renderer->set_pixbuf (2, ::get_icon("mute-enabled"));
101         mute_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
102
103         TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
104
105         mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
106         mute_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
107         mute_state_column->set_alignment(ALIGN_CENTER);
108         mute_state_column->set_expand(false);
109         mute_state_column->set_fixed_width(15);
110
111         // Solo enable toggle
112         CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
113
114         solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
115         solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
116         solo_col_renderer->set_pixbuf (3, ::get_icon("soloed-by-others"));
117         solo_col_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
118
119         TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
120
121         solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
122         solo_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
123         solo_state_column->set_alignment(ALIGN_CENTER);
124         solo_state_column->set_expand(false);
125         solo_state_column->set_fixed_width(15);
126
127         // Solo isolate toggle
128         CellRendererPixbufMulti* solo_iso_renderer = manage (new CellRendererPixbufMulti());
129
130         solo_iso_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
131         solo_iso_renderer->set_pixbuf (1, ::get_icon("solo-isolated"));
132         solo_iso_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_isolate_toggled));
133
134         TreeViewColumn* solo_isolate_state_column = manage (new TreeViewColumn("SI", *solo_iso_renderer));
135
136         solo_isolate_state_column->add_attribute(solo_iso_renderer->property_state(), _columns.solo_isolate_state);
137         solo_isolate_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
138         solo_isolate_state_column->set_alignment(ALIGN_CENTER);
139         solo_isolate_state_column->set_expand(false);
140         solo_isolate_state_column->set_fixed_width(22);
141
142         // Solo safe toggle
143         CellRendererPixbufMulti* solo_safe_renderer = manage (new CellRendererPixbufMulti ());
144
145         solo_safe_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
146         solo_safe_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
147         solo_safe_renderer->signal_changed().connect (sigc::mem_fun (*this, &EditorRoutes::on_tv_solo_safe_toggled));
148
149         TreeViewColumn* solo_safe_state_column = manage (new TreeViewColumn(_("SS"), *solo_safe_renderer));
150         solo_safe_state_column->add_attribute(solo_safe_renderer->property_state(), _columns.solo_safe_state);
151         solo_safe_state_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
152         solo_safe_state_column->set_alignment(ALIGN_CENTER);
153         solo_safe_state_column->set_expand(false);
154         solo_safe_state_column->set_fixed_width(22);
155
156         _display.append_column (*rec_state_column);
157         _display.append_column (*mute_state_column);
158         _display.append_column (*solo_state_column);
159         _display.append_column (*solo_isolate_state_column);
160         _display.append_column (*solo_safe_state_column);
161         
162         int colnum = _display.append_column (_("Name"), _columns.text);
163         TreeViewColumn* c = _display.get_column (colnum-1);
164         c->set_data ("i_am_the_tab_column", (void*) 0xfeedface);
165         _display.append_column (_("V"), _columns.visible);
166         
167         _display.set_headers_visible (true);
168         _display.set_name ("TrackListDisplay");
169         _display.get_selection()->set_mode (SELECTION_SINGLE);
170         _display.get_selection()->set_select_function (sigc::mem_fun (*this, &EditorRoutes::selection_filter));
171         _display.set_reorderable (true);
172         _display.set_rules_hint (true);
173         _display.set_size_request (100, -1);
174         _display.add_object_drag (_columns.route.index(), "routes");
175
176         CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (5));
177
178         assert (name_cell);
179         name_cell->signal_editing_started().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit_started));
180
181         TreeViewColumn* name_column = _display.get_column (5);
182
183         assert (name_column);
184
185         name_column->add_attribute (name_cell->property_editable(), _columns.name_editable);
186         name_column->set_sizing(TREE_VIEW_COLUMN_FIXED);
187         name_column->set_expand(true);
188         name_column->set_min_width(50);
189
190         name_cell->property_editable() = true;
191         name_cell->signal_edited().connect (sigc::mem_fun (*this, &EditorRoutes::name_edit));
192
193         // Set the visible column cell renderer to radio toggle
194         CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*> (_display.get_column_cell_renderer (6));
195
196         visible_cell->property_activatable() = true;
197         visible_cell->property_radio() = false;
198         visible_cell->signal_toggled().connect (sigc::mem_fun (*this, &EditorRoutes::visible_changed));
199         
200         TreeViewColumn* visible_col = dynamic_cast<TreeViewColumn*> (_display.get_column (6));
201         visible_col->set_expand(false);
202         visible_col->set_sizing(TREE_VIEW_COLUMN_FIXED);
203         visible_col->set_fixed_width(30);
204         visible_col->set_alignment(ALIGN_CENTER);
205         
206         _model->signal_row_deleted().connect (sigc::mem_fun (*this, &EditorRoutes::route_deleted));
207         _model->signal_rows_reordered().connect (sigc::mem_fun (*this, &EditorRoutes::reordered));
208         
209         _display.signal_button_press_event().connect (sigc::mem_fun (*this, &EditorRoutes::button_press), false);
210         _scroller.signal_key_press_event().connect (sigc::mem_fun(*this, &EditorRoutes::key_press), false);
211
212         _scroller.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditorRoutes::focus_in), false);
213         _scroller.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditorRoutes::focus_out));
214
215         _display.signal_enter_notify_event().connect (sigc::mem_fun (*this, &EditorRoutes::enter_notify), false);
216         _display.signal_leave_notify_event().connect (sigc::mem_fun (*this, &EditorRoutes::leave_notify), false);
217
218         _display.set_enable_search (false);
219
220         Route::SyncOrderKeys.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::sync_order_keys, this, _1), gui_context());
221 }
222
223 bool
224 EditorRoutes::focus_in (GdkEventFocus*)
225 {
226         Window* win = dynamic_cast<Window*> (_scroller.get_toplevel ());
227
228         if (win) {
229                 old_focus = win->get_focus ();
230         } else {
231                 old_focus = 0;
232         }
233
234         name_editable = 0;
235
236         /* try to do nothing on focus in (doesn't work, hence selection_count nonsense) */
237         return true;
238 }
239
240 bool
241 EditorRoutes::focus_out (GdkEventFocus*)
242 {
243         if (old_focus) {
244                 old_focus->grab_focus ();
245                 old_focus = 0;
246         }
247
248         return false;
249 }
250
251 bool
252 EditorRoutes::enter_notify (GdkEventCrossing*)
253 {
254         if (name_editable) {
255                 return true;
256         }
257         
258         /* arm counter so that ::selection_filter() will deny selecting anything for the 
259            next two attempts to change selection status.
260         */
261         selection_countdown = 2;
262         _scroller.grab_focus ();
263         Keyboard::magic_widget_grab_focus ();
264         return false;
265 }
266
267 bool
268 EditorRoutes::leave_notify (GdkEventCrossing*)
269 {
270         selection_countdown = 0;
271
272         if (old_focus) {
273                 old_focus->grab_focus ();
274                 old_focus = 0;
275         }
276
277         Keyboard::magic_widget_drop_focus ();
278         return false;
279 }
280
281 void
282 EditorRoutes::set_session (Session* s)
283 {
284         SessionHandlePtr::set_session (s);
285
286         initial_display ();
287
288         if (_session) {
289                 _session->SoloChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::solo_changed_so_update_mute, this), gui_context());
290                 _session->RecordStateChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
291         }
292 }
293
294 void
295 EditorRoutes::on_tv_rec_enable_changed (std::string const & path_string)
296 {
297         // Get the model row that has been toggled.
298         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
299
300         TimeAxisView* tv = row[_columns.tv];
301         RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
302
303         if (rtv && rtv->track()) {
304                 boost::shared_ptr<RouteList> rl (new RouteList);
305                 rl->push_back (rtv->route());
306                 _session->set_record_enabled (rl, !rtv->track()->record_enabled(), Session::rt_cleanup);
307         }
308 }
309
310 void
311 EditorRoutes::on_tv_mute_enable_toggled (std::string const & path_string)
312 {
313         // Get the model row that has been toggled.
314         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
315
316         TimeAxisView *tv = row[_columns.tv];
317         RouteTimeAxisView *rtv = dynamic_cast<RouteTimeAxisView*> (tv);
318         
319         if (rtv != 0) {
320                 boost::shared_ptr<RouteList> rl (new RouteList);
321                 rl->push_back (rtv->route());
322                 _session->set_mute (rl, !rtv->route()->muted(), Session::rt_cleanup);
323         }
324 }
325
326 void
327 EditorRoutes::on_tv_solo_enable_toggled (std::string const & path_string)
328 {
329         // Get the model row that has been toggled.
330         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
331
332         TimeAxisView *tv = row[_columns.tv];
333         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
334
335         if (rtv != 0) {
336                 boost::shared_ptr<RouteList> rl (new RouteList);
337                 rl->push_back (rtv->route());
338                 if (Config->get_solo_control_is_listen_control()) {
339                         _session->set_listen (rl, !rtv->route()->listening_via_monitor(), Session::rt_cleanup);
340                 } else {
341                         _session->set_solo (rl, !rtv->route()->self_soloed(), Session::rt_cleanup);
342                 }
343         }
344 }
345
346 void
347 EditorRoutes::on_tv_solo_isolate_toggled (std::string const & path_string)
348 {
349         // Get the model row that has been toggled.
350         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
351
352         TimeAxisView *tv = row[_columns.tv];
353         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
354
355         if (rtv) {
356                 rtv->route()->set_solo_isolated (!rtv->route()->solo_isolated(), this);
357         }
358 }
359
360 void
361 EditorRoutes::on_tv_solo_safe_toggled (std::string const & path_string)
362 {
363         // Get the model row that has been toggled.
364         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
365
366         TimeAxisView *tv = row[_columns.tv];
367         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
368
369         if (rtv) {
370                 rtv->route()->set_solo_safe (!rtv->route()->solo_safe(), this);
371         }
372 }
373
374 void
375 EditorRoutes::build_menu ()
376 {
377         using namespace Menu_Helpers;
378         using namespace Gtk;
379
380         _menu = new Menu;
381
382         MenuList& items = _menu->items();
383         _menu->set_name ("ArdourContextMenu");
384
385         items.push_back (MenuElem (_("Show All"), sigc::mem_fun (*this, &EditorRoutes::show_all_routes)));
386         items.push_back (MenuElem (_("Hide All"), sigc::mem_fun (*this, &EditorRoutes::hide_all_routes)));
387         items.push_back (MenuElem (_("Show All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
388         items.push_back (MenuElem (_("Hide All Audio Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
389         items.push_back (MenuElem (_("Show All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::show_all_audiobus)));
390         items.push_back (MenuElem (_("Hide All Audio Busses"), sigc::mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
391         items.push_back (MenuElem (_("Show All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::show_all_miditracks)));
392         items.push_back (MenuElem (_("Hide All Midi Tracks"), sigc::mem_fun (*this, &EditorRoutes::hide_all_miditracks)));
393         items.push_back (MenuElem (_("Show Tracks With Regions Under Playhead"), sigc::mem_fun (*this, &EditorRoutes::show_tracks_with_regions_at_playhead)));
394 }
395
396 void
397 EditorRoutes::show_menu ()
398 {
399         if (_menu == 0) {
400                 build_menu ();
401         }
402
403         _menu->popup (1, gtk_get_current_event_time());
404 }
405
406 void
407 EditorRoutes::redisplay ()
408 {
409         if (_no_redisplay || !_session) {
410                 return;
411         }
412
413         TreeModel::Children rows = _model->children();
414         TreeModel::Children::iterator i;
415         uint32_t position;
416         int n;
417
418         for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
419                 TimeAxisView *tv = (*i)[_columns.tv];
420                 boost::shared_ptr<Route> route = (*i)[_columns.route];
421
422                 if (tv == 0) {
423                         // just a "title" row
424                         continue;
425                 }
426
427                 if (!_redisplay_does_not_reset_order_keys) {
428                         /* this reorder is caused by user action, so reassign sort order keys
429                            to tracks.
430                         */
431                         route->set_order_key (N_ ("editor"), n);
432                 }
433
434                 bool visible = (*i)[_columns.visible];
435
436                 /* show or hide the TimeAxisView */
437                 if (visible) {
438                         tv->set_marked_for_display (true);
439                         position += tv->show_at (position, n, &_editor->edit_controls_vbox);
440                         tv->clip_to_viewport ();
441                 } else {
442                         tv->set_marked_for_display (false);
443                         tv->hide ();
444                 }
445
446                 n++;
447         }
448
449
450         /* whenever we go idle, update the track view list to reflect the new order.
451            we can't do this here, because we could mess up something that is traversing
452            the track order and has caused a redisplay of the list.
453         */
454         Glib::signal_idle().connect (sigc::mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
455
456         _editor->reset_controls_layout_height (position);
457         _editor->reset_controls_layout_width ();
458         _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
459         _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
460
461         if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
462                 /*
463                    We're increasing the size of the canvas while the bottom is visible.
464                    We scroll down to keep in step with the controls layout.
465                 */
466                 _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
467         }
468
469         if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
470                 _session->sync_order_keys (N_ ("editor"));
471         }
472 }
473
474 void
475 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
476 {
477         if (!_session || _session->deletion_in_progress()) {
478                 return;
479         }
480                 
481         /* this could require an order reset & sync */
482         _session->set_remote_control_ids();
483         _ignore_reorder = true;
484         redisplay ();
485         _ignore_reorder = false;
486 }
487
488 void
489 EditorRoutes::visible_changed (std::string const & path)
490 {
491         if (_session && _session->deletion_in_progress()) {
492                 return;
493         }
494
495         TreeIter iter;
496
497         if ((iter = _model->get_iter (path))) {
498                 TimeAxisView* tv = (*iter)[_columns.tv];
499                 if (tv) {
500                         bool visible = (*iter)[_columns.visible];
501                         (*iter)[_columns.visible] = !visible;
502                 }
503         }
504
505         _redisplay_does_not_reset_order_keys = true;
506         _session->set_remote_control_ids();
507         redisplay ();
508         _redisplay_does_not_reset_order_keys = false;
509 }
510
511 void
512 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
513 {
514         TreeModel::Row row;
515
516         _redisplay_does_not_sync_order_keys = true;
517         suspend_redisplay ();
518
519         for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
520
521                 row = *(_model->append ());
522
523                 row[_columns.text] = (*x)->route()->name();
524                 row[_columns.visible] = (*x)->marked_for_display();
525                 row[_columns.tv] = *x;
526                 row[_columns.route] = (*x)->route ();
527                 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
528                 row[_columns.mute_state] = (*x)->route()->muted();
529                 row[_columns.solo_state] = RouteUI::solo_visual_state ((*x)->route());
530                 row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated();
531                 row[_columns.solo_safe_state] = (*x)->route()->solo_safe();
532                 row[_columns.name_editable] = true;
533
534                 _ignore_reorder = true;
535
536                 /* added a new fresh one at the end */
537                 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
538                         (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
539                 }
540
541                 _ignore_reorder = false;
542
543                 boost::weak_ptr<Route> wr ((*x)->route());
544
545                 (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
546                 (*x)->route()->PropertyChanged.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::route_property_changed, this, _1, wr), gui_context());
547
548                 if ((*x)->is_track()) {
549                         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
550                         t->RecordEnableChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
551                 }
552
553                 if ((*x)->is_midi_track()) {
554                         boost::shared_ptr<MidiTrack> t = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
555                         t->StepEditStatusChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
556                 }
557
558                 (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
559                 (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
560                 (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, ui_bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
561                 (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
562                 (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context());
563         }
564
565         update_rec_display ();
566         update_mute_display ();
567         update_solo_display (true);
568         update_solo_isolate_display ();
569         update_solo_safe_display ();
570         resume_redisplay ();
571         _redisplay_does_not_sync_order_keys = false;
572 }
573
574 void
575 EditorRoutes::handle_gui_changes (string const & what, void*)
576 {
577         ENSURE_GUI_THREAD (*this, &EditorRoutes::handle_gui_changes, what, src)
578
579         if (what == "track_height") {
580                 /* Optional :make tracks change height while it happens, instead
581                    of on first-idle
582                 */
583                 //update_canvas_now ();
584                 redisplay ();
585         }
586
587         if (what == "visible_tracks") {
588                 redisplay ();
589         }
590 }
591
592 void
593 EditorRoutes::route_removed (TimeAxisView *tv)
594 {
595         ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
596
597         TreeModel::Children rows = _model->children();
598         TreeModel::Children::iterator ri;
599
600         /* the core model has changed, there is no need to sync
601            view orders.
602         */
603
604         _redisplay_does_not_sync_order_keys = true;
605
606         for (ri = rows.begin(); ri != rows.end(); ++ri) {
607                 if ((*ri)[_columns.tv] == tv) {
608                         _model->erase (ri);
609                         break;
610                 }
611         }
612
613         _redisplay_does_not_sync_order_keys = false;
614 }
615
616 void
617 EditorRoutes::route_property_changed (const PropertyChange& what_changed, boost::weak_ptr<Route> r)
618 {
619         if (!what_changed.contains (ARDOUR::Properties::name)) {
620                 return;
621         }
622
623         ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
624
625         boost::shared_ptr<Route> route = r.lock ();
626
627         if (!route) {
628                 return;
629         }
630
631         TreeModel::Children rows = _model->children();
632         TreeModel::Children::iterator i;
633
634         for (i = rows.begin(); i != rows.end(); ++i) {
635                 boost::shared_ptr<Route> t = (*i)[_columns.route];
636                 if (t == route) {
637                         (*i)[_columns.text] = route->name();
638                         break;
639                 }
640         }
641 }
642
643 void
644 EditorRoutes::update_visibility ()
645 {
646         TreeModel::Children rows = _model->children();
647         TreeModel::Children::iterator i;
648
649         suspend_redisplay ();
650
651         for (i = rows.begin(); i != rows.end(); ++i) {
652                 TimeAxisView *tv = (*i)[_columns.tv];
653                 (*i)[_columns.visible] = tv->marked_for_display ();
654                 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
655         }
656
657         resume_redisplay ();
658 }
659
660 void
661 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
662 {
663         TreeModel::Children rows = _model->children();
664         TreeModel::Children::iterator i;
665
666         for (i = rows.begin(); i != rows.end(); ++i) {
667                 if ((*i)[_columns.tv] == &tv) {
668                         (*i)[_columns.visible] = false;
669                         break;
670                 }
671         }
672
673         redisplay ();
674 }
675
676 void
677 EditorRoutes::show_track_in_display (TimeAxisView& tv)
678 {
679         TreeModel::Children rows = _model->children();
680         TreeModel::Children::iterator i;
681
682         for (i = rows.begin(); i != rows.end(); ++i) {
683                 if ((*i)[_columns.tv] == &tv) {
684                         (*i)[_columns.visible] = true;
685                         break;
686                 }
687         }
688
689         redisplay ();
690 }
691
692 void
693 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
694 {
695         redisplay ();
696 }
697
698 /** If src != "editor", take editor order keys from each route and use them to rearrange the
699  *  route list so that the visual arrangement of routes matches the order keys from the routes.
700  */
701 void
702 EditorRoutes::sync_order_keys (string const & src)
703 {
704         vector<int> neworder;
705         TreeModel::Children rows = _model->children();
706         TreeModel::Children::iterator ri;
707
708         if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & (Session::Loading|Session::Deletion)) || rows.empty()) {
709                 return;
710         }
711
712         for (ri = rows.begin(); ri != rows.end(); ++ri) {
713                 neworder.push_back (0);
714         }
715
716         bool changed = false;
717         int order;
718
719         for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
720                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
721
722                 int old_key = order;
723                 int new_key = route->order_key (N_ ("editor"));
724
725                 neworder[new_key] = old_key;
726
727                 if (new_key != old_key) {
728                         changed = true;
729                 }
730         }
731
732         if (changed) {
733                 _redisplay_does_not_reset_order_keys = true;
734                 _model->reorder (neworder);
735                 _redisplay_does_not_reset_order_keys = false;
736         }
737 }
738
739
740 void
741 EditorRoutes::hide_all_tracks (bool /*with_select*/)
742 {
743         TreeModel::Children rows = _model->children();
744         TreeModel::Children::iterator i;
745
746         suspend_redisplay ();
747
748         for (i = rows.begin(); i != rows.end(); ++i) {
749
750                 TreeModel::Row row = (*i);
751                 TimeAxisView *tv = row[_columns.tv];
752
753                 if (tv == 0) {
754                         continue;
755                 }
756
757                 row[_columns.visible] = false;
758         }
759
760         resume_redisplay ();
761
762         /* XXX this seems like a hack and half, but its not clear where to put this
763            otherwise.
764         */
765
766         //reset_scrolling_region ();
767 }
768
769 void
770 EditorRoutes::set_all_tracks_visibility (bool yn)
771 {
772         TreeModel::Children rows = _model->children();
773         TreeModel::Children::iterator i;
774
775         suspend_redisplay ();
776
777         for (i = rows.begin(); i != rows.end(); ++i) {
778
779                 TreeModel::Row row = (*i);
780                 TimeAxisView* tv = row[_columns.tv];
781
782                 if (tv == 0) {
783                         continue;
784                 }
785
786                 (*i)[_columns.visible] = yn;
787         }
788
789         resume_redisplay ();
790 }
791
792 void
793 EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
794 {
795         TreeModel::Children rows = _model->children();
796         TreeModel::Children::iterator i;
797
798         suspend_redisplay ();
799
800         for (i = rows.begin(); i != rows.end(); ++i) {
801           
802                 TreeModel::Row row = (*i);
803                 TimeAxisView* tv = row[_columns.tv];
804                 
805                 AudioTimeAxisView* atv;
806                 MidiTimeAxisView* mtv;
807                 
808                 if (tv == 0) {
809                         continue;
810                 }
811
812                 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
813                         switch (tracks) {
814                         case 0:
815                                 (*i)[_columns.visible] = yn;
816                                 break;
817
818                         case 1:
819                                 if (atv->is_audio_track()) {
820                                         (*i)[_columns.visible] = yn;
821                                 }
822                                 break;
823
824                         case 2:
825                                 if (!atv->is_audio_track()) {
826                                         (*i)[_columns.visible] = yn;
827                                 }
828                                 break;
829                         }
830                 }
831                 else if ((mtv = dynamic_cast<MidiTimeAxisView*>(tv)) != 0) {
832                         switch (tracks) {
833                         case 0:
834                                 (*i)[_columns.visible] = yn;
835                                 break;
836
837                         case 3:
838                                 if (mtv->is_midi_track()) {
839                                         (*i)[_columns.visible] = yn;
840                                 }
841                                 break;
842                         }
843                 }
844         }
845
846         resume_redisplay ();
847 }
848
849 void
850 EditorRoutes::hide_all_routes ()
851 {
852         set_all_tracks_visibility (false);
853 }
854
855 void
856 EditorRoutes::show_all_routes ()
857 {
858         set_all_tracks_visibility (true);
859 }
860
861 void
862 EditorRoutes::show_all_audiotracks()
863 {
864         set_all_audio_midi_visibility (1, true);
865 }
866 void
867 EditorRoutes::hide_all_audiotracks ()
868 {
869         set_all_audio_midi_visibility (1, false);
870 }
871
872 void
873 EditorRoutes::show_all_audiobus ()
874 {
875         set_all_audio_midi_visibility (2, true);
876 }
877 void
878 EditorRoutes::hide_all_audiobus ()
879 {
880         set_all_audio_midi_visibility (2, false);
881 }
882
883 void
884 EditorRoutes::show_all_miditracks()
885 {
886         set_all_audio_midi_visibility (3, true);
887 }
888 void
889 EditorRoutes::hide_all_miditracks ()
890 {
891         set_all_audio_midi_visibility (3, false);
892 }
893
894 bool
895 EditorRoutes::key_press (GdkEventKey* ev)
896 {
897         TreeViewColumn *col;
898         boost::shared_ptr<RouteList> rl (new RouteList);
899         TreePath path;
900
901         switch (ev->keyval) {
902         case GDK_Tab:
903         case GDK_ISO_Left_Tab:
904
905                 /* If we appear to be editing something, leave that cleanly and appropriately.
906                 */
907                 if (name_editable) {
908                         name_editable->editing_done ();
909                         name_editable = 0;
910                 } 
911
912                 col = _display.get_column (5); // select&focus on name column
913
914                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
915                         treeview_select_previous (_display, _model, col);
916                 } else {
917                         treeview_select_next (_display, _model, col);
918                 }
919
920                 return true;
921                 break;
922
923         case 'm':
924                 if (get_relevant_routes (rl)) {
925                         _session->set_mute (rl, !rl->front()->muted(), Session::rt_cleanup);
926                 }
927                 return true;
928                 break;
929
930         case 's':
931                 if (Config->get_solo_control_is_listen_control()) {
932                         _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
933                 } else {
934                         _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
935                 }
936                 return true;
937                 break;
938
939         case 'r':
940                 if (get_relevant_routes (rl)) {
941                         _session->set_record_enabled (rl, !rl->front()->record_enabled(), Session::rt_cleanup);
942                 }
943                 break;
944
945         default:
946                 break;
947         }
948
949         return false;
950 }
951
952 bool
953 EditorRoutes::get_relevant_routes (boost::shared_ptr<RouteList> rl)
954 {
955         TimeAxisView* tv;
956         RouteTimeAxisView* rtv;
957         RefPtr<TreeSelection> selection = _display.get_selection();
958         TreePath path;
959         TreeIter iter;
960
961         if (selection->count_selected_rows() != 0) {
962
963                 /* use selection */
964
965                 RefPtr<TreeModel> tm = RefPtr<TreeModel>::cast_dynamic (_model);
966                 iter = selection->get_selected (tm);
967
968         } else {
969                 /* use mouse pointer */
970
971                 int x, y;
972                 int bx, by;
973
974                 _display.get_pointer (x, y);
975                 _display.convert_widget_to_bin_window_coords (x, y, bx, by);
976
977                 if (_display.get_path_at_pos (bx, by, path)) {
978                         iter = _model->get_iter (path);
979                 }
980         }
981
982         if (iter) {
983                 tv = (*iter)[_columns.tv];
984                 if (tv) {
985                         rtv = dynamic_cast<RouteTimeAxisView*>(tv);
986                         if (rtv) {
987                                 rl->push_back (rtv->route());
988                         }
989                 }
990         }
991
992         return !rl->empty();
993 }
994
995 bool
996 EditorRoutes::button_press (GdkEventButton* ev)
997 {
998         if (Keyboard::is_context_menu_event (ev)) {
999                 show_menu ();
1000                 return true;
1001         }
1002         
1003         //Scroll editor canvas to selected track
1004         if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1005                 
1006                 TreeModel::Path path;
1007                 TreeViewColumn *tvc;
1008                 int cell_x;
1009                 int cell_y;
1010                 
1011                 _display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y);
1012
1013                 // Get the model row.
1014                 Gtk::TreeModel::Row row = *_model->get_iter (path);
1015                 
1016                 TimeAxisView *tv = row[_columns.tv];
1017                 
1018                 int y_pos = tv->y_position();
1019                 
1020                 //Clamp the y pos so that we do not extend beyond the canvas full height.
1021                 if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){
1022                     y_pos = _editor->full_canvas_height - _editor->_canvas_height;
1023                 }
1024                 
1025                 //Only scroll to if the track is visible
1026                 if(y_pos != -1){
1027                     _editor->reset_y_origin (y_pos);
1028                 }
1029         }
1030         
1031         return false;
1032 }
1033
1034 bool
1035 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
1036 {
1037         if (selection_countdown) {
1038                 if (--selection_countdown == 0) {
1039                         return true;
1040                 } else {
1041                         /* no selection yet ... */
1042                         return false;
1043                 }
1044         }
1045         return true;
1046 }
1047
1048 struct EditorOrderRouteSorter {
1049     bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
1050             /* use of ">" forces the correct sort order */
1051             return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
1052     }
1053 };
1054
1055 void
1056 EditorRoutes::initial_display ()
1057 {
1058         suspend_redisplay ();
1059         _model->clear ();
1060
1061         if (!_session) {
1062                 resume_redisplay ();
1063                 return;
1064         }
1065
1066         boost::shared_ptr<RouteList> routes = _session->get_routes();
1067         RouteList r (*routes);
1068         EditorOrderRouteSorter sorter;
1069
1070         r.sort (sorter);
1071         _editor->handle_new_route (r);
1072
1073         /* don't show master bus in a new session */
1074
1075         if (ARDOUR_UI::instance()->session_is_new ()) {
1076
1077                 TreeModel::Children rows = _model->children();
1078                 TreeModel::Children::iterator i;
1079
1080                 _no_redisplay = true;
1081
1082                 for (i = rows.begin(); i != rows.end(); ++i) {
1083
1084                         TimeAxisView *tv =  (*i)[_columns.tv];
1085                         RouteTimeAxisView *rtv;
1086
1087                         if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
1088                                 if (rtv->route()->is_master()) {
1089                                         _display.get_selection()->unselect (i);
1090                                 }
1091                         }
1092                 }
1093
1094                 _no_redisplay = false;
1095                 redisplay ();
1096         }
1097
1098         resume_redisplay ();
1099 }
1100
1101 void
1102 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
1103 {
1104         _redisplay_does_not_sync_order_keys = true;
1105         _session->set_remote_control_ids();
1106         redisplay ();
1107         _redisplay_does_not_sync_order_keys = false;
1108 }
1109
1110 void
1111 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
1112                                              int x, int y,
1113                                              const SelectionData& data,
1114                                              guint info, guint time)
1115 {
1116         if (data.get_target() == "GTK_TREE_MODEL_ROW") {
1117                 _display.on_drag_data_received (context, x, y, data, info, time);
1118                 return;
1119         }
1120
1121         context->drag_finish (true, false, time);
1122 }
1123
1124 void
1125 EditorRoutes::move_selected_tracks (bool up)
1126 {
1127         if (_editor->selection->tracks.empty()) {
1128                 return;
1129         }
1130
1131         typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
1132         std::list<ViewRoute> view_routes;
1133         std::vector<int> neworder;
1134         TreeModel::Children rows = _model->children();
1135         TreeModel::Children::iterator ri;
1136
1137         for (ri = rows.begin(); ri != rows.end(); ++ri) {
1138                 TimeAxisView* tv = (*ri)[_columns.tv];
1139                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
1140
1141                 view_routes.push_back (ViewRoute (tv, route));
1142         }
1143
1144         list<ViewRoute>::iterator trailing;
1145         list<ViewRoute>::iterator leading;
1146
1147         if (up) {
1148
1149                 trailing = view_routes.begin();
1150                 leading = view_routes.begin();
1151
1152                 ++leading;
1153
1154                 while (leading != view_routes.end()) {
1155                         if (_editor->selection->selected (leading->first)) {
1156                                 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
1157                                 leading = view_routes.erase (leading);
1158                         } else {
1159                                 ++leading;
1160                                 ++trailing;
1161                         }
1162                 }
1163
1164         } else {
1165
1166                 /* if we could use reverse_iterator in list::insert, this code
1167                    would be a beautiful reflection of the code above. but we can't
1168                    and so it looks like a bit of a mess.
1169                 */
1170
1171                 trailing = view_routes.end();
1172                 leading = view_routes.end();
1173
1174                 --leading; if (leading == view_routes.begin()) { return; }
1175                 --leading;
1176                 --trailing;
1177
1178                 while (1) {
1179
1180                         if (_editor->selection->selected (leading->first)) {
1181                                 list<ViewRoute>::iterator tmp;
1182
1183                                 /* need to insert *after* trailing, not *before* it,
1184                                    which is what insert (iter, val) normally does.
1185                                 */
1186
1187                                 tmp = trailing;
1188                                 tmp++;
1189
1190                                 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
1191
1192                                 /* can't use iter = cont.erase (iter); form here, because
1193                                    we need iter to move backwards.
1194                                 */
1195
1196                                 tmp = leading;
1197                                 --tmp;
1198
1199                                 bool done = false;
1200
1201                                 if (leading == view_routes.begin()) {
1202                                         /* the one we've just inserted somewhere else
1203                                            was the first in the list. erase this copy,
1204                                            and then break, because we're done.
1205                                         */
1206                                         done = true;
1207                                 }
1208
1209                                 view_routes.erase (leading);
1210
1211                                 if (done) {
1212                                         break;
1213                                 }
1214
1215                                 leading = tmp;
1216
1217                         } else {
1218                                 if (leading == view_routes.begin()) {
1219                                         break;
1220                                 }
1221                                 --leading;
1222                                 --trailing;
1223                         }
1224                 };
1225         }
1226
1227         for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
1228                 neworder.push_back (leading->second->order_key (N_ ("editor")));
1229         }
1230
1231         _model->reorder (neworder);
1232
1233        _session->sync_order_keys (N_ ("editor"));
1234 }
1235
1236 void
1237 EditorRoutes::update_rec_display ()
1238 {
1239         TreeModel::Children rows = _model->children();
1240         TreeModel::Children::iterator i;
1241
1242         for (i = rows.begin(); i != rows.end(); ++i) {
1243                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1244
1245                 if (boost::dynamic_pointer_cast<Track> (route)) {
1246                         boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1247
1248                         if (route->record_enabled()) {
1249                                 if (_session->record_status() == Session::Recording) {
1250                                         (*i)[_columns.rec_state] = 1;
1251                                 } else {
1252                                         (*i)[_columns.rec_state] = 2;
1253                                 }
1254                         } else if (mt && mt->step_editing()) {
1255                                 (*i)[_columns.rec_state] = 3;
1256                         } else {
1257                                 (*i)[_columns.rec_state] = 0;
1258                         }
1259                 
1260                         (*i)[_columns.name_editable] = !route->record_enabled ();
1261                 }
1262         }
1263 }
1264
1265 void
1266 EditorRoutes::update_mute_display ()
1267 {
1268         TreeModel::Children rows = _model->children();
1269         TreeModel::Children::iterator i;
1270
1271         for (i = rows.begin(); i != rows.end(); ++i) {
1272                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1273                 (*i)[_columns.mute_state] = RouteUI::mute_visual_state (_session, route);
1274         }
1275 }
1276
1277 void
1278 EditorRoutes::update_solo_display (bool /* selfsoloed */)
1279 {
1280         TreeModel::Children rows = _model->children();
1281         TreeModel::Children::iterator i;
1282
1283         for (i = rows.begin(); i != rows.end(); ++i) {
1284                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1285                 (*i)[_columns.solo_state] = RouteUI::solo_visual_state (route);
1286         }
1287 }
1288
1289 void
1290 EditorRoutes::update_solo_isolate_display ()
1291 {
1292         TreeModel::Children rows = _model->children();
1293         TreeModel::Children::iterator i;
1294
1295         for (i = rows.begin(); i != rows.end(); ++i) {
1296                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1297                 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_visual_state (route) > 0 ? 1 : 0;
1298         }
1299 }
1300
1301 void
1302 EditorRoutes::update_solo_safe_display ()
1303 {
1304         TreeModel::Children rows = _model->children();
1305         TreeModel::Children::iterator i;
1306
1307         for (i = rows.begin(); i != rows.end(); ++i) {
1308                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1309                 (*i)[_columns.solo_safe_state] = RouteUI::solo_safe_visual_state (route) > 0 ? 1 : 0;
1310         }
1311 }
1312
1313 list<TimeAxisView*>
1314 EditorRoutes::views () const
1315 {
1316         list<TimeAxisView*> v;
1317         for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1318                 v.push_back ((*i)[_columns.tv]);
1319         }
1320
1321         return v;
1322 }
1323
1324 void
1325 EditorRoutes::clear ()
1326 {
1327         _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1328         _model->clear ();
1329         _display.set_model (_model);
1330 }
1331
1332 void
1333 EditorRoutes::name_edit_started (CellEditable* ce, const Glib::ustring&)
1334 {
1335         name_editable = ce;
1336
1337         /* give it a special name */
1338
1339         Gtk::Entry *e = dynamic_cast<Gtk::Entry*> (ce);
1340
1341         if (e) {
1342                 e->set_name (X_("RouteNameEditorEntry"));
1343         }
1344 }
1345
1346 void
1347 EditorRoutes::name_edit (std::string const & path, std::string const & new_text)
1348 {
1349         name_editable = 0;
1350
1351         TreeIter iter = _model->get_iter (path);
1352
1353         if (!iter) {
1354                 return;
1355         }
1356
1357         boost::shared_ptr<Route> route = (*iter)[_columns.route];
1358
1359         if (route && route->name() != new_text) {
1360                 route->set_name (new_text);
1361         }
1362 }
1363
1364 void
1365 EditorRoutes::solo_changed_so_update_mute ()
1366 {
1367         update_mute_display ();
1368 }
1369
1370 void
1371 EditorRoutes::show_tracks_with_regions_at_playhead ()
1372 {
1373         boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1374
1375         set<TimeAxisView*> show;
1376         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1377                 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1378                 if (tav) {
1379                         show.insert (tav);
1380                 }
1381         }
1382
1383         suspend_redisplay ();
1384         
1385         TreeModel::Children rows = _model->children ();
1386         for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1387                 TimeAxisView* tv = (*i)[_columns.tv];
1388                 (*i)[_columns.visible] = (show.find (tv) != show.end());
1389         }
1390
1391         resume_redisplay ();
1392 }