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