some provisional support for "real" solo-isolate behaviour, subject to more discussio...
[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 "ardour/diskstream.h"
28 #include "ardour/session.h"
29
30 #include "editor.h"
31 #include "keyboard.h"
32 #include "ardour_ui.h"
33 #include "audio_time_axis.h"
34 #include "midi_time_axis.h"
35 #include "mixer_strip.h"
36 #include "gui_thread.h"
37 #include "actions.h"
38 #include "utils.h"
39 #include "editor_group_tabs.h"
40 #include "editor_routes.h"
41
42 #include "pbd/unknown_type.h"
43
44 #include "ardour/route.h"
45
46 #include "gtkmm2ext/cell_renderer_pixbuf_multi.h"
47 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
48
49 #include "i18n.h"
50
51 using namespace std;
52 using namespace sigc;
53 using namespace ARDOUR;
54 using namespace PBD;
55 using namespace Gtk;
56 using namespace Gtkmm2ext;
57 using namespace Glib;
58
59 EditorRoutes::EditorRoutes (Editor* e)
60         : EditorComponent (e),
61           _ignore_reorder (false),
62           _no_redisplay (false),
63           _redisplay_does_not_sync_order_keys (false),
64           _redisplay_does_not_reset_order_keys (false),
65           _menu (0)
66 {
67         _scroller.add (_display);
68         _scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
69
70         _model = ListStore::create (_columns);
71         _display.set_model (_model);
72
73         // Record enable toggle
74         CellRendererPixbufToggle* rec_col_renderer = manage (new CellRendererPixbufToggle());
75
76         rec_col_renderer->set_active_pixbuf (::get_icon("rec-enabled"));
77         rec_col_renderer->set_inactive_pixbuf (::get_icon("act-disabled"));
78         rec_col_renderer->signal_toggled().connect (mem_fun (*this, &EditorRoutes::on_tv_rec_enable_toggled));
79
80         Gtk::TreeViewColumn* rec_state_column = manage (new TreeViewColumn("R", *rec_col_renderer));
81
82         rec_state_column->add_attribute(rec_col_renderer->property_active(), _columns.rec_enabled);
83         rec_state_column->add_attribute(rec_col_renderer->property_visible(), _columns.is_track);
84
85         // Mute enable toggle
86         CellRendererPixbufMulti* mute_col_renderer = manage (new CellRendererPixbufMulti());
87
88         mute_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
89         mute_col_renderer->set_pixbuf (1, ::get_icon("mute-enabled"));
90         mute_col_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_mute_enable_toggled));
91
92         Gtk::TreeViewColumn* mute_state_column = manage (new TreeViewColumn("M", *mute_col_renderer));
93
94         mute_state_column->add_attribute(mute_col_renderer->property_state(), _columns.mute_state);
95         mute_state_column->add_attribute(mute_col_renderer->property_visible(), _columns.is_track);
96
97         // Solo enable toggle
98         CellRendererPixbufMulti* solo_col_renderer = manage (new CellRendererPixbufMulti());
99
100         solo_col_renderer->set_pixbuf (0, ::get_icon("act-disabled"));
101         solo_col_renderer->set_pixbuf (1, ::get_icon("solo-enabled"));
102         solo_col_renderer->signal_changed().connect (mem_fun (*this, &EditorRoutes::on_tv_solo_enable_toggled));
103
104         Gtk::TreeViewColumn* solo_state_column = manage (new TreeViewColumn("S", *solo_col_renderer));
105
106         solo_state_column->add_attribute(solo_col_renderer->property_state(), _columns.solo_state);
107         solo_state_column->add_attribute(solo_col_renderer->property_visible(), _columns.is_track);
108
109         
110         _display.append_column (*rec_state_column);
111         _display.append_column (*mute_state_column);
112         _display.append_column (*solo_state_column);
113         _display.append_column (_("Show"), _columns.visible);
114         _display.append_column (_("Name"), _columns.text);
115
116         _display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
117         _display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
118         _display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
119         _display.get_column (3)->set_data (X_("colnum"), GUINT_TO_POINTER(3));
120         _display.get_column (4)->set_data (X_("colnum"), GUINT_TO_POINTER(4));
121
122         _display.set_headers_visible (true);
123         _display.set_name ("TrackListDisplay");
124         _display.get_selection()->set_mode (SELECTION_SINGLE);
125         _display.set_reorderable (true);
126         _display.set_rules_hint (true);
127         _display.set_size_request (100, -1);
128         _display.add_object_drag (_columns.route.index(), "routes");
129
130         CellRendererText* name_cell = dynamic_cast<CellRendererText*> (_display.get_column_cell_renderer (4));
131         
132         assert (name_cell);
133         name_cell->property_editable() = true;
134         name_cell->signal_edited().connect (mem_fun (*this, &EditorRoutes::name_edit));
135
136         CellRendererToggle* visible_cell = dynamic_cast<CellRendererToggle*>(_display.get_column_cell_renderer (3));
137
138         visible_cell->property_activatable() = true;
139         visible_cell->property_radio() = false;
140
141         _model->signal_row_deleted().connect (mem_fun (*this, &EditorRoutes::route_deleted));
142         _model->signal_row_changed().connect (mem_fun (*this, &EditorRoutes::changed));
143         _model->signal_rows_reordered().connect (mem_fun (*this, &EditorRoutes::reordered));
144         _display.signal_button_press_event().connect (mem_fun (*this, &EditorRoutes::button_press), false);
145
146         Route::SyncOrderKeys.connect (mem_fun (*this, &EditorRoutes::sync_order_keys));
147 }
148
149 void
150 EditorRoutes::connect_to_session (Session* s)
151 {
152         EditorComponent::connect_to_session (s);
153
154         initial_display ();
155 }
156
157 void
158 EditorRoutes::on_tv_rec_enable_toggled (Glib::ustring const & path_string)
159 {
160         // Get the model row that has been toggled.
161         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
162
163         TimeAxisView *tv = row[_columns.tv];
164         AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
165
166         if (atv != 0 && atv->is_audio_track()){
167                 atv->reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !atv->track()->record_enabled(), this);
168         }
169 }
170
171 void
172 EditorRoutes::on_tv_mute_enable_toggled (Glib::ustring const & path_string)
173 {
174         // Get the model row that has been toggled.
175         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
176
177         TimeAxisView *tv = row[_columns.tv];
178         AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
179
180         if (atv != 0 && atv->is_audio_track()){
181                 atv->reversibly_apply_track_boolean ("mute-enable change", &Track::set_mute, !atv->track()->muted(), this);
182         }
183 }
184
185 void
186 EditorRoutes::on_tv_solo_enable_toggled (Glib::ustring const & path_string)
187 {
188         // Get the model row that has been toggled.
189         Gtk::TreeModel::Row row = *_model->get_iter (Gtk::TreeModel::Path (path_string));
190
191         TimeAxisView *tv = row[_columns.tv];
192         AudioTimeAxisView *atv = dynamic_cast<AudioTimeAxisView*> (tv);
193
194         if (atv != 0 && atv->is_audio_track()){
195                 atv->reversibly_apply_track_boolean ("solo-enable change", &Track::set_solo, !atv->track()->soloed(), this);
196         }
197 }
198
199 void
200 EditorRoutes::build_menu ()
201 {
202         using namespace Menu_Helpers;
203         using namespace Gtk;
204
205         _menu = new Menu;
206
207         MenuList& items = _menu->items();
208         _menu->set_name ("ArdourContextMenu");
209
210         items.push_back (MenuElem (_("Show All"), mem_fun (*this, &EditorRoutes::show_all_routes)));
211         items.push_back (MenuElem (_("Hide All"), mem_fun (*this, &EditorRoutes::hide_all_routes)));
212         items.push_back (MenuElem (_("Show All Audio Tracks"), mem_fun (*this, &EditorRoutes::show_all_audiotracks)));
213         items.push_back (MenuElem (_("Hide All Audio Tracks"), mem_fun (*this, &EditorRoutes::hide_all_audiotracks)));
214         items.push_back (MenuElem (_("Show All Audio Busses"), mem_fun (*this, &EditorRoutes::show_all_audiobus)));
215         items.push_back (MenuElem (_("Hide All Audio Busses"), mem_fun (*this, &EditorRoutes::hide_all_audiobus)));
216
217 }
218
219 void
220 EditorRoutes::show_menu ()
221 {
222         if (_menu == 0) {
223                 build_menu ();
224         }
225
226         _menu->popup (1, gtk_get_current_event_time());
227 }
228
229 void
230 EditorRoutes::redisplay ()
231 {
232         TreeModel::Children rows = _model->children();
233         TreeModel::Children::iterator i;
234         uint32_t position;
235         int n;
236
237         if (_no_redisplay) {
238                 return;
239         }
240
241         for (n = 0, position = 0, i = rows.begin(); i != rows.end(); ++i) {
242                 TimeAxisView *tv = (*i)[_columns.tv];
243                 boost::shared_ptr<Route> route = (*i)[_columns.route];
244
245                 if (tv == 0) {
246                         // just a "title" row
247                         continue;
248                 }
249
250                 if (!_redisplay_does_not_reset_order_keys) {
251                         /* this reorder is caused by user action, so reassign sort order keys
252                            to tracks.
253                         */
254                         route->set_order_key (N_ ("editor"), n);
255                 }
256
257                 bool visible = (*i)[_columns.visible];
258
259                 /* show or hide the TimeAxisView */
260                 if (visible) {
261                         tv->set_marked_for_display (true);
262                         position += tv->show_at (position, n, &_editor->edit_controls_vbox);
263                         tv->clip_to_viewport ();
264                 } else {
265                         tv->set_marked_for_display (false);
266                         tv->hide ();
267                 }
268
269                 n++;
270         }
271
272         /* whenever we go idle, update the track view list to reflect the new order.
273            we can't do this here, because we could mess up something that is traversing
274            the track order and has caused a redisplay of the list.
275         */
276         Glib::signal_idle().connect (mem_fun (*_editor, &Editor::sync_track_view_list_and_routes));
277
278         _editor->full_canvas_height = position + _editor->canvas_timebars_vsize;
279         _editor->vertical_adjustment.set_upper (_editor->full_canvas_height);
280
281         if ((_editor->vertical_adjustment.get_value() + _editor->_canvas_height) > _editor->vertical_adjustment.get_upper()) {
282                 /*
283                    We're increasing the size of the canvas while the bottom is visible.
284                    We scroll down to keep in step with the controls layout.
285                 */
286                 _editor->vertical_adjustment.set_value (_editor->full_canvas_height - _editor->_canvas_height);
287         }
288
289         if (!_redisplay_does_not_reset_order_keys && !_redisplay_does_not_sync_order_keys) {
290                 _session->sync_order_keys (N_ ("editor"));
291         }
292 }
293
294 void
295 EditorRoutes::route_deleted (Gtk::TreeModel::Path const &)
296 {
297         /* this could require an order reset & sync */
298         _session->set_remote_control_ids();
299         _ignore_reorder = true;
300         redisplay ();
301         _ignore_reorder = false;
302 }
303
304
305 void
306 EditorRoutes::changed (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &)
307 {
308         /* never reset order keys because of a property change */
309         _redisplay_does_not_reset_order_keys = true;
310         _session->set_remote_control_ids();
311         redisplay ();
312         _redisplay_does_not_reset_order_keys = false;
313 }
314
315 void
316 EditorRoutes::routes_added (list<RouteTimeAxisView*> routes)
317 {
318         TreeModel::Row row;
319
320         _redisplay_does_not_sync_order_keys = true;
321         suspend_redisplay ();
322
323         for (list<RouteTimeAxisView*>::iterator x = routes.begin(); x != routes.end(); ++x) {
324
325                 row = *(_model->append ());
326
327                 row[_columns.text] = (*x)->route()->name();
328                 row[_columns.visible] = (*x)->marked_for_display();
329                 row[_columns.tv] = *x;
330                 row[_columns.route] = (*x)->route ();
331                 row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> ((*x)->route()) != 0);
332
333                 _ignore_reorder = true;
334
335                 /* added a new fresh one at the end */
336                 if ((*x)->route()->order_key (N_ ("editor")) == -1) {
337                         (*x)->route()->set_order_key (N_ ("editor"), _model->children().size()-1);
338                 }
339
340                 _ignore_reorder = false;
341
342                 boost::weak_ptr<Route> wr ((*x)->route());
343                 (*x)->route()->gui_changed.connect (mem_fun (*this, &EditorRoutes::handle_gui_changes));
344                 (*x)->route()->NameChanged.connect (bind (mem_fun (*this, &EditorRoutes::route_name_changed), wr));
345                 (*x)->GoingAway.connect (bind (mem_fun (*this, &EditorRoutes::route_removed), *x));
346
347                 if ((*x)->is_track()) {
348                         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> ((*x)->route());
349                         t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &EditorRoutes::update_rec_display));
350                         t->mute_changed.connect (mem_fun (*this, &EditorRoutes::update_mute_display));
351                         t->solo_changed.connect (mem_fun (*this, &EditorRoutes::update_solo_display));
352                 }
353         }
354
355         resume_redisplay ();
356         _redisplay_does_not_sync_order_keys = false;
357 }
358
359 void
360 EditorRoutes::handle_gui_changes (string const & what, void *src)
361 {
362         ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRoutes::handle_gui_changes), what, src));
363
364         if (what == "track_height") {
365                 /* Optional :make tracks change height while it happens, instead
366                    of on first-idle
367                 */
368                 //update_canvas_now ();
369                 redisplay ();
370         }
371
372         if (what == "visible_tracks") {
373                 redisplay ();
374         }
375 }
376
377 void
378 EditorRoutes::route_removed (TimeAxisView *tv)
379 {
380         ENSURE_GUI_THREAD (bind (mem_fun(*this, &EditorRoutes::route_removed), tv));
381
382         TreeModel::Children rows = _model->children();
383         TreeModel::Children::iterator ri;
384
385         /* the core model has changed, there is no need to sync
386            view orders.
387         */
388
389         _redisplay_does_not_sync_order_keys = true;
390
391         for (ri = rows.begin(); ri != rows.end(); ++ri) {
392                 if ((*ri)[_columns.tv] == tv) {
393                         _model->erase (ri);
394                         break;
395                 }
396         }
397
398         _redisplay_does_not_sync_order_keys = false;
399 }
400
401 void
402 EditorRoutes::route_name_changed (boost::weak_ptr<Route> r)
403 {
404         ENSURE_GUI_THREAD (bind (mem_fun (*this, &EditorRoutes::route_name_changed), r));
405
406         boost::shared_ptr<Route> route = r.lock ();
407         if (!route) {
408                 return;
409         }
410
411         TreeModel::Children rows = _model->children();
412         TreeModel::Children::iterator i;
413
414         for (i = rows.begin(); i != rows.end(); ++i) {
415                 boost::shared_ptr<Route> t = (*i)[_columns.route];
416                 if (t == route) {
417                         (*i)[_columns.text] = route->name();
418                         break;
419                 }
420         }
421 }
422
423 void
424 EditorRoutes::update_visibility ()
425 {
426         TreeModel::Children rows = _model->children();
427         TreeModel::Children::iterator i;
428
429         suspend_redisplay ();
430
431         for (i = rows.begin(); i != rows.end(); ++i) {
432                 TimeAxisView *tv = (*i)[_columns.tv];
433                 (*i)[_columns.visible] = tv->marked_for_display ();
434                 cerr << "marked " << tv->name() << " for display = " << tv->marked_for_display() << endl;
435         }
436
437         resume_redisplay ();
438 }
439
440 void
441 EditorRoutes::hide_track_in_display (TimeAxisView& tv)
442 {
443         TreeModel::Children rows = _model->children();
444         TreeModel::Children::iterator i;
445
446         for (i = rows.begin(); i != rows.end(); ++i) {
447                 if ((*i)[_columns.tv] == &tv) {
448                         (*i)[_columns.visible] = false;
449                         break;
450                 }
451         }
452 }
453
454 void
455 EditorRoutes::show_track_in_display (TimeAxisView& tv)
456 {
457         TreeModel::Children rows = _model->children();
458         TreeModel::Children::iterator i;
459
460         for (i = rows.begin(); i != rows.end(); ++i) {
461                 if ((*i)[_columns.tv] == &tv) {
462                         (*i)[_columns.visible] = true;
463                         break;
464                 }
465         }
466 }
467
468 void
469 EditorRoutes::reordered (TreeModel::Path const &, TreeModel::iterator const &, int* /*what*/)
470 {
471         redisplay ();
472 }
473
474 /** If src != "editor", take editor order keys from each route and use them to rearrange the
475  *  route list so that the visual arrangement of routes matches the order keys from the routes.
476  */
477 void
478 EditorRoutes::sync_order_keys (string const & src)
479 {
480         vector<int> neworder;
481         TreeModel::Children rows = _model->children();
482         TreeModel::Children::iterator ri;
483
484         if (src == N_ ("editor") || !_session || (_session->state_of_the_state() & Session::Loading) || rows.empty()) {
485                 return;
486         }
487
488         for (ri = rows.begin(); ri != rows.end(); ++ri) {
489                 neworder.push_back (0);
490         }
491
492         bool changed = false;
493         int order;
494
495         for (order = 0, ri = rows.begin(); ri != rows.end(); ++ri, ++order) {
496                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
497
498                 int old_key = order;
499                 int new_key = route->order_key (N_ ("editor"));
500
501                 neworder[new_key] = old_key;
502
503                 if (new_key != old_key) {
504                         changed = true;
505                 }
506         }
507
508         if (changed) {
509                 _redisplay_does_not_reset_order_keys = true;
510                 _model->reorder (neworder);
511                 _redisplay_does_not_reset_order_keys = false;
512         }
513 }
514
515
516 void
517 EditorRoutes::hide_all_tracks (bool /*with_select*/)
518 {
519         TreeModel::Children rows = _model->children();
520         TreeModel::Children::iterator i;
521
522         suspend_redisplay ();
523
524         for (i = rows.begin(); i != rows.end(); ++i) {
525
526                 TreeModel::Row row = (*i);
527                 TimeAxisView *tv = row[_columns.tv];
528
529                 if (tv == 0) {
530                         continue;
531                 }
532
533                 row[_columns.visible] = false;
534         }
535
536         resume_redisplay ();
537
538         /* XXX this seems like a hack and half, but its not clear where to put this
539            otherwise.
540         */
541
542         //reset_scrolling_region ();
543 }
544
545 void
546 EditorRoutes::set_all_tracks_visibility (bool yn)
547 {
548         TreeModel::Children rows = _model->children();
549         TreeModel::Children::iterator i;
550
551         suspend_redisplay ();
552
553         for (i = rows.begin(); i != rows.end(); ++i) {
554
555                 TreeModel::Row row = (*i);
556                 TimeAxisView* tv = row[_columns.tv];
557
558                 if (tv == 0) {
559                         continue;
560                 }
561
562                 (*i)[_columns.visible] = yn;
563         }
564
565         resume_redisplay ();
566 }
567
568 void
569 EditorRoutes::set_all_audio_visibility (int tracks, bool yn)
570 {
571         TreeModel::Children rows = _model->children();
572         TreeModel::Children::iterator i;
573
574         suspend_redisplay ();
575
576         for (i = rows.begin(); i != rows.end(); ++i) {
577                 TreeModel::Row row = (*i);
578                 TimeAxisView* tv = row[_columns.tv];
579                 AudioTimeAxisView* atv;
580
581                 if (tv == 0) {
582                         continue;
583                 }
584
585                 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
586                         switch (tracks) {
587                         case 0:
588                                 (*i)[_columns.visible] = yn;
589                                 break;
590
591                         case 1:
592                                 if (atv->is_audio_track()) {
593                                         (*i)[_columns.visible] = yn;
594                                 }
595                                 break;
596
597                         case 2:
598                                 if (!atv->is_audio_track()) {
599                                         (*i)[_columns.visible] = yn;
600                                 }
601                                 break;
602                         }
603                 }
604         }
605
606         resume_redisplay ();
607 }
608
609 void
610 EditorRoutes::hide_all_routes ()
611 {
612         set_all_tracks_visibility (false);
613 }
614
615 void
616 EditorRoutes::show_all_routes ()
617 {
618         set_all_tracks_visibility (true);
619 }
620
621 void
622 EditorRoutes::show_all_audiobus ()
623 {
624         set_all_audio_visibility (2, true);
625 }
626 void
627 EditorRoutes::hide_all_audiobus ()
628 {
629         set_all_audio_visibility (2, false);
630 }
631
632 void
633 EditorRoutes::show_all_audiotracks()
634 {
635         set_all_audio_visibility (1, true);
636 }
637 void
638 EditorRoutes::hide_all_audiotracks ()
639 {
640         set_all_audio_visibility (1, false);
641 }
642
643 bool
644 EditorRoutes::button_press (GdkEventButton* ev)
645 {
646         if (Keyboard::is_context_menu_event (ev)) {
647                 show_menu ();
648                 return true;
649         }
650
651         TreeIter iter;
652         TreeModel::Path path;
653         TreeViewColumn* column;
654         int cellx;
655         int celly;
656
657         if (!_display.get_path_at_pos ((int)ev->x, (int)ev->y, path, column, cellx, celly)) {
658                 return false;
659         }
660
661         switch (GPOINTER_TO_UINT (column->get_data (X_("colnum")))) {
662
663         case 0:
664                 /* allow normal processing to occur */
665                 return false;
666         case 1:
667                 /* allow normal processing to occur */
668                 return false;
669         case 2:
670                 /* allow normal processing to occur */
671                 return false;           
672         case 3:
673                 if ((iter = _model->get_iter (path))) {
674                         TimeAxisView* tv = (*iter)[_columns.tv];
675                         if (tv) {
676                                 bool visible = (*iter)[_columns.visible];
677                                 (*iter)[_columns.visible] = !visible;
678                         }
679                 }
680                 return true;
681
682         case 4:
683                 /* allow normal processing to occur */
684                 return false;
685
686         default:
687                 break;
688         }
689
690         return false;
691 }
692
693 bool
694 EditorRoutes::selection_filter (Glib::RefPtr<TreeModel> const &, TreeModel::Path const &, bool)
695 {
696         return true;
697 }
698
699 struct EditorOrderRouteSorter {
700     bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
701             /* use of ">" forces the correct sort order */
702             return a->order_key (N_ ("editor")) < b->order_key (N_ ("editor"));
703     }
704 };
705
706 void
707 EditorRoutes::initial_display ()
708 {
709         boost::shared_ptr<RouteList> routes = _session->get_routes();
710         RouteList r (*routes);
711         EditorOrderRouteSorter sorter;
712
713         r.sort (sorter);
714
715         suspend_redisplay ();
716
717         _model->clear ();
718         _editor->handle_new_route (r);
719
720         /* don't show master bus in a new session */
721
722         if (ARDOUR_UI::instance()->session_is_new ()) {
723
724                 TreeModel::Children rows = _model->children();
725                 TreeModel::Children::iterator i;
726
727                 _no_redisplay = true;
728
729                 for (i = rows.begin(); i != rows.end(); ++i) {
730                         TimeAxisView *tv =  (*i)[_columns.tv];
731                         RouteTimeAxisView *rtv;
732
733                         if ((rtv = dynamic_cast<RouteTimeAxisView*>(tv)) != 0) {
734                                 if (rtv->route()->is_master()) {
735                                         _display.get_selection()->unselect (i);
736                                 }
737                         }
738                 }
739
740                 _no_redisplay = false;
741                 redisplay ();
742         }
743
744         resume_redisplay ();
745 }
746
747 void
748 EditorRoutes::track_list_reorder (Gtk::TreeModel::Path const &, Gtk::TreeModel::iterator const &, int* /*new_order*/)
749 {
750         _redisplay_does_not_sync_order_keys = true;
751         _session->set_remote_control_ids();
752         redisplay ();
753         _redisplay_does_not_sync_order_keys = false;
754 }
755
756 void
757 EditorRoutes::display_drag_data_received (const RefPtr<Gdk::DragContext>& context,
758                                              int x, int y,
759                                              const SelectionData& data,
760                                              guint info, guint time)
761 {
762         if (data.get_target() == "GTK_TREE_MODEL_ROW") {
763                 _display.on_drag_data_received (context, x, y, data, info, time);
764                 return;
765         }
766
767         context->drag_finish (true, false, time);
768 }
769
770 void
771 EditorRoutes::move_selected_tracks (bool up)
772 {
773         if (_editor->selection->tracks.empty()) {
774                 return;
775         }
776
777         typedef std::pair<TimeAxisView*,boost::shared_ptr<Route> > ViewRoute;
778         std::list<ViewRoute> view_routes;
779         std::vector<int> neworder;
780         TreeModel::Children rows = _model->children();
781         TreeModel::Children::iterator ri;
782
783         for (ri = rows.begin(); ri != rows.end(); ++ri) {
784                 TimeAxisView* tv = (*ri)[_columns.tv];
785                 boost::shared_ptr<Route> route = (*ri)[_columns.route];
786
787                 view_routes.push_back (ViewRoute (tv, route));
788         }
789
790         list<ViewRoute>::iterator trailing;
791         list<ViewRoute>::iterator leading;
792
793         if (up) {
794
795                 trailing = view_routes.begin();
796                 leading = view_routes.begin();
797
798                 ++leading;
799
800                 while (leading != view_routes.end()) {
801                         if (_editor->selection->selected (leading->first)) {
802                                 view_routes.insert (trailing, ViewRoute (leading->first, leading->second));
803                                 leading = view_routes.erase (leading);
804                         } else {
805                                 ++leading;
806                                 ++trailing;
807                         }
808                 }
809
810         } else {
811
812                 /* if we could use reverse_iterator in list::insert, this code
813                    would be a beautiful reflection of the code above. but we can't
814                    and so it looks like a bit of a mess.
815                 */
816
817                 trailing = view_routes.end();
818                 leading = view_routes.end();
819
820                 --leading; if (leading == view_routes.begin()) { return; }
821                 --leading;
822                 --trailing;
823
824                 while (1) {
825
826                         if (_editor->selection->selected (leading->first)) {
827                                 list<ViewRoute>::iterator tmp;
828
829                                 /* need to insert *after* trailing, not *before* it,
830                                    which is what insert (iter, val) normally does.
831                                 */
832
833                                 tmp = trailing;
834                                 tmp++;
835
836                                 view_routes.insert (tmp, ViewRoute (leading->first, leading->second));
837
838                                 /* can't use iter = cont.erase (iter); form here, because
839                                    we need iter to move backwards.
840                                 */
841
842                                 tmp = leading;
843                                 --tmp;
844
845                                 bool done = false;
846
847                                 if (leading == view_routes.begin()) {
848                                         /* the one we've just inserted somewhere else
849                                            was the first in the list. erase this copy,
850                                            and then break, because we're done.
851                                         */
852                                         done = true;
853                                 }
854
855                                 view_routes.erase (leading);
856
857                                 if (done) {
858                                         break;
859                                 }
860
861                                 leading = tmp;
862
863                         } else {
864                                 if (leading == view_routes.begin()) {
865                                         break;
866                                 }
867                                 --leading;
868                                 --trailing;
869                         }
870                 };
871         }
872
873         for (leading = view_routes.begin(); leading != view_routes.end(); ++leading) {
874                 neworder.push_back (leading->second->order_key (N_ ("editor")));
875         }
876
877         _model->reorder (neworder);
878
879         _session->sync_order_keys (N_ ("editor"));
880 }
881
882 void
883 EditorRoutes::update_rec_display ()
884 {
885         TreeModel::Children rows = _model->children();
886         TreeModel::Children::iterator i;
887
888         for (i = rows.begin(); i != rows.end(); ++i) {
889                 boost::shared_ptr<Route> route = (*i)[_columns.route];
890
891                 if (boost::dynamic_pointer_cast<Track>(route)) {
892
893                         if (route->record_enabled()){
894                                 (*i)[_columns.rec_enabled] = true;
895                         } else {
896                                 (*i)[_columns.rec_enabled] = false;
897                         }
898                 }
899         }
900 }
901
902 void
903 EditorRoutes::update_mute_display (void* /*src*/)
904 {
905         TreeModel::Children rows = _model->children();
906         TreeModel::Children::iterator i;
907
908         for (i = rows.begin(); i != rows.end(); ++i) {
909                 boost::shared_ptr<Route> route = (*i)[_columns.route];
910
911                 if (boost::dynamic_pointer_cast<Track>(route)) {
912
913                         if (route->muted()){
914                                 (*i)[_columns.mute_state] = 1;
915                         } else {
916                                 (*i)[_columns.mute_state] = 0;
917                         }
918                 }
919         }
920 }
921
922 void
923 EditorRoutes::update_solo_display (void* /*src*/)
924 {
925         TreeModel::Children rows = _model->children();
926         TreeModel::Children::iterator i;
927
928         for (i = rows.begin(); i != rows.end(); ++i) {
929                 boost::shared_ptr<Route> route = (*i)[_columns.route];
930
931                 if (boost::dynamic_pointer_cast<Track>(route)) {
932
933                         if (route->soloed()){
934                                 (*i)[_columns.solo_state] = 1;
935                         } else {
936                                 (*i)[_columns.solo_state] = 0;
937                         }
938                 }
939         }
940 }
941
942 list<TimeAxisView*>
943 EditorRoutes::views () const
944 {
945         list<TimeAxisView*> v;
946         for (TreeModel::Children::iterator i = _model->children().begin(); i != _model->children().end(); ++i) {
947                 v.push_back ((*i)[_columns.tv]);
948         }
949
950         return v;
951 }
952
953 void
954 EditorRoutes::clear ()
955 {
956         _display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
957         _model->clear ();
958         _display.set_model (_model);
959 }
960
961 void
962 EditorRoutes::name_edit (Glib::ustring const & path, Glib::ustring const & new_text)
963 {
964         TreeIter iter = _model->get_iter (path);
965         if (!iter) {
966                 return;
967         }
968
969         boost::shared_ptr<Route> route = (*iter)[_columns.route];
970
971         if (route) {
972                 route->set_name (new_text);
973         }
974 }