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