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