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