merge with master, including manual merge conflict resolution
[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, _1), 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                         tv->clip_to_viewport ();
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         _editor->vertical_adjustment.set_upper (_editor->_full_canvas_height);
539
540         if ((_editor->vertical_adjustment.get_value() + _editor->_visible_canvas_height) > _editor->vertical_adjustment.get_upper()) {
541                 /*
542                    We're increasing the size of the canvas while the bottom is visible.
543                    We scroll down to keep in step with the controls layout.
544                 */
545                 _editor->vertical_adjustment.set_value (_editor->_full_canvas_height - _editor->_visible_canvas_height);
546         }
547 }
548
549 void
550 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
551 {
552         /* this happens as the second step of a DnD within the treeview as well
553            as when a row/route is actually deleted.
554         */
555         DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview row deleted\n");
556         sync_order_keys_from_treeview ();
557 }
558
559 void
560 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
561 {
562         DEBUG_TRACE (DEBUG::OrderKeys, "editor routes treeview reordered\n");
563         sync_order_keys_from_treeview ();
564 }
565
566 void
567 EditorRoutes::visible_changed (std::string const & path)
568 {
569         if (_session && _session->deletion_in_progress()) {
570                 return;
571         }
572
573         TreeIter iter;
574
575         if ((iter = _model->get_iter (path))) {
576                 TimeAxisView* tv = (*iter)[_columns.tv];
577                 if (tv) {
578                         bool visible = (*iter)[_columns.visible];
579
580                         if (tv->set_marked_for_display (!visible)) {
581                                 update_visibility ();
582                         }
583                 }
584         }
585 }
586
587 void
588 EditorRoutes::active_changed (std::string const & path)
589 {
590         if (_session && _session->deletion_in_progress ()) {
591                 return;
592         }
593
594         Gtk::TreeModel::Row row = *_model->get_iter (path);
595         boost::shared_ptr<Route> route = row[_columns.route];
596         bool const active = row[_columns.active];
597         route->set_active (!active, this);
598 }
599
600 void
601 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
602 {
603         TreeModel::Row row;
604         PBD::Unwinder<bool> at (_adding_routes, true);
605
606         suspend_redisplay ();
607
608         _display.set_model (Glib::RefPtr<ListStore>());
609
610         for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
611
612                 boost::shared_ptr<MidiTrack> midi_trk = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
613
614                 row = *(_model->append ());
615
616                 row[_columns.text] = (*x)->route()->name();
617                 row[_columns.visible] = (*x)->marked_for_display();
618                 row[_columns.active] = (*x)->route()->active ();
619                 row[_columns.tv] = *x;
620                 row[_columns.route] = (*x)->route ();
621                 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
622
623                 if (midi_trk) {
624                         row[_columns.is_input_active] = midi_trk->input_active ();
625                         row[_columns.is_midi] = true;
626                 } else {
627                         row[_columns.is_input_active] = false;
628                         row[_columns.is_midi] = false;
629                 }
630
631                 row[_columns.mute_state] = (*x)->route()->muted() ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off;
632                 row[_columns.solo_state] = RouteUI::solo_active_state ((*x)->route());
633                 row[_columns.solo_visible] = !(*x)->route()->is_master ();
634                 row[_columns.solo_isolate_state] = (*x)->route()->solo_isolated();
635                 row[_columns.solo_safe_state] = (*x)->route()->solo_safe();
636                 row[_columns.name_editable] = true;
637
638                 boost::weak_ptr<Route> wr ((*x)->route());
639
640                 (*x)->route()->gui_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::handle_gui_changes, this, _1, _2), gui_context());
641                 (*x)->route()->PropertyChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::route_property_changed, this, _1, wr), gui_context());
642
643                 if ((*x)->is_track()) {
644                         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
645                         t->RecordEnableChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
646                 }
647
648                 if ((*x)->is_midi_track()) {
649                         boost::shared_ptr<MidiTrack> t = boost::dynamic_pointer_cast<MidiTrack> ((*x)->route());
650                         t->StepEditStatusChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_rec_display, this), gui_context());
651                         t->InputActiveChanged.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_input_active_display, this), gui_context());
652                 }
653
654                 (*x)->route()->mute_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_mute_display, this), gui_context());
655                 (*x)->route()->solo_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
656                 (*x)->route()->listen_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_display, this, _1), gui_context());
657                 (*x)->route()->solo_isolated_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_isolate_display, this), gui_context());
658                 (*x)->route()->solo_safe_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_solo_safe_display, this), gui_context());
659                 (*x)->route()->active_changed.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::update_active_display, this), gui_context ());
660
661         }
662
663         update_rec_display ();
664         update_mute_display ();
665         update_solo_display (true);
666         update_solo_isolate_display ();
667         update_solo_safe_display ();
668         update_input_active_display ();
669         update_active_display ();
670
671         resume_redisplay ();
672         _display.set_model (_model);
673
674         /* now update route order keys from the treeview/track display order */
675
676         sync_order_keys_from_treeview ();
677 }
678
679 void
680 EditorRoutes::handle_gui_changes (string const & what, void*)
681 {
682         if (_adding_routes) {
683                 return;
684         }
685
686         if (what == "track_height") {
687                 /* Optional :make tracks change height while it happens, instead
688                    of on first-idle
689                 */
690                 //update_canvas_now ();
691                 redisplay ();
692         }
693
694         if (what == "visible_tracks") {
695                 redisplay ();
696         }
697 }
698
699 void
700 EditorRoutes::route_removed (TimeAxisView *tv)
701 {
702         ENSURE_GUI_THREAD (*this, &EditorRoutes::route_removed, tv)
703
704         TreeModel::Children rows = _model->children();
705         TreeModel::Children::iterator ri;
706
707         for (ri = rows.begin(); ri != rows.end(); ++ri) {
708                 if ((*ri)[_columns.tv] == tv) {
709                         _model->erase (ri);
710                         break;
711                 }
712         }
713
714         /* the deleted signal for the treeview/model will take 
715            care of any updates.
716         */
717 }
718
719 void
720 EditorRoutes::route_property_changed (const PropertyChange& what_changed, boost::weak_ptr<Route> r)
721 {
722         if (!what_changed.contains (ARDOUR::Properties::name)) {
723                 return;
724         }
725
726         ENSURE_GUI_THREAD (*this, &EditorRoutes::route_name_changed, r)
727
728         boost::shared_ptr<Route> route = r.lock ();
729
730         if (!route) {
731                 return;
732         }
733
734         TreeModel::Children rows = _model->children();
735         TreeModel::Children::iterator i;
736
737         for (i = rows.begin(); i != rows.end(); ++i) {
738                 boost::shared_ptr<Route> t = (*i)[_columns.route];
739                 if (t == route) {
740                         (*i)[_columns.text] = route->name();
741                         break;
742                 }
743         }
744 }
745
746 void
747 EditorRoutes::update_active_display ()
748 {
749         TreeModel::Children rows = _model->children();
750         TreeModel::Children::iterator i;
751
752         for (i = rows.begin(); i != rows.end(); ++i) {
753                 boost::shared_ptr<Route> route = (*i)[_columns.route];
754                 (*i)[_columns.active] = route->active ();
755         }
756 }
757
758 void
759 EditorRoutes::update_visibility ()
760 {
761         TreeModel::Children rows = _model->children();
762         TreeModel::Children::iterator i;
763
764         suspend_redisplay ();
765
766         for (i = rows.begin(); i != rows.end(); ++i) {
767                 TimeAxisView *tv = (*i)[_columns.tv];
768                 (*i)[_columns.visible] = tv->marked_for_display ();
769         }
770
771         /* force route order keys catch up with visibility changes
772          */
773
774         sync_order_keys_from_treeview ();
775
776         resume_redisplay ();
777 }
778
779 void
780 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
781 {
782         TreeModel::Children rows = _model->children();
783         TreeModel::Children::iterator i;
784
785         for (i = rows.begin(); i != rows.end(); ++i) {
786                 if ((*i)[_columns.tv] == &tv) {
787                         tv.set_marked_for_display (false);
788                         (*i)[_columns.visible] = false;
789                         redisplay ();
790                         break;
791                 }
792         }
793 }
794
795 void
796 EditorRoutes::show_track_in_display (TimeAxisView& tv)
797 {
798         TreeModel::Children rows = _model->children();
799         TreeModel::Children::iterator i;
800
801
802         for (i = rows.begin(); i != rows.end(); ++i) {
803                 if ((*i)[_columns.tv] == &tv) {
804                         tv.set_marked_for_display (true);
805                         (*i)[_columns.visible] = true;
806                         redisplay ();
807                         break;
808                 }
809         }
810 }
811
812 void
813 EditorRoutes::reset_remote_control_ids ()
814 {
815         if (Config->get_remote_model() != EditorOrdered || !_session || _session->deletion_in_progress()) {
816                 return;
817         }
818
819         TreeModel::Children rows = _model->children();
820         
821         if (rows.empty()) {
822                 return;
823         }
824
825         
826         DEBUG_TRACE (DEBUG::OrderKeys, "editor reset remote control ids\n");
827
828         TreeModel::Children::iterator ri;
829         bool rid_change = false;
830         uint32_t rid = 1;
831         uint32_t invisible_key = UINT32_MAX;
832
833         for (ri = rows.begin(); ri != rows.end(); ++ri) {
834
835                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
836                 bool visible = (*ri)[_columns.visible];
837
838
839                 if (!route->is_master() && !route->is_monitor()) {
840
841                         uint32_t new_rid = (visible ? rid : invisible_key--);
842
843                         if (new_rid != route->remote_control_id()) {
844                                 route->set_remote_control_id_from_order_key (EditorSort, new_rid);      
845                                 rid_change = true;
846                         }
847                         
848                         if (visible) {
849                                 rid++;
850                         }
851
852                 }
853         }
854
855         if (rid_change) {
856                 /* tell the world that we changed the remote control IDs */
857                 _session->notify_remote_id_change ();
858         }
859 }
860
861
862 void
863 EditorRoutes::sync_order_keys_from_treeview ()
864 {
865         if (_ignore_reorder || !_session || _session->deletion_in_progress()) {
866                 return;
867         }
868
869         TreeModel::Children rows = _model->children();
870         
871         if (rows.empty()) {
872                 return;
873         }
874
875         
876         DEBUG_TRACE (DEBUG::OrderKeys, "editor sync order keys from treeview\n");
877
878         TreeModel::Children::iterator ri;
879         bool changed = false;
880         bool rid_change = false;
881         uint32_t order = 0;
882         uint32_t rid = 1;
883         uint32_t invisible_key = UINT32_MAX;
884
885         for (ri = rows.begin(); ri != rows.end(); ++ri) {
886
887                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
888                 bool visible = (*ri)[_columns.visible];
889
890                 uint32_t old_key = route->order_key (EditorSort);
891
892                 if (order != old_key) {
893                         route->set_order_key (EditorSort, order);
894
895                         changed = true;
896                 }
897
898                 if ((Config->get_remote_model() == EditorOrdered) && !route->is_master() && !route->is_monitor()) {
899
900                         uint32_t new_rid = (visible ? rid : invisible_key--);
901
902                         if (new_rid != route->remote_control_id()) {
903                                 route->set_remote_control_id_from_order_key (EditorSort, new_rid);      
904                                 rid_change = true;
905                         }
906                         
907                         if (visible) {
908                                 rid++;
909                         }
910
911                 }
912
913                 ++order;
914         }
915         
916         if (changed) {
917                 /* tell the world that we changed the editor sort keys */
918                 _session->sync_order_keys (EditorSort);
919         }
920
921         if (rid_change) {
922                 /* tell the world that we changed the remote control IDs */
923                 _session->notify_remote_id_change ();
924         }
925 }
926
927 void
928 EditorRoutes::sync_treeview_from_order_keys (RouteSortOrderKey src)
929 {
930         /* Some route order key(s) for `src' has been changed, make sure that 
931            we update out tree/list model and GUI to reflect the change.
932         */
933
934         if (!_session || _session->deletion_in_progress()) {
935                 return;
936         }
937
938         DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("editor sync model from order keys, src = %1\n", enum_2_string (src)));
939
940         if (src == MixerSort) {
941
942                 if (!Config->get_sync_all_route_ordering()) {
943                         /* mixer sort keys changed - we don't care */
944                         return;
945                 }
946
947                 DEBUG_TRACE (DEBUG::OrderKeys, "reset editor order key to match mixer\n");
948
949                 /* mixer sort keys were changed, update the editor sort
950                  * keys since "sync mixer+editor order" is enabled.
951                  */
952
953                 boost::shared_ptr<RouteList> r = _session->get_routes ();
954                 
955                 for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
956                         (*i)->sync_order_keys (src);
957                 }
958         }
959
960         /* we could get here after either a change in the Mixer or Editor sort
961          * order, but either way, the mixer order keys reflect the intended
962          * order for the GUI, so reorder the treeview model to match it.
963          */
964
965         vector<int> neworder;
966         TreeModel::Children rows = _model->children();
967         uint32_t old_order = 0;
968         bool changed = false;
969
970         if (rows.empty()) {
971                 return;
972         }
973
974         OrderKeySortedRoutes sorted_routes;
975
976         for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri, ++old_order) {
977                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
978                 sorted_routes.push_back (RoutePlusOrderKey (route, old_order, route->order_key (EditorSort)));
979         }
980
981         SortByNewDisplayOrder cmp;
982
983         sort (sorted_routes.begin(), sorted_routes.end(), cmp);
984         neworder.assign (sorted_routes.size(), 0);
985
986         uint32_t n = 0;
987         
988         for (OrderKeySortedRoutes::iterator sr = sorted_routes.begin(); sr != sorted_routes.end(); ++sr, ++n) {
989
990                 neworder[n] = sr->old_display_order;
991
992                 if (sr->old_display_order != n) {
993                         changed = true;
994                 }
995
996                 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("EDITOR change order for %1 from %2 to %3\n",
997                                                                sr->route->name(), sr->old_display_order, n));
998         }
999
1000         if (changed) {
1001                 Unwinder<bool> uw (_ignore_reorder, true);
1002                 _model->reorder (neworder);
1003         }
1004
1005         redisplay ();
1006 }
1007
1008 void
1009 EditorRoutes::hide_all_tracks (bool /*with_select*/)
1010 {
1011         TreeModel::Children rows = _model->children();
1012         TreeModel::Children::iterator i;
1013
1014         suspend_redisplay ();
1015
1016         for (i = rows.begin(); i != rows.end(); ++i) {
1017
1018                 TreeModel::Row row = (*i);
1019                 TimeAxisView *tv = row[_columns.tv];
1020
1021                 if (tv == 0) {
1022                         continue;
1023                 }
1024
1025                 row[_columns.visible] = false;
1026         }
1027
1028         resume_redisplay ();
1029
1030         /* XXX this seems like a hack and half, but its not clear where to put this
1031            otherwise.
1032         */
1033
1034         //reset_scrolling_region ();
1035 }
1036
1037 void
1038 EditorRoutes::set_all_tracks_visibility (bool yn)
1039 {
1040         TreeModel::Children rows = _model->children();
1041         TreeModel::Children::iterator i;
1042
1043         suspend_redisplay ();
1044
1045         for (i = rows.begin(); i != rows.end(); ++i) {
1046
1047                 TreeModel::Row row = (*i);
1048                 TimeAxisView* tv = row[_columns.tv];
1049
1050                 if (tv == 0) {
1051                         continue;
1052                 }
1053
1054                 tv->set_marked_for_display (yn);
1055                 (*i)[_columns.visible] = yn;
1056         }
1057
1058         /* force route order keys catch up with visibility changes
1059          */
1060
1061         sync_order_keys_from_treeview ();
1062
1063         resume_redisplay ();
1064 }
1065
1066 void
1067 EditorRoutes::set_all_audio_midi_visibility (int tracks, bool yn)
1068 {
1069         TreeModel::Children rows = _model->children();
1070         TreeModel::Children::iterator i;
1071
1072         suspend_redisplay ();
1073
1074         for (i = rows.begin(); i != rows.end(); ++i) {
1075
1076                 TreeModel::Row row = (*i);
1077                 TimeAxisView* tv = row[_columns.tv];
1078
1079                 AudioTimeAxisView* atv;
1080                 MidiTimeAxisView* mtv;
1081
1082                 if (tv == 0) {
1083                         continue;
1084                 }
1085
1086                 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1087                         switch (tracks) {
1088                         case 0:
1089                                 (*i)[_columns.visible] = yn;
1090                                 break;
1091
1092                         case 1:
1093                                 if (atv->is_audio_track()) {
1094                                         (*i)[_columns.visible] = yn;
1095                                 }
1096                                 break;
1097
1098                         case 2:
1099                                 if (!atv->is_audio_track()) {
1100                                         (*i)[_columns.visible] = yn;
1101                                 }
1102                                 break;
1103                         }
1104                 }
1105                 else if ((mtv = dynamic_cast<MidiTimeAxisView*>(tv)) != 0) {
1106                         switch (tracks) {
1107                         case 0:
1108                                 (*i)[_columns.visible] = yn;
1109                                 break;
1110
1111                         case 3:
1112                                 if (mtv->is_midi_track()) {
1113                                         (*i)[_columns.visible] = yn;
1114                                 }
1115                                 break;
1116                         }
1117                 }
1118         }
1119
1120         /* force route order keys catch up with visibility changes
1121          */
1122
1123         sync_order_keys_from_treeview ();
1124
1125         resume_redisplay ();
1126 }
1127
1128 void
1129 EditorRoutes::hide_all_routes ()
1130 {
1131         set_all_tracks_visibility (false);
1132 }
1133
1134 void
1135 EditorRoutes::show_all_routes ()
1136 {
1137         set_all_tracks_visibility (true);
1138 }
1139
1140 void
1141 EditorRoutes::show_all_audiotracks()
1142 {
1143         set_all_audio_midi_visibility (1, true);
1144 }
1145 void
1146 EditorRoutes::hide_all_audiotracks ()
1147 {
1148         set_all_audio_midi_visibility (1, false);
1149 }
1150
1151 void
1152 EditorRoutes::show_all_audiobus ()
1153 {
1154         set_all_audio_midi_visibility (2, true);
1155 }
1156 void
1157 EditorRoutes::hide_all_audiobus ()
1158 {
1159         set_all_audio_midi_visibility (2, false);
1160 }
1161
1162 void
1163 EditorRoutes::show_all_miditracks()
1164 {
1165         set_all_audio_midi_visibility (3, true);
1166 }
1167 void
1168 EditorRoutes::hide_all_miditracks ()
1169 {
1170         set_all_audio_midi_visibility (3, false);
1171 }
1172
1173 bool
1174 EditorRoutes::key_press (GdkEventKey* ev)
1175 {
1176         TreeViewColumn *col;
1177         boost::shared_ptr<RouteList> rl (new RouteList);
1178         TreePath path;
1179
1180         switch (ev->keyval) {
1181         case GDK_Tab:
1182         case GDK_ISO_Left_Tab:
1183
1184                 /* If we appear to be editing something, leave that cleanly and appropriately.
1185                 */
1186                 if (name_editable) {
1187                         name_editable->editing_done ();
1188                         name_editable = 0;
1189                 }
1190
1191                 col = _display.get_column (_name_column); // select&focus on name column
1192
1193                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1194                         treeview_select_previous (_display, _model, col);
1195                 } else {
1196                         treeview_select_next (_display, _model, col);
1197                 }
1198
1199                 return true;
1200                 break;
1201
1202         case 'm':
1203                 if (get_relevant_routes (rl)) {
1204                         _session->set_mute (rl, !rl->front()->muted(), Session::rt_cleanup);
1205                 }
1206                 return true;
1207                 break;
1208
1209         case 's':
1210                 if (get_relevant_routes (rl)) {
1211                         if (Config->get_solo_control_is_listen_control()) {
1212                                 _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
1213                         } else {
1214                                 _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
1215                         }
1216                 }
1217                 return true;
1218                 break;
1219
1220         case 'r':
1221                 if (get_relevant_routes (rl)) {
1222                         _session->set_record_enabled (rl, !rl->front()->record_enabled(), Session::rt_cleanup);
1223                 }
1224                 break;
1225
1226         default:
1227                 break;
1228         }
1229
1230         return false;
1231 }
1232
1233 bool
1234 EditorRoutes::get_relevant_routes (boost::shared_ptr<RouteList> rl)
1235 {
1236         TimeAxisView* tv;
1237         RouteTimeAxisView* rtv;
1238         RefPtr<TreeSelection> selection = _display.get_selection();
1239         TreePath path;
1240         TreeIter iter;
1241
1242         if (selection->count_selected_rows() != 0) {
1243
1244                 /* use selection */
1245
1246                 RefPtr<TreeModel> tm = RefPtr<TreeModel>::cast_dynamic (_model);
1247                 iter = selection->get_selected (tm);
1248
1249         } else {
1250                 /* use mouse pointer */
1251
1252                 int x, y;
1253                 int bx, by;
1254
1255                 _display.get_pointer (x, y);
1256                 _display.convert_widget_to_bin_window_coords (x, y, bx, by);
1257
1258                 if (_display.get_path_at_pos (bx, by, path)) {
1259                         iter = _model->get_iter (path);
1260                 }
1261         }
1262
1263         if (iter) {
1264                 tv = (*iter)[_columns.tv];
1265                 if (tv) {
1266                         rtv = dynamic_cast<RouteTimeAxisView*>(tv);
1267                         if (rtv) {
1268                                 rl->push_back (rtv->route());
1269                         }
1270                 }
1271         }
1272
1273         return !rl->empty();
1274 }
1275
1276 bool
1277 EditorRoutes::button_press (GdkEventButton* ev)
1278 {
1279         if (Keyboard::is_context_menu_event (ev)) {
1280                 show_menu ();
1281                 return true;
1282         }
1283
1284         TreeModel::Path path;
1285         TreeViewColumn *tvc;
1286         int cell_x;
1287         int cell_y;
1288
1289         if (!_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y)) {
1290                 /* cancel selection */
1291                 _display.get_selection()->unselect_all ();
1292                 /* end any editing by grabbing focus */
1293                 _display.grab_focus ();
1294                 return true;
1295         }
1296
1297         //Scroll editor canvas to selected track
1298         if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1299
1300                 // Get the model row.
1301                 Gtk::TreeModel::Row row = *_model->get_iter (path);
1302
1303                 TimeAxisView *tv = row[_columns.tv];
1304
1305                 int y_pos = tv->y_position();
1306
1307                 //Clamp the y pos so that we do not extend beyond the canvas full height.
1308                 if (_editor->_full_canvas_height - y_pos < _editor->_visible_canvas_height){
1309                     y_pos = _editor->_full_canvas_height - _editor->_visible_canvas_height;
1310                 }
1311
1312                 //Only scroll to if the track is visible
1313                 if(y_pos != -1){
1314                     _editor->reset_y_origin (y_pos);
1315                 }
1316         }
1317
1318         return false;
1319 }
1320
1321 bool
1322 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
1323 {
1324         if (selection_countdown) {
1325                 if (--selection_countdown == 0) {
1326                         return true;
1327                 } else {
1328                         /* no selection yet ... */
1329                         return false;
1330                 }
1331         }
1332         return true;
1333 }
1334
1335 struct EditorOrderRouteSorter {
1336     bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
1337             if (a->is_master()) {
1338                     /* master before everything else */
1339                     return true;
1340             } else if (b->is_master()) {
1341                     /* everything else before master */
1342                     return false;
1343             }
1344             return a->order_key (EditorSort) < b->order_key (EditorSort);
1345     }
1346 };
1347
1348 void
1349 EditorRoutes::initial_display ()
1350 {
1351         suspend_redisplay ();
1352         _model->clear ();
1353
1354         if (!_session) {
1355                 resume_redisplay ();
1356                 return;
1357         }
1358
1359         boost::shared_ptr<RouteList> routes = _session->get_routes();
1360
1361         if (ARDOUR_UI::instance()->session_is_new ()) {
1362
1363                 /* new session: stamp all routes with the right editor order
1364                  * key
1365                  */
1366
1367                 _editor->add_routes (*(routes.get()));
1368                 
1369         } else {
1370
1371                 /* existing session: sort a copy of the route list by
1372                  * editor-order and add its contents to the display.
1373                  */
1374
1375                 RouteList r (*routes);
1376                 EditorOrderRouteSorter sorter;
1377                 
1378                 r.sort (sorter);
1379                 _editor->add_routes (r);
1380                 
1381         }
1382
1383         resume_redisplay ();
1384 }
1385
1386 void
1387 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
1388                                              int x, int y,
1389                                              const SelectionData& data,
1390                                              guint info, guint time)
1391 {
1392         if (data.get_target() == "GTK_TREE_MODEL_ROW") {
1393                 _display.on_drag_data_received (context, x, y, data, info, time);
1394                 return;
1395         }
1396
1397         context->drag_finish (true, false, time);
1398 }
1399
1400 void
1401 EditorRoutes::move_selected_tracks (bool up)
1402 {
1403         if (_editor->selection->tracks.empty()) {
1404                 return;
1405         }
1406
1407         typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
1408         std::list<ViewRoute> view_routes;
1409         std::vector<int> neworder;
1410         TreeModel::Children rows = _model->children();
1411         TreeModel::Children::iterator ri;
1412
1413         for (ri = rows.begin(); ri != rows.end(); ++ri) {
1414                 TimeAxisView* tv = (*ri)[_columns.tv];
1415                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
1416
1417                 view_routes.push_back (ViewRoute (tv, route));
1418         }
1419
1420         list<ViewRoute>::iterator trailing;
1421         list<ViewRoute>::iterator leading;
1422
1423         if (up) {
1424
1425                 trailing = view_routes.begin();
1426                 leading = view_routes.begin();
1427
1428                 ++leading;
1429
1430                 while (leading != view_routes.end()) {
1431                         if (_editor->selection->selected (leading->first)) {
1432                                 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
1433                                 leading = view_routes.erase (leading);
1434                         } else {
1435                                 ++leading;
1436                                 ++trailing;
1437                         }
1438                 }
1439
1440         } else {
1441
1442                 /* if we could use reverse_iterator in list::insert, this code
1443                    would be a beautiful reflection of the code above. but we can't
1444                    and so it looks like a bit of a mess.
1445                 */
1446
1447                 trailing = view_routes.end();
1448                 leading = view_routes.end();
1449
1450                 --leading; if (leading == view_routes.begin()) { return; }
1451                 --leading;
1452                 --trailing;
1453
1454                 while (1) {
1455
1456                         if (_editor->selection->selected (leading->first)) {
1457                                 list<ViewRoute>::iterator tmp;
1458
1459                                 /* need to insert *after* trailing, not *before* it,
1460                                    which is what insert (iter, val) normally does.
1461                                 */
1462
1463                                 tmp = trailing;
1464                                 tmp++;
1465
1466                                 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
1467
1468                                 /* can't use iter = cont.erase (iter); form here, because
1469                                    we need iter to move backwards.
1470                                 */
1471
1472                                 tmp = leading;
1473                                 --tmp;
1474
1475                                 bool done = false;
1476
1477                                 if (leading == view_routes.begin()) {
1478                                         /* the one we've just inserted somewhere else
1479                                            was the first in the list. erase this copy,
1480                                            and then break, because we're done.
1481                                         */
1482                                         done = true;
1483                                 }
1484
1485                                 view_routes.erase (leading);
1486
1487                                 if (done) {
1488                                         break;
1489                                 }
1490
1491                                 leading = tmp;
1492
1493                         } else {
1494                                 if (leading == view_routes.begin()) {
1495                                         break;
1496                                 }
1497                                 --leading;
1498                                 --trailing;
1499                         }
1500                 };
1501         }
1502
1503         for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
1504                 uint32_t order = leading->second->order_key (EditorSort);
1505                 neworder.push_back (order);
1506         }
1507
1508 #ifndef NDEBUG
1509         DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n");
1510         for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1511                 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("\t%1\n", *i));
1512         }
1513         DEBUG_TRACE (DEBUG::OrderKeys, "-------\n");
1514
1515         for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1516                 if (*i >= (int) neworder.size()) {
1517                         cerr << "Trying to move something to " << *i << " of " << neworder.size() << endl;
1518                 }
1519                 assert (*i < (int) neworder.size ());
1520         }
1521 #endif  
1522
1523         _model->reorder (neworder);
1524 }
1525
1526 void
1527 EditorRoutes::update_input_active_display ()
1528 {
1529         TreeModel::Children rows = _model->children();
1530         TreeModel::Children::iterator i;
1531
1532         for (i = rows.begin(); i != rows.end(); ++i) {
1533                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1534
1535                 if (boost::dynamic_pointer_cast<Track> (route)) {
1536                         boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1537                         
1538                         if (mt) {
1539                                 (*i)[_columns.is_input_active] = mt->input_active();
1540                         }
1541                 }
1542         }
1543 }
1544
1545 void
1546 EditorRoutes::update_rec_display ()
1547 {
1548         TreeModel::Children rows = _model->children();
1549         TreeModel::Children::iterator i;
1550
1551         for (i = rows.begin(); i != rows.end(); ++i) {
1552                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1553
1554                 if (boost::dynamic_pointer_cast<Track> (route)) {
1555                         boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1556
1557                         if (route->record_enabled()) {
1558                                 if (_session->record_status() == Session::Recording) {
1559                                         (*i)[_columns.rec_state] = 1;
1560                                 } else {
1561                                         (*i)[_columns.rec_state] = 2;
1562                                 }
1563                         } else if (mt && mt->step_editing()) {
1564                                 (*i)[_columns.rec_state] = 3;
1565                         } else {
1566                                 (*i)[_columns.rec_state] = 0;
1567                         }
1568
1569                         (*i)[_columns.name_editable] = !route->record_enabled ();
1570                 }
1571         }
1572 }
1573
1574 void
1575 EditorRoutes::update_mute_display ()
1576 {
1577         TreeModel::Children rows = _model->children();
1578         TreeModel::Children::iterator i;
1579
1580         for (i = rows.begin(); i != rows.end(); ++i) {
1581                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1582                 (*i)[_columns.mute_state] = RouteUI::mute_active_state (_session, route);
1583         }
1584 }
1585
1586 void
1587 EditorRoutes::update_solo_display (bool /* selfsoloed */)
1588 {
1589         TreeModel::Children rows = _model->children();
1590         TreeModel::Children::iterator i;
1591
1592         for (i = rows.begin(); i != rows.end(); ++i) {
1593                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1594                 (*i)[_columns.solo_state] = RouteUI::solo_active_state (route);
1595         }
1596 }
1597
1598 void
1599 EditorRoutes::update_solo_isolate_display ()
1600 {
1601         TreeModel::Children rows = _model->children();
1602         TreeModel::Children::iterator i;
1603
1604         for (i = rows.begin(); i != rows.end(); ++i) {
1605                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1606                 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_active_state (route) ? 1 : 0;
1607         }
1608 }
1609
1610 void
1611 EditorRoutes::update_solo_safe_display ()
1612 {
1613         TreeModel::Children rows = _model->children();
1614         TreeModel::Children::iterator i;
1615
1616         for (i = rows.begin(); i != rows.end(); ++i) {
1617                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1618                 (*i)[_columns.solo_safe_state] = RouteUI::solo_safe_active_state (route) ? 1 : 0;
1619         }
1620 }
1621
1622 list<TimeAxisView*>
1623 EditorRoutes::views () const
1624 {
1625         list<TimeAxisView*> v;
1626         for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1627                 v.push_back ((*i)[_columns.tv]);
1628         }
1629
1630         return v;
1631 }
1632
1633 void
1634 EditorRoutes::clear ()
1635 {
1636         _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1637         _model->clear ();
1638         _display.set_model (_model);
1639 }
1640
1641 void
1642 EditorRoutes::name_edit_started (CellEditable* ce, const Glib::ustring&)
1643 {
1644         name_editable = ce;
1645
1646         /* give it a special name */
1647
1648         Gtk::Entry *e = dynamic_cast<Gtk::Entry*> (ce);
1649
1650         if (e) {
1651                 e->set_name (X_("RouteNameEditorEntry"));
1652         }
1653 }
1654
1655 void
1656 EditorRoutes::name_edit (std::string const & path, std::string const & new_text)
1657 {
1658         name_editable = 0;
1659
1660         TreeIter iter = _model->get_iter (path);
1661
1662         if (!iter) {
1663                 return;
1664         }
1665
1666         boost::shared_ptr<Route> route = (*iter)[_columns.route];
1667
1668         if (route && route->name() != new_text) {
1669                 route->set_name (new_text);
1670         }
1671 }
1672
1673 void
1674 EditorRoutes::solo_changed_so_update_mute ()
1675 {
1676         update_mute_display ();
1677 }
1678
1679 void
1680 EditorRoutes::show_tracks_with_regions_at_playhead ()
1681 {
1682         boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1683
1684         set<TimeAxisView*> show;
1685         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1686                 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1687                 if (tav) {
1688                         show.insert (tav);
1689                 }
1690         }
1691
1692         suspend_redisplay ();
1693
1694         TreeModel::Children rows = _model->children ();
1695         for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1696                 TimeAxisView* tv = (*i)[_columns.tv];
1697                 (*i)[_columns.visible] = (show.find (tv) != show.end());
1698         }
1699
1700         resume_redisplay ();
1701 }
1702