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