finish recent revert
[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         /* leave _color alone in the group case so that tracks can retain their
1339          * own pre-group colors.
1340          */
1341
1342         char buf[64];
1343         _color = c;
1344         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1345         
1346         /* note: we use the route state ID here so that color is the same for both
1347            the time axis view and the mixer strip
1348         */
1349         
1350         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1351         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1352 }
1353
1354 /** @return GUI state ID for things that are common to the route in all its representations */
1355 string
1356 RouteUI::route_state_id () const
1357 {
1358         return string_compose (X_("route %1"), _route->id().to_s());
1359 }
1360
1361 int
1362 RouteUI::set_color_from_route ()
1363 {
1364         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1365
1366         if (str.empty()) {
1367                 return 1;
1368         }
1369
1370         int r, g, b;
1371
1372         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1373
1374         _color.set_red (r);
1375         _color.set_green (g);
1376         _color.set_blue (b);
1377
1378         return 0;
1379 }
1380
1381 void
1382 RouteUI::remove_this_route (bool apply_to_selection)
1383 {
1384         if (apply_to_selection) {
1385                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1386         } else {
1387                 if ((route()->is_master() || route()->is_monitor()) &&
1388                     !Config->get_allow_special_bus_removal()) {
1389                         MessageDialog msg (_("That would be bad news ...."),
1390                                            false,
1391                                            Gtk::MESSAGE_INFO,
1392                                    Gtk::BUTTONS_OK);
1393                         msg.set_secondary_text (string_compose (_(
1394 "Removing the master or monitor bus is such a bad idea\n\
1395 that %1 is not going to allow it.\n\
1396 \n\
1397 If you really want to do this sort of thing\n\
1398 edit your ardour.rc file to set the\n\
1399 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1400
1401                         msg.present ();
1402                         msg.run ();
1403                         return;
1404                 }
1405
1406                 vector<string> choices;
1407                 string prompt;
1408
1409                 if (is_track()) {
1410                         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());
1411                 } else {
1412                         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());
1413                 }
1414
1415                 choices.push_back (_("No, do nothing."));
1416                 choices.push_back (_("Yes, remove it."));
1417
1418                 string title;
1419                 if (is_track()) {
1420                         title = _("Remove track");
1421                 } else {
1422                         title = _("Remove bus");
1423                 }
1424
1425                 Choice prompter (title, prompt, choices);
1426
1427                 if (prompter.run () == 1) {
1428                         Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1429                 }
1430         }
1431 }
1432
1433 gint
1434 RouteUI::idle_remove_this_route (RouteUI *rui)
1435 {
1436         rui->_session->remove_route (rui->route());
1437         return false;
1438 }
1439
1440 /** @return true if this name should be used for the route, otherwise false */
1441 bool
1442 RouteUI::verify_new_route_name (const std::string& name)
1443 {
1444         if (name.find (':') == string::npos) {
1445                 return true;
1446         }
1447         
1448         MessageDialog colon_msg (
1449                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1450                 false, MESSAGE_QUESTION, BUTTONS_NONE
1451                 );
1452         
1453         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1454         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1455
1456         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1457 }
1458
1459 void
1460 RouteUI::route_rename ()
1461 {
1462         ArdourPrompter name_prompter (true);
1463         string result;
1464         bool done = false;
1465
1466         if (is_track()) {
1467                 name_prompter.set_title (_("Rename Track"));
1468         } else {
1469                 name_prompter.set_title (_("Rename Bus"));
1470         }
1471         name_prompter.set_prompt (_("New name:"));
1472         name_prompter.set_initial_text (_route->name());
1473         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1474         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1475         name_prompter.show_all ();
1476
1477         while (!done) {
1478                 switch (name_prompter.run ()) {
1479                 case Gtk::RESPONSE_ACCEPT:
1480                         name_prompter.get_result (result);
1481                         name_prompter.hide ();
1482                         if (result.length()) {
1483                                 if (verify_new_route_name (result)) {
1484                                         _route->set_name (result);
1485                                         done = true;
1486                                 } else {
1487                                         /* back to name prompter */
1488                                 }
1489
1490                         } else {
1491                                 /* nothing entered, just get out of here */
1492                                 done = true;
1493                         }
1494                         break;
1495                 default:
1496                         done = true;
1497                         break;
1498                 }
1499         }
1500
1501         return;
1502
1503 }
1504
1505 void
1506 RouteUI::property_changed (const PropertyChange& what_changed)
1507 {
1508         if (what_changed.contains (ARDOUR::Properties::name)) {
1509                 name_label.set_text (_route->name());
1510         }
1511 }
1512
1513 void
1514 RouteUI::set_route_active (bool a, bool apply_to_selection)
1515 {
1516         if (apply_to_selection) {
1517                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1518         } else {
1519                 _route->set_active (a, this);
1520         }
1521 }
1522
1523 void
1524 RouteUI::toggle_denormal_protection ()
1525 {
1526         if (denormal_menu_item) {
1527
1528                 bool x;
1529
1530                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1531
1532                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1533                         _route->set_denormal_protection (x);
1534                 }
1535         }
1536 }
1537
1538 void
1539 RouteUI::denormal_protection_changed ()
1540 {
1541         if (denormal_menu_item) {
1542                 denormal_menu_item->set_active (_route->denormal_protection());
1543         }
1544 }
1545
1546 void
1547 RouteUI::disconnect_input ()
1548 {
1549         _route->input()->disconnect (this);
1550 }
1551
1552 void
1553 RouteUI::disconnect_output ()
1554 {
1555         _route->output()->disconnect (this);
1556 }
1557
1558 bool
1559 RouteUI::is_track () const
1560 {
1561         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1562 }
1563
1564 boost::shared_ptr<Track>
1565 RouteUI::track() const
1566 {
1567         return boost::dynamic_pointer_cast<Track>(_route);
1568 }
1569
1570 bool
1571 RouteUI::is_audio_track () const
1572 {
1573         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1574 }
1575
1576 boost::shared_ptr<AudioTrack>
1577 RouteUI::audio_track() const
1578 {
1579         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1580 }
1581
1582 bool
1583 RouteUI::is_midi_track () const
1584 {
1585         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1586 }
1587
1588 boost::shared_ptr<MidiTrack>
1589 RouteUI::midi_track() const
1590 {
1591         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1592 }
1593
1594 bool
1595 RouteUI::has_audio_outputs () const
1596 {
1597         return (_route->n_outputs().n_audio() > 0);
1598 }
1599
1600 string
1601 RouteUI::name() const
1602 {
1603         return _route->name();
1604 }
1605
1606 void
1607 RouteUI::map_frozen ()
1608 {
1609         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1610
1611         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1612
1613         if (at) {
1614                 switch (at->freeze_state()) {
1615                 case AudioTrack::Frozen:
1616                         rec_enable_button->set_sensitive (false);
1617                         break;
1618                 default:
1619                         rec_enable_button->set_sensitive (true);
1620                         break;
1621                 }
1622         }
1623 }
1624
1625 void
1626 RouteUI::adjust_latency ()
1627 {
1628         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1629 }
1630
1631 void
1632 RouteUI::save_as_template ()
1633 {
1634         std::string path;
1635         std::string safe_name;
1636         string name;
1637
1638         path = ARDOUR::user_route_template_directory ();
1639
1640         if (g_mkdir_with_parents (path.c_str(), 0755)) {
1641                 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1642                 return;
1643         }
1644
1645         Prompter p (true); // modal
1646
1647         p.set_title (_("Save As Template"));
1648         p.set_prompt (_("Template name:"));
1649         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1650         switch (p.run()) {
1651         case RESPONSE_ACCEPT:
1652                 break;
1653         default:
1654                 return;
1655         }
1656
1657         p.hide ();
1658         p.get_result (name, true);
1659
1660         safe_name = legalize_for_path (name);
1661         safe_name += template_suffix;
1662
1663         path = Glib::build_filename (path, safe_name);
1664
1665         _route->save_as_template (path, name);
1666 }
1667
1668 void
1669 RouteUI::check_rec_enable_sensitivity ()
1670 {
1671         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1672                 rec_enable_button->set_sensitive (false);
1673         } else {
1674                 rec_enable_button->set_sensitive (true);
1675         }
1676
1677         update_monitoring_display ();
1678 }
1679
1680 void
1681 RouteUI::parameter_changed (string const & p)
1682 {
1683         /* this handles RC and per-session parameter changes */
1684
1685         if (p == "disable-disarm-during-roll") {
1686                 check_rec_enable_sensitivity ();
1687         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1688                 set_button_names ();
1689         } else if (p == "auto-input") {
1690                 update_monitoring_display ();
1691         }
1692 }
1693
1694 void
1695 RouteUI::step_gain_up ()
1696 {
1697         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1698 }
1699
1700 void
1701 RouteUI::page_gain_up ()
1702 {
1703         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1704 }
1705
1706 void
1707 RouteUI::step_gain_down ()
1708 {
1709         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1710 }
1711
1712 void
1713 RouteUI::page_gain_down ()
1714 {
1715         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1716 }
1717
1718 void
1719 RouteUI::open_remote_control_id_dialog ()
1720 {
1721         ArdourDialog dialog (_("Remote Control ID"));
1722         SpinButton* spin = 0;
1723
1724         dialog.get_vbox()->set_border_width (18);
1725
1726         if (Config->get_remote_model() == UserOrdered) {
1727                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1728                 
1729                 HBox* hbox = manage (new HBox);
1730                 hbox->set_spacing (6);
1731                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1732                 spin = manage (new SpinButton);
1733                 spin->set_digits (0);
1734                 spin->set_increments (1, 10);
1735                 spin->set_range (0, limit);
1736                 spin->set_value (_route->remote_control_id());
1737                 hbox->pack_start (*spin);
1738                 dialog.get_vbox()->pack_start (*hbox);
1739                 
1740                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1741                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1742         } else {
1743                 Label* l = manage (new Label());
1744                 if (_route->is_master() || _route->is_monitor()) {
1745                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1746                                                          "The remote control ID of %3 cannot be changed."),
1747                                                        Glib::Markup::escape_text (_route->name()),
1748                                                        _route->remote_control_id(),
1749                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1750                 } else {
1751                         l->set_markup (string_compose (_("The remote control ID of %6 is: %3\n\n\n"
1752                                                          "Remote Control IDs are currently determined by track/bus ordering in %1\n\n"
1753                                                          "%4Use the User Interaction tab of the Preferences window if you want to change this%5"),
1754                                                        (Config->get_remote_model() == MixerOrdered ? _("the mixer") : ("the editor")),
1755                                                        (is_track() ? _("track") : _("bus")),
1756                                                        _route->remote_control_id(),
1757                                                        "<span size=\"small\" style=\"italic\">",
1758                                                        "</span>",
1759                                                        Glib::Markup::escape_text (_route->name())));
1760                 }
1761                 dialog.get_vbox()->pack_start (*l);
1762                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1763         }
1764
1765         dialog.show_all ();
1766         int const r = dialog.run ();
1767
1768         if (r == RESPONSE_ACCEPT && spin) {
1769                 _route->set_remote_control_id (spin->get_value_as_int ());
1770         }
1771 }
1772
1773 void
1774 RouteUI::setup_invert_buttons ()
1775 {
1776         /* remove old invert buttons */
1777         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1778                 _invert_button_box.remove (**i);
1779         }
1780
1781         _invert_buttons.clear ();
1782
1783         if (!_route || !_route->input()) {
1784                 return;
1785         }
1786
1787         uint32_t const N = _route->input()->n_ports().n_audio ();
1788
1789         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1790
1791         for (uint32_t i = 0; i < to_add; ++i) {
1792                 ArdourButton* b = manage (new ArdourButton);
1793                 b->set_size_request(20,20);
1794                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1795                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1796
1797                 b->set_name (X_("invert button"));
1798                 if (to_add == 1) {
1799                         if (N > 1) {
1800                                 b->set_text (string_compose (X_("Ø (%1)"), N));
1801                         } else {
1802                                 b->set_text (X_("Ø"));
1803                         }
1804                 } else {
1805                         b->set_text (string_compose (X_("Ø%1"), i + 1));
1806                 }
1807
1808                 if (N <= _max_invert_buttons) {
1809                         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));
1810                 } else {
1811                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1812                 }
1813
1814                 _invert_buttons.push_back (b);
1815                 _invert_button_box.pack_start (*b);
1816         }
1817
1818         _invert_button_box.set_spacing (1);
1819         _invert_button_box.show_all ();
1820 }
1821
1822 void
1823 RouteUI::set_invert_button_state ()
1824 {
1825         ++_i_am_the_modifier;
1826
1827         uint32_t const N = _route->input()->n_ports().n_audio();
1828         if (N > _max_invert_buttons) {
1829
1830                 /* One button for many channels; explicit active if all channels are inverted,
1831                    implicit active if some are, off if none are.
1832                 */
1833
1834                 ArdourButton* b = _invert_buttons.front ();
1835                 
1836                 if (_route->phase_invert().count() == _route->phase_invert().size()) {
1837                         b->set_active_state (Gtkmm2ext::ExplicitActive);
1838                 } else if (_route->phase_invert().any()) {
1839                         b->set_active_state (Gtkmm2ext::ImplicitActive);
1840                 } else {
1841                         b->set_active_state (Gtkmm2ext::Off);
1842                 }
1843
1844         } else {
1845
1846                 /* One button per channel; just set active */
1847
1848                 int j = 0;
1849                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1850                         (*i)->set_active (_route->phase_invert (j));
1851                 }
1852                 
1853         }
1854
1855         --_i_am_the_modifier;
1856 }
1857
1858 bool
1859 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1860 {
1861         if (ev->button == 1 && i < _invert_buttons.size()) {
1862                 uint32_t const N = _route->input()->n_ports().n_audio ();
1863                 if (N <= _max_invert_buttons) {
1864                         /* left-click inverts phase so long as we have a button per channel */
1865                         _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1866                         return true;
1867                 }
1868         }
1869         return false;
1870 }
1871
1872
1873 bool
1874 RouteUI::invert_press (GdkEventButton* ev)
1875 {
1876         using namespace Menu_Helpers;
1877
1878         uint32_t const N = _route->input()->n_ports().n_audio();
1879         if (N <= _max_invert_buttons && ev->button != 3) {
1880                 /* If we have an invert button per channel, we only pop
1881                    up a menu on right-click; left click is handled
1882                    on release.
1883                 */
1884                 return true;
1885         }
1886         
1887         delete _invert_menu;
1888         _invert_menu = new Menu;
1889         _invert_menu->set_name ("ArdourContextMenu");
1890         MenuList& items = _invert_menu->items ();
1891
1892         for (uint32_t i = 0; i < N; ++i) {
1893                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1894                 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1895                 ++_i_am_the_modifier;
1896                 e->set_active (_route->phase_invert (i));
1897                 --_i_am_the_modifier;
1898         }
1899
1900         _invert_menu->popup (0, ev->time);
1901
1902         return false;
1903 }
1904
1905 void
1906 RouteUI::invert_menu_toggled (uint32_t c)
1907 {
1908         if (_i_am_the_modifier) {
1909                 return;
1910         }
1911
1912         _route->set_phase_invert (c, !_route->phase_invert (c));
1913 }
1914
1915 void
1916 RouteUI::set_invert_sensitive (bool yn)
1917 {
1918         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1919                 (*b)->set_sensitive (yn);
1920         }
1921 }
1922
1923 void
1924 RouteUI::request_redraw ()
1925 {
1926         if (_route) {
1927                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1928         }
1929 }
1930
1931 /** The Route's gui_changed signal has been emitted */
1932 void
1933 RouteUI::route_gui_changed (string what_changed)
1934 {
1935         if (what_changed == "color") {
1936                 if (set_color_from_route () == 0) {
1937                         route_color_changed ();
1938                 }
1939         }
1940 }
1941
1942 /** @return the color that this route should use; it maybe its own,
1943     or it maybe that of its route group.
1944 */
1945 Gdk::Color
1946 RouteUI::color () const
1947 {
1948         RouteGroup* g = _route->route_group ();
1949         
1950         if (g && g->is_color()) {
1951                 return GroupTabs::group_color (g);
1952         }
1953
1954         return _color;
1955 }
1956
1957 void
1958 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
1959 {
1960         _showing_sends_to = send_to;
1961         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
1962 }
1963
1964 void
1965 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
1966 {
1967         if (_route == send_to) {
1968                 show_sends_button->set_active (true);
1969                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
1970         } else {
1971                 show_sends_button->set_active (false);
1972                 send_blink_connection.disconnect ();
1973         }
1974 }
1975
1976 RouteGroup*
1977 RouteUI::route_group() const
1978 {
1979         return _route->route_group();
1980 }