Introduce Ctrl+Shift+Click on lock solo in the mixer.
[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->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1456                 return true;
1457         }
1458
1459         bool view = solo_safe_led->active_state();
1460         bool model = _route->solo_safe();
1461
1462         if (ev->button == 1) {
1463                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1464                         boost::shared_ptr<RouteList> rl (_session->get_routes());
1465                         if (model) {
1466                                 /* disable solo safe for all routes */
1467                                 DisplaySuspender ds;
1468                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1469                                         (*i)->set_solo_safe (false, this);
1470                                 }
1471                         } else {
1472                                 /* enable solo safe for all routes */
1473                                 DisplaySuspender ds;
1474                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1475                                         (*i)->set_solo_safe (true, this);
1476                                 }
1477                         }
1478                 }
1479                 else {
1480                         if (model == view) {
1481                                 /* flip just this route */
1482                                 _route->set_solo_safe (!view, this);
1483                         }
1484                 }
1485         }
1486
1487         return false;
1488 }
1489
1490 void
1491 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1492 {
1493         bool view = check->get_active();
1494         bool model = _route->solo_isolated();
1495
1496         /* called AFTER the view has changed */
1497
1498         if (model != view) {
1499                 _route->set_solo_isolated (view, this);
1500         }
1501 }
1502
1503 void
1504 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1505 {
1506         _route->set_solo_safe (check->get_active(), this);
1507 }
1508
1509 /** Ask the user to choose a colour, and then apply that color to my route
1510  */
1511 void
1512 RouteUI::choose_color ()
1513 {
1514         bool picked;
1515         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1516
1517         if (picked) {
1518                 set_color(color);
1519         }
1520 }
1521
1522 /** Set the route's own color.  This may not be used for display if
1523  *  the route is in a group which shares its color with its routes.
1524  */
1525 void
1526 RouteUI::set_color (const Gdk::Color & c)
1527 {
1528         /* leave _color alone in the group case so that tracks can retain their
1529          * own pre-group colors.
1530          */
1531
1532         char buf[64];
1533         _color = c;
1534         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1535         
1536         /* note: we use the route state ID here so that color is the same for both
1537            the time axis view and the mixer strip
1538         */
1539         
1540         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1541         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1542 }
1543
1544 /** @return GUI state ID for things that are common to the route in all its representations */
1545 string
1546 RouteUI::route_state_id () const
1547 {
1548         return string_compose (X_("route %1"), _route->id().to_s());
1549 }
1550
1551 int
1552 RouteUI::set_color_from_route ()
1553 {
1554         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1555
1556         if (str.empty()) {
1557                 return 1;
1558         }
1559
1560         int r, g, b;
1561
1562         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1563
1564         _color.set_red (r);
1565         _color.set_green (g);
1566         _color.set_blue (b);
1567
1568         return 0;
1569 }
1570
1571 /** @return true if this name should be used for the route, otherwise false */
1572 bool
1573 RouteUI::verify_new_route_name (const std::string& name)
1574 {
1575         if (name.find (':') == string::npos) {
1576                 return true;
1577         }
1578         
1579         MessageDialog colon_msg (
1580                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1581                 false, MESSAGE_QUESTION, BUTTONS_NONE
1582                 );
1583         
1584         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1585         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1586
1587         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1588 }
1589
1590 void
1591 RouteUI::route_rename ()
1592 {
1593         ArdourPrompter name_prompter (true);
1594         string result;
1595         bool done = false;
1596
1597         if (is_track()) {
1598                 name_prompter.set_title (_("Rename Track"));
1599         } else {
1600                 name_prompter.set_title (_("Rename Bus"));
1601         }
1602         name_prompter.set_prompt (_("New name:"));
1603         name_prompter.set_initial_text (_route->name());
1604         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1605         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1606         name_prompter.show_all ();
1607
1608         while (!done) {
1609                 switch (name_prompter.run ()) {
1610                 case Gtk::RESPONSE_ACCEPT:
1611                         name_prompter.get_result (result);
1612                         name_prompter.hide ();
1613                         if (result.length()) {
1614                                 if (verify_new_route_name (result)) {
1615                                         _route->set_name (result);
1616                                         done = true;
1617                                 } else {
1618                                         /* back to name prompter */
1619                                 }
1620
1621                         } else {
1622                                 /* nothing entered, just get out of here */
1623                                 done = true;
1624                         }
1625                         break;
1626                 default:
1627                         done = true;
1628                         break;
1629                 }
1630         }
1631
1632         return;
1633
1634 }
1635
1636 void
1637 RouteUI::property_changed (const PropertyChange& what_changed)
1638 {
1639         if (what_changed.contains (ARDOUR::Properties::name)) {
1640                 name_label.set_text (_route->name());
1641         }
1642 }
1643
1644 void
1645 RouteUI::toggle_comment_editor ()
1646 {
1647 //      if (ignore_toggle) {
1648 //              return;
1649 //      }
1650
1651         if (comment_window && comment_window->is_visible ()) {
1652                 comment_window->hide ();
1653         } else {
1654                 open_comment_editor ();
1655         }
1656 }
1657
1658
1659 void
1660 RouteUI::open_comment_editor ()
1661 {
1662         if (comment_window == 0) {
1663                 setup_comment_editor ();
1664         }
1665
1666         string title;
1667         title = _route->name();
1668         title += _(": comment editor");
1669
1670         comment_window->set_title (title);
1671         comment_window->present();
1672 }
1673
1674 void
1675 RouteUI::setup_comment_editor ()
1676 {
1677         comment_window = new ArdourWindow (""); // title will be reset to show route
1678         comment_window->set_skip_taskbar_hint (true);
1679         comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1680         comment_window->set_default_size (400, 200);
1681
1682         comment_area = manage (new TextView());
1683         comment_area->set_name ("MixerTrackCommentArea");
1684         comment_area->set_wrap_mode (WRAP_WORD);
1685         comment_area->set_editable (true);
1686         comment_area->get_buffer()->set_text (_route->comment());
1687         comment_area->show ();
1688
1689         comment_window->add (*comment_area);
1690 }
1691
1692 void
1693 RouteUI::comment_changed (void *src)
1694 {
1695         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1696
1697         if (src != this) {
1698                 ignore_comment_edit = true;
1699                 if (comment_area) {
1700                         comment_area->get_buffer()->set_text (_route->comment());
1701                 }
1702                 ignore_comment_edit = false;
1703         }
1704 }
1705
1706 void
1707 RouteUI::comment_editor_done_editing ()
1708 {
1709         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1710
1711         string const str = comment_area->get_buffer()->get_text();
1712         if (str == _route->comment ()) {
1713                 return;
1714         }
1715
1716         _route->set_comment (str, this);
1717 }
1718
1719 void
1720 RouteUI::set_route_active (bool a, bool apply_to_selection)
1721 {
1722         if (apply_to_selection) {
1723                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1724         } else {
1725                 _route->set_active (a, this);
1726         }
1727 }
1728
1729 void
1730 RouteUI::toggle_denormal_protection ()
1731 {
1732         if (denormal_menu_item) {
1733
1734                 bool x;
1735
1736                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1737
1738                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1739                         _route->set_denormal_protection (x);
1740                 }
1741         }
1742 }
1743
1744 void
1745 RouteUI::denormal_protection_changed ()
1746 {
1747         if (denormal_menu_item) {
1748                 denormal_menu_item->set_active (_route->denormal_protection());
1749         }
1750 }
1751
1752 void
1753 RouteUI::disconnect_input ()
1754 {
1755         _route->input()->disconnect (this);
1756 }
1757
1758 void
1759 RouteUI::disconnect_output ()
1760 {
1761         _route->output()->disconnect (this);
1762 }
1763
1764 bool
1765 RouteUI::is_track () const
1766 {
1767         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1768 }
1769
1770 boost::shared_ptr<Track>
1771 RouteUI::track() const
1772 {
1773         return boost::dynamic_pointer_cast<Track>(_route);
1774 }
1775
1776 bool
1777 RouteUI::is_audio_track () const
1778 {
1779         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1780 }
1781
1782 boost::shared_ptr<AudioTrack>
1783 RouteUI::audio_track() const
1784 {
1785         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1786 }
1787
1788 bool
1789 RouteUI::is_midi_track () const
1790 {
1791         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1792 }
1793
1794 boost::shared_ptr<MidiTrack>
1795 RouteUI::midi_track() const
1796 {
1797         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1798 }
1799
1800 bool
1801 RouteUI::has_audio_outputs () const
1802 {
1803         return (_route->n_outputs().n_audio() > 0);
1804 }
1805
1806 string
1807 RouteUI::name() const
1808 {
1809         return _route->name();
1810 }
1811
1812 void
1813 RouteUI::map_frozen ()
1814 {
1815         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1816
1817         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1818
1819         if (at) {
1820                 switch (at->freeze_state()) {
1821                 case AudioTrack::Frozen:
1822                         rec_enable_button->set_sensitive (false);
1823                         break;
1824                 default:
1825                         rec_enable_button->set_sensitive (true);
1826                         break;
1827                 }
1828         }
1829 }
1830
1831 void
1832 RouteUI::adjust_latency ()
1833 {
1834         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1835 }
1836
1837 void
1838 RouteUI::save_as_template ()
1839 {
1840         std::string path;
1841         std::string safe_name;
1842         string name;
1843
1844         path = ARDOUR::user_route_template_directory ();
1845
1846         if (g_mkdir_with_parents (path.c_str(), 0755)) {
1847                 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1848                 return;
1849         }
1850
1851         Prompter p (true); // modal
1852
1853         p.set_title (_("Save As Template"));
1854         p.set_prompt (_("Template name:"));
1855         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1856         switch (p.run()) {
1857         case RESPONSE_ACCEPT:
1858                 break;
1859         default:
1860                 return;
1861         }
1862
1863         p.hide ();
1864         p.get_result (name, true);
1865
1866         safe_name = legalize_for_path (name);
1867         safe_name += template_suffix;
1868
1869         path = Glib::build_filename (path, safe_name);
1870
1871         _route->save_as_template (path, name);
1872 }
1873
1874 void
1875 RouteUI::check_rec_enable_sensitivity ()
1876 {
1877         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1878                 rec_enable_button->set_sensitive (false);
1879         } else {
1880                 rec_enable_button->set_sensitive (true);
1881         }
1882
1883         update_monitoring_display ();
1884 }
1885
1886 void
1887 RouteUI::parameter_changed (string const & p)
1888 {
1889         /* this handles RC and per-session parameter changes */
1890
1891         if (p == "disable-disarm-during-roll") {
1892                 check_rec_enable_sensitivity ();
1893         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1894                 set_button_names ();
1895         } else if (p == "auto-input") {
1896                 update_monitoring_display ();
1897         } else if (p == "blink-rec-arm") {
1898                 if (UIConfiguration::instance().get_blink_rec_arm()) {
1899                         rec_blink_connection.disconnect ();
1900                         rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1901                 } else {
1902                         rec_blink_connection.disconnect ();
1903                         RouteUI::blink_rec_display(false);
1904                 }
1905         }
1906 }
1907
1908 void
1909 RouteUI::step_gain_up ()
1910 {
1911         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1912 }
1913
1914 void
1915 RouteUI::page_gain_up ()
1916 {
1917         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1918 }
1919
1920 void
1921 RouteUI::step_gain_down ()
1922 {
1923         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1924 }
1925
1926 void
1927 RouteUI::page_gain_down ()
1928 {
1929         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1930 }
1931
1932 void
1933 RouteUI::open_remote_control_id_dialog ()
1934 {
1935         ArdourDialog dialog (_("Remote Control ID"));
1936         SpinButton* spin = 0;
1937
1938         dialog.get_vbox()->set_border_width (18);
1939
1940         if (Config->get_remote_model() == UserOrdered) {
1941                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1942                 
1943                 HBox* hbox = manage (new HBox);
1944                 hbox->set_spacing (6);
1945                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1946                 spin = manage (new SpinButton);
1947                 spin->set_digits (0);
1948                 spin->set_increments (1, 10);
1949                 spin->set_range (0, limit);
1950                 spin->set_value (_route->remote_control_id());
1951                 hbox->pack_start (*spin);
1952                 dialog.get_vbox()->pack_start (*hbox);
1953                 
1954                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1955                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1956         } else {
1957                 Label* l = manage (new Label());
1958                 if (_route->is_master() || _route->is_monitor()) {
1959                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1960                                                          "The remote control ID of %3 cannot be changed."),
1961                                                        Glib::Markup::escape_text (_route->name()),
1962                                                        _route->remote_control_id(),
1963                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1964                 } else {
1965                         l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1966                                                          "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1967                                                          "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1968                                                        (is_track() ? _("track") : _("bus")),
1969                                                        _route->remote_control_id(),
1970                                                        "<span size=\"small\" style=\"italic\">",
1971                                                        "</span>",
1972                                                        Glib::Markup::escape_text (_route->name()),
1973                                                        PROGRAM_NAME));
1974                 }
1975                 dialog.get_vbox()->pack_start (*l);
1976                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1977         }
1978
1979         dialog.show_all ();
1980         int const r = dialog.run ();
1981
1982         if (r == RESPONSE_ACCEPT && spin) {
1983                 _route->set_remote_control_id (spin->get_value_as_int ());
1984         }
1985 }
1986
1987 void
1988 RouteUI::setup_invert_buttons ()
1989 {
1990         /* remove old invert buttons */
1991         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1992                 _invert_button_box.remove (**i);
1993         }
1994
1995         _invert_buttons.clear ();
1996
1997         if (!_route || !_route->input()) {
1998                 return;
1999         }
2000
2001         uint32_t const N = _route->input()->n_ports().n_audio ();
2002
2003         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2004
2005         for (uint32_t i = 0; i < to_add; ++i) {
2006                 ArdourButton* b = manage (new ArdourButton);
2007                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2008                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2009
2010                 b->set_name (X_("invert button"));
2011                 if (to_add == 1) {
2012                         if (N > 1) {
2013                                 b->set_text (string_compose (X_("Ø (%1)"), N));
2014                         } else {
2015                                 b->set_text (X_("Ø"));
2016                         }
2017                 } else {
2018                         b->set_text (string_compose (X_("Ø%1"), i + 1));
2019                 }
2020
2021                 if (N <= _max_invert_buttons) {
2022                         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));
2023                 } else {
2024                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2025                 }
2026
2027                 _invert_buttons.push_back (b);
2028                 _invert_button_box.pack_start (*b);
2029         }
2030
2031         _invert_button_box.set_spacing (1);
2032         _invert_button_box.show_all ();
2033 }
2034
2035 void
2036 RouteUI::set_invert_button_state ()
2037 {
2038         uint32_t const N = _route->input()->n_ports().n_audio();
2039         if (N > _max_invert_buttons) {
2040
2041                 /* One button for many channels; explicit active if all channels are inverted,
2042                    implicit active if some are, off if none are.
2043                 */
2044
2045                 ArdourButton* b = _invert_buttons.front ();
2046                 
2047                 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2048                         b->set_active_state (Gtkmm2ext::ExplicitActive);
2049                 } else if (_route->phase_invert().any()) {
2050                         b->set_active_state (Gtkmm2ext::ImplicitActive);
2051                 } else {
2052                         b->set_active_state (Gtkmm2ext::Off);
2053                 }
2054
2055         } else {
2056
2057                 /* One button per channel; just set active */
2058
2059                 int j = 0;
2060                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2061                         (*i)->set_active (_route->phase_invert (j));
2062                 }
2063                 
2064         }
2065 }
2066
2067 bool
2068 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2069 {
2070         if (ev->button == 1 && i < _invert_buttons.size()) {
2071                 uint32_t const N = _route->input()->n_ports().n_audio ();
2072                 if (N <= _max_invert_buttons) {
2073                         /* left-click inverts phase so long as we have a button per channel */
2074                         _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2075                         return false;
2076                 }
2077         }
2078         return false;
2079 }
2080
2081
2082 bool
2083 RouteUI::invert_press (GdkEventButton* ev)
2084 {
2085         using namespace Menu_Helpers;
2086
2087         uint32_t const N = _route->input()->n_ports().n_audio();
2088         if (N <= _max_invert_buttons && ev->button != 3) {
2089                 /* If we have an invert button per channel, we only pop
2090                    up a menu on right-click; left click is handled
2091                    on release.
2092                 */
2093                 return false;
2094         }
2095         
2096         delete _invert_menu;
2097         _invert_menu = new Menu;
2098         _invert_menu->set_name ("ArdourContextMenu");
2099         MenuList& items = _invert_menu->items ();
2100
2101         for (uint32_t i = 0; i < N; ++i) {
2102                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2103                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2104                 ++_i_am_the_modifier;
2105                 e->set_active (_route->phase_invert (i));
2106                 --_i_am_the_modifier;
2107         }
2108
2109         _invert_menu->popup (0, ev->time);
2110
2111         return true;
2112 }
2113
2114 void
2115 RouteUI::invert_menu_toggled (uint32_t c)
2116 {
2117         if (_i_am_the_modifier) {
2118                 return;
2119         }
2120
2121         _route->set_phase_invert (c, !_route->phase_invert (c));
2122 }
2123
2124 void
2125 RouteUI::set_invert_sensitive (bool yn)
2126 {
2127         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2128                 (*b)->set_sensitive (yn);
2129         }
2130 }
2131
2132 void
2133 RouteUI::request_redraw ()
2134 {
2135         if (_route) {
2136                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2137         }
2138 }
2139
2140 /** The Route's gui_changed signal has been emitted */
2141 void
2142 RouteUI::route_gui_changed (string what_changed)
2143 {
2144         if (what_changed == "color") {
2145                 if (set_color_from_route () == 0) {
2146                         route_color_changed ();
2147                 }
2148         }
2149 }
2150
2151 void
2152 RouteUI::track_mode_changed (void)
2153 {
2154         assert(is_track());
2155         switch (track()->mode()) {
2156                 case ARDOUR::NonLayered:
2157                 case ARDOUR::Normal:
2158                         rec_enable_button->set_icon (ArdourIcon::RecButton);
2159                         break;
2160                 case ARDOUR::Destructive:
2161                         rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2162                         break;
2163         }
2164         rec_enable_button->queue_draw();
2165 }
2166
2167 /** @return the color that this route should use; it maybe its own,
2168     or it maybe that of its route group.
2169 */
2170 Gdk::Color
2171 RouteUI::color () const
2172 {
2173         RouteGroup* g = _route->route_group ();
2174         
2175         if (g && g->is_color()) {
2176                 Gdk::Color c;
2177                 set_color_from_rgba (c, GroupTabs::group_color (g));
2178                 return c;
2179         }
2180
2181         return _color;
2182 }
2183
2184 void
2185 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2186 {
2187         _showing_sends_to = send_to;
2188         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2189 }
2190
2191 void
2192 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2193 {
2194         if (_route == send_to) {
2195                 show_sends_button->set_active (true);
2196                 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2197         } else {
2198                 show_sends_button->set_active (false);
2199                 send_blink_connection.disconnect ();
2200         }
2201 }
2202
2203 RouteGroup*
2204 RouteUI::route_group() const
2205 {
2206         return _route->route_group();
2207 }