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