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