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