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