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