provide control over precisely what aspects of an ArdourButton are rendered, and...
[ardour.git] / gtk2_ardour / route_ui.cc
1 /*
2     Copyright (C) 2002-2006 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 <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
26
27 #include "ardour/route_group.h"
28 #include "ardour/dB.h"
29 #include "pbd/memento_command.h"
30 #include "pbd/stacktrace.h"
31 #include "pbd/controllable.h"
32 #include "pbd/enumwriter.h"
33
34 #include "ardour_ui.h"
35 #include "editor.h"
36 #include "route_ui.h"
37 #include "ardour_button.h"
38 #include "keyboard.h"
39 #include "utils.h"
40 #include "prompter.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
46 #include "route_time_axis.h"
47 #include "group_tabs.h"
48
49 #include "ardour/route.h"
50 #include "ardour/event_type_map.h"
51 #include "ardour/session.h"
52 #include "ardour/audioengine.h"
53 #include "ardour/audio_track.h"
54 #include "ardour/midi_track.h"
55 #include "ardour/template_utils.h"
56 #include "ardour/filename_extensions.h"
57 #include "ardour/directory_names.h"
58 #include "ardour/profile.h"
59
60 #include "i18n.h"
61 using namespace Gtk;
62 using namespace Gtkmm2ext;
63 using namespace ARDOUR;
64 using namespace PBD;
65
66 uint32_t RouteUI::_max_invert_buttons = 3;
67
68 RouteUI::RouteUI (ARDOUR::Session* sess)
69         : AxisView(sess)
70 {
71         init ();
72 }
73
74 RouteUI::~RouteUI()
75 {
76         _route.reset (); /* drop reference to route, so that it can be cleaned up */
77         route_connections.drop_connections ();
78
79         delete solo_menu;
80         delete mute_menu;
81         delete sends_menu;
82         delete record_menu;
83         delete _invert_menu;
84         delete solo_safe_image;
85 }
86
87 void
88 RouteUI::init ()
89 {
90         self_destruct = true;
91         mute_menu = 0;
92         solo_menu = 0;
93         sends_menu = 0;
94         record_menu = 0;
95         _invert_menu = 0;
96         pre_fader_mute_check = 0;
97         post_fader_mute_check = 0;
98         listen_mute_check = 0;
99         main_mute_check = 0;
100         solo_safe_check = 0;
101         solo_isolated_check = 0;
102         solo_isolated_led = 0;
103         solo_safe_led = 0;
104         _solo_release = 0;
105         _mute_release = 0;
106         denormal_menu_item = 0;
107         step_edit_item = 0;
108         multiple_mute_change = false;
109         multiple_solo_change = false;
110         _i_am_the_modifier = 0;
111         solo_safe_image = 0;
112
113         setup_invert_buttons ();
114
115         mute_button = manage (new BindableToggleButton ());
116         // mute_button->set_self_managed (true);
117         mute_button->set_name ("MuteButton");
118         mute_button->add (mute_button_label);
119         mute_button_label.show ();
120         UI::instance()->set_tip (mute_button, _("Mute this track"), "");
121
122         solo_button = manage (new BindableToggleButton ());
123         // solo_button->set_self_managed (true);
124         solo_button->set_name ("SoloButton");
125         solo_button->add (solo_button_label);
126         solo_button_label.show ();
127         UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
128         solo_button->set_no_show_all (true);
129
130         rec_enable_button = manage (new BindableToggleButton ());
131         rec_enable_button->set_name ("RecordEnableButton");
132         // rec_enable_button->set_self_managed (true);
133         rec_enable_button->add (rec_enable_button_label);
134         rec_enable_button_label.show ();
135         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
136
137         show_sends_button = manage (new BindableToggleButton (""));
138         show_sends_button->set_name ("SendAlert");
139         // show_sends_button->set_self_managed (true);
140         UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
141
142         monitor_input_button = manage (new ArdourButton (ArdourButton::led_default_elements));
143         monitor_input_button->set_name ("monitor");
144         monitor_input_button->set_text (_("In"));
145         UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
146         monitor_input_button->set_no_show_all (true);
147
148         monitor_disk_button = manage (new ArdourButton (ArdourButton::led_default_elements));
149         monitor_disk_button->set_name ("monitor");
150         monitor_disk_button->set_text (_("Disk"));
151         UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
152         monitor_disk_button->set_no_show_all (true);
153
154         _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
155         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
156         _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
157
158         _session->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
159         Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
160
161         rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
162         rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
163
164         show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
165         show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
166
167         solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
168         solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
169         mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
170         mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
171         
172         monitor_input_button->set_distinct_led_click (false);
173         monitor_disk_button->set_distinct_led_click (false);
174
175         monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
176         monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
177
178         monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
179         monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
180 }
181
182 void
183 RouteUI::reset ()
184 {
185         route_connections.drop_connections ();
186
187         delete solo_menu;
188         solo_menu = 0;
189
190         delete mute_menu;
191         mute_menu = 0;
192
193         denormal_menu_item = 0;
194 }
195
196 void
197 RouteUI::self_delete ()
198 {
199         delete this;
200 }
201
202 void
203 RouteUI::set_route (boost::shared_ptr<Route> rp)
204 {
205         reset ();
206
207         _route = rp;
208
209         if (set_color_from_route()) {
210                 set_color (unique_random_color());
211         }
212
213         if (self_destruct) {
214                 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
215         }
216
217         mute_button->set_controllable (_route->mute_control());
218         solo_button->set_controllable (_route->solo_control());
219
220         _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
221         _route->mute_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::mute_changed, this, _1), gui_context());
222
223         _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
224         _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
225         _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
226         _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
227
228         _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
229         _route->PropertyChanged.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::property_changed, this, _1), gui_context());
230
231         _route->io_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::setup_invert_buttons, this), gui_context ());
232         _route->gui_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
233
234         if (_session->writable() && is_track()) {
235                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
236
237                 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
238                 
239                 rec_enable_button->show();
240                 rec_enable_button->set_controllable (t->rec_enable_control());
241
242                 update_rec_display ();
243
244                 if (is_midi_track()) {
245                         midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
246                                                                     ui_bind (&RouteUI::step_edit_changed, this, _1), gui_context());
247                 }
248
249         }
250
251         if (is_track()) {
252                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
253                 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
254
255                 update_monitoring_display ();
256         }
257
258         mute_button->unset_flags (Gtk::CAN_FOCUS);
259         solo_button->unset_flags (Gtk::CAN_FOCUS);
260
261         mute_button->show();
262
263         if (_route->is_monitor()) {
264                 solo_button->hide ();
265         } else {
266                 solo_button->show();
267         }
268
269         map_frozen ();
270
271         setup_invert_buttons ();
272         set_invert_button_state ();
273 }
274
275 void
276 RouteUI::polarity_changed ()
277 {
278         if (!_route) {
279                 return;
280         }
281
282         set_invert_button_state ();
283 }
284
285 bool
286 RouteUI::mute_press (GdkEventButton* ev)
287 {
288         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
289                 return true;
290         }
291
292         multiple_mute_change = false;
293
294         if (!_i_am_the_modifier) {
295
296                 if (Keyboard::is_context_menu_event (ev)) {
297
298                         if (mute_menu == 0){
299                                 build_mute_menu();
300                         }
301
302                         mute_menu->popup(0,ev->time);
303
304                 } else {
305
306                         if (Keyboard::is_button2_event (ev)) {
307                                 // Primary-button2 click is the midi binding click
308                                 // button2-click is "momentary"
309
310
311                                 if (mute_button->on_button_press_event (ev)) {
312                                         return true;
313                                 }
314
315                                 _mute_release = new SoloMuteRelease (_route->muted ());
316                         }
317
318                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
319
320                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
321
322                                         if (_mute_release) {
323                                                 _mute_release->routes = _session->get_routes ();
324                                         }
325
326                                         _session->set_mute (_session->get_routes(), !_route->muted());
327
328                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
329
330                                         /* Primary-button1 applies change to the mix group even if it is not active
331                                            NOTE: Primary-button2 is MIDI learn.
332                                         */
333
334                                         if (ev->button == 1 && _route->route_group()) {
335                                                 if (_mute_release) {
336                                                         _mute_release->routes = _session->get_routes ();
337                                                 }
338
339                                                 _session->set_mute (_session->get_routes(), !_route->muted(), Session::rt_cleanup, true);
340                                         }
341
342                                 } else {
343
344                                         /* plain click applies change to this route */
345
346                                         boost::shared_ptr<RouteList> rl (new RouteList);
347                                         rl->push_back (_route);
348
349                                         if (_mute_release) {
350                                                 _mute_release->routes = rl;
351                                         }
352
353                                         _session->set_mute (rl, !_route->muted());
354
355                                 }
356                         }
357                 }
358
359         }
360
361         return true;
362 }
363
364 bool
365 RouteUI::mute_release (GdkEventButton*)
366 {
367         if (!_i_am_the_modifier) {
368                 if (_mute_release){
369                         _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
370                         delete _mute_release;
371                         _mute_release = 0;
372                 }
373         }
374
375         return true;
376 }
377
378 bool
379 RouteUI::solo_press(GdkEventButton* ev)
380 {
381         /* ignore double/triple clicks */
382
383         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
384                 return true;
385         }
386
387         multiple_solo_change = false;
388
389         if (!_i_am_the_modifier) {
390
391                 if (Keyboard::is_context_menu_event (ev)) {
392
393                         if (!solo_isolated_led) {
394
395                                 if (solo_menu == 0) {
396                                         build_solo_menu ();
397                                 }
398
399                                 solo_menu->popup (1, ev->time);
400                         }
401
402                 } else {
403
404                         if (Keyboard::is_button2_event (ev)) {
405
406                                 // Primary-button2 click is the midi binding click
407                                 // button2-click is "momentary"
408
409                                 if (solo_button->on_button_press_event (ev)) {
410                                         return true;
411                                 }
412
413                                 _solo_release = new SoloMuteRelease (_route->self_soloed());
414                         }
415
416                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
417
418                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
419
420                                         /* Primary-Tertiary-click applies change to all routes */
421
422                                         if (_solo_release) {
423                                                 _solo_release->routes = _session->get_routes ();
424                                         }
425
426                                         if (Config->get_solo_control_is_listen_control()) {
427                                                 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
428                                         } else {
429                                                 _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, true);
430                                         }
431
432                                 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
433
434                                         // Primary-Secondary-click: exclusively solo this track
435
436                                         if (_solo_release) {
437                                                 _solo_release->exclusive = true;
438
439                                                 boost::shared_ptr<RouteList> routes = _session->get_routes();
440
441                                                 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
442                                                         if ((*i)->soloed ()) {
443                                                                 _solo_release->routes_on->push_back (*i);
444                                                         } else {
445                                                                 _solo_release->routes_off->push_back (*i);
446                                                         }
447                                                 }
448                                         }
449
450                                         if (Config->get_solo_control_is_listen_control()) {
451                                                 /* ??? we need a just_one_listen() method */
452                                         } else {
453                                                 _session->set_just_one_solo (_route, true);
454                                         }
455
456                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
457
458                                         // shift-click: toggle solo isolated status
459
460                                         _route->set_solo_isolated (!_route->solo_isolated(), this);
461                                         delete _solo_release;
462                                         _solo_release = 0;
463
464                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
465
466                                         /* Primary-button1: solo mix group.
467                                            NOTE: Primary-button2 is MIDI learn.
468                                         */
469
470                                         if (ev->button == 1 && _route->route_group()) {
471
472                                                 if (_solo_release) {
473                                                         _solo_release->routes = _route->route_group()->route_list();
474                                                 }
475
476                                                 if (Config->get_solo_control_is_listen_control()) {
477                                                         _session->set_listen (_route->route_group()->route_list(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
478                                                 } else {
479                                                         _session->set_solo (_route->route_group()->route_list(), !_route->self_soloed(),  Session::rt_cleanup, true);
480                                                 }
481                                         }
482
483                                 } else {
484
485                                         /* click: solo this route */
486
487                                         boost::shared_ptr<RouteList> rl (new RouteList);
488                                         rl->push_back (route());
489
490                                         if (_solo_release) {
491                                                 _solo_release->routes = rl;
492                                         }
493
494                                         if (Config->get_solo_control_is_listen_control()) {
495                                                 _session->set_listen (rl, !_route->listening_via_monitor());
496                                         } else {
497                                                 _session->set_solo (rl, !_route->self_soloed());
498                                         }
499                                 }
500                         }
501                 }
502         }
503
504         return true;
505 }
506
507 bool
508 RouteUI::solo_release (GdkEventButton*)
509 {
510         if (!_i_am_the_modifier) {
511
512                 if (_solo_release) {
513
514                         if (_solo_release->exclusive) {
515
516                         } else {
517                                 if (Config->get_solo_control_is_listen_control()) {
518                                         _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
519                                 } else {
520                                         _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
521                                 }
522                         }
523
524                         delete _solo_release;
525                         _solo_release = 0;
526                 }
527         }
528
529         return true;
530 }
531
532 bool
533 RouteUI::rec_enable_press(GdkEventButton* ev)
534 {
535         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
536                 return true;
537         }
538
539         if (!_session->engine().connected()) {
540                 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
541                 msg.run ();
542                 return true;
543         }
544
545         if (is_midi_track()) {
546
547                 /* cannot rec-enable while step-editing */
548
549                 if (midi_track()->step_editing()) {
550                         return true;
551                 }
552         }
553
554         if (!_i_am_the_modifier && is_track() && rec_enable_button) {
555
556                 if (Keyboard::is_button2_event (ev)) {
557
558                         // do nothing on midi sigc::bind event
559                         return rec_enable_button->on_button_press_event (ev);
560
561                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
562
563                         _session->set_record_enabled (_session->get_routes(), !rec_enable_button->get_active());
564
565                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
566
567                         /* Primary-button1 applies change to the route group (even if it is not active)
568                            NOTE: Primary-button2 is MIDI learn.
569                         */
570                         if (ev->button == 1 && _route->route_group()) {
571                                 _session->set_record_enabled (_route->route_group()->route_list(), !rec_enable_button->get_active(), Session::rt_cleanup, true);
572                         }
573
574                 } else if (Keyboard::is_context_menu_event (ev)) {
575
576                         /* do this on release */
577
578                 } else {
579
580                         boost::shared_ptr<RouteList> rl (new RouteList);
581                         rl->push_back (route());
582                         _session->set_record_enabled (rl, !rec_enable_button->get_active());
583                 }
584         }
585
586         return true;
587 }
588
589 void
590 RouteUI::monitoring_changed ()
591 {
592         update_monitoring_display ();
593 }
594
595 void
596 RouteUI::update_monitoring_display ()
597 {
598         if (!_route) {
599                 return;
600         }
601
602         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
603
604         if (!t) {
605                 return;
606         }
607
608         MonitorState ms = t->monitoring_state();
609
610         if (t->monitoring_choice() & MonitorInput) {
611                 monitor_input_button->set_active_state (CairoWidget::Active);
612         } else {
613                 if (ms & MonitoringInput) {
614                         monitor_input_button->set_active_state (CairoWidget::Mid);
615                 } else {
616                         monitor_input_button->unset_active_state ();
617                 }
618         }
619
620         if (t->monitoring_choice() & MonitorDisk) {
621                 monitor_disk_button->set_active_state (CairoWidget::Active);
622         } else {
623                 if (ms & MonitoringDisk) {
624                         monitor_disk_button->set_active_state (CairoWidget::Mid);
625                 } else {
626                         monitor_disk_button->unset_active_state ();
627                 }
628         }
629 }
630
631 bool
632 RouteUI::monitor_input_press(GdkEventButton* ev)
633 {
634         return true;
635 }
636
637 bool
638 RouteUI::monitor_input_release(GdkEventButton* ev)
639 {
640         return monitor_release (ev, MonitorInput);
641 }
642
643 bool
644 RouteUI::monitor_disk_press (GdkEventButton* ev)
645 {
646         return true;
647 }
648
649 bool
650 RouteUI::monitor_disk_release (GdkEventButton* ev)
651 {
652         return monitor_release (ev, MonitorDisk);
653 }
654
655 bool
656 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
657 {       
658         if (ev->button != 1) {
659                 return false;
660         }
661
662         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
663
664         if (!t) {
665                 return true;
666         }
667
668         MonitorChoice mc;
669         boost::shared_ptr<RouteList> rl;
670         
671         /* XXX for now, monitoring choices are orthogonal. cue monitoring 
672            will follow in 3.X but requires mixing the input and playback (disk)
673            signal together, which requires yet more buffers.
674         */
675
676         if (t->monitoring_choice() & monitor_choice) {
677                 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
678         } else {
679                 /* this line will change when the options are non-orthogonal */
680                 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
681                 mc = monitor_choice;
682         }
683
684         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {       
685                 rl = _session->get_routes ();
686
687         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
688                 if (_route->route_group() && _route->route_group()->is_monitoring()) {
689                         rl = _route->route_group()->route_list();
690                 } else {
691                         rl.reset (new RouteList);
692                         rl->push_back (route());
693                 }
694         } else {
695                 rl.reset (new RouteList);
696                 rl->push_back (route());
697         }
698
699         _session->set_monitoring (rl, mc, Session::rt_cleanup, true);           
700
701         return true;
702 }
703
704 void
705 RouteUI::build_record_menu ()
706 {
707         if (record_menu) {
708                 return;
709         }
710
711         /* no rec-button context menu for non-MIDI tracks
712          */
713
714         if (is_midi_track()) {
715                 record_menu = new Menu;
716                 record_menu->set_name ("ArdourContextMenu");
717
718                 using namespace Menu_Helpers;
719                 MenuList& items = record_menu->items();
720
721                 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
722                 step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
723
724                 if (_route->record_enabled()) {
725                         step_edit_item->set_sensitive (false);
726                 }
727
728                 step_edit_item->set_active (midi_track()->step_editing());
729         }
730 }
731
732 void
733 RouteUI::toggle_step_edit ()
734 {
735         if (!is_midi_track() || _route->record_enabled()) {
736                 return;
737         }
738
739         midi_track()->set_step_editing (step_edit_item->get_active());
740 }
741
742 void
743 RouteUI::step_edit_changed (bool yn)
744 {
745         if (yn) {
746                 if (rec_enable_button) {
747                         rec_enable_button->set_visual_state (3);
748                 }
749
750                 start_step_editing ();
751
752                 if (step_edit_item) {
753                         step_edit_item->set_active (true);
754                 }
755
756         } else {
757
758                 if (rec_enable_button) {
759                         rec_enable_button->set_visual_state (0);
760                 }
761
762                 stop_step_editing ();
763
764                 if (step_edit_item) {
765                         step_edit_item->set_active (false);
766                 }
767         }
768 }
769
770 bool
771 RouteUI::rec_enable_release (GdkEventButton* ev)
772 {
773         if (Keyboard::is_context_menu_event (ev)) {
774                 build_record_menu ();
775                 if (record_menu) {
776                         record_menu->popup (1, ev->time);
777                 }
778                 return true;
779         }
780
781         return true;
782 }
783
784 void
785 RouteUI::build_sends_menu ()
786 {
787         using namespace Menu_Helpers;
788
789         sends_menu = new Menu;
790         sends_menu->set_name ("ArdourContextMenu");
791         MenuList& items = sends_menu->items();
792
793         items.push_back (
794                 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
795                 );
796
797         items.push_back (
798                 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
799                 );
800
801         items.push_back (
802                 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
803                 );
804
805         items.push_back (
806                 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
807                 );
808
809         items.push_back (
810                 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
811                 );
812
813         items.push_back (
814                 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
815
816         items.push_back (
817                 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
818                 );
819
820         items.push_back (
821                 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
822                 );
823
824         items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
825         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
826         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
827
828 }
829
830 void
831 RouteUI::create_sends (Placement p, bool include_buses)
832 {
833         _session->globally_add_internal_sends (_route, p, include_buses);
834 }
835
836 void
837 RouteUI::create_selected_sends (Placement p, bool include_buses)
838 {
839         boost::shared_ptr<RouteList> rlist (new RouteList);
840         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
841
842         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
843                 RouteTimeAxisView* rtv;
844                 RouteUI* rui;
845                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
846                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
847                                 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
848                                         rlist->push_back (rui->route());
849                                 }
850                         }
851                 }
852         }
853
854         _session->add_internal_sends (_route, p, rlist);
855 }
856
857 void
858 RouteUI::set_sends_gain_from_track ()
859 {
860         _session->globally_set_send_gains_from_track (_route);
861 }
862
863 void
864 RouteUI::set_sends_gain_to_zero ()
865 {
866         _session->globally_set_send_gains_to_zero (_route);
867 }
868
869 void
870 RouteUI::set_sends_gain_to_unity ()
871 {
872         _session->globally_set_send_gains_to_unity (_route);
873 }
874
875 bool
876 RouteUI::show_sends_press(GdkEventButton* ev)
877 {
878         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
879                 return true;
880         }
881
882         if (!_i_am_the_modifier && !is_track() && show_sends_button) {
883
884                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
885
886                         // do nothing on midi sigc::bind event
887                         return false;
888
889                 } else if (Keyboard::is_context_menu_event (ev)) {
890
891                         if (sends_menu == 0) {
892                                 build_sends_menu ();
893                         }
894
895                         sends_menu->popup (0, ev->time);
896
897                 } else {
898
899                         /* change button state */
900
901                         show_sends_button->set_active (!show_sends_button->get_active());
902
903                         /* start blinking */
904
905                         if (show_sends_button->get_active()) {
906                                 /* show sends to this bus */
907                                 MixerStrip::SwitchIO (_route);
908                                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun(*this, &RouteUI::send_blink));
909                         } else {
910                                 /* everybody back to normal */
911                                 send_blink_connection.disconnect ();
912                                 MixerStrip::SwitchIO (boost::shared_ptr<Route>());
913                         }
914
915                 }
916         }
917
918         return true;
919 }
920
921 bool
922 RouteUI::show_sends_release (GdkEventButton*)
923 {
924         return true;
925 }
926
927 void
928 RouteUI::send_blink (bool onoff)
929 {
930         if (!show_sends_button) {
931                 return;
932         }
933
934         if (onoff) {
935                 show_sends_button->set_state (STATE_ACTIVE);
936         } else {
937                 show_sends_button->set_state (STATE_NORMAL);
938         }
939 }
940
941 int
942 RouteUI::solo_visual_state (boost::shared_ptr<Route> r)
943 {
944         if (r->is_master() || r->is_monitor()) {
945                 return 0;
946         }
947
948         if (Config->get_solo_control_is_listen_control()) {
949
950                 if (r->listening_via_monitor()) {
951                         return 1;
952                 } else {
953                         return 0;
954                 }
955
956         }
957
958         if (r->soloed()) {
959                 if (!r->self_soloed()) {
960                         return 3;
961                 } else {
962                         return 1;
963                 }
964         } else {
965                 return 0;
966         }
967 }
968
969 int
970 RouteUI::solo_visual_state_with_isolate (boost::shared_ptr<Route> r)
971 {
972         if (r->is_master() || r->is_monitor()) {
973                 return 0;
974         }
975
976         if (Config->get_solo_control_is_listen_control()) {
977
978                 if (r->listening_via_monitor()) {
979                         return 1;
980                 } else {
981                         return 0;
982                 }
983
984         }
985
986         if (r->solo_isolated()) {
987                 return 2;
988         } else if (r->soloed()) {
989                 if (!r->self_soloed()) {
990                         return 3;
991                 } else {
992                         return 1;
993                 }
994         } else {
995                 return 0;
996         }
997 }
998
999 int
1000 RouteUI::solo_isolate_visual_state (boost::shared_ptr<Route> r)
1001 {
1002         if (r->is_master() || r->is_monitor()) {
1003                 return 0;
1004         }
1005
1006         if (r->solo_isolated()) {
1007                 return 1;
1008         } else {
1009                 return 0;
1010         }
1011 }
1012
1013 int
1014 RouteUI::solo_safe_visual_state (boost::shared_ptr<Route> r)
1015 {
1016         if (r->is_master() || r->is_monitor()) {
1017                 return 0;
1018         }
1019
1020         if (r->solo_safe()) {
1021                 return 1;
1022         } else {
1023                 return 0;
1024         }
1025 }
1026
1027 void
1028 RouteUI::update_solo_display ()
1029 {
1030         bool x;
1031
1032         if (Config->get_solo_control_is_listen_control()) {
1033
1034                 if (solo_button->get_active() != (x = _route->listening_via_monitor())) {
1035                         ++_i_am_the_modifier;
1036                         solo_button->set_active(x);
1037                         --_i_am_the_modifier;
1038                 }
1039
1040         } else {
1041
1042                 if (solo_button->get_active() != (x = _route->soloed())) {
1043                         ++_i_am_the_modifier;
1044                         solo_button->set_active (x);
1045                         --_i_am_the_modifier;
1046                 }
1047
1048         }
1049
1050         bool yn = _route->solo_safe ();
1051
1052         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1053                 solo_safe_check->set_active (yn);
1054         }
1055
1056         yn = _route->solo_isolated ();
1057
1058         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1059                 solo_isolated_check->set_active (yn);
1060         }
1061
1062         set_button_names ();
1063
1064         if (solo_isolated_led) {
1065                 if (_route->solo_isolated()) {
1066                         solo_isolated_led->set_active_state (CairoWidget::Active);
1067                 } else {
1068                         solo_isolated_led->unset_active_state ();
1069                 }
1070         }
1071
1072         if (solo_safe_led) {
1073                 if (_route->solo_safe()) {
1074                         solo_safe_led->set_active_state (CairoWidget::Active);
1075                 } else {
1076                         solo_safe_led->unset_active_state ();
1077                 }
1078         }
1079
1080         solo_button->set_visual_state (solo_visual_state (_route));
1081
1082         /* some changes to solo status can affect mute display, so catch up
1083          */
1084
1085         update_mute_display ();
1086 }
1087
1088 void
1089 RouteUI::solo_changed_so_update_mute ()
1090 {
1091         update_mute_display ();
1092 }
1093
1094 void
1095 RouteUI::mute_changed(void* /*src*/)
1096 {
1097         update_mute_display ();
1098 }
1099
1100 int
1101 RouteUI::mute_visual_state (Session* s, boost::shared_ptr<Route> r)
1102 {
1103         if (r->is_master() || r->is_monitor()) {
1104                 return 0;
1105         }
1106
1107
1108         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1109
1110                 if (r->muted ()) {
1111                         /* full mute */
1112                         return 2;
1113                 } else if (s->soloing() && !r->soloed() && !r->solo_isolated()) {
1114                         return 1;
1115                 } else {
1116                         /* no mute at all */
1117                         return 0;
1118                 }
1119
1120         } else {
1121
1122                 if (r->muted()) {
1123                         /* full mute */
1124                         return 2;
1125                 } else {
1126                         /* no mute at all */
1127                         return 0;
1128                 }
1129         }
1130
1131         return 0;
1132 }
1133
1134 void
1135 RouteUI::update_mute_display ()
1136 {
1137         if (!_route) {
1138                 return;
1139         }
1140
1141         bool model = _route->muted();
1142         bool view = mute_button->get_active();
1143
1144         /* first make sure the button's "depressed" visual
1145            is correct.
1146         */
1147
1148         if (model != view) {
1149                 ++_i_am_the_modifier;
1150                 mute_button->set_active (model);
1151                 --_i_am_the_modifier;
1152         }
1153
1154         mute_button->set_visual_state (mute_visual_state (_session, _route));
1155 }
1156
1157 void
1158 RouteUI::route_rec_enable_changed ()
1159 {
1160         update_rec_display ();
1161         update_monitoring_display ();
1162 }
1163
1164 void
1165 RouteUI::session_rec_enable_changed ()
1166 {
1167         update_rec_display ();
1168         update_monitoring_display ();
1169 }
1170
1171 void
1172 RouteUI::update_rec_display ()
1173 {
1174         if (!rec_enable_button || !_route) {
1175                 return;
1176         }
1177
1178         bool model = _route->record_enabled();
1179         bool view = rec_enable_button->get_active();
1180
1181         /* first make sure the button's "depressed" visual
1182            is correct.
1183         */
1184
1185         if (model != view) {
1186                 ++_i_am_the_modifier;
1187                 rec_enable_button->set_active (model);
1188                 --_i_am_the_modifier;
1189         }
1190
1191         /* now make sure its color state is correct */
1192
1193         if (model) {
1194                 switch (_session->record_status ()) {
1195                 case Session::Recording:
1196                         rec_enable_button->set_visual_state (1);
1197                         break;
1198
1199                 case Session::Disabled:
1200                 case Session::Enabled:
1201                         rec_enable_button->set_visual_state (2);
1202                         break;
1203
1204                 }
1205
1206                 if (step_edit_item) {
1207                         step_edit_item->set_sensitive (false);
1208                 }
1209
1210         } else {
1211                 rec_enable_button->set_visual_state (0);
1212
1213                 if (step_edit_item) {
1214                         step_edit_item->set_sensitive (true);
1215                 }
1216         }
1217
1218
1219         check_rec_enable_sensitivity ();
1220 }
1221
1222 void
1223 RouteUI::build_solo_menu (void)
1224 {
1225         using namespace Menu_Helpers;
1226
1227         solo_menu = new Menu;
1228         solo_menu->set_name ("ArdourContextMenu");
1229         MenuList& items = solo_menu->items();
1230         CheckMenuItem* check;
1231
1232         check = new CheckMenuItem(_("Solo Isolate"));
1233         check->set_active (_route->solo_isolated());
1234         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1235         items.push_back (CheckMenuElem(*check));
1236         solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1237         check->show_all();
1238
1239         check = new CheckMenuItem(_("Solo Safe"));
1240         check->set_active (_route->solo_safe());
1241         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1242         items.push_back (CheckMenuElem(*check));
1243         solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1244         check->show_all();
1245
1246         //items.push_back (SeparatorElem());
1247         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1248
1249 }
1250
1251 void
1252 RouteUI::build_mute_menu(void)
1253 {
1254         using namespace Menu_Helpers;
1255
1256         mute_menu = new Menu;
1257         mute_menu->set_name ("ArdourContextMenu");
1258
1259         MenuList& items = mute_menu->items();
1260
1261         pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1262         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1263         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1264         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1265         pre_fader_mute_check->show_all();
1266
1267         post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1268         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1269         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1270         items.push_back (CheckMenuElem(*post_fader_mute_check));
1271         post_fader_mute_check->show_all();
1272
1273         listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1274         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1275         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1276         items.push_back (CheckMenuElem(*listen_mute_check));
1277         listen_mute_check->show_all();
1278
1279         main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1280         init_mute_menu(MuteMaster::Main, main_mute_check);
1281         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1282         items.push_back (CheckMenuElem(*main_mute_check));
1283         main_mute_check->show_all();
1284
1285         //items.push_back (SeparatorElem());
1286         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1287
1288         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1289 }
1290
1291 void
1292 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1293 {
1294         check->set_active (_route->mute_points() & mp);
1295 }
1296
1297 void
1298 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1299 {
1300         if (check->get_active()) {
1301                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1302         } else {
1303                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1304         }
1305 }
1306
1307 void
1308 RouteUI::muting_change ()
1309 {
1310         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1311
1312         bool yn;
1313         MuteMaster::MutePoint current = _route->mute_points ();
1314
1315         yn = (current & MuteMaster::PreFader);
1316
1317         if (pre_fader_mute_check->get_active() != yn) {
1318                 pre_fader_mute_check->set_active (yn);
1319         }
1320
1321         yn = (current & MuteMaster::PostFader);
1322
1323         if (post_fader_mute_check->get_active() != yn) {
1324                 post_fader_mute_check->set_active (yn);
1325         }
1326
1327         yn = (current & MuteMaster::Listen);
1328
1329         if (listen_mute_check->get_active() != yn) {
1330                 listen_mute_check->set_active (yn);
1331         }
1332
1333         yn = (current & MuteMaster::Main);
1334
1335         if (main_mute_check->get_active() != yn) {
1336                 main_mute_check->set_active (yn);
1337         }
1338 }
1339
1340 bool
1341 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1342 {
1343         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1344                 return true;
1345         }
1346
1347         bool view = solo_isolated_led->active_state();
1348         bool model = _route->solo_isolated();
1349
1350         /* called BEFORE the view has changed */
1351
1352         if (ev->button == 1) {
1353                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1354
1355                         if (model) {
1356                                 /* disable isolate for all routes */
1357                                 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1358                         }
1359
1360                 } else {
1361                         if (model == view) {
1362
1363                                 /* flip just this route */
1364
1365                                 boost::shared_ptr<RouteList> rl (new RouteList);
1366                                 rl->push_back (_route);
1367                                 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1368                         }
1369                 }
1370         }
1371
1372         return true;
1373 }
1374
1375 bool
1376 RouteUI::solo_safe_button_release (GdkEventButton*)
1377 {
1378         _route->set_solo_safe (!solo_safe_led->active_state(), this);
1379         return true;
1380 }
1381
1382 void
1383 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1384 {
1385         bool view = check->get_active();
1386         bool model = _route->solo_isolated();
1387
1388         /* called AFTER the view has changed */
1389
1390         if (model != view) {
1391                 _route->set_solo_isolated (view, this);
1392         }
1393 }
1394
1395 void
1396 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1397 {
1398         _route->set_solo_safe (check->get_active(), this);
1399 }
1400
1401 /** Ask the user to choose a colour, and then set all selected tracks
1402  *  to that colour.
1403  */
1404 void
1405 RouteUI::choose_color ()
1406 {
1407         bool picked;
1408         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1409
1410         if (picked) {
1411                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1412                         boost::bind (&RouteUI::set_color, _1, color)
1413                         );
1414         }
1415 }
1416
1417 /** Set the route's own color.  This may not be used for display if
1418  *  the route is in a group which shares its color with its routes.
1419  */
1420 void
1421 RouteUI::set_color (const Gdk::Color & c)
1422 {
1423         char buf[64];
1424
1425         _color = c;
1426
1427         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1428
1429         /* note: we use the route state ID here so that color is the same for both
1430            the time axis view and the mixer strip
1431         */
1432         
1433         gui_object_state().set<string> (route_state_id(), X_("color"), buf);
1434         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1435 }
1436
1437 /** @return GUI state ID for things that are common to the route in all its representations */
1438 string
1439 RouteUI::route_state_id () const
1440 {
1441         return string_compose (X_("route %1"), _route->id().to_s());
1442 }
1443
1444 int
1445 RouteUI::set_color_from_route ()
1446 {
1447         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1448
1449         if (str.empty()) {
1450                 return 1;
1451         }
1452
1453         int r, g, b;
1454
1455         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1456
1457         _color.set_red (r);
1458         _color.set_green (g);
1459         _color.set_blue (b);
1460
1461         return 0;
1462 }
1463
1464 void
1465 RouteUI::remove_this_route (bool apply_to_selection)
1466 {
1467         if (apply_to_selection) {
1468                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1469         } else {
1470                 if ((route()->is_master() || route()->is_monitor()) &&
1471                     !Config->get_allow_special_bus_removal()) {
1472                         MessageDialog msg (_("That would be bad news ...."),
1473                                            false,
1474                                            Gtk::MESSAGE_INFO,
1475                                    Gtk::BUTTONS_OK);
1476                         msg.set_secondary_text (string_compose (_(
1477 "Removing the master or monitor bus is such a bad idea\n\
1478 that %1 is not going to allow it.\n\
1479 \n\
1480 If you really want to do this sort of thing\n\
1481 edit your ardour.rc file to set the\n\
1482 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1483
1484                         msg.present ();
1485                         msg.run ();
1486                         return;
1487                 }
1488
1489                 vector<string> choices;
1490                 string prompt;
1491
1492                 if (is_track()) {
1493                         prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1494                 } else {
1495                         prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1496                 }
1497
1498                 choices.push_back (_("No, do nothing."));
1499                 choices.push_back (_("Yes, remove it."));
1500
1501                 string title;
1502                 if (is_track()) {
1503                         title = _("Remove track");
1504                 } else {
1505                         title = _("Remove bus");
1506                 }
1507
1508                 Choice prompter (title, prompt, choices);
1509
1510                 if (prompter.run () == 1) {
1511                         Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1512                 }
1513         }
1514 }
1515
1516 gint
1517 RouteUI::idle_remove_this_route (RouteUI *rui)
1518 {
1519         rui->_session->remove_route (rui->route());
1520         return false;
1521 }
1522
1523 /** @return true if this name should be used for the route, otherwise false */
1524 bool
1525 RouteUI::verify_new_route_name (const std::string& name)
1526 {
1527         if (name.find (':') == string::npos) {
1528                 return true;
1529         }
1530         
1531         MessageDialog colon_msg (
1532                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1533                 false, MESSAGE_QUESTION, BUTTONS_NONE
1534                 );
1535         
1536         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1537         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1538
1539         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1540 }
1541
1542 void
1543 RouteUI::route_rename ()
1544 {
1545         ArdourPrompter name_prompter (true);
1546         string result;
1547         bool done = false;
1548
1549         if (is_track()) {
1550                 name_prompter.set_title (_("Rename Track"));
1551         } else {
1552                 name_prompter.set_title (_("Rename Bus"));
1553         }
1554         name_prompter.set_prompt (_("New name:"));
1555         name_prompter.set_initial_text (_route->name());
1556         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1557         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1558         name_prompter.show_all ();
1559
1560         while (!done) {
1561                 switch (name_prompter.run ()) {
1562                 case Gtk::RESPONSE_ACCEPT:
1563                         name_prompter.get_result (result);
1564                         name_prompter.hide ();
1565                         if (result.length()) {
1566                                 if (verify_new_route_name (result)) {
1567                                         _route->set_name (result);
1568                                         done = true;
1569                                 } else {
1570                                         /* back to name prompter */
1571                                 }
1572
1573                         } else {
1574                                 /* nothing entered, just get out of here */
1575                                 done = true;
1576                         }
1577                         break;
1578                 }
1579         }
1580
1581         return;
1582
1583 }
1584
1585 void
1586 RouteUI::property_changed (const PropertyChange& what_changed)
1587 {
1588         if (what_changed.contains (ARDOUR::Properties::name)) {
1589                 name_label.set_text (_route->name());
1590         }
1591 }
1592
1593 void
1594 RouteUI::set_route_active (bool a, bool apply_to_selection)
1595 {
1596         if (apply_to_selection) {
1597                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1598         } else {
1599                 _route->set_active (a, this);
1600         }
1601 }
1602
1603 void
1604 RouteUI::toggle_denormal_protection ()
1605 {
1606         if (denormal_menu_item) {
1607
1608                 bool x;
1609
1610                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1611
1612                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1613                         _route->set_denormal_protection (x);
1614                 }
1615         }
1616 }
1617
1618 void
1619 RouteUI::denormal_protection_changed ()
1620 {
1621         if (denormal_menu_item) {
1622                 denormal_menu_item->set_active (_route->denormal_protection());
1623         }
1624 }
1625
1626 void
1627 RouteUI::disconnect_input ()
1628 {
1629         _route->input()->disconnect (this);
1630 }
1631
1632 void
1633 RouteUI::disconnect_output ()
1634 {
1635         _route->output()->disconnect (this);
1636 }
1637
1638 bool
1639 RouteUI::is_track () const
1640 {
1641         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1642 }
1643
1644 boost::shared_ptr<Track>
1645 RouteUI::track() const
1646 {
1647         return boost::dynamic_pointer_cast<Track>(_route);
1648 }
1649
1650 bool
1651 RouteUI::is_audio_track () const
1652 {
1653         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1654 }
1655
1656 boost::shared_ptr<AudioTrack>
1657 RouteUI::audio_track() const
1658 {
1659         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1660 }
1661
1662 bool
1663 RouteUI::is_midi_track () const
1664 {
1665         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1666 }
1667
1668 boost::shared_ptr<MidiTrack>
1669 RouteUI::midi_track() const
1670 {
1671         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1672 }
1673
1674 bool
1675 RouteUI::has_audio_outputs () const
1676 {
1677         return (_route->n_outputs().n_audio() > 0);
1678 }
1679
1680 string
1681 RouteUI::name() const
1682 {
1683         return _route->name();
1684 }
1685
1686 void
1687 RouteUI::map_frozen ()
1688 {
1689         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1690
1691         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1692
1693         if (at) {
1694                 switch (at->freeze_state()) {
1695                 case AudioTrack::Frozen:
1696                         rec_enable_button->set_sensitive (false);
1697                         break;
1698                 default:
1699                         rec_enable_button->set_sensitive (true);
1700                         break;
1701                 }
1702         }
1703 }
1704
1705 void
1706 RouteUI::adjust_latency ()
1707 {
1708         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1709 }
1710
1711 void
1712 RouteUI::save_as_template ()
1713 {
1714         sys::path path;
1715         std::string safe_name;
1716         string name;
1717
1718         path = ARDOUR::user_route_template_directory ();
1719
1720         if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1721                 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1722                 return;
1723         }
1724
1725         Prompter p (true); // modal
1726
1727         p.set_title (_("Save As Template"));
1728         p.set_prompt (_("Template name:"));
1729         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1730         switch (p.run()) {
1731         case RESPONSE_ACCEPT:
1732                 break;
1733         default:
1734                 return;
1735         }
1736
1737         p.hide ();
1738         p.get_result (name, true);
1739
1740         safe_name = legalize_for_path (name);
1741         safe_name += template_suffix;
1742
1743         path /= safe_name;
1744
1745         _route->save_as_template (path.to_string(), name);
1746 }
1747
1748 void
1749 RouteUI::check_rec_enable_sensitivity ()
1750 {
1751         if (_session->transport_rolling() && rec_enable_button->get_active() && Config->get_disable_disarm_during_roll()) {
1752                 rec_enable_button->set_sensitive (false);
1753         } else {
1754                 rec_enable_button->set_sensitive (true);
1755         }
1756
1757         update_monitoring_display ();
1758 }
1759
1760 void
1761 RouteUI::parameter_changed (string const & p)
1762 {
1763         /* this handles RC and per-session parameter changes */
1764
1765         if (p == "disable-disarm-during-roll") {
1766                 check_rec_enable_sensitivity ();
1767         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1768                 set_button_names ();
1769         } else if (p == "auto-input") {
1770                 update_monitoring_display ();
1771         }
1772 }
1773
1774 void
1775 RouteUI::step_gain_up ()
1776 {
1777         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1778 }
1779
1780 void
1781 RouteUI::page_gain_up ()
1782 {
1783         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1784 }
1785
1786 void
1787 RouteUI::step_gain_down ()
1788 {
1789         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1790 }
1791
1792 void
1793 RouteUI::page_gain_down ()
1794 {
1795         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1796 }
1797
1798 void
1799 RouteUI::open_remote_control_id_dialog ()
1800 {
1801         ArdourDialog dialog (_("Remote Control ID"));
1802
1803         uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1804
1805         HBox* hbox = manage (new HBox);
1806         hbox->set_spacing (6);
1807         hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1808         SpinButton* spin = manage (new SpinButton);
1809         spin->set_digits (0);
1810         spin->set_increments (1, 10);
1811         spin->set_range (0, limit);
1812         spin->set_value (_route->remote_control_id());
1813         hbox->pack_start (*spin);
1814         dialog.get_vbox()->pack_start (*hbox);
1815
1816         dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1817         dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1818
1819         dialog.show_all ();
1820         int const r = dialog.run ();
1821
1822         if (r == RESPONSE_ACCEPT) {
1823                 _route->set_remote_control_id (spin->get_value_as_int ());
1824         }
1825 }
1826
1827 void
1828 RouteUI::setup_invert_buttons ()
1829 {
1830         /* remove old invert buttons */
1831         for (list<BindableToggleButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1832                 _invert_button_box.remove (**i);
1833         }
1834
1835         _invert_buttons.clear ();
1836
1837         if (!_route || !_route->input()) {
1838                 return;
1839         }
1840
1841         uint32_t const N = _route->input()->n_ports().n_audio ();
1842
1843         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1844
1845         for (uint32_t i = 0; i < to_add; ++i) {
1846                 BindableToggleButton* b = manage (new BindableToggleButton);
1847                 b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_toggled), i, b));
1848                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1849
1850                 b->set_name (X_("MixerInvertButton"));
1851                 if (to_add == 1) {
1852                         b->add (*manage (new Label (X_("Ø"))));
1853                 } else {
1854                         b->add (*manage (new Label (string_compose (X_("Ø%1"), i + 1))));
1855                 }
1856
1857                 if (N <= 4) {
1858                         UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) channel %1 of this track.  Right-click to show menu."), i + 1));
1859                 } else {
1860                         UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) all channels of this track.  Right-click to show menu."), i + 1));
1861                 }
1862
1863                 _invert_buttons.push_back (b);
1864                 _invert_button_box.pack_start (*b);
1865         }
1866
1867         _invert_button_box.show_all ();
1868 }
1869
1870 void
1871 RouteUI::set_invert_button_state ()
1872 {
1873         ++_i_am_the_modifier;
1874
1875         uint32_t const N = _route->input()->n_ports().n_audio();
1876         if (N > _max_invert_buttons) {
1877                 _invert_buttons.front()->set_active (_route->phase_invert().any());
1878                 --_i_am_the_modifier;
1879                 return;
1880         }
1881
1882         int j = 0;
1883         for (list<BindableToggleButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1884                 (*i)->set_active (_route->phase_invert (j));
1885         }
1886
1887         --_i_am_the_modifier;
1888 }
1889
1890 void
1891 RouteUI::invert_toggled (uint32_t i, BindableToggleButton* b)
1892 {
1893         if (_i_am_the_modifier) {
1894                 return;
1895         }
1896
1897         uint32_t const N = _route->input()->n_ports().n_audio();
1898         if (N <= _max_invert_buttons) {
1899                 _route->set_phase_invert (i, b->get_active ());
1900         } else {
1901                 boost::dynamic_bitset<> p (N);
1902                 if (b->get_active ()) {
1903                         p.set ();
1904                 }
1905                 _route->set_phase_invert (p);
1906         }
1907 }
1908
1909 bool
1910 RouteUI::invert_press (GdkEventButton* ev)
1911 {
1912         using namespace Menu_Helpers;
1913
1914         if (ev->button != 3) {
1915                 return true;
1916         }
1917
1918         delete _invert_menu;
1919         _invert_menu = new Menu;
1920         _invert_menu->set_name ("ArdourContextMenu");
1921         MenuList& items = _invert_menu->items ();
1922
1923         uint32_t const N = _route->input()->n_ports().n_audio();
1924         for (uint32_t i = 0; i < N; ++i) {
1925                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1926                 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1927                 ++_i_am_the_modifier;
1928                 e->set_active (_route->phase_invert (i));
1929                 --_i_am_the_modifier;
1930         }
1931
1932         _invert_menu->popup (0, ev->time);
1933
1934         return false;
1935 }
1936
1937 void
1938 RouteUI::invert_menu_toggled (uint32_t c)
1939 {
1940         if (_i_am_the_modifier) {
1941                 return;
1942         }
1943
1944         _route->set_phase_invert (c, !_route->phase_invert (c));
1945 }
1946
1947 void
1948 RouteUI::set_invert_sensitive (bool yn)
1949 {
1950         for (list<BindableToggleButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1951                 (*b)->set_sensitive (yn);
1952         }
1953 }
1954
1955 void
1956 RouteUI::request_redraw ()
1957 {
1958         if (_route) {
1959                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1960         }
1961 }
1962
1963 /** The Route's gui_changed signal has been emitted */
1964 void
1965 RouteUI::route_gui_changed (string what_changed)
1966 {
1967         if (what_changed == "color") {
1968                 if (set_color_from_route () == 0) {
1969                         route_color_changed ();
1970                 }
1971         }
1972 }
1973
1974 /** @return the color that this route should use; it maybe its own,
1975     or it maybe that of its route group.
1976 */
1977 Gdk::Color
1978 RouteUI::color () const
1979 {
1980         RouteGroup* g = _route->route_group ();
1981         
1982         if (g && g->is_color()) {
1983                 return GroupTabs::group_color (g);
1984         }
1985
1986         return _color;
1987 }