Remove unused code.
[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 x;
991
992         if (Config->get_solo_control_is_listen_control()) {
993
994                 if ((bool) solo_button->active_state() != (x = _route->listening_via_monitor())) {
995                         ++_i_am_the_modifier;
996                         solo_button->set_active_state (Active);
997                         --_i_am_the_modifier;
998                 }
999
1000         } else {
1001
1002                 if ((bool) solo_button->active_state() != (x = _route->soloed())) {
1003                         ++_i_am_the_modifier;
1004                         if (x) {
1005                                 solo_button->set_active_state (Active);
1006                         } else {
1007                                 solo_button->unset_active_state();
1008                         }
1009                         --_i_am_the_modifier;
1010                 }
1011
1012         }
1013
1014         bool yn = _route->solo_safe ();
1015
1016         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1017                 solo_safe_check->set_active (yn);
1018         }
1019
1020         yn = _route->solo_isolated ();
1021
1022         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1023                 solo_isolated_check->set_active (yn);
1024         }
1025
1026         set_button_names ();
1027
1028         if (solo_isolated_led) {
1029                 if (_route->solo_isolated()) {
1030                         solo_isolated_led->set_active_state (Gtkmm2ext::Active);
1031                 } else {
1032                         solo_isolated_led->unset_active_state ();
1033                 }
1034         }
1035
1036         if (solo_safe_led) {
1037                 if (_route->solo_safe()) {
1038                         solo_safe_led->set_active_state (Gtkmm2ext::Active);
1039                 } else {
1040                         solo_safe_led->unset_active_state ();
1041                 }
1042         }
1043
1044         solo_button->set_active_state (solo_active_state (_route));
1045
1046         /* some changes to solo status can affect mute display, so catch up
1047          */
1048
1049         update_mute_display ();
1050 }
1051
1052 void
1053 RouteUI::solo_changed_so_update_mute ()
1054 {
1055         update_mute_display ();
1056 }
1057
1058 void
1059 RouteUI::mute_changed(void* /*src*/)
1060 {
1061         update_mute_display ();
1062 }
1063
1064 ActiveState
1065 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1066 {
1067         if (r->is_monitor()) {
1068                 return ActiveState(0);
1069         }
1070
1071
1072         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1073
1074                 if (r->muted ()) {
1075                         /* full mute */
1076                         return Active;
1077                 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1078                         /* master is NEVER muted by others */
1079                         return Mid;
1080                 } else {
1081                         /* no mute at all */
1082                         return ActiveState(0);
1083                 }
1084
1085         } else {
1086
1087                 if (r->muted()) {
1088                         /* full mute */
1089                         return Active;
1090                 } else {
1091                         /* no mute at all */
1092                         return ActiveState(0);
1093                 }
1094         }
1095
1096         return ActiveState(0);
1097 }
1098
1099 void
1100 RouteUI::update_mute_display ()
1101 {
1102         if (!_route) {
1103                 return;
1104         }
1105
1106         mute_button->set_active_state (mute_active_state (_session, _route));
1107 }
1108
1109 void
1110 RouteUI::route_rec_enable_changed ()
1111 {
1112         update_rec_display ();
1113         update_monitoring_display ();
1114 }
1115
1116 void
1117 RouteUI::session_rec_enable_changed ()
1118 {
1119         update_rec_display ();
1120         update_monitoring_display ();
1121 }
1122
1123 void
1124 RouteUI::update_rec_display ()
1125 {
1126         if (!rec_enable_button || !_route) {
1127                 return;
1128         }
1129
1130         if (_route->record_enabled()) {
1131                 switch (_session->record_status ()) {
1132                 case Session::Recording:
1133                         rec_enable_button->set_active_state (Active);
1134                         break;
1135
1136                 case Session::Disabled:
1137                 case Session::Enabled:
1138                         rec_enable_button->set_active_state (Mid);
1139                         break;
1140
1141                 }
1142
1143                 if (step_edit_item) {
1144                         step_edit_item->set_sensitive (false);
1145                 }
1146
1147         } else {
1148                 rec_enable_button->unset_active_state ();
1149
1150                 if (step_edit_item) {
1151                         step_edit_item->set_sensitive (true);
1152                 }
1153         }
1154
1155
1156         check_rec_enable_sensitivity ();
1157 }
1158
1159 void
1160 RouteUI::build_solo_menu (void)
1161 {
1162         using namespace Menu_Helpers;
1163
1164         solo_menu = new Menu;
1165         solo_menu->set_name ("ArdourContextMenu");
1166         MenuList& items = solo_menu->items();
1167         CheckMenuItem* check;
1168
1169         check = new CheckMenuItem(_("Solo Isolate"));
1170         check->set_active (_route->solo_isolated());
1171         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1172         items.push_back (CheckMenuElem(*check));
1173         solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1174         check->show_all();
1175
1176         check = new CheckMenuItem(_("Solo Safe"));
1177         check->set_active (_route->solo_safe());
1178         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1179         items.push_back (CheckMenuElem(*check));
1180         solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1181         check->show_all();
1182
1183         //items.push_back (SeparatorElem());
1184         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1185
1186 }
1187
1188 void
1189 RouteUI::build_mute_menu(void)
1190 {
1191         using namespace Menu_Helpers;
1192
1193         mute_menu = new Menu;
1194         mute_menu->set_name ("ArdourContextMenu");
1195
1196         MenuList& items = mute_menu->items();
1197
1198         pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1199         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1200         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1201         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1202         pre_fader_mute_check->show_all();
1203
1204         post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1205         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1206         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1207         items.push_back (CheckMenuElem(*post_fader_mute_check));
1208         post_fader_mute_check->show_all();
1209
1210         listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1211         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1212         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1213         items.push_back (CheckMenuElem(*listen_mute_check));
1214         listen_mute_check->show_all();
1215
1216         main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1217         init_mute_menu(MuteMaster::Main, main_mute_check);
1218         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1219         items.push_back (CheckMenuElem(*main_mute_check));
1220         main_mute_check->show_all();
1221
1222         //items.push_back (SeparatorElem());
1223         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1224
1225         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1226 }
1227
1228 void
1229 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1230 {
1231         check->set_active (_route->mute_points() & mp);
1232 }
1233
1234 void
1235 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1236 {
1237         if (check->get_active()) {
1238                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1239         } else {
1240                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1241         }
1242 }
1243
1244 void
1245 RouteUI::muting_change ()
1246 {
1247         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1248
1249         bool yn;
1250         MuteMaster::MutePoint current = _route->mute_points ();
1251
1252         yn = (current & MuteMaster::PreFader);
1253
1254         if (pre_fader_mute_check->get_active() != yn) {
1255                 pre_fader_mute_check->set_active (yn);
1256         }
1257
1258         yn = (current & MuteMaster::PostFader);
1259
1260         if (post_fader_mute_check->get_active() != yn) {
1261                 post_fader_mute_check->set_active (yn);
1262         }
1263
1264         yn = (current & MuteMaster::Listen);
1265
1266         if (listen_mute_check->get_active() != yn) {
1267                 listen_mute_check->set_active (yn);
1268         }
1269
1270         yn = (current & MuteMaster::Main);
1271
1272         if (main_mute_check->get_active() != yn) {
1273                 main_mute_check->set_active (yn);
1274         }
1275 }
1276
1277 bool
1278 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1279 {
1280         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1281                 return true;
1282         }
1283
1284         bool view = solo_isolated_led->active_state();
1285         bool model = _route->solo_isolated();
1286
1287         /* called BEFORE the view has changed */
1288
1289         if (ev->button == 1) {
1290                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1291
1292                         if (model) {
1293                                 /* disable isolate for all routes */
1294                                 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1295                         }
1296
1297                 } else {
1298                         if (model == view) {
1299
1300                                 /* flip just this route */
1301
1302                                 boost::shared_ptr<RouteList> rl (new RouteList);
1303                                 rl->push_back (_route);
1304                                 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1305                         }
1306                 }
1307         }
1308
1309         return true;
1310 }
1311
1312 bool
1313 RouteUI::solo_safe_button_release (GdkEventButton*)
1314 {
1315         _route->set_solo_safe (!solo_safe_led->active_state(), this);
1316         return true;
1317 }
1318
1319 void
1320 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1321 {
1322         bool view = check->get_active();
1323         bool model = _route->solo_isolated();
1324
1325         /* called AFTER the view has changed */
1326
1327         if (model != view) {
1328                 _route->set_solo_isolated (view, this);
1329         }
1330 }
1331
1332 void
1333 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1334 {
1335         _route->set_solo_safe (check->get_active(), this);
1336 }
1337
1338 /** Ask the user to choose a colour, and then set all selected tracks
1339  *  to that colour.
1340  */
1341 void
1342 RouteUI::choose_color ()
1343 {
1344         bool picked;
1345         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1346
1347         if (picked) {
1348                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1349                         boost::bind (&RouteUI::set_color, _1, color)
1350                         );
1351         }
1352 }
1353
1354 /** Set the route's own color.  This may not be used for display if
1355  *  the route is in a group which shares its color with its routes.
1356  */
1357 void
1358 RouteUI::set_color (const Gdk::Color & c)
1359 {
1360         char buf[64];
1361
1362         _color = c;
1363
1364         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1365
1366         /* note: we use the route state ID here so that color is the same for both
1367            the time axis view and the mixer strip
1368         */
1369         
1370         gui_object_state().set<string> (route_state_id(), X_("color"), buf);
1371         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1372 }
1373
1374 /** @return GUI state ID for things that are common to the route in all its representations */
1375 string
1376 RouteUI::route_state_id () const
1377 {
1378         return string_compose (X_("route %1"), _route->id().to_s());
1379 }
1380
1381 int
1382 RouteUI::set_color_from_route ()
1383 {
1384         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1385
1386         if (str.empty()) {
1387                 return 1;
1388         }
1389
1390         int r, g, b;
1391
1392         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1393
1394         _color.set_red (r);
1395         _color.set_green (g);
1396         _color.set_blue (b);
1397
1398         return 0;
1399 }
1400
1401 void
1402 RouteUI::remove_this_route (bool apply_to_selection)
1403 {
1404         if (apply_to_selection) {
1405                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1406         } else {
1407                 if ((route()->is_master() || route()->is_monitor()) &&
1408                     !Config->get_allow_special_bus_removal()) {
1409                         MessageDialog msg (_("That would be bad news ...."),
1410                                            false,
1411                                            Gtk::MESSAGE_INFO,
1412                                    Gtk::BUTTONS_OK);
1413                         msg.set_secondary_text (string_compose (_(
1414 "Removing the master or monitor bus is such a bad idea\n\
1415 that %1 is not going to allow it.\n\
1416 \n\
1417 If you really want to do this sort of thing\n\
1418 edit your ardour.rc file to set the\n\
1419 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1420
1421                         msg.present ();
1422                         msg.run ();
1423                         return;
1424                 }
1425
1426                 vector<string> choices;
1427                 string prompt;
1428
1429                 if (is_track()) {
1430                         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());
1431                 } else {
1432                         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());
1433                 }
1434
1435                 choices.push_back (_("No, do nothing."));
1436                 choices.push_back (_("Yes, remove it."));
1437
1438                 string title;
1439                 if (is_track()) {
1440                         title = _("Remove track");
1441                 } else {
1442                         title = _("Remove bus");
1443                 }
1444
1445                 Choice prompter (title, prompt, choices);
1446
1447                 if (prompter.run () == 1) {
1448                         Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1449                 }
1450         }
1451 }
1452
1453 gint
1454 RouteUI::idle_remove_this_route (RouteUI *rui)
1455 {
1456         rui->_session->remove_route (rui->route());
1457         return false;
1458 }
1459
1460 /** @return true if this name should be used for the route, otherwise false */
1461 bool
1462 RouteUI::verify_new_route_name (const std::string& name)
1463 {
1464         if (name.find (':') == string::npos) {
1465                 return true;
1466         }
1467         
1468         MessageDialog colon_msg (
1469                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1470                 false, MESSAGE_QUESTION, BUTTONS_NONE
1471                 );
1472         
1473         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1474         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1475
1476         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1477 }
1478
1479 void
1480 RouteUI::route_rename ()
1481 {
1482         ArdourPrompter name_prompter (true);
1483         string result;
1484         bool done = false;
1485
1486         if (is_track()) {
1487                 name_prompter.set_title (_("Rename Track"));
1488         } else {
1489                 name_prompter.set_title (_("Rename Bus"));
1490         }
1491         name_prompter.set_prompt (_("New name:"));
1492         name_prompter.set_initial_text (_route->name());
1493         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1494         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1495         name_prompter.show_all ();
1496
1497         while (!done) {
1498                 switch (name_prompter.run ()) {
1499                 case Gtk::RESPONSE_ACCEPT:
1500                         name_prompter.get_result (result);
1501                         name_prompter.hide ();
1502                         if (result.length()) {
1503                                 if (verify_new_route_name (result)) {
1504                                         _route->set_name (result);
1505                                         done = true;
1506                                 } else {
1507                                         /* back to name prompter */
1508                                 }
1509
1510                         } else {
1511                                 /* nothing entered, just get out of here */
1512                                 done = true;
1513                         }
1514                         break;
1515                 default:
1516                         done = true;
1517                         break;
1518                 }
1519         }
1520
1521         return;
1522
1523 }
1524
1525 void
1526 RouteUI::property_changed (const PropertyChange& what_changed)
1527 {
1528         if (what_changed.contains (ARDOUR::Properties::name)) {
1529                 name_label.set_text (_route->name());
1530         }
1531 }
1532
1533 void
1534 RouteUI::set_route_active (bool a, bool apply_to_selection)
1535 {
1536         if (apply_to_selection) {
1537                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1538         } else {
1539                 _route->set_active (a, this);
1540         }
1541 }
1542
1543 void
1544 RouteUI::toggle_denormal_protection ()
1545 {
1546         if (denormal_menu_item) {
1547
1548                 bool x;
1549
1550                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1551
1552                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1553                         _route->set_denormal_protection (x);
1554                 }
1555         }
1556 }
1557
1558 void
1559 RouteUI::denormal_protection_changed ()
1560 {
1561         if (denormal_menu_item) {
1562                 denormal_menu_item->set_active (_route->denormal_protection());
1563         }
1564 }
1565
1566 void
1567 RouteUI::disconnect_input ()
1568 {
1569         _route->input()->disconnect (this);
1570 }
1571
1572 void
1573 RouteUI::disconnect_output ()
1574 {
1575         _route->output()->disconnect (this);
1576 }
1577
1578 bool
1579 RouteUI::is_track () const
1580 {
1581         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1582 }
1583
1584 boost::shared_ptr<Track>
1585 RouteUI::track() const
1586 {
1587         return boost::dynamic_pointer_cast<Track>(_route);
1588 }
1589
1590 bool
1591 RouteUI::is_audio_track () const
1592 {
1593         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1594 }
1595
1596 boost::shared_ptr<AudioTrack>
1597 RouteUI::audio_track() const
1598 {
1599         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1600 }
1601
1602 bool
1603 RouteUI::is_midi_track () const
1604 {
1605         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1606 }
1607
1608 boost::shared_ptr<MidiTrack>
1609 RouteUI::midi_track() const
1610 {
1611         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1612 }
1613
1614 bool
1615 RouteUI::has_audio_outputs () const
1616 {
1617         return (_route->n_outputs().n_audio() > 0);
1618 }
1619
1620 string
1621 RouteUI::name() const
1622 {
1623         return _route->name();
1624 }
1625
1626 void
1627 RouteUI::map_frozen ()
1628 {
1629         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1630
1631         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1632
1633         if (at) {
1634                 switch (at->freeze_state()) {
1635                 case AudioTrack::Frozen:
1636                         rec_enable_button->set_sensitive (false);
1637                         break;
1638                 default:
1639                         rec_enable_button->set_sensitive (true);
1640                         break;
1641                 }
1642         }
1643 }
1644
1645 void
1646 RouteUI::adjust_latency ()
1647 {
1648         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1649 }
1650
1651 void
1652 RouteUI::save_as_template ()
1653 {
1654         sys::path path;
1655         std::string safe_name;
1656         string name;
1657
1658         path = ARDOUR::user_route_template_directory ();
1659
1660         if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1661                 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1662                 return;
1663         }
1664
1665         Prompter p (true); // modal
1666
1667         p.set_title (_("Save As Template"));
1668         p.set_prompt (_("Template name:"));
1669         p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1670         switch (p.run()) {
1671         case RESPONSE_ACCEPT:
1672                 break;
1673         default:
1674                 return;
1675         }
1676
1677         p.hide ();
1678         p.get_result (name, true);
1679
1680         safe_name = legalize_for_path (name);
1681         safe_name += template_suffix;
1682
1683         path /= safe_name;
1684
1685         _route->save_as_template (path.to_string(), name);
1686 }
1687
1688 void
1689 RouteUI::check_rec_enable_sensitivity ()
1690 {
1691         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1692                 rec_enable_button->set_sensitive (false);
1693         } else {
1694                 rec_enable_button->set_sensitive (true);
1695         }
1696
1697         update_monitoring_display ();
1698 }
1699
1700 void
1701 RouteUI::parameter_changed (string const & p)
1702 {
1703         /* this handles RC and per-session parameter changes */
1704
1705         if (p == "disable-disarm-during-roll") {
1706                 check_rec_enable_sensitivity ();
1707         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1708                 set_button_names ();
1709         } else if (p == "auto-input") {
1710                 update_monitoring_display ();
1711         }
1712 }
1713
1714 void
1715 RouteUI::step_gain_up ()
1716 {
1717         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1718 }
1719
1720 void
1721 RouteUI::page_gain_up ()
1722 {
1723         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1724 }
1725
1726 void
1727 RouteUI::step_gain_down ()
1728 {
1729         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1730 }
1731
1732 void
1733 RouteUI::page_gain_down ()
1734 {
1735         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1736 }
1737
1738 void
1739 RouteUI::open_remote_control_id_dialog ()
1740 {
1741         ArdourDialog dialog (_("Remote Control ID"));
1742
1743         uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1744
1745         HBox* hbox = manage (new HBox);
1746         hbox->set_spacing (6);
1747         hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1748         SpinButton* spin = manage (new SpinButton);
1749         spin->set_digits (0);
1750         spin->set_increments (1, 10);
1751         spin->set_range (0, limit);
1752         spin->set_value (_route->remote_control_id());
1753         hbox->pack_start (*spin);
1754         dialog.get_vbox()->pack_start (*hbox);
1755
1756         dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1757         dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1758
1759         dialog.show_all ();
1760         int const r = dialog.run ();
1761
1762         if (r == RESPONSE_ACCEPT) {
1763                 _route->set_remote_control_id (spin->get_value_as_int ());
1764         }
1765 }
1766
1767 void
1768 RouteUI::setup_invert_buttons ()
1769 {
1770         /* remove old invert buttons */
1771         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1772                 _invert_button_box.remove (**i);
1773         }
1774
1775         _invert_buttons.clear ();
1776
1777         if (!_route || !_route->input()) {
1778                 return;
1779         }
1780
1781         uint32_t const N = _route->input()->n_ports().n_audio ();
1782
1783         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1784
1785         for (uint32_t i = 0; i < to_add; ++i) {
1786                 ArdourButton* b = manage (new ArdourButton);
1787                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1788                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1789
1790                 b->set_name (X_("mixer strip button"));
1791                 if (to_add == 1) {
1792                         b->set_text (X_("Ø"));
1793                 } else {
1794                         b->set_text (string_compose (X_("Ø%1"), i + 1));
1795                 }
1796
1797                 if (N <= 4) {
1798                         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));
1799                 } else {
1800                         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));
1801                 }
1802
1803                 _invert_buttons.push_back (b);
1804                 _invert_button_box.pack_start (*b);
1805         }
1806
1807         _invert_button_box.set_spacing (1);
1808         _invert_button_box.show_all ();
1809 }
1810
1811 void
1812 RouteUI::set_invert_button_state ()
1813 {
1814         ++_i_am_the_modifier;
1815
1816         uint32_t const N = _route->input()->n_ports().n_audio();
1817         if (N > _max_invert_buttons) {
1818                 _invert_buttons.front()->set_active (_route->phase_invert().any());
1819                 --_i_am_the_modifier;
1820                 return;
1821         }
1822
1823         int j = 0;
1824         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1825                 (*i)->set_active (_route->phase_invert (j));
1826         }
1827
1828         --_i_am_the_modifier;
1829 }
1830
1831 bool
1832 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1833 {
1834         if (ev->button == 1 && i < _invert_buttons.size()) {
1835                 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1836                 return true;
1837         }
1838         return false;
1839 }
1840
1841
1842 bool
1843 RouteUI::invert_press (GdkEventButton* ev)
1844 {
1845         using namespace Menu_Helpers;
1846         
1847         if (ev->button != 3) {
1848                 return true;
1849         }
1850
1851         delete _invert_menu;
1852         _invert_menu = new Menu;
1853         _invert_menu->set_name ("ArdourContextMenu");
1854         MenuList& items = _invert_menu->items ();
1855
1856         uint32_t const N = _route->input()->n_ports().n_audio();
1857         for (uint32_t i = 0; i < N; ++i) {
1858                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1859                 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1860                 ++_i_am_the_modifier;
1861                 e->set_active (_route->phase_invert (i));
1862                 --_i_am_the_modifier;
1863         }
1864
1865         _invert_menu->popup (0, ev->time);
1866
1867         return false;
1868 }
1869
1870 void
1871 RouteUI::invert_menu_toggled (uint32_t c)
1872 {
1873         if (_i_am_the_modifier) {
1874                 return;
1875         }
1876
1877         _route->set_phase_invert (c, !_route->phase_invert (c));
1878 }
1879
1880 void
1881 RouteUI::set_invert_sensitive (bool yn)
1882 {
1883         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1884                 (*b)->set_sensitive (yn);
1885         }
1886 }
1887
1888 void
1889 RouteUI::request_redraw ()
1890 {
1891         if (_route) {
1892                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1893         }
1894 }
1895
1896 /** The Route's gui_changed signal has been emitted */
1897 void
1898 RouteUI::route_gui_changed (string what_changed)
1899 {
1900         if (what_changed == "color") {
1901                 if (set_color_from_route () == 0) {
1902                         route_color_changed ();
1903                 }
1904         }
1905 }
1906
1907 /** @return the color that this route should use; it maybe its own,
1908     or it maybe that of its route group.
1909 */
1910 Gdk::Color
1911 RouteUI::color () const
1912 {
1913         RouteGroup* g = _route->route_group ();
1914         
1915         if (g && g->is_color()) {
1916                 return GroupTabs::group_color (g);
1917         }
1918
1919         return _color;
1920 }
1921
1922 void
1923 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
1924 {
1925         _showing_sends_to = send_to;
1926         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
1927 }
1928
1929 void
1930 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
1931 {
1932         if (_route == send_to) {
1933                 show_sends_button->set_active_state (Gtkmm2ext::Active);
1934                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
1935         } else {
1936                 show_sends_button->unset_active_state ();
1937                 send_blink_connection.disconnect ();
1938         }
1939 }
1940
1941 RouteGroup*
1942 RouteUI::route_group() const
1943 {
1944         return _route->route_group();
1945 }