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