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