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