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