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