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