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