a variety of changes that get closer to correctly functioning behaviour for VCA solo...
[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 <boost/algorithm/string.hpp>
21
22 #include <gtkmm2ext/gtk_ui.h>
23 #include <gtkmm2ext/choice.h>
24 #include <gtkmm2ext/doi.h>
25 #include <gtkmm2ext/bindable_button.h>
26 #include <gtkmm2ext/barcontroller.h>
27 #include <gtkmm2ext/gtk_ui.h>
28 #include <gtkmm2ext/utils.h>
29
30 #include "pbd/memento_command.h"
31 #include "pbd/stacktrace.h"
32 #include "pbd/controllable.h"
33 #include "pbd/enumwriter.h"
34
35 #include "ardour/dB.h"
36 #include "ardour/route_group.h"
37 #include "ardour/solo_isolate_control.h"
38 #include "ardour/vca.h"
39 #include "ardour/vca_manager.h"
40 #include "ardour/audio_track.h"
41 #include "ardour/audioengine.h"
42 #include "ardour/filename_extensions.h"
43 #include "ardour/midi_track.h"
44 #include "ardour/monitor_control.h"
45 #include "ardour/internal_send.h"
46 #include "ardour/profile.h"
47 #include "ardour/phase_control.h"
48 #include "ardour/send.h"
49 #include "ardour/route.h"
50 #include "ardour/session.h"
51 #include "ardour/template_utils.h"
52
53 #include "ardour_ui.h"
54 #include "editor.h"
55 #include "route_ui.h"
56 #include "ardour_button.h"
57 #include "keyboard.h"
58 #include "utils.h"
59 #include "plugin_pin_dialog.h"
60 #include "prompter.h"
61 #include "gui_thread.h"
62 #include "ardour_dialog.h"
63 #include "latency_gui.h"
64 #include "mixer_strip.h"
65 #include "automation_time_axis.h"
66 #include "route_time_axis.h"
67 #include "group_tabs.h"
68 #include "timers.h"
69 #include "ui_config.h"
70
71
72 #include "i18n.h"
73 using namespace Gtk;
74 using namespace Gtkmm2ext;
75 using namespace ARDOUR;
76 using namespace ARDOUR_UI_UTILS;
77 using namespace PBD;
78 using namespace std;
79
80 uint32_t RouteUI::_max_invert_buttons = 3;
81 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
82 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
83 std::string RouteUI::program_port_prefix;
84
85 RouteUI::RouteUI (ARDOUR::Session* sess)
86         : AxisView(sess)
87         , mute_menu(0)
88         , solo_menu(0)
89         , sends_menu(0)
90         , record_menu(0)
91         , comment_window(0)
92         , comment_area(0)
93         , input_selector (0)
94         , output_selector (0)
95         , _invert_menu(0)
96 {
97         if (program_port_prefix.empty()) {
98                 // compare to gtk2_ardour/port_group.cc
99                 string lpn (PROGRAM_NAME);
100                 boost::to_lower (lpn);
101                 program_port_prefix = lpn + ":"; // e.g. "ardour:"
102         }
103         if (sess) init ();
104 }
105
106 RouteUI::~RouteUI()
107 {
108         if (_route) {
109                 gui_object_state().remove_node (route_state_id());
110         }
111
112         _route.reset (); /* drop reference to route, so that it can be cleaned up */
113         route_connections.drop_connections ();
114
115         delete solo_menu;
116         delete mute_menu;
117         delete sends_menu;
118         delete record_menu;
119         delete comment_window;
120         delete input_selector;
121         delete output_selector;
122         delete _invert_menu;
123
124         send_blink_connection.disconnect ();
125         rec_blink_connection.disconnect ();
126 }
127
128 void
129 RouteUI::init ()
130 {
131         self_destruct = true;
132         mute_menu = 0;
133         solo_menu = 0;
134         sends_menu = 0;
135         record_menu = 0;
136         _invert_menu = 0;
137         pre_fader_mute_check = 0;
138         post_fader_mute_check = 0;
139         listen_mute_check = 0;
140         main_mute_check = 0;
141         solo_safe_check = 0;
142         solo_isolated_check = 0;
143         solo_isolated_led = 0;
144         solo_safe_led = 0;
145         _solo_release = 0;
146         _mute_release = 0;
147         denormal_menu_item = 0;
148         step_edit_item = 0;
149         rec_safe_item = 0;
150         multiple_mute_change = false;
151         multiple_solo_change = false;
152         _i_am_the_modifier = 0;
153         vca_button = 0;
154
155         input_selector = 0;
156         output_selector = 0;
157
158         setup_invert_buttons ();
159
160         mute_button = manage (new ArdourButton);
161         mute_button->set_name ("mute button");
162         UI::instance()->set_tip (mute_button, _("Mute this track"), "");
163
164         solo_button = manage (new ArdourButton);
165         solo_button->set_name ("solo button");
166         UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
167         solo_button->set_no_show_all (true);
168
169         rec_enable_button = manage (new ArdourButton);
170         rec_enable_button->set_name ("record enable button");
171         rec_enable_button->set_icon (ArdourIcon::RecButton);
172         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
173
174         if (UIConfiguration::instance().get_blink_rec_arm()) {
175                 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
176         }
177
178         show_sends_button = manage (new ArdourButton);
179         show_sends_button->set_name ("send alert button");
180         UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
181
182         monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
183         monitor_input_button->set_name ("monitor button");
184         monitor_input_button->set_text (_("In"));
185         UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
186         monitor_input_button->set_no_show_all (true);
187
188         monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
189         monitor_disk_button->set_name ("monitor button");
190         monitor_disk_button->set_text (_("Disk"));
191         UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
192         monitor_disk_button->set_no_show_all (true);
193
194         _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
195         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
196         _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
197
198         _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
199         Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
200
201         rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
202         rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
203
204         show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
205         show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
206
207         solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
208         solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
209         mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
210         mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
211
212         monitor_input_button->set_distinct_led_click (false);
213         monitor_disk_button->set_distinct_led_click (false);
214
215         monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
216         monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
217
218         monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
219         monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
220
221         BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
222 }
223
224 void
225 RouteUI::reset ()
226 {
227         route_connections.drop_connections ();
228
229         delete solo_menu;
230         solo_menu = 0;
231
232         delete mute_menu;
233         mute_menu = 0;
234
235         denormal_menu_item = 0;
236 }
237
238 void
239 RouteUI::self_delete ()
240 {
241         delete this;
242 }
243
244 void
245 RouteUI::set_route (boost::shared_ptr<Route> rp)
246 {
247         reset ();
248
249         _route = rp;
250
251         if (set_color_from_route()) {
252                 set_color (unique_random_color());
253         }
254
255         if (self_destruct) {
256                 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
257         }
258
259         delete input_selector;
260         input_selector = 0;
261
262         delete output_selector;
263         output_selector = 0;
264
265         mute_button->set_controllable (_route->mute_control());
266         solo_button->set_controllable (_route->solo_control());
267
268         _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
269
270         _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this), gui_context());
271
272         _route->mute_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context());
273         _route->solo_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
274         _route->solo_safe_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
275         _route->solo_isolate_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
276         _route->phase_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
277
278         if (is_track()) {
279                 track()->FreezeChange.connect (*this, invalidator (*this), boost::bind (&RouteUI::map_frozen, this), gui_context());
280                 track()->TrackModeChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::track_mode_changed, this), gui_context());
281                 track_mode_changed();
282         }
283
284
285         _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
286
287         _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
288         _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
289
290         if (_session->writable() && is_track()) {
291                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
292
293                 t->rec_enable_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
294                 t->rec_safe_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
295
296                 rec_enable_button->show();
297                 rec_enable_button->set_controllable (t->rec_enable_control());
298
299                 if (is_midi_track()) {
300                         midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
301                                                                     boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
302                 }
303
304         }
305
306         /* this will work for busses and tracks, and needs to be called to
307            set up the name entry/name label display.
308         */
309
310         if (is_track()) {
311                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
312                 t->monitoring_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_monitoring_display, this), gui_context());
313
314                 update_monitoring_display ();
315         }
316
317         mute_button->unset_flags (Gtk::CAN_FOCUS);
318         solo_button->unset_flags (Gtk::CAN_FOCUS);
319
320         mute_button->show();
321
322         if (_route->is_monitor() || _route->is_master()) {
323                 solo_button->hide ();
324         } else {
325                 solo_button->show();
326         }
327
328         map_frozen ();
329
330         setup_invert_buttons ();
331         set_invert_button_state ();
332
333         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
334         bus_send_display_changed (s);
335
336         update_mute_display ();
337         update_solo_display ();
338
339         if (!UIConfiguration::instance().get_blink_rec_arm()) {
340                 blink_rec_display(true); // set initial rec-en button state
341         }
342
343         check_rec_enable_sensitivity ();
344         maybe_add_route_print_mgr ();
345         route_color_changed();
346 }
347
348 void
349 RouteUI::polarity_changed ()
350 {
351         if (!_route) {
352                 return;
353         }
354
355         set_invert_button_state ();
356 }
357
358 bool
359 RouteUI::mute_press (GdkEventButton* ev)
360 {
361         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
362                 return true;
363         }
364
365         //if this is a binding action, let the ArdourButton handle it
366         if ( BindingProxy::is_bind_action(ev) )
367                 return false;
368
369         multiple_mute_change = false;
370
371         if (Keyboard::is_context_menu_event (ev)) {
372
373                 if (mute_menu == 0){
374                         build_mute_menu();
375                 }
376
377                 mute_menu->popup(0,ev->time);
378
379                 return true;
380
381         } else {
382
383                 if (Keyboard::is_button2_event (ev)) {
384                         // button2-click is "momentary"
385
386                         _mute_release = new SoloMuteRelease (_route->mute_control()->muted ());
387                 }
388
389                 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
390
391                         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
392
393                                 /* toggle mute on everything (but
394                                  * exclude the master and monitor)
395                                  *
396                                  * because we are going to erase
397                                  * elements of the list we need to work
398                                  * on a copy.
399                                  */
400
401                                 boost::shared_ptr<RouteList> copy (new RouteList);
402
403                                 *copy = *_session->get_routes ();
404
405                                 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
406                                         if ((*i)->is_master() || (*i)->is_monitor()) {
407                                                 i = copy->erase (i);
408                                         } else {
409                                                 ++i;
410                                         }
411                                 }
412
413                                 if (_mute_release) {
414                                         _mute_release->routes = copy;
415                                 }
416
417                                 DisplaySuspender ds;
418                                 _session->set_controls (route_list_to_control_list (copy, &Route::mute_control), _route->muted_by_self() ? 0.0 : 1.0, Controllable::UseGroup);
419
420                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
421
422                                 /* Primary-button1 inverts the implication of
423                                    the group being active. If the group is
424                                    active (for mute), then this modifier means
425                                    "do not apply to mute". If the group is
426                                    inactive (for mute), then this modifier
427                                    means "apply to route". This is all
428                                    accomplished by passing just the actual
429                                    route, along with the InverseGroup group
430                                    control disposition.
431
432                                    NOTE: Primary-button2 is MIDI learn.
433                                 */
434
435                                 boost::shared_ptr<RouteList> rl;
436
437                                 if (ev->button == 1) {
438
439                                         rl.reset (new RouteList);
440                                         rl->push_back (_route);
441
442                                         if (_mute_release) {
443                                                 _mute_release->routes = rl;
444                                         }
445
446                                         DisplaySuspender ds;
447                                         _session->set_controls (route_list_to_control_list (rl, &Route::mute_control), _route->muted_by_self() ? 0.0 : 1.0, Controllable::InverseGroup);
448                                 }
449
450                         } else {
451
452                                 /* plain click applies change to this route */
453
454                                 boost::shared_ptr<RouteList> rl (new RouteList);
455                                 rl->push_back (_route);
456
457                                 if (_mute_release) {
458                                         _mute_release->routes = rl;
459                                 }
460
461                                 _session->set_control (_route->mute_control(), _route->muted_by_self() ? 0.0 : 1.0, Controllable::UseGroup);
462
463                         }
464                 }
465         }
466
467         return false;
468 }
469
470 bool
471 RouteUI::mute_release (GdkEventButton* /*ev*/)
472 {
473         if (_mute_release){
474                 DisplaySuspender ds;
475                 _session->set_controls (route_list_to_control_list (_mute_release->routes, &Route::mute_control), _mute_release->active, Controllable::UseGroup);
476                 delete _mute_release;
477                 _mute_release = 0;
478         }
479
480         return false;
481 }
482
483 void
484 RouteUI::edit_output_configuration ()
485 {
486         if (output_selector == 0) {
487
488                 boost::shared_ptr<Send> send;
489                 boost::shared_ptr<IO> output;
490
491                 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
492                         if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
493                                 output = send->output();
494                         } else {
495                                 output = _route->output ();
496                         }
497                 } else {
498                         output = _route->output ();
499                 }
500
501                 output_selector = new IOSelectorWindow (_session, output);
502         }
503
504         if (output_selector->is_visible()) {
505                 output_selector->get_toplevel()->get_window()->raise();
506         } else {
507                 output_selector->present ();
508         }
509
510         //output_selector->set_keep_above (true);
511 }
512
513 void
514 RouteUI::edit_input_configuration ()
515 {
516         if (input_selector == 0) {
517                 input_selector = new IOSelectorWindow (_session, _route->input());
518         }
519
520         if (input_selector->is_visible()) {
521                 input_selector->get_toplevel()->get_window()->raise();
522         } else {
523                 input_selector->present ();
524         }
525
526         //input_selector->set_keep_above (true);
527 }
528
529 bool
530 RouteUI::solo_press(GdkEventButton* ev)
531 {
532         /* ignore double/triple clicks */
533
534         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
535                 return true;
536         }
537
538         //if this is a binding action, let the ArdourButton handle it
539         if ( BindingProxy::is_bind_action(ev) )
540                 return false;
541
542         multiple_solo_change = false;
543
544         if (Keyboard::is_context_menu_event (ev)) {
545
546                 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
547                     ! (solo_safe_led && solo_safe_led->is_visible())) {
548
549                         if (solo_menu == 0) {
550                                 build_solo_menu ();
551                         }
552
553                         solo_menu->popup (1, ev->time);
554                 }
555
556         } else {
557
558                 if (Keyboard::is_button2_event (ev)) {
559
560                         // button2-click is "momentary"
561                         _solo_release = new SoloMuteRelease (_route->self_soloed());
562                 }
563
564                 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
565
566                         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
567
568                                 /* Primary-Tertiary-click applies change to all routes */
569
570                                 if (_solo_release) {
571                                         _solo_release->routes = _session->get_routes ();
572                                 }
573
574                                 DisplaySuspender ds;
575                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Route::solo_control), !_route->solo_control()->get_value(), Controllable::UseGroup);
576
577                         } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
578
579                                 // Primary-Secondary-click: exclusively solo this track
580
581                                 if (_solo_release) {
582                                         _solo_release->exclusive = true;
583
584                                         boost::shared_ptr<RouteList> routes = _session->get_routes();
585
586                                         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
587                                                 if ((*i)->soloed ()) {
588                                                         _solo_release->routes_on->push_back (*i);
589                                                 } else {
590                                                         _solo_release->routes_off->push_back (*i);
591                                                 }
592                                         }
593                                 }
594
595                                 if (Config->get_solo_control_is_listen_control()) {
596                                         /* ??? we need a just_one_listen() method */
597                                 } else {
598                                         DisplaySuspender ds;
599                                         boost::shared_ptr<ControlList> cl (new ControlList);
600                                         cl->push_back (_route->solo_control());
601                                         _session->set_controls (cl, 1.0, Controllable::NoGroup);
602                                 }
603
604                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
605
606                                 // shift-click: toggle solo isolated status
607
608                                 _route->solo_isolate_control()->set_value (_route->solo_isolate_control()->get_value() ? 0.0 : 1.0, Controllable::UseGroup);
609                                 delete _solo_release;
610                                 _solo_release = 0;
611
612                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
613
614                                 /* Primary-button1: solo mix group.
615                                    NOTE: Primary-button2 is MIDI learn.
616                                 */
617
618                                 /* Primary-button1 applies change to the mix group even if it is not active
619                                    NOTE: Primary-button2 is MIDI learn.
620                                 */
621
622                                 boost::shared_ptr<RouteList> rl;
623
624                                 if (ev->button == 1) {
625
626                                         /* Primary-button1 inverts the implication of
627                                            the group being active. If the group is
628                                            active (for solo), then this modifier means
629                                            "do not apply to solo". If the group is
630                                            inactive (for mute), then this modifier
631                                            means "apply to route". This is all
632                                            accomplished by passing just the actual
633                                            route, along with the InverseGroup group
634                                            control disposition.
635
636                                            NOTE: Primary-button2 is MIDI learn.
637                                         */
638
639                                         rl.reset (new RouteList);
640                                         rl->push_back (_route);
641
642                                         if (_solo_release) {
643                                                 _solo_release->routes = rl;
644                                         }
645
646                                         DisplaySuspender ds;
647
648                                         _session->set_controls (route_list_to_control_list (rl, &Route::solo_control), !_route->self_soloed(), Controllable::InverseGroup);
649                                 }
650
651                                 delete _solo_release;
652                                 _solo_release = 0;
653
654                         } else {
655
656                                 /* click: solo this route */
657
658                                 boost::shared_ptr<RouteList> rl (new RouteList);
659                                 rl->push_back (route());
660
661                                 if (_solo_release) {
662                                         _solo_release->routes = rl;
663                                 }
664
665                                 DisplaySuspender ds;
666                                 _session->set_controls (route_list_to_control_list (rl, &Route::solo_control), !_route->self_soloed(), Controllable::UseGroup);
667                         }
668                 }
669         }
670
671         return false;
672 }
673
674 bool
675 RouteUI::solo_release (GdkEventButton* /*ev*/)
676 {
677         if (_solo_release) {
678
679                 if (_solo_release->exclusive) {
680
681                 } else {
682                         DisplaySuspender ds;
683                         _session->set_controls (route_list_to_control_list (_solo_release->routes, &Route::solo_control), _solo_release->active ? 1.0 : 0.0, Controllable::UseGroup);
684                 }
685
686                 delete _solo_release;
687                 _solo_release = 0;
688         }
689
690         return false;
691 }
692
693 bool
694 RouteUI::rec_enable_press(GdkEventButton* ev)
695 {
696         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
697                 return true;
698         }
699
700         //if this is a binding action, let the ArdourButton handle it
701         if ( BindingProxy::is_bind_action(ev) )
702                 return false;
703
704         if (!_session->engine().connected()) {
705                 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
706                 msg.run ();
707                 return false;
708         }
709
710         if (is_midi_track()) {
711
712                 /* rec-enable button exits from step editing */
713
714                 if (midi_track()->step_editing()) {
715                         midi_track()->set_step_editing (false);
716                         return false;
717                 }
718         }
719
720         if (is_track() && rec_enable_button) {
721
722                 if (Keyboard::is_button2_event (ev)) {
723
724                         //rec arm does not have a momentary mode
725                         return false;
726
727                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
728
729                         DisplaySuspender ds;
730                         _session->set_controls (route_list_to_control_list (_session->get_routes(), &Track::rec_enable_control), !track()->rec_enable_control()->get_value(), Controllable::NoGroup);
731
732                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
733
734                         /* Primary-button1 applies change to the route group (even if it is not active)
735                            NOTE: Primary-button2 is MIDI learn.
736                         */
737
738                         if (ev->button == 1) {
739
740                                 boost::shared_ptr<RouteList> rl;
741
742                                 rl.reset (new RouteList);
743                                 rl->push_back (_route);
744
745                                 DisplaySuspender ds;
746                                 _session->set_controls (route_list_to_control_list (rl, &Track::rec_enable_control), !track()->rec_enable_control()->get_value(), Controllable::InverseGroup);
747                         }
748
749                 } else if (Keyboard::is_context_menu_event (ev)) {
750
751                         /* do this on release */
752
753                 } else {
754
755                         boost::shared_ptr<Track> trk = track();
756                         _session->set_control (trk->rec_enable_control(), !trk->rec_enable_control()->get_value(), Controllable::UseGroup);
757                 }
758         }
759
760         return false;
761 }
762
763 void
764 RouteUI::update_monitoring_display ()
765 {
766         if (!_route) {
767                 return;
768         }
769
770         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
771
772         if (!t) {
773                 return;
774         }
775
776         MonitorState ms = t->monitoring_state();
777
778         if (t->monitoring_control()->monitoring_choice() & MonitorInput) {
779                 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
780         } else {
781                 if (ms & MonitoringInput) {
782                         monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
783                 } else {
784                         monitor_input_button->unset_active_state ();
785                 }
786         }
787
788         if (t->monitoring_control()->monitoring_choice() & MonitorDisk) {
789                 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
790         } else {
791                 if (ms & MonitoringDisk) {
792                         monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
793                 } else {
794                         monitor_disk_button->unset_active_state ();
795                 }
796         }
797 }
798
799 bool
800 RouteUI::monitor_input_press(GdkEventButton*)
801 {
802         return false;
803 }
804
805 bool
806 RouteUI::monitor_input_release(GdkEventButton* ev)
807 {
808         return monitor_release (ev, MonitorInput);
809 }
810
811 bool
812 RouteUI::monitor_disk_press (GdkEventButton*)
813 {
814         return false;
815 }
816
817 bool
818 RouteUI::monitor_disk_release (GdkEventButton* ev)
819 {
820         return monitor_release (ev, MonitorDisk);
821 }
822
823 bool
824 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
825 {
826         if (ev->button != 1) {
827                 return false;
828         }
829
830         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
831
832         if (!t) {
833                 return true;
834         }
835
836         MonitorChoice mc;
837         boost::shared_ptr<RouteList> rl;
838
839         /* XXX for now, monitoring choices are orthogonal. cue monitoring
840            will follow in 3.X but requires mixing the input and playback (disk)
841            signal together, which requires yet more buffers.
842         */
843
844         if (t->monitoring_control()->monitoring_choice() & monitor_choice) {
845                 mc = MonitorChoice (t->monitoring_control()->monitoring_choice() & ~monitor_choice);
846         } else {
847                 /* this line will change when the options are non-orthogonal */
848                 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
849                 mc = monitor_choice;
850         }
851
852         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
853                 rl = _session->get_routes ();
854
855         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
856                 if (_route->route_group() && _route->route_group()->is_monitoring()) {
857                         rl = _route->route_group()->route_list();
858                 } else {
859                         rl.reset (new RouteList);
860                         rl->push_back (route());
861                 }
862         } else {
863                 rl.reset (new RouteList);
864                 rl->push_back (route());
865         }
866
867         DisplaySuspender ds;
868         _session->set_controls (route_list_to_control_list (rl, &Route::monitoring_control), (double) mc, Controllable::UseGroup);
869
870         return false;
871 }
872
873 void
874 RouteUI::build_record_menu ()
875 {
876         if (!record_menu) {
877                 record_menu = new Menu;
878                 record_menu->set_name ("ArdourContextMenu");
879                 using namespace Menu_Helpers;
880                 MenuList& items = record_menu->items();
881
882                 items.push_back (CheckMenuElem (_("Rec-Safe"), sigc::mem_fun (*this, &RouteUI::toggle_rec_safe)));
883                 rec_safe_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
884
885                 if (is_midi_track()) {
886                         items.push_back (SeparatorElem());
887                         items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
888                         step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
889                 }
890         }
891
892         if (step_edit_item) {
893                 if (track()->rec_enable_control()->get_value()) {
894                         step_edit_item->set_sensitive (false);
895                 }
896                 step_edit_item->set_active (midi_track()->step_editing());
897         }
898         if (rec_safe_item) {
899                 rec_safe_item->set_sensitive (!_route->record_enabled());
900                 rec_safe_item->set_active (_route->record_safe());
901         }
902 }
903
904 void
905 RouteUI::toggle_step_edit ()
906 {
907         if (!is_midi_track() || track()->rec_enable_control()->get_value()) {
908                 return;
909         }
910
911         midi_track()->set_step_editing (step_edit_item->get_active());
912 }
913
914 void
915 RouteUI::toggle_rec_safe ()
916 {
917         if (_route->record_enabled()) {
918                 return;
919         }
920         DisplaySuspender ds;
921         boost::shared_ptr<RouteList> rl (new RouteList);
922         rl->push_back (_route);
923         _session->set_record_safe (rl, rec_safe_item->get_active (), Session::rt_cleanup);
924 }
925
926 void
927 RouteUI::step_edit_changed (bool yn)
928 {
929         if (yn) {
930                 if (rec_enable_button) {
931                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
932                 }
933
934                 start_step_editing ();
935
936                 if (step_edit_item) {
937                         step_edit_item->set_active (true);
938                 }
939
940         } else {
941
942                 if (rec_enable_button) {
943                         rec_enable_button->unset_active_state ();
944                 }
945
946                 stop_step_editing ();
947
948                 if (step_edit_item) {
949                         step_edit_item->set_active (false);
950                 }
951         }
952 }
953
954 bool
955 RouteUI::rec_enable_release (GdkEventButton* ev)
956 {
957         if (Keyboard::is_context_menu_event (ev)) {
958                 build_record_menu ();
959                 if (record_menu) {
960                         record_menu->popup (1, ev->time);
961                 }
962                 return false;
963         }
964
965         return false;
966 }
967
968 void
969 RouteUI::build_sends_menu ()
970 {
971         using namespace Menu_Helpers;
972
973         sends_menu = new Menu;
974         sends_menu->set_name ("ArdourContextMenu");
975         MenuList& items = sends_menu->items();
976
977         items.push_back (
978                 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
979                 );
980
981         items.push_back (
982                 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
983                 );
984
985         items.push_back (
986                 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
987                 );
988
989         items.push_back (
990                 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
991                 );
992
993         items.push_back (
994                 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
995                 );
996
997         items.push_back (
998                 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
999
1000         items.push_back (
1001                 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
1002                 );
1003
1004         items.push_back (
1005                 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
1006                 );
1007
1008         items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
1009         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
1010         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
1011
1012 }
1013
1014 void
1015 RouteUI::create_sends (Placement p, bool include_buses)
1016 {
1017         _session->globally_add_internal_sends (_route, p, include_buses);
1018 }
1019
1020 void
1021 RouteUI::create_selected_sends (Placement p, bool include_buses)
1022 {
1023         boost::shared_ptr<RouteList> rlist (new RouteList);
1024         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
1025
1026         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
1027                 RouteTimeAxisView* rtv;
1028                 RouteUI* rui;
1029                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1030                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1031                                 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1032                                         rlist->push_back (rui->route());
1033                                 }
1034                         }
1035                 }
1036         }
1037
1038         _session->add_internal_sends (_route, p, rlist);
1039 }
1040
1041 void
1042 RouteUI::set_sends_gain_from_track ()
1043 {
1044         _session->globally_set_send_gains_from_track (_route);
1045 }
1046
1047 void
1048 RouteUI::set_sends_gain_to_zero ()
1049 {
1050         _session->globally_set_send_gains_to_zero (_route);
1051 }
1052
1053 void
1054 RouteUI::set_sends_gain_to_unity ()
1055 {
1056         _session->globally_set_send_gains_to_unity (_route);
1057 }
1058
1059 bool
1060 RouteUI::show_sends_press(GdkEventButton* ev)
1061 {
1062         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1063                 return true;
1064         }
1065
1066         if (!is_track() && show_sends_button) {
1067
1068                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1069
1070                         // do nothing on midi sigc::bind event
1071                         return false;
1072
1073                 } else if (Keyboard::is_context_menu_event (ev)) {
1074
1075                         if (sends_menu == 0) {
1076                                 build_sends_menu ();
1077                         }
1078
1079                         sends_menu->popup (0, ev->time);
1080
1081                 } else {
1082
1083                         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1084
1085                         if (s == _route) {
1086                                 set_showing_sends_to (boost::shared_ptr<Route> ());
1087                         } else {
1088                                 set_showing_sends_to (_route);
1089                         }
1090                 }
1091         }
1092
1093         return true;
1094 }
1095
1096 bool
1097 RouteUI::show_sends_release (GdkEventButton*)
1098 {
1099         return true;
1100 }
1101
1102 void
1103 RouteUI::send_blink (bool onoff)
1104 {
1105         if (!show_sends_button) {
1106                 return;
1107         }
1108
1109         if (onoff) {
1110                 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1111         } else {
1112                 show_sends_button->unset_active_state ();
1113         }
1114 }
1115
1116 Gtkmm2ext::ActiveState
1117 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1118 {
1119         if (!r->can_solo()) {
1120                 return Gtkmm2ext::Off;
1121         }
1122
1123         if (Config->get_solo_control_is_listen_control()) {
1124
1125                 if (r->listening_via_monitor()) {
1126                         return Gtkmm2ext::ExplicitActive;
1127                 } else {
1128                         return Gtkmm2ext::Off;
1129                 }
1130
1131         }
1132
1133         if (r->soloed()) {
1134                 if (!r->self_soloed()) {
1135                         return Gtkmm2ext::ImplicitActive;
1136                 } else {
1137                         return Gtkmm2ext::ExplicitActive;
1138                 }
1139         } else {
1140                 return Gtkmm2ext::Off;
1141         }
1142 }
1143
1144 Gtkmm2ext::ActiveState
1145 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1146 {
1147         if (r->is_master() || r->is_monitor()) {
1148                 return Gtkmm2ext::Off;
1149         }
1150
1151         if (r->solo_isolate_control()->solo_isolated()) {
1152                 return Gtkmm2ext::ExplicitActive;
1153         } else {
1154                 return Gtkmm2ext::Off;
1155         }
1156 }
1157
1158 Gtkmm2ext::ActiveState
1159 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1160 {
1161         if (r->is_master() || r->is_monitor()) {
1162                 return Gtkmm2ext::Off;
1163         }
1164
1165         if (r->solo_safe_control()->solo_safe()) {
1166                 return Gtkmm2ext::ExplicitActive;
1167         } else {
1168                 return Gtkmm2ext::Off;
1169         }
1170 }
1171
1172 void
1173 RouteUI::update_solo_display ()
1174 {
1175         bool yn = _route->solo_safe_control()->solo_safe ();
1176
1177         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1178                 solo_safe_check->set_active (yn);
1179         }
1180
1181         yn = _route->solo_isolate_control()->solo_isolated ();
1182
1183         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1184                 solo_isolated_check->set_active (yn);
1185         }
1186
1187         set_button_names ();
1188
1189         if (solo_isolated_led) {
1190                 if (_route->solo_isolate_control()->solo_isolated()) {
1191                         solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1192                 } else {
1193                         solo_isolated_led->unset_active_state ();
1194                 }
1195         }
1196
1197         if (solo_safe_led) {
1198                 if (_route->solo_safe_control()->solo_safe()) {
1199                         solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1200                 } else {
1201                         solo_safe_led->unset_active_state ();
1202                 }
1203         }
1204
1205         solo_button->set_active_state (solo_active_state (_route));
1206
1207         /* some changes to solo status can affect mute display, so catch up
1208          */
1209
1210         update_mute_display ();
1211 }
1212
1213 void
1214 RouteUI::solo_changed_so_update_mute ()
1215 {
1216         update_mute_display ();
1217 }
1218
1219 ActiveState
1220 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1221 {
1222         if (r->is_monitor()) {
1223                 return ActiveState(0);
1224         }
1225
1226         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1227
1228                 std::cerr << r->name() << " self " << r->mute_control()->muted_by_self() << " others " << r->muted_by_others() << " soloing " << r->muted_by_others_soloing() << std::endl;
1229
1230                 if (r->mute_control()->muted_by_self ()) {
1231                         /* full mute */
1232                         return Gtkmm2ext::ExplicitActive;
1233                 } else if (r->muted_by_others_soloing () || r->muted_by_others()) {
1234                         /* this will reflect both solo mutes AND master mutes */
1235                         return Gtkmm2ext::ImplicitActive;
1236                 } else {
1237                         /* no mute at all */
1238                         return Gtkmm2ext::Off;
1239                 }
1240
1241         } else {
1242
1243                 if (r->mute_control()->muted_by_self()) {
1244                         /* full mute */
1245                         return Gtkmm2ext::ExplicitActive;
1246                 } else if (r->muted_by_others()) {
1247                         /* this shows only master mutes, not mute-by-others-soloing */
1248                         return Gtkmm2ext::ImplicitActive;
1249                 } else {
1250                         /* no mute at all */
1251                         return Gtkmm2ext::Off;
1252                 }
1253         }
1254
1255         return ActiveState(0);
1256 }
1257
1258 void
1259 RouteUI::update_mute_display ()
1260 {
1261         if (!_route) {
1262                 return;
1263         }
1264
1265         mute_button->set_active_state (mute_active_state (_session, _route));
1266 }
1267
1268 void
1269 RouteUI::update_vca_display ()
1270 {
1271         if (!vca_button) {
1272                 return;
1273         }
1274
1275         VCAList vcas (_session->vca_manager().vcas());
1276         string label;
1277
1278         for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) {
1279                 if (_route->slaved_to (*v)) {
1280                         if (!label.empty()) {
1281                                 label += ' ';
1282                         }
1283                         label += PBD::to_string ((*v)->number(), std::dec);
1284                 }
1285         }
1286
1287         if (label.empty()) {
1288                 label = _("-vca-");
1289                 vca_button->set_active_state (Gtkmm2ext::Off);
1290         } else {
1291                 vca_button->set_active_state (Gtkmm2ext::ExplicitActive);
1292         }
1293
1294         vca_button->set_text (label);
1295 }
1296
1297 void
1298 RouteUI::route_rec_enable_changed ()
1299 {
1300         blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
1301         update_monitoring_display ();
1302 }
1303
1304 void
1305 RouteUI::session_rec_enable_changed ()
1306 {
1307         blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
1308         update_monitoring_display ();
1309 }
1310
1311 void
1312 RouteUI::blink_rec_display (bool blinkOn)
1313 {
1314         if (!rec_enable_button || !_route) {
1315                 return;
1316         }
1317
1318         if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1319                 return;
1320         }
1321
1322         if (!is_track()) {
1323                 return;
1324         }
1325
1326         if (track()->rec_enable_control()->get_value()) {
1327                 switch (_session->record_status ()) {
1328                 case Session::Recording:
1329                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1330                         break;
1331
1332                 case Session::Disabled:
1333                 case Session::Enabled:
1334                         if (UIConfiguration::instance().get_blink_rec_arm()) {
1335                                 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1336                         } else {
1337                                 rec_enable_button->set_active_state ( ImplicitActive );
1338                         }
1339                         break;
1340                 }
1341
1342                 if (step_edit_item) {
1343                         step_edit_item->set_sensitive (false);
1344                 }
1345
1346         } else {
1347                 rec_enable_button->unset_active_state ();
1348
1349                 if (step_edit_item) {
1350                         step_edit_item->set_sensitive (true);
1351                 }
1352         }
1353
1354         check_rec_enable_sensitivity ();
1355 }
1356
1357 void
1358 RouteUI::build_solo_menu (void)
1359 {
1360         using namespace Menu_Helpers;
1361
1362         solo_menu = new Menu;
1363         solo_menu->set_name ("ArdourContextMenu");
1364         MenuList& items = solo_menu->items();
1365         Gtk::CheckMenuItem* check;
1366
1367         check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1368         check->set_active (_route->solo_isolate_control()->solo_isolated());
1369         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1370         items.push_back (CheckMenuElem(*check));
1371         solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1372         check->show_all();
1373
1374         check = new Gtk::CheckMenuItem(_("Solo Safe"));
1375         check->set_active (_route->solo_safe_control()->solo_safe());
1376         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1377         items.push_back (CheckMenuElem(*check));
1378         solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1379         check->show_all();
1380
1381         //items.push_back (SeparatorElem());
1382         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1383
1384 }
1385
1386 void
1387 RouteUI::build_mute_menu(void)
1388 {
1389         using namespace Menu_Helpers;
1390
1391         mute_menu = new Menu;
1392         mute_menu->set_name ("ArdourContextMenu");
1393
1394         MenuList& items = mute_menu->items();
1395
1396         pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1397         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1398         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1399         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1400         pre_fader_mute_check->show_all();
1401
1402         post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1403         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1404         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1405         items.push_back (CheckMenuElem(*post_fader_mute_check));
1406         post_fader_mute_check->show_all();
1407
1408         listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1409         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1410         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1411         items.push_back (CheckMenuElem(*listen_mute_check));
1412         listen_mute_check->show_all();
1413
1414         main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1415         init_mute_menu(MuteMaster::Main, main_mute_check);
1416         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1417         items.push_back (CheckMenuElem(*main_mute_check));
1418         main_mute_check->show_all();
1419
1420         //items.push_back (SeparatorElem());
1421         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1422
1423         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1424 }
1425
1426 void
1427 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1428 {
1429         check->set_active (_route->mute_control()->mute_points() & mp);
1430 }
1431
1432 void
1433 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1434 {
1435         if (check->get_active()) {
1436                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() | mp));
1437         } else {
1438                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() & ~mp));
1439         }
1440 }
1441
1442 void
1443 RouteUI::muting_change ()
1444 {
1445         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1446
1447         bool yn;
1448         MuteMaster::MutePoint current = _route->mute_control()->mute_points ();
1449
1450         yn = (current & MuteMaster::PreFader);
1451
1452         if (pre_fader_mute_check->get_active() != yn) {
1453                 pre_fader_mute_check->set_active (yn);
1454         }
1455
1456         yn = (current & MuteMaster::PostFader);
1457
1458         if (post_fader_mute_check->get_active() != yn) {
1459                 post_fader_mute_check->set_active (yn);
1460         }
1461
1462         yn = (current & MuteMaster::Listen);
1463
1464         if (listen_mute_check->get_active() != yn) {
1465                 listen_mute_check->set_active (yn);
1466         }
1467
1468         yn = (current & MuteMaster::Main);
1469
1470         if (main_mute_check->get_active() != yn) {
1471                 main_mute_check->set_active (yn);
1472         }
1473 }
1474
1475 bool
1476 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1477 {
1478         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1479                 return true;
1480         }
1481
1482         bool view = solo_isolated_led->active_state();
1483         bool model = _route->solo_isolate_control()->solo_isolated();
1484
1485         /* called BEFORE the view has changed */
1486
1487         if (ev->button == 1) {
1488                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1489
1490                         if (model) {
1491                                 /* disable isolate for all routes */
1492                                 DisplaySuspender ds;
1493                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Route::solo_isolate_control), 0.0, Controllable::NoGroup);
1494                         } else {
1495                                 /* enable isolate for all routes */
1496                                 DisplaySuspender ds;
1497                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Route::solo_isolate_control), 1.0, Controllable::NoGroup);
1498                         }
1499
1500                 } else {
1501
1502                         if (model == view) {
1503
1504                                 /* flip just this route */
1505
1506                                 boost::shared_ptr<RouteList> rl (new RouteList);
1507                                 rl->push_back (_route);
1508                                 DisplaySuspender ds;
1509                                 _session->set_controls (route_list_to_control_list (rl, &Route::solo_isolate_control), view ? 0.0 : 1.0, Controllable::NoGroup);
1510                         }
1511                 }
1512         }
1513
1514         return false;
1515 }
1516
1517 bool
1518 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1519 {
1520         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1521                 return true;
1522         }
1523
1524         bool view = solo_safe_led->active_state();
1525         bool model = _route->solo_safe_control()->solo_safe();
1526
1527         if (ev->button == 1) {
1528                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1529                         boost::shared_ptr<RouteList> rl (_session->get_routes());
1530                         if (model) {
1531                                 /* disable solo safe for all routes */
1532                                 DisplaySuspender ds;
1533                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1534                                         (*i)->solo_safe_control()->set_value (0.0, Controllable::NoGroup);
1535                                 }
1536                         } else {
1537                                 /* enable solo safe for all routes */
1538                                 DisplaySuspender ds;
1539                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1540                                         (*i)->solo_safe_control()->set_value (1.0, Controllable::NoGroup);
1541                                 }
1542                         }
1543                 }
1544                 else {
1545                         if (model == view) {
1546                                 /* flip just this route */
1547                                 _route->solo_safe_control()->set_value (view ? 0.0 : 1.0, Controllable::NoGroup);
1548                         }
1549                 }
1550         }
1551
1552         return false;
1553 }
1554
1555 void
1556 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1557 {
1558         bool view = check->get_active();
1559         bool model = _route->solo_isolate_control()->solo_isolated();
1560
1561         /* called AFTER the view has changed */
1562
1563         if (model != view) {
1564                 _route->solo_isolate_control()->set_value (view ? 1.0 : 0.0, Controllable::UseGroup);
1565         }
1566 }
1567
1568 void
1569 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1570 {
1571         _route->solo_safe_control()->set_value (check->get_active() ? 1.0 : 0.0, Controllable::UseGroup);
1572 }
1573
1574 /** Ask the user to choose a colour, and then apply that color to my route
1575  */
1576 void
1577 RouteUI::choose_color ()
1578 {
1579         bool picked;
1580         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1581
1582         if (picked) {
1583                 set_color(color);
1584         }
1585 }
1586
1587 /** Set the route's own color.  This may not be used for display if
1588  *  the route is in a group which shares its color with its routes.
1589  */
1590 void
1591 RouteUI::set_color (const Gdk::Color & c)
1592 {
1593         /* leave _color alone in the group case so that tracks can retain their
1594          * own pre-group colors.
1595          */
1596
1597         char buf[64];
1598         _color = c;
1599         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1600
1601         /* note: we use the route state ID here so that color is the same for both
1602            the time axis view and the mixer strip
1603         */
1604
1605         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1606         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1607 }
1608
1609 /** @return GUI state ID for things that are common to the route in all its representations */
1610 string
1611 RouteUI::route_state_id () const
1612 {
1613         return string_compose (X_("route %1"), _route->id().to_s());
1614 }
1615
1616 int
1617 RouteUI::set_color_from_route ()
1618 {
1619         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1620
1621         if (str.empty()) {
1622                 return 1;
1623         }
1624
1625         int r, g, b;
1626
1627         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1628
1629         _color.set_red (r);
1630         _color.set_green (g);
1631         _color.set_blue (b);
1632
1633         return 0;
1634 }
1635
1636 /** @return true if this name should be used for the route, otherwise false */
1637 bool
1638 RouteUI::verify_new_route_name (const std::string& name)
1639 {
1640         if (name.find (':') == string::npos) {
1641                 return true;
1642         }
1643
1644         MessageDialog colon_msg (
1645                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1646                 false, MESSAGE_QUESTION, BUTTONS_NONE
1647                 );
1648
1649         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1650         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1651
1652         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1653 }
1654
1655 void
1656 RouteUI::route_rename ()
1657 {
1658         ArdourPrompter name_prompter (true);
1659         string result;
1660         bool done = false;
1661
1662         if (is_track()) {
1663                 name_prompter.set_title (_("Rename Track"));
1664         } else {
1665                 name_prompter.set_title (_("Rename Bus"));
1666         }
1667         name_prompter.set_prompt (_("New name:"));
1668         name_prompter.set_initial_text (_route->name());
1669         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1670         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1671         name_prompter.show_all ();
1672
1673         while (!done) {
1674                 switch (name_prompter.run ()) {
1675                 case Gtk::RESPONSE_ACCEPT:
1676                         name_prompter.get_result (result);
1677                         name_prompter.hide ();
1678                         if (result.length()) {
1679                                 if (verify_new_route_name (result)) {
1680                                         _route->set_name (result);
1681                                         done = true;
1682                                 } else {
1683                                         /* back to name prompter */
1684                                 }
1685
1686                         } else {
1687                                 /* nothing entered, just get out of here */
1688                                 done = true;
1689                         }
1690                         break;
1691                 default:
1692                         done = true;
1693                         break;
1694                 }
1695         }
1696
1697         return;
1698
1699 }
1700
1701 void
1702 RouteUI::property_changed (const PropertyChange& what_changed)
1703 {
1704         if (what_changed.contains (ARDOUR::Properties::name)) {
1705                 name_label.set_text (_route->name());
1706         }
1707 }
1708
1709 void
1710 RouteUI::toggle_comment_editor ()
1711 {
1712 //      if (ignore_toggle) {
1713 //              return;
1714 //      }
1715
1716         if (comment_window && comment_window->is_visible ()) {
1717                 comment_window->hide ();
1718         } else {
1719                 open_comment_editor ();
1720         }
1721 }
1722
1723
1724 void
1725 RouteUI::open_comment_editor ()
1726 {
1727         if (comment_window == 0) {
1728                 setup_comment_editor ();
1729         }
1730
1731         string title;
1732         title = _route->name();
1733         title += _(": comment editor");
1734
1735         comment_window->set_title (title);
1736         comment_window->present();
1737 }
1738
1739 void
1740 RouteUI::setup_comment_editor ()
1741 {
1742         comment_window = new ArdourWindow (""); // title will be reset to show route
1743         comment_window->set_skip_taskbar_hint (true);
1744         comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1745         comment_window->set_default_size (400, 200);
1746
1747         comment_area = manage (new TextView());
1748         comment_area->set_name ("MixerTrackCommentArea");
1749         comment_area->set_wrap_mode (WRAP_WORD);
1750         comment_area->set_editable (true);
1751         comment_area->get_buffer()->set_text (_route->comment());
1752         comment_area->show ();
1753
1754         comment_window->add (*comment_area);
1755 }
1756
1757 void
1758 RouteUI::comment_changed ()
1759 {
1760         ignore_comment_edit = true;
1761         if (comment_area) {
1762                 comment_area->get_buffer()->set_text (_route->comment());
1763         }
1764         ignore_comment_edit = false;
1765 }
1766
1767 void
1768 RouteUI::comment_editor_done_editing ()
1769 {
1770         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1771
1772         string const str = comment_area->get_buffer()->get_text();
1773         if (str == _route->comment ()) {
1774                 return;
1775         }
1776
1777         _route->set_comment (str, this);
1778 }
1779
1780 void
1781 RouteUI::set_route_active (bool a, bool apply_to_selection)
1782 {
1783         if (apply_to_selection) {
1784                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1785         } else {
1786                 _route->set_active (a, this);
1787         }
1788 }
1789
1790 void
1791 RouteUI::duplicate_selected_routes ()
1792 {
1793         ARDOUR_UI::instance()->start_duplicate_routes();
1794 }
1795
1796 void
1797 RouteUI::toggle_denormal_protection ()
1798 {
1799         if (denormal_menu_item) {
1800
1801                 bool x;
1802
1803                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1804
1805                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1806                         _route->set_denormal_protection (x);
1807                 }
1808         }
1809 }
1810
1811 void
1812 RouteUI::denormal_protection_changed ()
1813 {
1814         if (denormal_menu_item) {
1815                 denormal_menu_item->set_active (_route->denormal_protection());
1816         }
1817 }
1818
1819 void
1820 RouteUI::disconnect_input ()
1821 {
1822         _route->input()->disconnect (this);
1823 }
1824
1825 void
1826 RouteUI::disconnect_output ()
1827 {
1828         _route->output()->disconnect (this);
1829 }
1830
1831 bool
1832 RouteUI::is_track () const
1833 {
1834         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1835 }
1836
1837 boost::shared_ptr<Track>
1838 RouteUI::track() const
1839 {
1840         return boost::dynamic_pointer_cast<Track>(_route);
1841 }
1842
1843 bool
1844 RouteUI::is_audio_track () const
1845 {
1846         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1847 }
1848
1849 boost::shared_ptr<AudioTrack>
1850 RouteUI::audio_track() const
1851 {
1852         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1853 }
1854
1855 bool
1856 RouteUI::is_midi_track () const
1857 {
1858         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1859 }
1860
1861 boost::shared_ptr<MidiTrack>
1862 RouteUI::midi_track() const
1863 {
1864         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1865 }
1866
1867 bool
1868 RouteUI::has_audio_outputs () const
1869 {
1870         return (_route->n_outputs().n_audio() > 0);
1871 }
1872
1873 string
1874 RouteUI::name() const
1875 {
1876         return _route->name();
1877 }
1878
1879 void
1880 RouteUI::map_frozen ()
1881 {
1882         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1883
1884         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1885
1886         if (at) {
1887                 check_rec_enable_sensitivity ();
1888         }
1889 }
1890
1891 void
1892 RouteUI::adjust_latency ()
1893 {
1894         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1895 }
1896
1897 bool
1898 RouteUI::process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir)
1899 {
1900         std::string path;
1901         std::string safe_name;
1902         std::string name;
1903
1904         prompter.get_result (name, true);
1905
1906         safe_name = legalize_for_path (name);
1907         safe_name += template_suffix;
1908
1909         path = Glib::build_filename (dir, safe_name);
1910
1911         if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1912                 bool overwrite = overwrite_file_dialog (prompter,
1913                                                         _("Confirm Template Overwrite"),
1914                                                         _("A template already exists with that name. Do you want to overwrite it?"));
1915
1916                 if (!overwrite) {
1917                         return false;
1918                 }
1919         }
1920
1921         _route->save_as_template (path, name);
1922
1923         return true;
1924 }
1925
1926 void
1927 RouteUI::save_as_template ()
1928 {
1929         std::string dir;
1930
1931         dir = ARDOUR::user_route_template_directory ();
1932
1933         if (g_mkdir_with_parents (dir.c_str(), 0755)) {
1934                 error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg;
1935                 return;
1936         }
1937
1938         ArdourPrompter prompter (true); // modal
1939
1940         prompter.set_title (_("Save As Template"));
1941         prompter.set_prompt (_("Template name:"));
1942         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1943
1944         bool finished = false;
1945         while (!finished) {
1946                 switch (prompter.run()) {
1947                 case RESPONSE_ACCEPT:
1948                         finished = process_save_template_prompter (prompter, dir);
1949                         break;
1950                 default:
1951                         finished = true;
1952                         break;
1953                 }
1954         }
1955 }
1956
1957 void
1958 RouteUI::check_rec_enable_sensitivity ()
1959 {
1960         if (!rec_enable_button) {
1961                 assert (0); // This should not happen
1962                 return;
1963         }
1964         if (!_session->writable()) {
1965                 rec_enable_button->set_sensitive (false);
1966                 return;
1967         }
1968
1969         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1970                 rec_enable_button->set_sensitive (false);
1971         } else if (is_audio_track ()  && track()->freeze_state() == AudioTrack::Frozen) {
1972                 rec_enable_button->set_sensitive (false);
1973         } else {
1974                 rec_enable_button->set_sensitive (true);
1975         }
1976         if (_route && _route->record_safe ()) {
1977                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
1978         } else {
1979                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() & ~Gtkmm2ext::Insensitive));
1980         }
1981         update_monitoring_display ();
1982 }
1983
1984 void
1985 RouteUI::parameter_changed (string const & p)
1986 {
1987         /* this handles RC and per-session parameter changes */
1988
1989         if (p == "disable-disarm-during-roll") {
1990                 check_rec_enable_sensitivity ();
1991         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1992                 set_button_names ();
1993         } else if (p == "auto-input") {
1994                 update_monitoring_display ();
1995         } else if (p == "blink-rec-arm") {
1996                 if (UIConfiguration::instance().get_blink_rec_arm()) {
1997                         rec_blink_connection.disconnect ();
1998                         rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1999                 } else {
2000                         rec_blink_connection.disconnect ();
2001                         RouteUI::blink_rec_display(false);
2002                 }
2003         }
2004 }
2005
2006 void
2007 RouteUI::step_gain_up ()
2008 {
2009         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), Controllable::UseGroup);
2010 }
2011
2012 void
2013 RouteUI::page_gain_up ()
2014 {
2015         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), Controllable::UseGroup);
2016 }
2017
2018 void
2019 RouteUI::step_gain_down ()
2020 {
2021         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), Controllable::UseGroup);
2022 }
2023
2024 void
2025 RouteUI::page_gain_down ()
2026 {
2027         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), Controllable::UseGroup);
2028 }
2029
2030 void
2031 RouteUI::open_remote_control_id_dialog ()
2032 {
2033         ArdourDialog dialog (_("Remote Control ID"));
2034         SpinButton* spin = 0;
2035
2036         dialog.get_vbox()->set_border_width (18);
2037
2038         if (Config->get_remote_model() == UserOrdered) {
2039                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
2040
2041                 HBox* hbox = manage (new HBox);
2042                 hbox->set_spacing (6);
2043                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
2044                 spin = manage (new SpinButton);
2045                 spin->set_digits (0);
2046                 spin->set_increments (1, 10);
2047                 spin->set_range (0, limit);
2048                 spin->set_value (_route->remote_control_id());
2049                 hbox->pack_start (*spin);
2050                 dialog.get_vbox()->pack_start (*hbox);
2051
2052                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2053                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
2054         } else {
2055                 Label* l = manage (new Label());
2056                 if (_route->is_master() || _route->is_monitor()) {
2057                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
2058                                                          "The remote control ID of %3 cannot be changed."),
2059                                                        Gtkmm2ext::markup_escape_text (_route->name()),
2060                                                        _route->remote_control_id(),
2061                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
2062                 } else {
2063                         l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
2064                                                          "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
2065                                                          "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
2066                                                        (is_track() ? _("track") : _("bus")),
2067                                                        _route->remote_control_id(),
2068                                                        "<span size=\"small\" style=\"italic\">",
2069                                                        "</span>",
2070                                                        Gtkmm2ext::markup_escape_text (_route->name()),
2071                                                        PROGRAM_NAME));
2072                 }
2073                 dialog.get_vbox()->pack_start (*l);
2074                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
2075         }
2076
2077         dialog.show_all ();
2078         int const r = dialog.run ();
2079
2080         if (r == RESPONSE_ACCEPT && spin) {
2081                 _route->set_remote_control_id (spin->get_value_as_int ());
2082         }
2083 }
2084
2085 void
2086 RouteUI::setup_invert_buttons ()
2087 {
2088         /* remove old invert buttons */
2089         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
2090                 _invert_button_box.remove (**i);
2091         }
2092
2093         _invert_buttons.clear ();
2094
2095         if (!_route || !_route->input()) {
2096                 return;
2097         }
2098
2099         uint32_t const N = _route->input()->n_ports().n_audio ();
2100
2101         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2102
2103         for (uint32_t i = 0; i < to_add; ++i) {
2104                 ArdourButton* b = manage (new ArdourButton);
2105                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2106                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2107
2108                 b->set_name (X_("invert button"));
2109                 if (to_add == 1) {
2110                         if (N > 1) {
2111                                 b->set_text (string_compose (X_("Ø (%1)"), N));
2112                         } else {
2113                                 b->set_text (X_("Ø"));
2114                         }
2115                 } else {
2116                         b->set_text (string_compose (X_("Ø%1"), i + 1));
2117                 }
2118
2119                 if (N <= _max_invert_buttons) {
2120                         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));
2121                 } else {
2122                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2123                 }
2124
2125                 _invert_buttons.push_back (b);
2126                 _invert_button_box.pack_start (*b);
2127         }
2128
2129         _invert_button_box.set_spacing (1);
2130         _invert_button_box.show_all ();
2131 }
2132
2133 void
2134 RouteUI::set_invert_button_state ()
2135 {
2136         uint32_t const N = _route->input()->n_ports().n_audio();
2137         if (N > _max_invert_buttons) {
2138
2139                 /* One button for many channels; explicit active if all channels are inverted,
2140                    implicit active if some are, off if none are.
2141                 */
2142
2143                 ArdourButton* b = _invert_buttons.front ();
2144
2145                 if (_route->phase_control()->count() == _route->phase_control()->size()) {
2146                         b->set_active_state (Gtkmm2ext::ExplicitActive);
2147                 } else if (_route->phase_control()->any()) {
2148                         b->set_active_state (Gtkmm2ext::ImplicitActive);
2149                 } else {
2150                         b->set_active_state (Gtkmm2ext::Off);
2151                 }
2152
2153         } else {
2154
2155                 /* One button per channel; just set active */
2156
2157                 int j = 0;
2158                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2159                         (*i)->set_active (_route->phase_control()->inverted (j));
2160                 }
2161
2162         }
2163 }
2164
2165 bool
2166 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2167 {
2168         if (ev->button == 1 && i < _invert_buttons.size()) {
2169                 uint32_t const N = _route->input()->n_ports().n_audio ();
2170                 if (N <= _max_invert_buttons) {
2171                         /* left-click inverts phase so long as we have a button per channel */
2172                         _route->phase_control()->set_phase_invert (i, !_invert_buttons[i]->get_active());
2173                         return false;
2174                 }
2175         }
2176         return false;
2177 }
2178
2179
2180 bool
2181 RouteUI::invert_press (GdkEventButton* ev)
2182 {
2183         using namespace Menu_Helpers;
2184
2185         uint32_t const N = _route->input()->n_ports().n_audio();
2186         if (N <= _max_invert_buttons && ev->button != 3) {
2187                 /* If we have an invert button per channel, we only pop
2188                    up a menu on right-click; left click is handled
2189                    on release.
2190                 */
2191                 return false;
2192         }
2193
2194         delete _invert_menu;
2195         _invert_menu = new Menu;
2196         _invert_menu->set_name ("ArdourContextMenu");
2197         MenuList& items = _invert_menu->items ();
2198
2199         for (uint32_t i = 0; i < N; ++i) {
2200                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2201                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2202                 ++_i_am_the_modifier;
2203                 e->set_active (_route->phase_control()->inverted (i));
2204                 --_i_am_the_modifier;
2205         }
2206
2207         _invert_menu->popup (0, ev->time);
2208
2209         return true;
2210 }
2211
2212 void
2213 RouteUI::invert_menu_toggled (uint32_t c)
2214 {
2215         if (_i_am_the_modifier) {
2216                 return;
2217         }
2218
2219
2220         _route->phase_control()->set_phase_invert (c, !_route->phase_control()->inverted (c));
2221 }
2222
2223 void
2224 RouteUI::set_invert_sensitive (bool yn)
2225 {
2226         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2227                 (*b)->set_sensitive (yn);
2228         }
2229 }
2230
2231 void
2232 RouteUI::request_redraw ()
2233 {
2234         if (_route) {
2235                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2236         }
2237 }
2238
2239 /** The Route's gui_changed signal has been emitted */
2240 void
2241 RouteUI::route_gui_changed (string what_changed)
2242 {
2243         if (what_changed == "color") {
2244                 if (set_color_from_route () == 0) {
2245                         route_color_changed ();
2246                 }
2247         }
2248 }
2249
2250 void
2251 RouteUI::track_mode_changed (void)
2252 {
2253         assert(is_track());
2254         switch (track()->mode()) {
2255                 case ARDOUR::NonLayered:
2256                 case ARDOUR::Normal:
2257                         rec_enable_button->set_icon (ArdourIcon::RecButton);
2258                         break;
2259                 case ARDOUR::Destructive:
2260                         rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2261                         break;
2262         }
2263         rec_enable_button->queue_draw();
2264 }
2265
2266 /** @return the color that this route should use; it maybe its own,
2267     or it maybe that of its route group.
2268 */
2269 Gdk::Color
2270 RouteUI::color () const
2271 {
2272         RouteGroup* g = _route->route_group ();
2273
2274         if (g && g->is_color()) {
2275                 Gdk::Color c;
2276                 set_color_from_rgba (c, GroupTabs::group_color (g));
2277                 return c;
2278         }
2279
2280         return _color;
2281 }
2282
2283 void
2284 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2285 {
2286         _showing_sends_to = send_to;
2287         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2288 }
2289
2290 void
2291 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2292 {
2293         if (_route == send_to) {
2294                 show_sends_button->set_active (true);
2295                 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2296         } else {
2297                 show_sends_button->set_active (false);
2298                 send_blink_connection.disconnect ();
2299         }
2300 }
2301
2302 RouteGroup*
2303 RouteUI::route_group() const
2304 {
2305         return _route->route_group();
2306 }
2307
2308
2309 RoutePinWindowProxy::RoutePinWindowProxy(std::string const &name, boost::shared_ptr<ARDOUR::Route> route)
2310         : WM::ProxyBase (name, string())
2311         , _route (boost::weak_ptr<Route> (route))
2312 {
2313         route->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&RoutePinWindowProxy::route_going_away, this), gui_context());
2314 }
2315
2316 RoutePinWindowProxy::~RoutePinWindowProxy()
2317 {
2318         _window = 0;
2319 }
2320
2321 ARDOUR::SessionHandlePtr*
2322 RoutePinWindowProxy::session_handle ()
2323 {
2324         ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2325         if (aw) { return aw; }
2326         return 0;
2327 }
2328
2329 Gtk::Window*
2330 RoutePinWindowProxy::get (bool create)
2331 {
2332         boost::shared_ptr<Route> r = _route.lock ();
2333         if (!r) {
2334                 return 0;
2335         }
2336
2337         if (!_window) {
2338                 if (!create) {
2339                         return 0;
2340                 }
2341                 _window = new PluginPinDialog (r);
2342                 ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2343                 if (aw) {
2344                         aw->set_session (_session);
2345                 }
2346                 _window->show_all ();
2347         }
2348         return _window;
2349 }
2350
2351 void
2352 RoutePinWindowProxy::route_going_away ()
2353 {
2354         delete _window;
2355         _window = 0;
2356         WM::Manager::instance().remove (this);
2357         going_away_connection.disconnect();
2358 }
2359
2360 void
2361 RouteUI::maybe_add_route_print_mgr ()
2362 {
2363         if (_route->pinmgr_proxy ()) {
2364                 return;
2365         }
2366         RoutePinWindowProxy* wp = new RoutePinWindowProxy (
2367                         string_compose ("RPM-%1", _route->id()), _route);
2368         wp->set_session (_session);
2369
2370         const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
2371         if (ui_xml) {
2372                 wp->set_state (*ui_xml, 0);
2373         }
2374
2375 #if 0
2376         void* existing_ui = _route->pinmgr_proxy ();
2377         if (existing_ui) {
2378                 wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
2379         }
2380 #endif
2381         _route->set_pingmgr_proxy (wp);
2382
2383         WM::Manager::instance().register_window (wp);
2384 }
2385
2386 void
2387 RouteUI::manage_pins ()
2388 {
2389         RoutePinWindowProxy* proxy = _route->pinmgr_proxy ();
2390         if (proxy) {
2391                 proxy->get (true);
2392                 proxy->present();
2393         }
2394 }