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