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