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