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