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