audio clocks: color tweaks from chris
[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 sigc::signal<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
68 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
69
70 RouteUI::RouteUI (ARDOUR::Session* sess)
71         : AxisView(sess)
72 {
73         init ();
74 }
75
76 RouteUI::~RouteUI()
77 {
78         _route.reset (); /* drop reference to route, so that it can be cleaned up */
79         route_connections.drop_connections ();
80
81         delete solo_menu;
82         delete mute_menu;
83         delete sends_menu;
84         delete record_menu;
85         delete _invert_menu;
86 }
87
88 void
89 RouteUI::init ()
90 {
91         self_destruct = true;
92         mute_menu = 0;
93         solo_menu = 0;
94         sends_menu = 0;
95         record_menu = 0;
96         _invert_menu = 0;
97         pre_fader_mute_check = 0;
98         post_fader_mute_check = 0;
99         listen_mute_check = 0;
100         main_mute_check = 0;
101         solo_safe_check = 0;
102         solo_isolated_check = 0;
103         solo_isolated_led = 0;
104         solo_safe_led = 0;
105         _solo_release = 0;
106         _mute_release = 0;
107         denormal_menu_item = 0;
108         step_edit_item = 0;
109         multiple_mute_change = false;
110         multiple_solo_change = false;
111         _i_am_the_modifier = 0;
112
113         setup_invert_buttons ();
114
115         mute_button = manage (new ArdourButton);
116         mute_button->set_name ("mute button");
117         UI::instance()->set_tip (mute_button, _("Mute this track"), "");
118
119         solo_button = manage (new ArdourButton);
120         solo_button->set_name ("solo button");
121         UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
122         solo_button->set_no_show_all (true);
123
124         rec_enable_button = manage (new ArdourButton);
125         rec_enable_button->set_name ("record enable button");
126         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
127
128         show_sends_button = manage (new ArdourButton);
129         show_sends_button->set_name ("send alert button");
130         UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
131
132         monitor_input_button = manage (new ArdourButton (ArdourButton::led_default_elements));
133         monitor_input_button->set_name ("monitor");
134         monitor_input_button->set_text (_("In"));
135         UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
136         monitor_input_button->set_no_show_all (true);
137
138         monitor_disk_button = manage (new ArdourButton (ArdourButton::led_default_elements));
139         monitor_disk_button->set_name ("monitor");
140         monitor_disk_button->set_text (_("Disk"));
141         UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
142         monitor_disk_button->set_no_show_all (true);
143
144         _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
145         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
146         _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
147
148         _session->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
149         Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
150
151         rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
152         rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
153
154         show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
155         show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
156
157         solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
158         solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
159         mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
160         mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
161         
162         monitor_input_button->set_distinct_led_click (false);
163         monitor_disk_button->set_distinct_led_click (false);
164
165         monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
166         monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
167
168         monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
169         monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
170
171         BusSendDisplayChanged.connect (sigc::mem_fun (*this, &RouteUI::bus_send_display_changed));
172 }
173
174 void
175 RouteUI::reset ()
176 {
177         route_connections.drop_connections ();
178
179         delete solo_menu;
180         solo_menu = 0;
181
182         delete mute_menu;
183         mute_menu = 0;
184
185         denormal_menu_item = 0;
186 }
187
188 void
189 RouteUI::self_delete ()
190 {
191         delete this;
192 }
193
194 void
195 RouteUI::set_route (boost::shared_ptr<Route> rp)
196 {
197         reset ();
198
199         _route = rp;
200
201         if (set_color_from_route()) {
202                 set_color (unique_random_color());
203         }
204
205         if (self_destruct) {
206                 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
207         }
208
209         mute_button->set_controllable (_route->mute_control());
210         solo_button->set_controllable (_route->solo_control());
211
212         _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
213         _route->mute_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::mute_changed, this, _1), gui_context());
214
215         _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
216         _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
217         _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
218         _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
219
220         _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
221         _route->PropertyChanged.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::property_changed, this, _1), gui_context());
222
223         _route->io_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::setup_invert_buttons, this), gui_context ());
224         _route->gui_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
225
226         if (_session->writable() && is_track()) {
227                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
228
229                 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
230                 
231                 rec_enable_button->show();
232                 rec_enable_button->set_controllable (t->rec_enable_control());
233
234                 update_rec_display ();
235
236                 if (is_midi_track()) {
237                         midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
238                                                                     ui_bind (&RouteUI::step_edit_changed, this, _1), gui_context());
239                 }
240
241         }
242
243         if (is_track()) {
244                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
245                 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
246
247                 update_monitoring_display ();
248         }
249
250         mute_button->unset_flags (Gtk::CAN_FOCUS);
251         solo_button->unset_flags (Gtk::CAN_FOCUS);
252
253         mute_button->show();
254
255         if (_route->is_monitor()) {
256                 solo_button->hide ();
257         } else {
258                 solo_button->show();
259         }
260
261         map_frozen ();
262
263         setup_invert_buttons ();
264         set_invert_button_state ();
265
266         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
267         bus_send_display_changed (s);
268
269         update_mute_display ();
270         update_solo_display ();
271 }
272
273 void
274 RouteUI::polarity_changed ()
275 {
276         if (!_route) {
277                 return;
278         }
279
280         set_invert_button_state ();
281 }
282
283 bool
284 RouteUI::mute_press (GdkEventButton* ev)
285 {
286         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
287                 return true;
288         }
289
290         multiple_mute_change = false;
291
292         if (!_i_am_the_modifier) {
293
294                 if (Keyboard::is_context_menu_event (ev)) {
295
296                         if (mute_menu == 0){
297                                 build_mute_menu();
298                         }
299
300                         mute_menu->popup(0,ev->time);
301
302                 } else {
303
304                         if (Keyboard::is_button2_event (ev)) {
305                                 // Primary-button2 click is the midi binding click
306                                 // button2-click is "momentary"
307
308
309                                 if (mute_button->on_button_press_event (ev)) {
310                                         return true;
311                                 }
312
313                                 _mute_release = new SoloMuteRelease (_route->muted ());
314                         }
315
316                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
317
318                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
319
320                                         if (_mute_release) {
321                                                 _mute_release->routes = _session->get_routes ();
322                                         }
323
324                                         _session->set_mute (_session->get_routes(), !_route->muted());
325
326                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
327
328                                         /* Primary-button1 applies change to the mix group even if it is not active
329                                            NOTE: Primary-button2 is MIDI learn.
330                                         */
331
332                                         if (ev->button == 1 && _route->route_group()) {
333                                                 if (_mute_release) {
334                                                         _mute_release->routes = _session->get_routes ();
335                                                 }
336
337                                                 _session->set_mute (_session->get_routes(), !_route->muted(), Session::rt_cleanup, true);
338                                         }
339
340                                 } else {
341
342                                         /* plain click applies change to this route */
343
344                                         boost::shared_ptr<RouteList> rl (new RouteList);
345                                         rl->push_back (_route);
346
347                                         if (_mute_release) {
348                                                 _mute_release->routes = rl;
349                                         }
350
351                                         _session->set_mute (rl, !_route->muted());
352
353                                 }
354                         }
355                 }
356
357         }
358
359         return true;
360 }
361
362 bool
363 RouteUI::mute_release (GdkEventButton*)
364 {
365         if (!_i_am_the_modifier) {
366                 if (_mute_release){
367                         _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
368                         delete _mute_release;
369                         _mute_release = 0;
370                 }
371         }
372
373         return true;
374 }
375
376 bool
377 RouteUI::solo_press(GdkEventButton* ev)
378 {
379         /* ignore double/triple clicks */
380
381         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
382                 return true;
383         }
384
385         multiple_solo_change = false;
386
387         if (!_i_am_the_modifier) {
388
389                 if (Keyboard::is_context_menu_event (ev)) {
390
391                         if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
392                             ! (solo_safe_led && solo_safe_led->is_visible())) {
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->active_state());
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->active_state(), 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->active_state());
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 (t->monitoring_choice() & MonitorInput) {
610                 monitor_input_button->set_active_state (Gtkmm2ext::Active);
611         } else {
612                 if (ms & MonitoringInput) {
613                         monitor_input_button->set_active_state (Gtkmm2ext::Mid);
614                 } else {
615                         monitor_input_button->unset_active_state ();
616                 }
617         }
618
619         if (t->monitoring_choice() & MonitorDisk) {
620                 monitor_disk_button->set_active_state (Gtkmm2ext::Active);
621         } else {
622                 if (ms & MonitoringDisk) {
623                         monitor_disk_button->set_active_state (Gtkmm2ext::Mid);
624                 } else {
625                         monitor_disk_button->unset_active_state ();
626                 }
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_active_state (Active);
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->unset_active_state ();
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                         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
899
900                         if (s == _route) {
901                                 set_showing_sends_to (boost::shared_ptr<Route> ());
902                         } else {
903                                 set_showing_sends_to (_route);
904                         }
905                 }
906         }
907
908         return true;
909 }
910
911 bool
912 RouteUI::show_sends_release (GdkEventButton*)
913 {
914         return true;
915 }
916
917 void
918 RouteUI::send_blink (bool onoff)
919 {
920         if (!show_sends_button) {
921                 return;
922         }
923
924         if (onoff) {
925                 show_sends_button->set_active_state (Gtkmm2ext::Active);
926         } else {
927                 show_sends_button->unset_active_state ();
928         }
929 }
930
931 Gtkmm2ext::ActiveState
932 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
933 {
934         if (r->is_master() || r->is_monitor()) {
935                 return ActiveState (0);
936         }
937
938         if (Config->get_solo_control_is_listen_control()) {
939
940                 if (r->listening_via_monitor()) {
941                         return Active;
942                 } else {
943                         return ActiveState (0);
944                 }
945
946         }
947
948         if (r->soloed()) {
949                 if (!r->self_soloed()) {
950                         return Mid;
951                 } else {
952                         return Active;
953                 }
954         } else {
955                 return ActiveState(0);
956         }
957 }
958
959 Gtkmm2ext::ActiveState
960 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
961 {
962         if (r->is_master() || r->is_monitor()) {
963                 return ActiveState (0);
964         }
965
966         if (r->solo_isolated()) {
967                 return Active;
968         } else {
969                 return ActiveState(0);
970         }
971 }
972
973 Gtkmm2ext::ActiveState
974 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
975 {
976         if (r->is_master() || r->is_monitor()) {
977                 return ActiveState (0);
978         }
979
980         if (r->solo_safe()) {
981                 return Active;
982         } else {
983                 return ActiveState (0);
984         }
985 }
986
987 void
988 RouteUI::update_solo_display ()
989 {
990         bool x;
991
992         if (Config->get_solo_control_is_listen_control()) {
993
994                 if ((bool) solo_button->active_state() != (x = _route->listening_via_monitor())) {
995                         ++_i_am_the_modifier;
996                         solo_button->set_active_state (Active);
997                         --_i_am_the_modifier;
998                 }
999
1000         } else {
1001
1002                 if ((bool) solo_button->active_state() != (x = _route->soloed())) {
1003                         ++_i_am_the_modifier;
1004                         if (x) {
1005                                 solo_button->set_active_state (Active);
1006                         } else {
1007                                 solo_button->unset_active_state();
1008                         }
1009                         --_i_am_the_modifier;
1010                 }
1011
1012         }
1013
1014         bool yn = _route->solo_safe ();
1015
1016         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1017                 solo_safe_check->set_active (yn);
1018         }
1019
1020         yn = _route->solo_isolated ();
1021
1022         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1023                 solo_isolated_check->set_active (yn);
1024         }
1025
1026         set_button_names ();
1027
1028         if (solo_isolated_led) {
1029                 if (_route->solo_isolated()) {
1030                         solo_isolated_led->set_active_state (Gtkmm2ext::Active);
1031                 } else {
1032                         solo_isolated_led->unset_active_state ();
1033                 }
1034         }
1035
1036         if (solo_safe_led) {
1037                 if (_route->solo_safe()) {
1038                         solo_safe_led->set_active_state (Gtkmm2ext::Active);
1039                 } else {
1040                         solo_safe_led->unset_active_state ();
1041                 }
1042         }
1043
1044         solo_button->set_active_state (solo_active_state (_route));
1045
1046         /* some changes to solo status can affect mute display, so catch up
1047          */
1048
1049         update_mute_display ();
1050 }
1051
1052 void
1053 RouteUI::solo_changed_so_update_mute ()
1054 {
1055         update_mute_display ();
1056 }
1057
1058 void
1059 RouteUI::mute_changed(void* /*src*/)
1060 {
1061         update_mute_display ();
1062 }
1063
1064 ActiveState
1065 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1066 {
1067         if (r->is_monitor()) {
1068                 return ActiveState(0);
1069         }
1070
1071
1072         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1073
1074                 if (r->muted ()) {
1075                         /* full mute */
1076                         return Active;
1077                 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1078                         /* master is NEVER muted by others */
1079                         return Mid;
1080                 } else {
1081                         /* no mute at all */
1082                         return ActiveState(0);
1083                 }
1084
1085         } else {
1086
1087                 if (r->muted()) {
1088                         /* full mute */
1089                         return Active;
1090                 } else {
1091                         /* no mute at all */
1092                         return ActiveState(0);
1093                 }
1094         }
1095
1096         return ActiveState(0);
1097 }
1098
1099 void
1100 RouteUI::update_mute_display ()
1101 {
1102         if (!_route) {
1103                 return;
1104         }
1105
1106         mute_button->set_active_state (mute_active_state (_session, _route));
1107 }
1108
1109 void
1110 RouteUI::route_rec_enable_changed ()
1111 {
1112         update_rec_display ();
1113         update_monitoring_display ();
1114 }
1115
1116 void
1117 RouteUI::session_rec_enable_changed ()
1118 {
1119         update_rec_display ();
1120         update_monitoring_display ();
1121 }
1122
1123 void
1124 RouteUI::update_rec_display ()
1125 {
1126         if (!rec_enable_button || !_route) {
1127                 return;
1128         }
1129
1130         if (_route->record_enabled()) {
1131                 switch (_session->record_status ()) {
1132                 case Session::Recording:
1133                         rec_enable_button->set_active_state (Active);
1134                         break;
1135
1136                 case Session::Disabled:
1137                 case Session::Enabled:
1138                         rec_enable_button->set_active_state (Mid);
1139                         break;
1140
1141                 }
1142
1143                 if (step_edit_item) {
1144                         step_edit_item->set_sensitive (false);
1145                 }
1146
1147         } else {
1148                 rec_enable_button->unset_active_state ();
1149
1150                 if (step_edit_item) {
1151                         step_edit_item->set_sensitive (true);
1152                 }
1153         }
1154
1155
1156         check_rec_enable_sensitivity ();
1157 }
1158
1159 void
1160 RouteUI::build_solo_menu (void)
1161 {
1162         using namespace Menu_Helpers;
1163
1164         solo_menu = new Menu;
1165         solo_menu->set_name ("ArdourContextMenu");
1166         MenuList& items = solo_menu->items();
1167         CheckMenuItem* check;
1168
1169         check = new CheckMenuItem(_("Solo Isolate"));
1170         check->set_active (_route->solo_isolated());
1171         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1172         items.push_back (CheckMenuElem(*check));
1173         solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1174         check->show_all();
1175
1176         check = new CheckMenuItem(_("Solo Safe"));
1177         check->set_active (_route->solo_safe());
1178         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1179         items.push_back (CheckMenuElem(*check));
1180         solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1181         check->show_all();
1182
1183         //items.push_back (SeparatorElem());
1184         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1185
1186 }
1187
1188 void
1189 RouteUI::build_mute_menu(void)
1190 {
1191         using namespace Menu_Helpers;
1192
1193         mute_menu = new Menu;
1194         mute_menu->set_name ("ArdourContextMenu");
1195
1196         MenuList& items = mute_menu->items();
1197
1198         pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1199         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1200         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1201         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1202         pre_fader_mute_check->show_all();
1203
1204         post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1205         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1206         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1207         items.push_back (CheckMenuElem(*post_fader_mute_check));
1208         post_fader_mute_check->show_all();
1209
1210         listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1211         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1212         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1213         items.push_back (CheckMenuElem(*listen_mute_check));
1214         listen_mute_check->show_all();
1215
1216         main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1217         init_mute_menu(MuteMaster::Main, main_mute_check);
1218         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1219         items.push_back (CheckMenuElem(*main_mute_check));
1220         main_mute_check->show_all();
1221
1222         //items.push_back (SeparatorElem());
1223         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1224
1225         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1226 }
1227
1228 void
1229 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1230 {
1231         check->set_active (_route->mute_points() & mp);
1232 }
1233
1234 void
1235 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1236 {
1237         if (check->get_active()) {
1238                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1239         } else {
1240                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1241         }
1242 }
1243
1244 void
1245 RouteUI::muting_change ()
1246 {
1247         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1248
1249         bool yn;
1250         MuteMaster::MutePoint current = _route->mute_points ();
1251
1252         yn = (current & MuteMaster::PreFader);
1253
1254         if (pre_fader_mute_check->get_active() != yn) {
1255                 pre_fader_mute_check->set_active (yn);
1256         }
1257
1258         yn = (current & MuteMaster::PostFader);
1259
1260         if (post_fader_mute_check->get_active() != yn) {
1261                 post_fader_mute_check->set_active (yn);
1262         }
1263
1264         yn = (current & MuteMaster::Listen);
1265
1266         if (listen_mute_check->get_active() != yn) {
1267                 listen_mute_check->set_active (yn);
1268         }
1269
1270         yn = (current & MuteMaster::Main);
1271
1272         if (main_mute_check->get_active() != yn) {
1273                 main_mute_check->set_active (yn);
1274         }
1275 }
1276
1277 bool
1278 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1279 {
1280         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1281                 return true;
1282         }
1283
1284         bool view = solo_isolated_led->active_state();
1285         bool model = _route->solo_isolated();
1286
1287         /* called BEFORE the view has changed */
1288
1289         if (ev->button == 1) {
1290                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1291
1292                         if (model) {
1293                                 /* disable isolate for all routes */
1294                                 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1295                         }
1296
1297                 } else {
1298                         if (model == view) {
1299
1300                                 /* flip just this route */
1301
1302                                 boost::shared_ptr<RouteList> rl (new RouteList);
1303                                 rl->push_back (_route);
1304                                 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1305                         }
1306                 }
1307         }
1308
1309         return true;
1310 }
1311
1312 bool
1313 RouteUI::solo_safe_button_release (GdkEventButton*)
1314 {
1315         _route->set_solo_safe (!solo_safe_led->active_state(), this);
1316         return true;
1317 }
1318
1319 void
1320 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1321 {
1322         bool view = check->get_active();
1323         bool model = _route->solo_isolated();
1324
1325         /* called AFTER the view has changed */
1326
1327         if (model != view) {
1328                 _route->set_solo_isolated (view, this);
1329         }
1330 }
1331
1332 void
1333 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1334 {
1335         _route->set_solo_safe (check->get_active(), this);
1336 }
1337
1338 /** Ask the user to choose a colour, and then set all selected tracks
1339  *  to that colour.
1340  */
1341 void
1342 RouteUI::choose_color ()
1343 {
1344         bool picked;
1345         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1346
1347         if (picked) {
1348                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1349                         boost::bind (&RouteUI::set_color, _1, color)
1350                         );
1351         }
1352 }
1353
1354 /** Set the route's own color.  This may not be used for display if
1355  *  the route is in a group which shares its color with its routes.
1356  */
1357 void
1358 RouteUI::set_color (const Gdk::Color & c)
1359 {
1360         char buf[64];
1361
1362         _color = c;
1363
1364         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1365
1366         /* note: we use the route state ID here so that color is the same for both
1367            the time axis view and the mixer strip
1368         */
1369         
1370         gui_object_state().set<string> (route_state_id(), X_("color"), buf);
1371         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1372 }
1373
1374 /** @return GUI state ID for things that are common to the route in all its representations */
1375 string
1376 RouteUI::route_state_id () const
1377 {
1378         return string_compose (X_("route %1"), _route->id().to_s());
1379 }
1380
1381 int
1382 RouteUI::set_color_from_route ()
1383 {
1384         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1385
1386         if (str.empty()) {
1387                 return 1;
1388         }
1389
1390         int r, g, b;
1391
1392         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1393
1394         _color.set_red (r);
1395         _color.set_green (g);
1396         _color.set_blue (b);
1397
1398         return 0;
1399 }
1400
1401 void
1402 RouteUI::remove_this_route (bool apply_to_selection)
1403 {
1404         if (apply_to_selection) {
1405                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1406         } else {
1407                 if ((route()->is_master() || route()->is_monitor()) &&
1408                     !Config->get_allow_special_bus_removal()) {
1409                         MessageDialog msg (_("That would be bad news ...."),
1410                                            false,
1411                                            Gtk::MESSAGE_INFO,
1412                                    Gtk::BUTTONS_OK);
1413                         msg.set_secondary_text (string_compose (_(
1414 "Removing the master or monitor bus is such a bad idea\n\
1415 that %1 is not going to allow it.\n\
1416 \n\
1417 If you really want to do this sort of thing\n\
1418 edit your ardour.rc file to set the\n\
1419 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1420
1421                         msg.present ();
1422                         msg.run ();
1423                         return;
1424                 }
1425
1426                 vector<string> choices;
1427                 string prompt;
1428
1429                 if (is_track()) {
1430                         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());
1431                 } else {
1432                         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());
1433                 }
1434
1435                 choices.push_back (_("No, do nothing."));
1436                 choices.push_back (_("Yes, remove it."));
1437
1438                 string title;
1439                 if (is_track()) {
1440                         title = _("Remove track");
1441                 } else {
1442                         title = _("Remove bus");
1443                 }
1444
1445                 Choice prompter (title, prompt, choices);
1446
1447                 if (prompter.run () == 1) {
1448                         Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1449                 }
1450         }
1451 }
1452
1453 gint
1454 RouteUI::idle_remove_this_route (RouteUI *rui)
1455 {
1456         rui->_session->remove_route (rui->route());
1457         return false;
1458 }
1459
1460 /** @return true if this name should be used for the route, otherwise false */
1461 bool
1462 RouteUI::verify_new_route_name (const std::string& name)
1463 {
1464         if (name.find (':') == string::npos) {
1465                 return true;
1466         }
1467         
1468         MessageDialog colon_msg (
1469                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1470                 false, MESSAGE_QUESTION, BUTTONS_NONE
1471                 );
1472         
1473         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1474         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1475
1476         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1477 }
1478
1479 void
1480 RouteUI::route_rename ()
1481 {
1482         ArdourPrompter name_prompter (true);
1483         string result;
1484         bool done = false;
1485
1486         if (is_track()) {
1487                 name_prompter.set_title (_("Rename Track"));
1488         } else {
1489                 name_prompter.set_title (_("Rename Bus"));
1490         }
1491         name_prompter.set_prompt (_("New name:"));
1492         name_prompter.set_initial_text (_route->name());
1493         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1494         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1495         name_prompter.show_all ();
1496
1497         while (!done) {
1498                 switch (name_prompter.run ()) {
1499                 case Gtk::RESPONSE_ACCEPT:
1500                         name_prompter.get_result (result);
1501                         name_prompter.hide ();
1502                         if (result.length()) {
1503                                 if (verify_new_route_name (result)) {
1504                                         _route->set_name (result);
1505                                         done = true;
1506                                 } else {
1507                                         /* back to name prompter */
1508                                 }
1509
1510                         } else {
1511                                 /* nothing entered, just get out of here */
1512                                 done = true;
1513                         }
1514                         break;
1515                 }
1516         }
1517
1518         return;
1519
1520 }
1521
1522 void
1523 RouteUI::property_changed (const PropertyChange& what_changed)
1524 {
1525         if (what_changed.contains (ARDOUR::Properties::name)) {
1526                 name_label.set_text (_route->name());
1527         }
1528 }
1529
1530 void
1531 RouteUI::set_route_active (bool a, bool apply_to_selection)
1532 {
1533         if (apply_to_selection) {
1534                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1535         } else {
1536                 _route->set_active (a, this);
1537         }
1538 }
1539
1540 void
1541 RouteUI::toggle_denormal_protection ()
1542 {
1543         if (denormal_menu_item) {
1544
1545                 bool x;
1546
1547                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1548
1549                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1550                         _route->set_denormal_protection (x);
1551                 }
1552         }
1553 }
1554
1555 void
1556 RouteUI::denormal_protection_changed ()
1557 {
1558         if (denormal_menu_item) {
1559                 denormal_menu_item->set_active (_route->denormal_protection());
1560         }
1561 }
1562
1563 void
1564 RouteUI::disconnect_input ()
1565 {
1566         _route->input()->disconnect (this);
1567 }
1568
1569 void
1570 RouteUI::disconnect_output ()
1571 {
1572         _route->output()->disconnect (this);
1573 }
1574
1575 bool
1576 RouteUI::is_track () const
1577 {
1578         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1579 }
1580
1581 boost::shared_ptr<Track>
1582 RouteUI::track() const
1583 {
1584         return boost::dynamic_pointer_cast<Track>(_route);
1585 }
1586
1587 bool
1588 RouteUI::is_audio_track () const
1589 {
1590         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1591 }
1592
1593 boost::shared_ptr<AudioTrack>
1594 RouteUI::audio_track() const
1595 {
1596         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1597 }
1598
1599 bool
1600 RouteUI::is_midi_track () const
1601 {
1602         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1603 }
1604
1605 boost::shared_ptr<MidiTrack>
1606 RouteUI::midi_track() const
1607 {
1608         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1609 }
1610
1611 bool
1612 RouteUI::has_audio_outputs () const
1613 {
1614         return (_route->n_outputs().n_audio() > 0);
1615 }
1616
1617 string
1618 RouteUI::name() const
1619 {
1620         return _route->name();
1621 }
1622
1623 void
1624 RouteUI::map_frozen ()
1625 {
1626         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1627
1628         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1629
1630         if (at) {
1631                 switch (at->freeze_state()) {
1632                 case AudioTrack::Frozen:
1633                         rec_enable_button->set_sensitive (false);
1634                         break;
1635                 default:
1636                         rec_enable_button->set_sensitive (true);
1637                         break;
1638                 }
1639         }
1640 }
1641
1642 void
1643 RouteUI::adjust_latency ()
1644 {
1645         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1646 }
1647
1648 void
1649 RouteUI::save_as_template ()
1650 {
1651         sys::path path;
1652         std::string safe_name;
1653         string name;
1654
1655         path = ARDOUR::user_route_template_directory ();
1656
1657         if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1658                 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1659                 return;
1660         }
1661
1662         Prompter p (true); // modal
1663
1664         p.set_title (_("Save As Template"));
1665         p.set_prompt (_("Template name:"));
1666         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1667         switch (p.run()) {
1668         case RESPONSE_ACCEPT:
1669                 break;
1670         default:
1671                 return;
1672         }
1673
1674         p.hide ();
1675         p.get_result (name, true);
1676
1677         safe_name = legalize_for_path (name);
1678         safe_name += template_suffix;
1679
1680         path /= safe_name;
1681
1682         _route->save_as_template (path.to_string(), name);
1683 }
1684
1685 void
1686 RouteUI::check_rec_enable_sensitivity ()
1687 {
1688         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1689                 rec_enable_button->set_sensitive (false);
1690         } else {
1691                 rec_enable_button->set_sensitive (true);
1692         }
1693
1694         update_monitoring_display ();
1695 }
1696
1697 void
1698 RouteUI::parameter_changed (string const & p)
1699 {
1700         /* this handles RC and per-session parameter changes */
1701
1702         if (p == "disable-disarm-during-roll") {
1703                 check_rec_enable_sensitivity ();
1704         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1705                 set_button_names ();
1706         } else if (p == "auto-input") {
1707                 update_monitoring_display ();
1708         }
1709 }
1710
1711 void
1712 RouteUI::step_gain_up ()
1713 {
1714         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1715 }
1716
1717 void
1718 RouteUI::page_gain_up ()
1719 {
1720         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1721 }
1722
1723 void
1724 RouteUI::step_gain_down ()
1725 {
1726         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1727 }
1728
1729 void
1730 RouteUI::page_gain_down ()
1731 {
1732         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1733 }
1734
1735 void
1736 RouteUI::open_remote_control_id_dialog ()
1737 {
1738         ArdourDialog dialog (_("Remote Control ID"));
1739
1740         uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1741
1742         HBox* hbox = manage (new HBox);
1743         hbox->set_spacing (6);
1744         hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1745         SpinButton* spin = manage (new SpinButton);
1746         spin->set_digits (0);
1747         spin->set_increments (1, 10);
1748         spin->set_range (0, limit);
1749         spin->set_value (_route->remote_control_id());
1750         hbox->pack_start (*spin);
1751         dialog.get_vbox()->pack_start (*hbox);
1752
1753         dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1754         dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1755
1756         dialog.show_all ();
1757         int const r = dialog.run ();
1758
1759         if (r == RESPONSE_ACCEPT) {
1760                 _route->set_remote_control_id (spin->get_value_as_int ());
1761         }
1762 }
1763
1764 void
1765 RouteUI::setup_invert_buttons ()
1766 {
1767         /* remove old invert buttons */
1768         for (list<BindableToggleButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1769                 _invert_button_box.remove (**i);
1770         }
1771
1772         _invert_buttons.clear ();
1773
1774         if (!_route || !_route->input()) {
1775                 return;
1776         }
1777
1778         uint32_t const N = _route->input()->n_ports().n_audio ();
1779
1780         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1781
1782         for (uint32_t i = 0; i < to_add; ++i) {
1783                 BindableToggleButton* b = manage (new BindableToggleButton);
1784                 b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_toggled), i, b));
1785                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1786
1787                 b->set_name (X_("MixerInvertButton"));
1788                 if (to_add == 1) {
1789                         b->add (*manage (new Label (X_("Ø"))));
1790                 } else {
1791                         b->add (*manage (new Label (string_compose (X_("Ø%1"), i + 1))));
1792                 }
1793
1794                 if (N <= 4) {
1795                         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));
1796                 } else {
1797                         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));
1798                 }
1799
1800                 _invert_buttons.push_back (b);
1801                 _invert_button_box.pack_start (*b);
1802         }
1803
1804         _invert_button_box.show_all ();
1805 }
1806
1807 void
1808 RouteUI::set_invert_button_state ()
1809 {
1810         ++_i_am_the_modifier;
1811
1812         uint32_t const N = _route->input()->n_ports().n_audio();
1813         if (N > _max_invert_buttons) {
1814                 _invert_buttons.front()->set_active (_route->phase_invert().any());
1815                 --_i_am_the_modifier;
1816                 return;
1817         }
1818
1819         int j = 0;
1820         for (list<BindableToggleButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1821                 (*i)->set_active (_route->phase_invert (j));
1822         }
1823
1824         --_i_am_the_modifier;
1825 }
1826
1827 void
1828 RouteUI::invert_toggled (uint32_t i, BindableToggleButton* b)
1829 {
1830         if (_i_am_the_modifier) {
1831                 return;
1832         }
1833
1834         uint32_t const N = _route->input()->n_ports().n_audio();
1835         if (N <= _max_invert_buttons) {
1836                 _route->set_phase_invert (i, b->get_active ());
1837         } else {
1838                 boost::dynamic_bitset<> p (N);
1839                 if (b->get_active ()) {
1840                         p.set ();
1841                 }
1842                 _route->set_phase_invert (p);
1843         }
1844 }
1845
1846 bool
1847 RouteUI::invert_press (GdkEventButton* ev)
1848 {
1849         using namespace Menu_Helpers;
1850
1851         if (ev->button != 3) {
1852                 return true;
1853         }
1854
1855         delete _invert_menu;
1856         _invert_menu = new Menu;
1857         _invert_menu->set_name ("ArdourContextMenu");
1858         MenuList& items = _invert_menu->items ();
1859
1860         uint32_t const N = _route->input()->n_ports().n_audio();
1861         for (uint32_t i = 0; i < N; ++i) {
1862                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1863                 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1864                 ++_i_am_the_modifier;
1865                 e->set_active (_route->phase_invert (i));
1866                 --_i_am_the_modifier;
1867         }
1868
1869         _invert_menu->popup (0, ev->time);
1870
1871         return false;
1872 }
1873
1874 void
1875 RouteUI::invert_menu_toggled (uint32_t c)
1876 {
1877         if (_i_am_the_modifier) {
1878                 return;
1879         }
1880
1881         _route->set_phase_invert (c, !_route->phase_invert (c));
1882 }
1883
1884 void
1885 RouteUI::set_invert_sensitive (bool yn)
1886 {
1887         for (list<BindableToggleButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1888                 (*b)->set_sensitive (yn);
1889         }
1890 }
1891
1892 void
1893 RouteUI::request_redraw ()
1894 {
1895         if (_route) {
1896                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1897         }
1898 }
1899
1900 /** The Route's gui_changed signal has been emitted */
1901 void
1902 RouteUI::route_gui_changed (string what_changed)
1903 {
1904         if (what_changed == "color") {
1905                 if (set_color_from_route () == 0) {
1906                         route_color_changed ();
1907                 }
1908         }
1909 }
1910
1911 /** @return the color that this route should use; it maybe its own,
1912     or it maybe that of its route group.
1913 */
1914 Gdk::Color
1915 RouteUI::color () const
1916 {
1917         RouteGroup* g = _route->route_group ();
1918         
1919         if (g && g->is_color()) {
1920                 return GroupTabs::group_color (g);
1921         }
1922
1923         return _color;
1924 }
1925
1926 void
1927 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
1928 {
1929         _showing_sends_to = send_to;
1930         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
1931 }
1932
1933 void
1934 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
1935 {
1936         if (_route == send_to) {
1937                 show_sends_button->set_active_state (Gtkmm2ext::Active);
1938                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
1939         } else {
1940                 show_sends_button->unset_active_state ();
1941                 send_blink_connection.disconnect ();
1942         }
1943 }
1944
1945 RouteGroup*
1946 RouteUI::route_group() const
1947 {
1948         return _route->route_group();
1949 }