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