updated .po files, with new plural forms
[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 + _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         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                 (*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 (Config->get_solo_control_is_listen_control()) {
1210                         _session->set_listen (rl, !rl->front()->listening_via_monitor(), Session::rt_cleanup);
1211                 } else {
1212                         _session->set_solo (rl, !rl->front()->self_soloed(), Session::rt_cleanup);
1213                 }
1214                 return true;
1215                 break;
1216
1217         case 'r':
1218                 if (get_relevant_routes (rl)) {
1219                         _session->set_record_enabled (rl, !rl->front()->record_enabled(), Session::rt_cleanup);
1220                 }
1221                 break;
1222
1223         default:
1224                 break;
1225         }
1226
1227         return false;
1228 }
1229
1230 bool
1231 EditorRoutes::get_relevant_routes (boost::shared_ptr<RouteList> rl)
1232 {
1233         TimeAxisView* tv;
1234         RouteTimeAxisView* rtv;
1235         RefPtr<TreeSelection> selection = _display.get_selection();
1236         TreePath path;
1237         TreeIter iter;
1238
1239         if (selection->count_selected_rows() != 0) {
1240
1241                 /* use selection */
1242
1243                 RefPtr<TreeModel> tm = RefPtr<TreeModel>::cast_dynamic (_model);
1244                 iter = selection->get_selected (tm);
1245
1246         } else {
1247                 /* use mouse pointer */
1248
1249                 int x, y;
1250                 int bx, by;
1251
1252                 _display.get_pointer (x, y);
1253                 _display.convert_widget_to_bin_window_coords (x, y, bx, by);
1254
1255                 if (_display.get_path_at_pos (bx, by, path)) {
1256                         iter = _model->get_iter (path);
1257                 }
1258         }
1259
1260         if (iter) {
1261                 tv = (*iter)[_columns.tv];
1262                 if (tv) {
1263                         rtv = dynamic_cast<RouteTimeAxisView*>(tv);
1264                         if (rtv) {
1265                                 rl->push_back (rtv->route());
1266                         }
1267                 }
1268         }
1269
1270         return !rl->empty();
1271 }
1272
1273 bool
1274 EditorRoutes::button_press (GdkEventButton* ev)
1275 {
1276         if (Keyboard::is_context_menu_event (ev)) {
1277                 show_menu ();
1278                 return true;
1279         }
1280
1281         TreeModel::Path path;
1282         TreeViewColumn *tvc;
1283         int cell_x;
1284         int cell_y;
1285
1286         if (!_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, tvc, cell_x, cell_y)) {
1287                 /* cancel selection */
1288                 _display.get_selection()->unselect_all ();
1289                 /* end any editing by grabbing focus */
1290                 _display.grab_focus ();
1291                 return true;
1292         }
1293
1294         //Scroll editor canvas to selected track
1295         if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1296
1297                 // Get the model row.
1298                 Gtk::TreeModel::Row row = *_model->get_iter (path);
1299
1300                 TimeAxisView *tv = row[_columns.tv];
1301
1302                 int y_pos = tv->y_position();
1303
1304                 //Clamp the y pos so that we do not extend beyond the canvas full height.
1305                 if (_editor->full_canvas_height - y_pos < _editor->_canvas_height){
1306                     y_pos = _editor->full_canvas_height - _editor->_canvas_height;
1307                 }
1308
1309                 //Only scroll to if the track is visible
1310                 if(y_pos != -1){
1311                     _editor->reset_y_origin (y_pos);
1312                 }
1313         }
1314
1315         return false;
1316 }
1317
1318 bool
1319 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const&, bool /*selected*/)
1320 {
1321         if (selection_countdown) {
1322                 if (--selection_countdown == 0) {
1323                         return true;
1324                 } else {
1325                         /* no selection yet ... */
1326                         return false;
1327                 }
1328         }
1329         return true;
1330 }
1331
1332 struct EditorOrderRouteSorter {
1333     bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
1334             if (a->is_master()) {
1335                     /* master before everything else */
1336                     return true;
1337             } else if (b->is_master()) {
1338                     /* everything else before master */
1339                     return false;
1340             }
1341             return a->order_key (EditorSort) < b->order_key (EditorSort);
1342     }
1343 };
1344
1345 void
1346 EditorRoutes::initial_display ()
1347 {
1348         suspend_redisplay ();
1349         _model->clear ();
1350
1351         if (!_session) {
1352                 resume_redisplay ();
1353                 return;
1354         }
1355
1356         boost::shared_ptr<RouteList> routes = _session->get_routes();
1357
1358         if (ARDOUR_UI::instance()->session_is_new ()) {
1359
1360                 /* new session: stamp all routes with the right editor order
1361                  * key
1362                  */
1363
1364                 _editor->add_routes (*(routes.get()));
1365                 
1366         } else {
1367
1368                 /* existing session: sort a copy of the route list by
1369                  * editor-order and add its contents to the display.
1370                  */
1371
1372                 RouteList r (*routes);
1373                 EditorOrderRouteSorter sorter;
1374                 
1375                 r.sort (sorter);
1376                 _editor->add_routes (r);
1377                 
1378         }
1379
1380         resume_redisplay ();
1381 }
1382
1383 void
1384 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
1385                                              int x, int y,
1386                                              const SelectionData& data,
1387                                              guint info, guint time)
1388 {
1389         if (data.get_target() == "GTK_TREE_MODEL_ROW") {
1390                 _display.on_drag_data_received (context, x, y, data, info, time);
1391                 return;
1392         }
1393
1394         context->drag_finish (true, false, time);
1395 }
1396
1397 void
1398 EditorRoutes::move_selected_tracks (bool up)
1399 {
1400         if (_editor->selection->tracks.empty()) {
1401                 return;
1402         }
1403
1404         typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
1405         std::list<ViewRoute> view_routes;
1406         std::vector<int> neworder;
1407         TreeModel::Children rows = _model->children();
1408         TreeModel::Children::iterator ri;
1409
1410         for (ri = rows.begin(); ri != rows.end(); ++ri) {
1411                 TimeAxisView* tv = (*ri)[_columns.tv];
1412                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
1413
1414                 view_routes.push_back (ViewRoute (tv, route));
1415         }
1416
1417         list<ViewRoute>::iterator trailing;
1418         list<ViewRoute>::iterator leading;
1419
1420         if (up) {
1421
1422                 trailing = view_routes.begin();
1423                 leading = view_routes.begin();
1424
1425                 ++leading;
1426
1427                 while (leading != view_routes.end()) {
1428                         if (_editor->selection->selected (leading->first)) {
1429                                 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
1430                                 leading = view_routes.erase (leading);
1431                         } else {
1432                                 ++leading;
1433                                 ++trailing;
1434                         }
1435                 }
1436
1437         } else {
1438
1439                 /* if we could use reverse_iterator in list::insert, this code
1440                    would be a beautiful reflection of the code above. but we can't
1441                    and so it looks like a bit of a mess.
1442                 */
1443
1444                 trailing = view_routes.end();
1445                 leading = view_routes.end();
1446
1447                 --leading; if (leading == view_routes.begin()) { return; }
1448                 --leading;
1449                 --trailing;
1450
1451                 while (1) {
1452
1453                         if (_editor->selection->selected (leading->first)) {
1454                                 list<ViewRoute>::iterator tmp;
1455
1456                                 /* need to insert *after* trailing, not *before* it,
1457                                    which is what insert (iter, val) normally does.
1458                                 */
1459
1460                                 tmp = trailing;
1461                                 tmp++;
1462
1463                                 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
1464
1465                                 /* can't use iter = cont.erase (iter); form here, because
1466                                    we need iter to move backwards.
1467                                 */
1468
1469                                 tmp = leading;
1470                                 --tmp;
1471
1472                                 bool done = false;
1473
1474                                 if (leading == view_routes.begin()) {
1475                                         /* the one we've just inserted somewhere else
1476                                            was the first in the list. erase this copy,
1477                                            and then break, because we're done.
1478                                         */
1479                                         done = true;
1480                                 }
1481
1482                                 view_routes.erase (leading);
1483
1484                                 if (done) {
1485                                         break;
1486                                 }
1487
1488                                 leading = tmp;
1489
1490                         } else {
1491                                 if (leading == view_routes.begin()) {
1492                                         break;
1493                                 }
1494                                 --leading;
1495                                 --trailing;
1496                         }
1497                 };
1498         }
1499
1500         for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
1501                 uint32_t order = leading->second->order_key (EditorSort);
1502                 neworder.push_back (order);
1503         }
1504
1505 #ifndef NDEBUG
1506         DEBUG_TRACE (DEBUG::OrderKeys, "New order after moving tracks:\n");
1507         for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1508                 DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("\t%1\n", *i));
1509         }
1510         DEBUG_TRACE (DEBUG::OrderKeys, "-------\n");
1511
1512         for (vector<int>::iterator i = neworder.begin(); i != neworder.end(); ++i) {
1513                 if (*i >= (int) neworder.size()) {
1514                         cerr << "Trying to move something to " << *i << " of " << neworder.size() << endl;
1515                 }
1516                 assert (*i < (int) neworder.size ());
1517         }
1518 #endif  
1519
1520         _model->reorder (neworder);
1521 }
1522
1523 void
1524 EditorRoutes::update_input_active_display ()
1525 {
1526         TreeModel::Children rows = _model->children();
1527         TreeModel::Children::iterator i;
1528
1529         for (i = rows.begin(); i != rows.end(); ++i) {
1530                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1531
1532                 if (boost::dynamic_pointer_cast<Track> (route)) {
1533                         boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1534                         
1535                         if (mt) {
1536                                 (*i)[_columns.is_input_active] = mt->input_active();
1537                         }
1538                 }
1539         }
1540 }
1541
1542 void
1543 EditorRoutes::update_rec_display ()
1544 {
1545         TreeModel::Children rows = _model->children();
1546         TreeModel::Children::iterator i;
1547
1548         for (i = rows.begin(); i != rows.end(); ++i) {
1549                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1550
1551                 if (boost::dynamic_pointer_cast<Track> (route)) {
1552                         boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
1553
1554                         if (route->record_enabled()) {
1555                                 if (_session->record_status() == Session::Recording) {
1556                                         (*i)[_columns.rec_state] = 1;
1557                                 } else {
1558                                         (*i)[_columns.rec_state] = 2;
1559                                 }
1560                         } else if (mt && mt->step_editing()) {
1561                                 (*i)[_columns.rec_state] = 3;
1562                         } else {
1563                                 (*i)[_columns.rec_state] = 0;
1564                         }
1565
1566                         (*i)[_columns.name_editable] = !route->record_enabled ();
1567                 }
1568         }
1569 }
1570
1571 void
1572 EditorRoutes::update_mute_display ()
1573 {
1574         TreeModel::Children rows = _model->children();
1575         TreeModel::Children::iterator i;
1576
1577         for (i = rows.begin(); i != rows.end(); ++i) {
1578                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1579                 (*i)[_columns.mute_state] = RouteUI::mute_active_state (_session, route);
1580         }
1581 }
1582
1583 void
1584 EditorRoutes::update_solo_display (bool /* selfsoloed */)
1585 {
1586         TreeModel::Children rows = _model->children();
1587         TreeModel::Children::iterator i;
1588
1589         for (i = rows.begin(); i != rows.end(); ++i) {
1590                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1591                 (*i)[_columns.solo_state] = RouteUI::solo_active_state (route);
1592         }
1593 }
1594
1595 void
1596 EditorRoutes::update_solo_isolate_display ()
1597 {
1598         TreeModel::Children rows = _model->children();
1599         TreeModel::Children::iterator i;
1600
1601         for (i = rows.begin(); i != rows.end(); ++i) {
1602                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1603                 (*i)[_columns.solo_isolate_state] = RouteUI::solo_isolate_active_state (route) ? 1 : 0;
1604         }
1605 }
1606
1607 void
1608 EditorRoutes::update_solo_safe_display ()
1609 {
1610         TreeModel::Children rows = _model->children();
1611         TreeModel::Children::iterator i;
1612
1613         for (i = rows.begin(); i != rows.end(); ++i) {
1614                 boost::shared_ptr<Route> route = (*i)[_columns.route];
1615                 (*i)[_columns.solo_safe_state] = RouteUI::solo_safe_active_state (route) ? 1 : 0;
1616         }
1617 }
1618
1619 list<TimeAxisView*>
1620 EditorRoutes::views () const
1621 {
1622         list<TimeAxisView*> v;
1623         for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
1624                 v.push_back ((*i)[_columns.tv]);
1625         }
1626
1627         return v;
1628 }
1629
1630 void
1631 EditorRoutes::clear ()
1632 {
1633         _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
1634         _model->clear ();
1635         _display.set_model (_model);
1636 }
1637
1638 void
1639 EditorRoutes::name_edit_started (CellEditable* ce, const Glib::ustring&)
1640 {
1641         name_editable = ce;
1642
1643         /* give it a special name */
1644
1645         Gtk::Entry *e = dynamic_cast<Gtk::Entry*> (ce);
1646
1647         if (e) {
1648                 e->set_name (X_("RouteNameEditorEntry"));
1649         }
1650 }
1651
1652 void
1653 EditorRoutes::name_edit (std::string const & path, std::string const & new_text)
1654 {
1655         name_editable = 0;
1656
1657         TreeIter iter = _model->get_iter (path);
1658
1659         if (!iter) {
1660                 return;
1661         }
1662
1663         boost::shared_ptr<Route> route = (*iter)[_columns.route];
1664
1665         if (route && route->name() != new_text) {
1666                 route->set_name (new_text);
1667         }
1668 }
1669
1670 void
1671 EditorRoutes::solo_changed_so_update_mute ()
1672 {
1673         update_mute_display ();
1674 }
1675
1676 void
1677 EditorRoutes::show_tracks_with_regions_at_playhead ()
1678 {
1679         boost::shared_ptr<RouteList> const r = _session->get_routes_with_regions_at (_session->transport_frame ());
1680
1681         set<TimeAxisView*> show;
1682         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
1683                 TimeAxisView* tav = _editor->axis_view_from_route (*i);
1684                 if (tav) {
1685                         show.insert (tav);
1686                 }
1687         }
1688
1689         suspend_redisplay ();
1690
1691         TreeModel::Children rows = _model->children ();
1692         for (TreeModel::Children::iterator i = rows.begin(); i != rows.end(); ++i) {
1693                 TimeAxisView* tv = (*i)[_columns.tv];
1694                 (*i)[_columns.visible] = (show.find (tv) != show.end());
1695         }
1696
1697         resume_redisplay ();
1698 }
1699