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