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