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