Merge branch 'uk-english'
[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_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::VectorIcon));
152         rec_enable_button->set_icon (ArdourButton::RecButton);
153         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
154
155         if (ARDOUR_UI::config()->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 (!ARDOUR_UI::config()->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->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1206                         /* master is NEVER muted by others */
1207                         return Gtkmm2ext::ImplicitActive;
1208                 } else {
1209                         /* no mute at all */
1210                         return Gtkmm2ext::Off;
1211                 }
1212
1213         } else {
1214
1215                 if (r->muted()) {
1216                         /* full mute */
1217                         return Gtkmm2ext::ExplicitActive;
1218                 } else {
1219                         /* no mute at all */
1220                         return Gtkmm2ext::Off;
1221                 }
1222         }
1223
1224         return ActiveState(0);
1225 }
1226
1227 void
1228 RouteUI::update_mute_display ()
1229 {
1230         if (!_route) {
1231                 return;
1232         }
1233
1234         mute_button->set_active_state (mute_active_state (_session, _route));
1235 }
1236
1237 void
1238 RouteUI::route_rec_enable_changed ()
1239 {
1240         blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
1241         update_monitoring_display ();
1242 }
1243
1244 void
1245 RouteUI::session_rec_enable_changed ()
1246 {
1247         blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
1248         update_monitoring_display ();
1249 }
1250
1251 void
1252 RouteUI::blink_rec_display (bool blinkOn)
1253 {
1254         if (!rec_enable_button || !_route) {
1255                 return;
1256         }
1257         if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1258                 return;
1259         }
1260
1261         if (_route->record_enabled()) {
1262                 switch (_session->record_status ()) {
1263                 case Session::Recording:
1264                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1265                         break;
1266
1267                 case Session::Disabled:
1268                 case Session::Enabled:
1269                         if ( ARDOUR_UI::config()->get_blink_rec_arm() )
1270                                                         rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1271                                                 else
1272                                                         rec_enable_button->set_active_state ( ImplicitActive );
1273                         break;
1274
1275                 }
1276
1277                 if (step_edit_item) {
1278                         step_edit_item->set_sensitive (false);
1279                 }
1280
1281         } else {
1282                 rec_enable_button->unset_active_state ();
1283
1284                 if (step_edit_item) {
1285                         step_edit_item->set_sensitive (true);
1286                 }
1287         }
1288
1289
1290         check_rec_enable_sensitivity ();
1291 }
1292
1293 void
1294 RouteUI::build_solo_menu (void)
1295 {
1296         using namespace Menu_Helpers;
1297
1298         solo_menu = new Menu;
1299         solo_menu->set_name ("ArdourContextMenu");
1300         MenuList& items = solo_menu->items();
1301         Gtk::CheckMenuItem* check;
1302
1303         check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1304         check->set_active (_route->solo_isolated());
1305         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1306         items.push_back (CheckMenuElem(*check));
1307         solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1308         check->show_all();
1309
1310         check = new Gtk::CheckMenuItem(_("Solo Safe"));
1311         check->set_active (_route->solo_safe());
1312         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1313         items.push_back (CheckMenuElem(*check));
1314         solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1315         check->show_all();
1316
1317         //items.push_back (SeparatorElem());
1318         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1319
1320 }
1321
1322 void
1323 RouteUI::build_mute_menu(void)
1324 {
1325         using namespace Menu_Helpers;
1326
1327         mute_menu = new Menu;
1328         mute_menu->set_name ("ArdourContextMenu");
1329
1330         MenuList& items = mute_menu->items();
1331
1332         pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1333         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1334         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1335         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1336         pre_fader_mute_check->show_all();
1337
1338         post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1339         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1340         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1341         items.push_back (CheckMenuElem(*post_fader_mute_check));
1342         post_fader_mute_check->show_all();
1343
1344         listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1345         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1346         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1347         items.push_back (CheckMenuElem(*listen_mute_check));
1348         listen_mute_check->show_all();
1349
1350         main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1351         init_mute_menu(MuteMaster::Main, main_mute_check);
1352         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1353         items.push_back (CheckMenuElem(*main_mute_check));
1354         main_mute_check->show_all();
1355
1356         //items.push_back (SeparatorElem());
1357         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1358
1359         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1360 }
1361
1362 void
1363 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1364 {
1365         check->set_active (_route->mute_points() & mp);
1366 }
1367
1368 void
1369 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1370 {
1371         if (check->get_active()) {
1372                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1373         } else {
1374                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1375         }
1376 }
1377
1378 void
1379 RouteUI::muting_change ()
1380 {
1381         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1382
1383         bool yn;
1384         MuteMaster::MutePoint current = _route->mute_points ();
1385
1386         yn = (current & MuteMaster::PreFader);
1387
1388         if (pre_fader_mute_check->get_active() != yn) {
1389                 pre_fader_mute_check->set_active (yn);
1390         }
1391
1392         yn = (current & MuteMaster::PostFader);
1393
1394         if (post_fader_mute_check->get_active() != yn) {
1395                 post_fader_mute_check->set_active (yn);
1396         }
1397
1398         yn = (current & MuteMaster::Listen);
1399
1400         if (listen_mute_check->get_active() != yn) {
1401                 listen_mute_check->set_active (yn);
1402         }
1403
1404         yn = (current & MuteMaster::Main);
1405
1406         if (main_mute_check->get_active() != yn) {
1407                 main_mute_check->set_active (yn);
1408         }
1409 }
1410
1411 bool
1412 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1413 {
1414         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1415                 return true;
1416         }
1417
1418         bool view = solo_isolated_led->active_state();
1419         bool model = _route->solo_isolated();
1420
1421         /* called BEFORE the view has changed */
1422
1423         if (ev->button == 1) {
1424                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1425
1426                         if (model) {
1427                                 /* disable isolate for all routes */
1428                                 DisplaySuspender ds;
1429                                 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1430                         }
1431
1432                 } else {
1433                         if (model == view) {
1434
1435                                 /* flip just this route */
1436
1437                                 boost::shared_ptr<RouteList> rl (new RouteList);
1438                                 rl->push_back (_route);
1439                                 DisplaySuspender ds;
1440                                 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1441                         }
1442                 }
1443         }
1444
1445         return false;
1446 }
1447
1448 bool
1449 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1450 {
1451         if (ev->button == 1) {
1452                 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1453         }
1454         return false;
1455 }
1456
1457 void
1458 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1459 {
1460         bool view = check->get_active();
1461         bool model = _route->solo_isolated();
1462
1463         /* called AFTER the view has changed */
1464
1465         if (model != view) {
1466                 _route->set_solo_isolated (view, this);
1467         }
1468 }
1469
1470 void
1471 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1472 {
1473         _route->set_solo_safe (check->get_active(), this);
1474 }
1475
1476 /** Ask the user to choose a colour, and then apply that color to my route
1477  */
1478 void
1479 RouteUI::choose_color ()
1480 {
1481         bool picked;
1482         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1483
1484         if (picked) {
1485                 set_color(color);
1486         }
1487 }
1488
1489 /** Set the route's own color.  This may not be used for display if
1490  *  the route is in a group which shares its color with its routes.
1491  */
1492 void
1493 RouteUI::set_color (const Gdk::Color & c)
1494 {
1495         /* leave _color alone in the group case so that tracks can retain their
1496          * own pre-group colors.
1497          */
1498
1499         char buf[64];
1500         _color = c;
1501         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1502         
1503         /* note: we use the route state ID here so that color is the same for both
1504            the time axis view and the mixer strip
1505         */
1506         
1507         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1508         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1509 }
1510
1511 /** @return GUI state ID for things that are common to the route in all its representations */
1512 string
1513 RouteUI::route_state_id () const
1514 {
1515         return string_compose (X_("route %1"), _route->id().to_s());
1516 }
1517
1518 int
1519 RouteUI::set_color_from_route ()
1520 {
1521         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1522
1523         if (str.empty()) {
1524                 return 1;
1525         }
1526
1527         int r, g, b;
1528
1529         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1530
1531         _color.set_red (r);
1532         _color.set_green (g);
1533         _color.set_blue (b);
1534
1535         return 0;
1536 }
1537
1538 /** @return true if this name should be used for the route, otherwise false */
1539 bool
1540 RouteUI::verify_new_route_name (const std::string& name)
1541 {
1542         if (name.find (':') == string::npos) {
1543                 return true;
1544         }
1545         
1546         MessageDialog colon_msg (
1547                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1548                 false, MESSAGE_QUESTION, BUTTONS_NONE
1549                 );
1550         
1551         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1552         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1553
1554         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1555 }
1556
1557 void
1558 RouteUI::route_rename ()
1559 {
1560         ArdourPrompter name_prompter (true);
1561         string result;
1562         bool done = false;
1563
1564         if (is_track()) {
1565                 name_prompter.set_title (_("Rename Track"));
1566         } else {
1567                 name_prompter.set_title (_("Rename Bus"));
1568         }
1569         name_prompter.set_prompt (_("New name:"));
1570         name_prompter.set_initial_text (_route->name());
1571         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1572         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1573         name_prompter.show_all ();
1574
1575         while (!done) {
1576                 switch (name_prompter.run ()) {
1577                 case Gtk::RESPONSE_ACCEPT:
1578                         name_prompter.get_result (result);
1579                         name_prompter.hide ();
1580                         if (result.length()) {
1581                                 if (verify_new_route_name (result)) {
1582                                         _route->set_name (result);
1583                                         done = true;
1584                                 } else {
1585                                         /* back to name prompter */
1586                                 }
1587
1588                         } else {
1589                                 /* nothing entered, just get out of here */
1590                                 done = true;
1591                         }
1592                         break;
1593                 default:
1594                         done = true;
1595                         break;
1596                 }
1597         }
1598
1599         return;
1600
1601 }
1602
1603 void
1604 RouteUI::property_changed (const PropertyChange& what_changed)
1605 {
1606         if (what_changed.contains (ARDOUR::Properties::name)) {
1607                 name_label.set_text (_route->name());
1608         }
1609 }
1610
1611 void
1612 RouteUI::toggle_comment_editor ()
1613 {
1614 //      if (ignore_toggle) {
1615 //              return;
1616 //      }
1617
1618         if (comment_window && comment_window->is_visible ()) {
1619                 comment_window->hide ();
1620         } else {
1621                 open_comment_editor ();
1622         }
1623 }
1624
1625
1626 void
1627 RouteUI::open_comment_editor ()
1628 {
1629         if (comment_window == 0) {
1630                 setup_comment_editor ();
1631         }
1632
1633         string title;
1634         title = _route->name();
1635         title += _(": comment editor");
1636
1637         comment_window->set_title (title);
1638         comment_window->present();
1639 }
1640
1641 void
1642 RouteUI::setup_comment_editor ()
1643 {
1644         comment_window = new ArdourWindow (""); // title will be reset to show route
1645         comment_window->set_skip_taskbar_hint (true);
1646         comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1647         comment_window->set_default_size (400, 200);
1648
1649         comment_area = manage (new TextView());
1650         comment_area->set_name ("MixerTrackCommentArea");
1651         comment_area->set_wrap_mode (WRAP_WORD);
1652         comment_area->set_editable (true);
1653         comment_area->get_buffer()->set_text (_route->comment());
1654         comment_area->show ();
1655
1656         comment_window->add (*comment_area);
1657 }
1658
1659 void
1660 RouteUI::comment_changed (void *src)
1661 {
1662         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1663
1664         if (src != this) {
1665                 ignore_comment_edit = true;
1666                 if (comment_area) {
1667                         comment_area->get_buffer()->set_text (_route->comment());
1668                 }
1669                 ignore_comment_edit = false;
1670         }
1671 }
1672
1673 void
1674 RouteUI::comment_editor_done_editing ()
1675 {
1676         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1677
1678         string const str = comment_area->get_buffer()->get_text();
1679         if (str == _route->comment ()) {
1680                 return;
1681         }
1682
1683         _route->set_comment (str, this);
1684 }
1685
1686 void
1687 RouteUI::set_route_active (bool a, bool apply_to_selection)
1688 {
1689         if (apply_to_selection) {
1690                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1691         } else {
1692                 _route->set_active (a, this);
1693         }
1694 }
1695
1696 void
1697 RouteUI::toggle_denormal_protection ()
1698 {
1699         if (denormal_menu_item) {
1700
1701                 bool x;
1702
1703                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1704
1705                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1706                         _route->set_denormal_protection (x);
1707                 }
1708         }
1709 }
1710
1711 void
1712 RouteUI::denormal_protection_changed ()
1713 {
1714         if (denormal_menu_item) {
1715                 denormal_menu_item->set_active (_route->denormal_protection());
1716         }
1717 }
1718
1719 void
1720 RouteUI::disconnect_input ()
1721 {
1722         _route->input()->disconnect (this);
1723 }
1724
1725 void
1726 RouteUI::disconnect_output ()
1727 {
1728         _route->output()->disconnect (this);
1729 }
1730
1731 bool
1732 RouteUI::is_track () const
1733 {
1734         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1735 }
1736
1737 boost::shared_ptr<Track>
1738 RouteUI::track() const
1739 {
1740         return boost::dynamic_pointer_cast<Track>(_route);
1741 }
1742
1743 bool
1744 RouteUI::is_audio_track () const
1745 {
1746         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1747 }
1748
1749 boost::shared_ptr<AudioTrack>
1750 RouteUI::audio_track() const
1751 {
1752         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1753 }
1754
1755 bool
1756 RouteUI::is_midi_track () const
1757 {
1758         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1759 }
1760
1761 boost::shared_ptr<MidiTrack>
1762 RouteUI::midi_track() const
1763 {
1764         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1765 }
1766
1767 bool
1768 RouteUI::has_audio_outputs () const
1769 {
1770         return (_route->n_outputs().n_audio() > 0);
1771 }
1772
1773 string
1774 RouteUI::name() const
1775 {
1776         return _route->name();
1777 }
1778
1779 void
1780 RouteUI::map_frozen ()
1781 {
1782         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1783
1784         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1785
1786         if (at) {
1787                 switch (at->freeze_state()) {
1788                 case AudioTrack::Frozen:
1789                         rec_enable_button->set_sensitive (false);
1790                         break;
1791                 default:
1792                         rec_enable_button->set_sensitive (true);
1793                         break;
1794                 }
1795         }
1796 }
1797
1798 void
1799 RouteUI::adjust_latency ()
1800 {
1801         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1802 }
1803
1804 void
1805 RouteUI::save_as_template ()
1806 {
1807         std::string path;
1808         std::string safe_name;
1809         string name;
1810
1811         path = ARDOUR::user_route_template_directory ();
1812
1813         if (g_mkdir_with_parents (path.c_str(), 0755)) {
1814                 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1815                 return;
1816         }
1817
1818         Prompter p (true); // modal
1819
1820         p.set_title (_("Save As Template"));
1821         p.set_prompt (_("Template name:"));
1822         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1823         switch (p.run()) {
1824         case RESPONSE_ACCEPT:
1825                 break;
1826         default:
1827                 return;
1828         }
1829
1830         p.hide ();
1831         p.get_result (name, true);
1832
1833         safe_name = legalize_for_path (name);
1834         safe_name += template_suffix;
1835
1836         path = Glib::build_filename (path, safe_name);
1837
1838         _route->save_as_template (path, name);
1839 }
1840
1841 void
1842 RouteUI::check_rec_enable_sensitivity ()
1843 {
1844         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1845                 rec_enable_button->set_sensitive (false);
1846         } else {
1847                 rec_enable_button->set_sensitive (true);
1848         }
1849
1850         update_monitoring_display ();
1851 }
1852
1853 void
1854 RouteUI::parameter_changed (string const & p)
1855 {
1856         /* this handles RC and per-session parameter changes */
1857
1858         if (p == "disable-disarm-during-roll") {
1859                 check_rec_enable_sensitivity ();
1860         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1861                 set_button_names ();
1862         } else if (p == "auto-input") {
1863                 update_monitoring_display ();
1864         } else if (p == "blink-rec-arm") {
1865                 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
1866                         rec_blink_connection.disconnect ();
1867                         rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1868                 } else {
1869                         rec_blink_connection.disconnect ();
1870                         RouteUI::blink_rec_display(false);
1871                 }
1872         }
1873 }
1874
1875 void
1876 RouteUI::step_gain_up ()
1877 {
1878         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1879 }
1880
1881 void
1882 RouteUI::page_gain_up ()
1883 {
1884         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1885 }
1886
1887 void
1888 RouteUI::step_gain_down ()
1889 {
1890         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1891 }
1892
1893 void
1894 RouteUI::page_gain_down ()
1895 {
1896         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1897 }
1898
1899 void
1900 RouteUI::open_remote_control_id_dialog ()
1901 {
1902         ArdourDialog dialog (_("Remote Control ID"));
1903         SpinButton* spin = 0;
1904
1905         dialog.get_vbox()->set_border_width (18);
1906
1907         if (Config->get_remote_model() == UserOrdered) {
1908                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1909                 
1910                 HBox* hbox = manage (new HBox);
1911                 hbox->set_spacing (6);
1912                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1913                 spin = manage (new SpinButton);
1914                 spin->set_digits (0);
1915                 spin->set_increments (1, 10);
1916                 spin->set_range (0, limit);
1917                 spin->set_value (_route->remote_control_id());
1918                 hbox->pack_start (*spin);
1919                 dialog.get_vbox()->pack_start (*hbox);
1920                 
1921                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1922                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1923         } else {
1924                 Label* l = manage (new Label());
1925                 if (_route->is_master() || _route->is_monitor()) {
1926                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1927                                                          "The remote control ID of %3 cannot be changed."),
1928                                                        Glib::Markup::escape_text (_route->name()),
1929                                                        _route->remote_control_id(),
1930                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1931                 } else {
1932                         l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1933                                                          "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1934                                                          "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1935                                                        (is_track() ? _("track") : _("bus")),
1936                                                        _route->remote_control_id(),
1937                                                        "<span size=\"small\" style=\"italic\">",
1938                                                        "</span>",
1939                                                        Glib::Markup::escape_text (_route->name()),
1940                                                        PROGRAM_NAME));
1941                 }
1942                 dialog.get_vbox()->pack_start (*l);
1943                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1944         }
1945
1946         dialog.show_all ();
1947         int const r = dialog.run ();
1948
1949         if (r == RESPONSE_ACCEPT && spin) {
1950                 _route->set_remote_control_id (spin->get_value_as_int ());
1951         }
1952 }
1953
1954 void
1955 RouteUI::setup_invert_buttons ()
1956 {
1957         /* remove old invert buttons */
1958         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1959                 _invert_button_box.remove (**i);
1960         }
1961
1962         _invert_buttons.clear ();
1963
1964         if (!_route || !_route->input()) {
1965                 return;
1966         }
1967
1968         uint32_t const N = _route->input()->n_ports().n_audio ();
1969
1970         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1971
1972         for (uint32_t i = 0; i < to_add; ++i) {
1973                 ArdourButton* b = manage (new ArdourButton);
1974                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
1975                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
1976
1977                 b->set_name (X_("invert button"));
1978                 if (to_add == 1) {
1979                         if (N > 1) {
1980                                 b->set_text (string_compose (X_("Ø (%1)"), N));
1981                         } else {
1982                                 b->set_text (X_("Ø"));
1983                         }
1984                 } else {
1985                         b->set_text (string_compose (X_("Ø%1"), i + 1));
1986                 }
1987
1988                 if (N <= _max_invert_buttons) {
1989                         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));
1990                 } else {
1991                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1992                 }
1993
1994                 _invert_buttons.push_back (b);
1995                 _invert_button_box.pack_start (*b);
1996         }
1997
1998         _invert_button_box.set_spacing (1);
1999         _invert_button_box.show_all ();
2000 }
2001
2002 void
2003 RouteUI::set_invert_button_state ()
2004 {
2005         uint32_t const N = _route->input()->n_ports().n_audio();
2006         if (N > _max_invert_buttons) {
2007
2008                 /* One button for many channels; explicit active if all channels are inverted,
2009                    implicit active if some are, off if none are.
2010                 */
2011
2012                 ArdourButton* b = _invert_buttons.front ();
2013                 
2014                 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2015                         b->set_active_state (Gtkmm2ext::ExplicitActive);
2016                 } else if (_route->phase_invert().any()) {
2017                         b->set_active_state (Gtkmm2ext::ImplicitActive);
2018                 } else {
2019                         b->set_active_state (Gtkmm2ext::Off);
2020                 }
2021
2022         } else {
2023
2024                 /* One button per channel; just set active */
2025
2026                 int j = 0;
2027                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2028                         (*i)->set_active (_route->phase_invert (j));
2029                 }
2030                 
2031         }
2032 }
2033
2034 bool
2035 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2036 {
2037         if (ev->button == 1 && i < _invert_buttons.size()) {
2038                 uint32_t const N = _route->input()->n_ports().n_audio ();
2039                 if (N <= _max_invert_buttons) {
2040                         /* left-click inverts phase so long as we have a button per channel */
2041                         _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2042                         return false;
2043                 }
2044         }
2045         return false;
2046 }
2047
2048
2049 bool
2050 RouteUI::invert_press (GdkEventButton* ev)
2051 {
2052         using namespace Menu_Helpers;
2053
2054         uint32_t const N = _route->input()->n_ports().n_audio();
2055         if (N <= _max_invert_buttons && ev->button != 3) {
2056                 /* If we have an invert button per channel, we only pop
2057                    up a menu on right-click; left click is handled
2058                    on release.
2059                 */
2060                 return false;
2061         }
2062         
2063         delete _invert_menu;
2064         _invert_menu = new Menu;
2065         _invert_menu->set_name ("ArdourContextMenu");
2066         MenuList& items = _invert_menu->items ();
2067
2068         for (uint32_t i = 0; i < N; ++i) {
2069                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2070                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2071                 ++_i_am_the_modifier;
2072                 e->set_active (_route->phase_invert (i));
2073                 --_i_am_the_modifier;
2074         }
2075
2076         _invert_menu->popup (0, ev->time);
2077
2078         return true;
2079 }
2080
2081 void
2082 RouteUI::invert_menu_toggled (uint32_t c)
2083 {
2084         if (_i_am_the_modifier) {
2085                 return;
2086         }
2087
2088         _route->set_phase_invert (c, !_route->phase_invert (c));
2089 }
2090
2091 void
2092 RouteUI::set_invert_sensitive (bool yn)
2093 {
2094         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2095                 (*b)->set_sensitive (yn);
2096         }
2097 }
2098
2099 void
2100 RouteUI::request_redraw ()
2101 {
2102         if (_route) {
2103                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2104         }
2105 }
2106
2107 /** The Route's gui_changed signal has been emitted */
2108 void
2109 RouteUI::route_gui_changed (string what_changed)
2110 {
2111         if (what_changed == "color") {
2112                 if (set_color_from_route () == 0) {
2113                         route_color_changed ();
2114                 }
2115         }
2116 }
2117
2118 void
2119 RouteUI::track_mode_changed (void)
2120 {
2121         assert(is_track());
2122         switch (track()->mode()) {
2123                 case ARDOUR::NonLayered:
2124                 case ARDOUR::Normal:
2125                         rec_enable_button->set_icon (ArdourButton::RecButton);
2126                         break;
2127                 case ARDOUR::Destructive:
2128                         rec_enable_button->set_icon (ArdourButton::RecTapeMode);
2129                         break;
2130         }
2131         rec_enable_button->queue_draw();
2132 }
2133
2134 /** @return the color that this route should use; it maybe its own,
2135     or it maybe that of its route group.
2136 */
2137 Gdk::Color
2138 RouteUI::color () const
2139 {
2140         RouteGroup* g = _route->route_group ();
2141         
2142         if (g && g->is_color()) {
2143                 Gdk::Color c;
2144                 set_color_from_rgba (c, GroupTabs::group_color (g));
2145                 return c;
2146         }
2147
2148         return _color;
2149 }
2150
2151 void
2152 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2153 {
2154         _showing_sends_to = send_to;
2155         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2156 }
2157
2158 void
2159 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2160 {
2161         if (_route == send_to) {
2162                 show_sends_button->set_active (true);
2163                 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2164         } else {
2165                 show_sends_button->set_active (false);
2166                 send_blink_connection.disconnect ();
2167         }
2168 }
2169
2170 RouteGroup*
2171 RouteUI::route_group() const
2172 {
2173         return _route->route_group();
2174 }