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