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