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