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