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