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