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