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