remove awful, inobvious, wrong and no longer necessary "_i_am_the_modifier" crap...
[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 (Keyboard::is_context_menu_event (ev)) {
301
302                 if (mute_menu == 0){
303                         build_mute_menu();
304                 }
305
306                 mute_menu->popup(0,ev->time);
307
308         } else {
309
310                 if (Keyboard::is_button2_event (ev)) {
311                         // Primary-button2 click is the midi binding click
312                         // button2-click is "momentary"
313
314
315                         if (mute_button->on_button_press_event (ev)) {
316                                 return true;
317                         }
318
319                         _mute_release = new SoloMuteRelease (_route->muted ());
320                 }
321
322                 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
323
324                         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
325
326                                 /* toggle mute on everything (but
327                                  * exclude the master and monitor)
328                                  *
329                                  * because we are going to erase
330                                  * elements of the list we need to work
331                                  * on a copy.
332                                  */
333                                         
334                                 boost::shared_ptr<RouteList> copy (new RouteList);
335
336                                 *copy = *_session->get_routes ();
337
338                                 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
339                                         if ((*i)->is_master() || (*i)->is_monitor()) {
340                                                 i = copy->erase (i);
341                                         } else {
342                                                 ++i;
343                                         }
344                                 }
345
346                                 if (_mute_release) {
347                                         _mute_release->routes = copy;
348                                 }
349
350                                 DisplaySuspender ds;
351                                 _session->set_mute (copy, !_route->muted());
352
353                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
354
355                                 /* Primary-button1 applies change to the mix group even if it is not active
356                                    NOTE: Primary-button2 is MIDI learn.
357                                 */
358
359                                 boost::shared_ptr<RouteList> rl;
360
361                                 if (ev->button == 1) { 
362
363                                         if (_route->route_group()) {
364                                                         
365                                                 rl = _route->route_group()->route_list();
366                                                         
367                                                 if (_mute_release) {
368                                                         _mute_release->routes = rl;
369                                                 }
370                                         } else {
371                                                 rl.reset (new RouteList);
372                                                 rl->push_back (_route);
373                                         }
374
375                                         DisplaySuspender ds;
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         return true;
397 }
398
399 bool
400 RouteUI::mute_release (GdkEventButton*)
401 {
402         if (_mute_release){
403                 DisplaySuspender ds;
404                 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
405                 delete _mute_release;
406                 _mute_release = 0;
407         }
408
409         return true;
410 }
411
412 bool
413 RouteUI::solo_press(GdkEventButton* ev)
414 {
415         /* ignore double/triple clicks */
416
417         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
418                 return true;
419         }
420
421         multiple_solo_change = false;
422
423         if (Keyboard::is_context_menu_event (ev)) {
424
425                 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
426                     ! (solo_safe_led && solo_safe_led->is_visible())) {
427
428                         if (solo_menu == 0) {
429                                 build_solo_menu ();
430                         }
431
432                         solo_menu->popup (1, ev->time);
433                 }
434
435         } else {
436
437                 if (Keyboard::is_button2_event (ev)) {
438
439                         // Primary-button2 click is the midi binding click
440                         // button2-click is "momentary"
441
442                         if (solo_button->on_button_press_event (ev)) {
443                                 return true;
444                         }
445
446                         _solo_release = new SoloMuteRelease (_route->self_soloed());
447                 }
448
449                 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
450
451                         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
452
453                                 /* Primary-Tertiary-click applies change to all routes */
454
455                                 if (_solo_release) {
456                                         _solo_release->routes = _session->get_routes ();
457                                 }
458
459                                 DisplaySuspender ds;
460                                 if (Config->get_solo_control_is_listen_control()) {
461                                         _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(),  Session::rt_cleanup, true);
462                                 } else {
463                                         _session->set_solo (_session->get_routes(), !_route->self_soloed(),  Session::rt_cleanup, true);
464                                 }
465
466                         } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
467
468                                 // Primary-Secondary-click: exclusively solo this track
469
470                                 if (_solo_release) {
471                                         _solo_release->exclusive = true;
472
473                                         boost::shared_ptr<RouteList> routes = _session->get_routes();
474
475                                         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
476                                                 if ((*i)->soloed ()) {
477                                                         _solo_release->routes_on->push_back (*i);
478                                                 } else {
479                                                         _solo_release->routes_off->push_back (*i);
480                                                 }
481                                         }
482                                 }
483
484                                 if (Config->get_solo_control_is_listen_control()) {
485                                         /* ??? we need a just_one_listen() method */
486                                 } else {
487                                         DisplaySuspender ds;
488                                         _session->set_just_one_solo (_route, true);
489                                 }
490
491                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
492
493                                 // shift-click: toggle solo isolated status
494
495                                 _route->set_solo_isolated (!_route->solo_isolated(), this);
496                                 delete _solo_release;
497                                 _solo_release = 0;
498
499                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
500
501                                 /* Primary-button1: solo mix group.
502                                    NOTE: Primary-button2 is MIDI learn.
503                                 */
504
505                                 /* Primary-button1 applies change to the mix group even if it is not active
506                                    NOTE: Primary-button2 is MIDI learn.
507                                 */
508
509                                 boost::shared_ptr<RouteList> rl;
510
511                                 if (ev->button == 1) { 
512
513                                         if (_route->route_group()) {
514                                                         
515                                                 rl = _route->route_group()->route_list();
516                                                         
517                                                 if (_solo_release) {
518                                                         _solo_release->routes = rl;
519                                                 }
520                                         } else {
521                                                 rl.reset (new RouteList);
522                                                 rl->push_back (_route);
523                                         }
524
525                                         DisplaySuspender ds;
526                                         if (Config->get_solo_control_is_listen_control()) {
527                                                 _session->set_listen (rl, !_route->listening_via_monitor(),  Session::rt_cleanup, true);
528                                         } else {
529                                                 _session->set_solo (rl, !_route->self_soloed(),  Session::rt_cleanup, true);
530                                         }
531                                 }
532
533                         } else {
534
535                                 /* click: solo this route */
536
537                                 boost::shared_ptr<RouteList> rl (new RouteList);
538                                 rl->push_back (route());
539
540                                 if (_solo_release) {
541                                         _solo_release->routes = rl;
542                                 }
543
544                                 DisplaySuspender ds;
545                                 if (Config->get_solo_control_is_listen_control()) {
546                                         _session->set_listen (rl, !_route->listening_via_monitor());
547                                 } else {
548                                         _session->set_solo (rl, !_route->self_soloed());
549                                 }
550                         }
551                 }
552         }
553
554         return true;
555 }
556
557 bool
558 RouteUI::solo_release (GdkEventButton*)
559 {
560         if (_solo_release) {
561
562                 if (_solo_release->exclusive) {
563
564                 } else {
565                         DisplaySuspender ds;
566                         if (Config->get_solo_control_is_listen_control()) {
567                                 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
568                         } else {
569                                 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
570                         }
571                 }
572
573                 delete _solo_release;
574                 _solo_release = 0;
575         }
576
577         return true;
578 }
579
580 bool
581 RouteUI::rec_enable_press(GdkEventButton* ev)
582 {
583         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
584                 return true;
585         }
586
587         if (!_session->engine().connected()) {
588                 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
589                 msg.run ();
590                 return true;
591         }
592
593         if (is_midi_track()) {
594
595                 /* rec-enable button exits from step editing */
596
597                 if (midi_track()->step_editing()) {
598                         midi_track()->set_step_editing (false);
599                         return true;
600                 }
601         }
602
603         if (is_track() && rec_enable_button) {
604
605                 if (Keyboard::is_button2_event (ev)) {
606
607                         // do nothing on midi sigc::bind event
608                         return rec_enable_button->on_button_press_event (ev);
609
610                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
611
612                         DisplaySuspender ds;
613                         _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
614
615                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
616
617                         /* Primary-button1 applies change to the route group (even if it is not active)
618                            NOTE: Primary-button2 is MIDI learn.
619                         */
620
621                         if (ev->button == 1) {
622
623                                 boost::shared_ptr<RouteList> rl;
624                                 
625                                 if (_route->route_group()) {
626                                         
627                                         rl = _route->route_group()->route_list();
628                                         
629                                 } else {
630                                         rl.reset (new RouteList);
631                                         rl->push_back (_route);
632                                 }
633
634                                 DisplaySuspender ds;
635                                 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
636                         }
637
638                 } else if (Keyboard::is_context_menu_event (ev)) {
639
640                         /* do this on release */
641
642                 } else {
643
644                         boost::shared_ptr<RouteList> rl (new RouteList);
645                         rl->push_back (route());
646                         DisplaySuspender ds;
647                         _session->set_record_enabled (rl, !rec_enable_button->active_state());
648                 }
649         }
650
651         return true;
652 }
653
654 void
655 RouteUI::monitoring_changed ()
656 {
657         update_monitoring_display ();
658 }
659
660 void
661 RouteUI::update_monitoring_display ()
662 {
663         if (!_route) {
664                 return;
665         }
666
667         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
668
669         if (!t) {
670                 return;
671         }
672
673         MonitorState ms = t->monitoring_state();
674
675         if (t->monitoring_choice() & MonitorInput) {
676                 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
677         } else {
678                 if (ms & MonitoringInput) {
679                         monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
680                 } else {
681                         monitor_input_button->unset_active_state ();
682                 }
683         }
684
685         if (t->monitoring_choice() & MonitorDisk) {
686                 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
687         } else {
688                 if (ms & MonitoringDisk) {
689                         monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
690                 } else {
691                         monitor_disk_button->unset_active_state ();
692                 }
693         }
694 }
695
696 bool
697 RouteUI::monitor_input_press(GdkEventButton*)
698 {
699         return true;
700 }
701
702 bool
703 RouteUI::monitor_input_release(GdkEventButton* ev)
704 {
705         return monitor_release (ev, MonitorInput);
706 }
707
708 bool
709 RouteUI::monitor_disk_press (GdkEventButton*)
710 {
711         return true;
712 }
713
714 bool
715 RouteUI::monitor_disk_release (GdkEventButton* ev)
716 {
717         return monitor_release (ev, MonitorDisk);
718 }
719
720 bool
721 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
722 {       
723         if (ev->button != 1) {
724                 return false;
725         }
726
727         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
728
729         if (!t) {
730                 return true;
731         }
732
733         MonitorChoice mc;
734         boost::shared_ptr<RouteList> rl;
735         
736         /* XXX for now, monitoring choices are orthogonal. cue monitoring 
737            will follow in 3.X but requires mixing the input and playback (disk)
738            signal together, which requires yet more buffers.
739         */
740
741         if (t->monitoring_choice() & monitor_choice) {
742                 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
743         } else {
744                 /* this line will change when the options are non-orthogonal */
745                 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
746                 mc = monitor_choice;
747         }
748
749         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {       
750                 rl = _session->get_routes ();
751
752         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
753                 if (_route->route_group() && _route->route_group()->is_monitoring()) {
754                         rl = _route->route_group()->route_list();
755                 } else {
756                         rl.reset (new RouteList);
757                         rl->push_back (route());
758                 }
759         } else {
760                 rl.reset (new RouteList);
761                 rl->push_back (route());
762         }
763
764         DisplaySuspender ds;
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 (!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                                 DisplaySuspender ds;
1338                                 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1339                         }
1340
1341                 } else {
1342                         if (model == view) {
1343
1344                                 /* flip just this route */
1345
1346                                 boost::shared_ptr<RouteList> rl (new RouteList);
1347                                 rl->push_back (_route);
1348                                 DisplaySuspender ds;
1349                                 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1350                         }
1351                 }
1352         }
1353
1354         return true;
1355 }
1356
1357 bool
1358 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1359 {
1360         if (ev->button == 1) {
1361                 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1362                 return true;
1363         }
1364         return false;
1365 }
1366
1367 void
1368 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1369 {
1370         bool view = check->get_active();
1371         bool model = _route->solo_isolated();
1372
1373         /* called AFTER the view has changed */
1374
1375         if (model != view) {
1376                 _route->set_solo_isolated (view, this);
1377         }
1378 }
1379
1380 void
1381 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1382 {
1383         _route->set_solo_safe (check->get_active(), this);
1384 }
1385
1386 /** Ask the user to choose a colour, and then set all selected tracks
1387  *  to that colour.
1388  */
1389 void
1390 RouteUI::choose_color ()
1391 {
1392         bool picked;
1393         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1394
1395         if (picked) {
1396                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1397                         boost::bind (&RouteUI::set_color, _1, color)
1398                         );
1399         }
1400 }
1401
1402 /** Set the route's own color.  This may not be used for display if
1403  *  the route is in a group which shares its color with its routes.
1404  */
1405 void
1406 RouteUI::set_color (const Gdk::Color & c)
1407 {
1408         /* leave _color alone in the group case so that tracks can retain their
1409          * own pre-group colors.
1410          */
1411
1412         char buf[64];
1413         _color = c;
1414         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1415         
1416         /* note: we use the route state ID here so that color is the same for both
1417            the time axis view and the mixer strip
1418         */
1419         
1420         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1421         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1422 }
1423
1424 /** @return GUI state ID for things that are common to the route in all its representations */
1425 string
1426 RouteUI::route_state_id () const
1427 {
1428         return string_compose (X_("route %1"), _route->id().to_s());
1429 }
1430
1431 int
1432 RouteUI::set_color_from_route ()
1433 {
1434         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1435
1436         if (str.empty()) {
1437                 return 1;
1438         }
1439
1440         int r, g, b;
1441
1442         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1443
1444         _color.set_red (r);
1445         _color.set_green (g);
1446         _color.set_blue (b);
1447
1448         return 0;
1449 }
1450
1451 void
1452 RouteUI::remove_this_route (bool apply_to_selection)
1453 {
1454         if (apply_to_selection) {
1455                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1456         } else {
1457                 if ((route()->is_master() || route()->is_monitor()) &&
1458                     !Config->get_allow_special_bus_removal()) {
1459                         MessageDialog msg (_("That would be bad news ...."),
1460                                            false,
1461                                            Gtk::MESSAGE_INFO,
1462                                    Gtk::BUTTONS_OK);
1463                         msg.set_secondary_text (string_compose (_(
1464 "Removing the master or monitor bus is such a bad idea\n\
1465 that %1 is not going to allow it.\n\
1466 \n\
1467 If you really want to do this sort of thing\n\
1468 edit your ardour.rc file to set the\n\
1469 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1470
1471                         msg.present ();
1472                         msg.run ();
1473                         return;
1474                 }
1475
1476                 vector<string> choices;
1477                 string prompt;
1478
1479                 if (is_track()) {
1480                         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());
1481                 } else {
1482                         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());
1483                 }
1484
1485                 choices.push_back (_("No, do nothing."));
1486                 choices.push_back (_("Yes, remove it."));
1487
1488                 string title;
1489                 if (is_track()) {
1490                         title = _("Remove track");
1491                 } else {
1492                         title = _("Remove bus");
1493                 }
1494
1495                 Choice prompter (title, prompt, choices);
1496
1497                 if (prompter.run () == 1) {
1498                         Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1499                 }
1500         }
1501 }
1502
1503 gint
1504 RouteUI::idle_remove_this_route (RouteUI *rui)
1505 {
1506         rui->_session->remove_route (rui->route());
1507         return false;
1508 }
1509
1510 /** @return true if this name should be used for the route, otherwise false */
1511 bool
1512 RouteUI::verify_new_route_name (const std::string& name)
1513 {
1514         if (name.find (':') == string::npos) {
1515                 return true;
1516         }
1517         
1518         MessageDialog colon_msg (
1519                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1520                 false, MESSAGE_QUESTION, BUTTONS_NONE
1521                 );
1522         
1523         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1524         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1525
1526         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1527 }
1528
1529 void
1530 RouteUI::route_rename ()
1531 {
1532         ArdourPrompter name_prompter (true);
1533         string result;
1534         bool done = false;
1535
1536         if (is_track()) {
1537                 name_prompter.set_title (_("Rename Track"));
1538         } else {
1539                 name_prompter.set_title (_("Rename Bus"));
1540         }
1541         name_prompter.set_prompt (_("New name:"));
1542         name_prompter.set_initial_text (_route->name());
1543         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1544         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1545         name_prompter.show_all ();
1546
1547         while (!done) {
1548                 switch (name_prompter.run ()) {
1549                 case Gtk::RESPONSE_ACCEPT:
1550                         name_prompter.get_result (result);
1551                         name_prompter.hide ();
1552                         if (result.length()) {
1553                                 if (verify_new_route_name (result)) {
1554                                         _route->set_name (result);
1555                                         done = true;
1556                                 } else {
1557                                         /* back to name prompter */
1558                                 }
1559
1560                         } else {
1561                                 /* nothing entered, just get out of here */
1562                                 done = true;
1563                         }
1564                         break;
1565                 default:
1566                         done = true;
1567                         break;
1568                 }
1569         }
1570
1571         return;
1572
1573 }
1574
1575 void
1576 RouteUI::property_changed (const PropertyChange& what_changed)
1577 {
1578         if (what_changed.contains (ARDOUR::Properties::name)) {
1579                 name_label.set_text (_route->name());
1580         }
1581 }
1582
1583 void
1584 RouteUI::set_route_active (bool a, bool apply_to_selection)
1585 {
1586         if (apply_to_selection) {
1587                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1588         } else {
1589                 _route->set_active (a, this);
1590         }
1591 }
1592
1593 void
1594 RouteUI::toggle_denormal_protection ()
1595 {
1596         if (denormal_menu_item) {
1597
1598                 bool x;
1599
1600                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1601
1602                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1603                         _route->set_denormal_protection (x);
1604                 }
1605         }
1606 }
1607
1608 void
1609 RouteUI::denormal_protection_changed ()
1610 {
1611         if (denormal_menu_item) {
1612                 denormal_menu_item->set_active (_route->denormal_protection());
1613         }
1614 }
1615
1616 void
1617 RouteUI::disconnect_input ()
1618 {
1619         _route->input()->disconnect (this);
1620 }
1621
1622 void
1623 RouteUI::disconnect_output ()
1624 {
1625         _route->output()->disconnect (this);
1626 }
1627
1628 bool
1629 RouteUI::is_track () const
1630 {
1631         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1632 }
1633
1634 boost::shared_ptr<Track>
1635 RouteUI::track() const
1636 {
1637         return boost::dynamic_pointer_cast<Track>(_route);
1638 }
1639
1640 bool
1641 RouteUI::is_audio_track () const
1642 {
1643         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1644 }
1645
1646 boost::shared_ptr<AudioTrack>
1647 RouteUI::audio_track() const
1648 {
1649         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1650 }
1651
1652 bool
1653 RouteUI::is_midi_track () const
1654 {
1655         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1656 }
1657
1658 boost::shared_ptr<MidiTrack>
1659 RouteUI::midi_track() const
1660 {
1661         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1662 }
1663
1664 bool
1665 RouteUI::has_audio_outputs () const
1666 {
1667         return (_route->n_outputs().n_audio() > 0);
1668 }
1669
1670 string
1671 RouteUI::name() const
1672 {
1673         return _route->name();
1674 }
1675
1676 void
1677 RouteUI::map_frozen ()
1678 {
1679         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1680
1681         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1682
1683         if (at) {
1684                 switch (at->freeze_state()) {
1685                 case AudioTrack::Frozen:
1686                         rec_enable_button->set_sensitive (false);
1687                         break;
1688                 default:
1689                         rec_enable_button->set_sensitive (true);
1690                         break;
1691                 }
1692         }
1693 }
1694
1695 void
1696 RouteUI::adjust_latency ()
1697 {
1698         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1699 }
1700
1701 void
1702 RouteUI::save_as_template ()
1703 {
1704         std::string path;
1705         std::string safe_name;
1706         string name;
1707
1708         path = ARDOUR::user_route_template_directory ();
1709
1710         if (g_mkdir_with_parents (path.c_str(), 0755)) {
1711                 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1712                 return;
1713         }
1714
1715         Prompter p (true); // modal
1716
1717         p.set_title (_("Save As Template"));
1718         p.set_prompt (_("Template name:"));
1719         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1720         switch (p.run()) {
1721         case RESPONSE_ACCEPT:
1722                 break;
1723         default:
1724                 return;
1725         }
1726
1727         p.hide ();
1728         p.get_result (name, true);
1729
1730         safe_name = legalize_for_path (name);
1731         safe_name += template_suffix;
1732
1733         path = Glib::build_filename (path, safe_name);
1734
1735         _route->save_as_template (path, name);
1736 }
1737
1738 void
1739 RouteUI::check_rec_enable_sensitivity ()
1740 {
1741         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1742                 rec_enable_button->set_sensitive (false);
1743         } else {
1744                 rec_enable_button->set_sensitive (true);
1745         }
1746
1747         update_monitoring_display ();
1748 }
1749
1750 void
1751 RouteUI::parameter_changed (string const & p)
1752 {
1753         /* this handles RC and per-session parameter changes */
1754
1755         if (p == "disable-disarm-during-roll") {
1756                 check_rec_enable_sensitivity ();
1757         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1758                 set_button_names ();
1759         } else if (p == "auto-input") {
1760                 update_monitoring_display ();
1761         }
1762 }
1763
1764 void
1765 RouteUI::step_gain_up ()
1766 {
1767         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1768 }
1769
1770 void
1771 RouteUI::page_gain_up ()
1772 {
1773         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1774 }
1775
1776 void
1777 RouteUI::step_gain_down ()
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_down ()
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::open_remote_control_id_dialog ()
1790 {
1791         ArdourDialog dialog (_("Remote Control ID"));
1792         SpinButton* spin = 0;
1793
1794         dialog.get_vbox()->set_border_width (18);
1795
1796         if (Config->get_remote_model() == UserOrdered) {
1797                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1798                 
1799                 HBox* hbox = manage (new HBox);
1800                 hbox->set_spacing (6);
1801                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1802                 spin = manage (new SpinButton);
1803                 spin->set_digits (0);
1804                 spin->set_increments (1, 10);
1805                 spin->set_range (0, limit);
1806                 spin->set_value (_route->remote_control_id());
1807                 hbox->pack_start (*spin);
1808                 dialog.get_vbox()->pack_start (*hbox);
1809                 
1810                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1811                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1812         } else {
1813                 Label* l = manage (new Label());
1814                 if (_route->is_master() || _route->is_monitor()) {
1815                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1816                                                          "The remote control ID of %3 cannot be changed."),
1817                                                        Glib::Markup::escape_text (_route->name()),
1818                                                        _route->remote_control_id(),
1819                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1820                 } else {
1821                         l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1822                                                          "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1823                                                          "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1824                                                        (is_track() ? _("track") : _("bus")),
1825                                                        _route->remote_control_id(),
1826                                                        "<span size=\"small\" style=\"italic\">",
1827                                                        "</span>",
1828                                                        Glib::Markup::escape_text (_route->name()),
1829                                                        PROGRAM_NAME));
1830                 }
1831                 dialog.get_vbox()->pack_start (*l);
1832                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1833         }
1834
1835         dialog.show_all ();
1836         int const r = dialog.run ();
1837
1838         if (r == RESPONSE_ACCEPT && spin) {
1839                 _route->set_remote_control_id (spin->get_value_as_int ());
1840         }
1841 }
1842
1843 void
1844 RouteUI::setup_invert_buttons ()
1845 {
1846         /* remove old invert buttons */
1847         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1848                 _invert_button_box.remove (**i);
1849         }
1850
1851         _invert_buttons.clear ();
1852
1853         if (!_route || !_route->input()) {
1854                 return;
1855         }
1856
1857         uint32_t const N = _route->input()->n_ports().n_audio ();
1858
1859         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1860
1861         for (uint32_t i = 0; i < to_add; ++i) {
1862                 ArdourButton* b = manage (new ArdourButton);
1863                 b->set_size_request(20,20);
1864                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1865                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1866
1867                 b->set_name (X_("invert button"));
1868                 if (to_add == 1) {
1869                         if (N > 1) {
1870                                 b->set_text (string_compose (X_("Ø (%1)"), N));
1871                         } else {
1872                                 b->set_text (X_("Ø"));
1873                         }
1874                 } else {
1875                         b->set_text (string_compose (X_("Ø%1"), i + 1));
1876                 }
1877
1878                 if (N <= _max_invert_buttons) {
1879                         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));
1880                 } else {
1881                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1882                 }
1883
1884                 _invert_buttons.push_back (b);
1885                 _invert_button_box.pack_start (*b);
1886         }
1887
1888         _invert_button_box.set_spacing (1);
1889         _invert_button_box.show_all ();
1890 }
1891
1892 void
1893 RouteUI::set_invert_button_state ()
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
1924 bool
1925 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1926 {
1927         if (ev->button == 1 && i < _invert_buttons.size()) {
1928                 uint32_t const N = _route->input()->n_ports().n_audio ();
1929                 if (N <= _max_invert_buttons) {
1930                         /* left-click inverts phase so long as we have a button per channel */
1931                         _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1932                         return true;
1933                 }
1934         }
1935         return false;
1936 }
1937
1938
1939 bool
1940 RouteUI::invert_press (GdkEventButton* ev)
1941 {
1942         using namespace Menu_Helpers;
1943
1944         uint32_t const N = _route->input()->n_ports().n_audio();
1945         if (N <= _max_invert_buttons && ev->button != 3) {
1946                 /* If we have an invert button per channel, we only pop
1947                    up a menu on right-click; left click is handled
1948                    on release.
1949                 */
1950                 return true;
1951         }
1952         
1953         delete _invert_menu;
1954         _invert_menu = new Menu;
1955         _invert_menu->set_name ("ArdourContextMenu");
1956         MenuList& items = _invert_menu->items ();
1957
1958         for (uint32_t i = 0; i < N; ++i) {
1959                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1960                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
1961                 ++_i_am_the_modifier;
1962                 e->set_active (_route->phase_invert (i));
1963                 --_i_am_the_modifier;
1964         }
1965
1966         _invert_menu->popup (0, ev->time);
1967
1968         return false;
1969 }
1970
1971 void
1972 RouteUI::invert_menu_toggled (uint32_t c)
1973 {
1974         if (_i_am_the_modifier) {
1975                 return;
1976         }
1977
1978         _route->set_phase_invert (c, !_route->phase_invert (c));
1979 }
1980
1981 void
1982 RouteUI::set_invert_sensitive (bool yn)
1983 {
1984         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1985                 (*b)->set_sensitive (yn);
1986         }
1987 }
1988
1989 void
1990 RouteUI::request_redraw ()
1991 {
1992         if (_route) {
1993                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1994         }
1995 }
1996
1997 /** The Route's gui_changed signal has been emitted */
1998 void
1999 RouteUI::route_gui_changed (string what_changed)
2000 {
2001         if (what_changed == "color") {
2002                 if (set_color_from_route () == 0) {
2003                         route_color_changed ();
2004                 }
2005         }
2006 }
2007
2008 /** @return the color that this route should use; it maybe its own,
2009     or it maybe that of its route group.
2010 */
2011 Gdk::Color
2012 RouteUI::color () const
2013 {
2014         RouteGroup* g = _route->route_group ();
2015         
2016         if (g && g->is_color()) {
2017                 Gdk::Color c;
2018                 set_color_from_rgba (c, GroupTabs::group_color (g));
2019                 return c;
2020         }
2021
2022         return _color;
2023 }
2024
2025 void
2026 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2027 {
2028         _showing_sends_to = send_to;
2029         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2030 }
2031
2032 void
2033 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2034 {
2035         if (_route == send_to) {
2036                 show_sends_button->set_active (true);
2037                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2038         } else {
2039                 show_sends_button->set_active (false);
2040                 send_blink_connection.disconnect ();
2041         }
2042 }
2043
2044 RouteGroup*
2045 RouteUI::route_group() const
2046 {
2047         return _route->route_group();
2048 }