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