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