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