09a9dc8972bd82e948bb081e8fd7ea54d2fbe30e
[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::monitoring_changed, this, _1, _2), 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() ? 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() ? 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() ? 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::monitoring_changed (bool, Controllable::GroupControlDisposition)
765 {
766         update_monitoring_display ();
767 }
768
769 void
770 RouteUI::update_monitoring_display ()
771 {
772         if (!_route) {
773                 return;
774         }
775
776         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
777
778         if (!t) {
779                 return;
780         }
781
782         MonitorState ms = t->monitoring_state();
783
784         if (t->monitoring_control()->monitoring_choice() & MonitorInput) {
785                 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
786         } else {
787                 if (ms & MonitoringInput) {
788                         monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
789                 } else {
790                         monitor_input_button->unset_active_state ();
791                 }
792         }
793
794         if (t->monitoring_control()->monitoring_choice() & MonitorDisk) {
795                 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
796         } else {
797                 if (ms & MonitoringDisk) {
798                         monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
799                 } else {
800                         monitor_disk_button->unset_active_state ();
801                 }
802         }
803 }
804
805 bool
806 RouteUI::monitor_input_press(GdkEventButton*)
807 {
808         return false;
809 }
810
811 bool
812 RouteUI::monitor_input_release(GdkEventButton* ev)
813 {
814         return monitor_release (ev, MonitorInput);
815 }
816
817 bool
818 RouteUI::monitor_disk_press (GdkEventButton*)
819 {
820         return false;
821 }
822
823 bool
824 RouteUI::monitor_disk_release (GdkEventButton* ev)
825 {
826         return monitor_release (ev, MonitorDisk);
827 }
828
829 bool
830 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
831 {
832         if (ev->button != 1) {
833                 return false;
834         }
835
836         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
837
838         if (!t) {
839                 return true;
840         }
841
842         MonitorChoice mc;
843         boost::shared_ptr<RouteList> rl;
844
845         /* XXX for now, monitoring choices are orthogonal. cue monitoring
846            will follow in 3.X but requires mixing the input and playback (disk)
847            signal together, which requires yet more buffers.
848         */
849
850         if (t->monitoring_control()->monitoring_choice() & monitor_choice) {
851                 mc = MonitorChoice (t->monitoring_control()->monitoring_choice() & ~monitor_choice);
852         } else {
853                 /* this line will change when the options are non-orthogonal */
854                 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
855                 mc = monitor_choice;
856         }
857
858         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
859                 rl = _session->get_routes ();
860
861         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
862                 if (_route->route_group() && _route->route_group()->is_monitoring()) {
863                         rl = _route->route_group()->route_list();
864                 } else {
865                         rl.reset (new RouteList);
866                         rl->push_back (route());
867                 }
868         } else {
869                 rl.reset (new RouteList);
870                 rl->push_back (route());
871         }
872
873         DisplaySuspender ds;
874         _session->set_controls (route_list_to_control_list (rl, &Route::monitoring_control), (double) mc, Controllable::UseGroup);
875
876         return false;
877 }
878
879 void
880 RouteUI::build_record_menu ()
881 {
882         if (!record_menu) {
883                 record_menu = new Menu;
884                 record_menu->set_name ("ArdourContextMenu");
885                 using namespace Menu_Helpers;
886                 MenuList& items = record_menu->items();
887
888                 items.push_back (CheckMenuElem (_("Rec-Safe"), sigc::mem_fun (*this, &RouteUI::toggle_rec_safe)));
889                 rec_safe_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
890
891                 if (is_midi_track()) {
892                         items.push_back (SeparatorElem());
893                         items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
894                         step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
895                 }
896         }
897
898         if (step_edit_item) {
899                 if (track()->rec_enable_control()->get_value()) {
900                         step_edit_item->set_sensitive (false);
901                 }
902                 step_edit_item->set_active (midi_track()->step_editing());
903         }
904         if (rec_safe_item) {
905                 rec_safe_item->set_sensitive (!_route->record_enabled());
906                 rec_safe_item->set_active (_route->record_safe());
907         }
908 }
909
910 void
911 RouteUI::toggle_step_edit ()
912 {
913         if (!is_midi_track() || track()->rec_enable_control()->get_value()) {
914                 return;
915         }
916
917         midi_track()->set_step_editing (step_edit_item->get_active());
918 }
919
920 void
921 RouteUI::toggle_rec_safe ()
922 {
923         if (_route->record_enabled()) {
924                 return;
925         }
926         DisplaySuspender ds;
927         boost::shared_ptr<RouteList> rl (new RouteList);
928         rl->push_back (_route);
929         _session->set_record_safe (rl, rec_safe_item->get_active (), Session::rt_cleanup);
930 }
931
932 void
933 RouteUI::step_edit_changed (bool yn)
934 {
935         if (yn) {
936                 if (rec_enable_button) {
937                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
938                 }
939
940                 start_step_editing ();
941
942                 if (step_edit_item) {
943                         step_edit_item->set_active (true);
944                 }
945
946         } else {
947
948                 if (rec_enable_button) {
949                         rec_enable_button->unset_active_state ();
950                 }
951
952                 stop_step_editing ();
953
954                 if (step_edit_item) {
955                         step_edit_item->set_active (false);
956                 }
957         }
958 }
959
960 bool
961 RouteUI::rec_enable_release (GdkEventButton* ev)
962 {
963         if (Keyboard::is_context_menu_event (ev)) {
964                 build_record_menu ();
965                 if (record_menu) {
966                         record_menu->popup (1, ev->time);
967                 }
968                 return false;
969         }
970
971         return false;
972 }
973
974 void
975 RouteUI::build_sends_menu ()
976 {
977         using namespace Menu_Helpers;
978
979         sends_menu = new Menu;
980         sends_menu->set_name ("ArdourContextMenu");
981         MenuList& items = sends_menu->items();
982
983         items.push_back (
984                 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
985                 );
986
987         items.push_back (
988                 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
989                 );
990
991         items.push_back (
992                 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
993                 );
994
995         items.push_back (
996                 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
997                 );
998
999         items.push_back (
1000                 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
1001                 );
1002
1003         items.push_back (
1004                 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
1005
1006         items.push_back (
1007                 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
1008                 );
1009
1010         items.push_back (
1011                 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
1012                 );
1013
1014         items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
1015         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
1016         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
1017
1018 }
1019
1020 void
1021 RouteUI::create_sends (Placement p, bool include_buses)
1022 {
1023         _session->globally_add_internal_sends (_route, p, include_buses);
1024 }
1025
1026 void
1027 RouteUI::create_selected_sends (Placement p, bool include_buses)
1028 {
1029         boost::shared_ptr<RouteList> rlist (new RouteList);
1030         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
1031
1032         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
1033                 RouteTimeAxisView* rtv;
1034                 RouteUI* rui;
1035                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1036                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1037                                 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1038                                         rlist->push_back (rui->route());
1039                                 }
1040                         }
1041                 }
1042         }
1043
1044         _session->add_internal_sends (_route, p, rlist);
1045 }
1046
1047 void
1048 RouteUI::set_sends_gain_from_track ()
1049 {
1050         _session->globally_set_send_gains_from_track (_route);
1051 }
1052
1053 void
1054 RouteUI::set_sends_gain_to_zero ()
1055 {
1056         _session->globally_set_send_gains_to_zero (_route);
1057 }
1058
1059 void
1060 RouteUI::set_sends_gain_to_unity ()
1061 {
1062         _session->globally_set_send_gains_to_unity (_route);
1063 }
1064
1065 bool
1066 RouteUI::show_sends_press(GdkEventButton* ev)
1067 {
1068         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1069                 return true;
1070         }
1071
1072         if (!is_track() && show_sends_button) {
1073
1074                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1075
1076                         // do nothing on midi sigc::bind event
1077                         return false;
1078
1079                 } else if (Keyboard::is_context_menu_event (ev)) {
1080
1081                         if (sends_menu == 0) {
1082                                 build_sends_menu ();
1083                         }
1084
1085                         sends_menu->popup (0, ev->time);
1086
1087                 } else {
1088
1089                         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1090
1091                         if (s == _route) {
1092                                 set_showing_sends_to (boost::shared_ptr<Route> ());
1093                         } else {
1094                                 set_showing_sends_to (_route);
1095                         }
1096                 }
1097         }
1098
1099         return true;
1100 }
1101
1102 bool
1103 RouteUI::show_sends_release (GdkEventButton*)
1104 {
1105         return true;
1106 }
1107
1108 void
1109 RouteUI::send_blink (bool onoff)
1110 {
1111         if (!show_sends_button) {
1112                 return;
1113         }
1114
1115         if (onoff) {
1116                 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1117         } else {
1118                 show_sends_button->unset_active_state ();
1119         }
1120 }
1121
1122 Gtkmm2ext::ActiveState
1123 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1124 {
1125         if (r->is_master() || r->is_monitor()) {
1126                 return Gtkmm2ext::Off;
1127         }
1128
1129         if (Config->get_solo_control_is_listen_control()) {
1130
1131                 if (r->listening_via_monitor()) {
1132                         return Gtkmm2ext::ExplicitActive;
1133                 } else {
1134                         return Gtkmm2ext::Off;
1135                 }
1136
1137         }
1138
1139         if (r->soloed()) {
1140                 if (!r->self_soloed()) {
1141                         return Gtkmm2ext::ImplicitActive;
1142                 } else {
1143                         return Gtkmm2ext::ExplicitActive;
1144                 }
1145         } else {
1146                 return Gtkmm2ext::Off;
1147         }
1148 }
1149
1150 Gtkmm2ext::ActiveState
1151 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1152 {
1153         if (r->is_master() || r->is_monitor()) {
1154                 return Gtkmm2ext::Off;
1155         }
1156
1157         if (r->solo_isolate_control()->solo_isolated()) {
1158                 return Gtkmm2ext::ExplicitActive;
1159         } else {
1160                 return Gtkmm2ext::Off;
1161         }
1162 }
1163
1164 Gtkmm2ext::ActiveState
1165 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1166 {
1167         if (r->is_master() || r->is_monitor()) {
1168                 return Gtkmm2ext::Off;
1169         }
1170
1171         if (r->solo_safe_control()->solo_safe()) {
1172                 return Gtkmm2ext::ExplicitActive;
1173         } else {
1174                 return Gtkmm2ext::Off;
1175         }
1176 }
1177
1178 void
1179 RouteUI::update_solo_display ()
1180 {
1181         bool yn = _route->solo_safe_control()->solo_safe ();
1182
1183         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1184                 solo_safe_check->set_active (yn);
1185         }
1186
1187         yn = _route->solo_isolate_control()->solo_isolated ();
1188
1189         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1190                 solo_isolated_check->set_active (yn);
1191         }
1192
1193         set_button_names ();
1194
1195         if (solo_isolated_led) {
1196                 if (_route->solo_isolate_control()->solo_isolated()) {
1197                         solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1198                 } else {
1199                         solo_isolated_led->unset_active_state ();
1200                 }
1201         }
1202
1203         if (solo_safe_led) {
1204                 if (_route->solo_safe_control()->solo_safe()) {
1205                         solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1206                 } else {
1207                         solo_safe_led->unset_active_state ();
1208                 }
1209         }
1210
1211         solo_button->set_active_state (solo_active_state (_route));
1212
1213         /* some changes to solo status can affect mute display, so catch up
1214          */
1215
1216         update_mute_display ();
1217 }
1218
1219 void
1220 RouteUI::solo_changed_so_update_mute ()
1221 {
1222         update_mute_display ();
1223 }
1224
1225 ActiveState
1226 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1227 {
1228         if (r->is_monitor()) {
1229                 return ActiveState(0);
1230         }
1231
1232         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1233
1234                 if (r->muted ()) {
1235                         /* full mute */
1236                         return Gtkmm2ext::ExplicitActive;
1237                 } else if (r->muted_by_others_soloing ()) {
1238                         /* this will reflect both solo mutes AND master mutes */
1239                         return Gtkmm2ext::ImplicitActive;
1240                 } else {
1241                         /* no mute at all */
1242                         return Gtkmm2ext::Off;
1243                 }
1244
1245         } else {
1246
1247                 if (r->muted()) {
1248                         /* full mute */
1249                         return Gtkmm2ext::ExplicitActive;
1250                 } else if (r->muted_by_others()) {
1251                         /* note the direct use of MuteMaster API here. We are
1252                            not interested in showing
1253                            others-soloed-so-this-muted status in this
1254                            conditional branch.
1255                         */
1256                         return Gtkmm2ext::ImplicitActive;
1257                 } else {
1258                         /* no mute at all */
1259                         return Gtkmm2ext::Off;
1260                 }
1261         }
1262
1263         return ActiveState(0);
1264 }
1265
1266 void
1267 RouteUI::update_mute_display ()
1268 {
1269         if (!_route) {
1270                 return;
1271         }
1272
1273         mute_button->set_active_state (mute_active_state (_session, _route));
1274 }
1275
1276 void
1277 RouteUI::update_vca_display ()
1278 {
1279         if (!vca_button) {
1280                 return;
1281         }
1282
1283         VCAList vcas (_session->vca_manager().vcas());
1284         string label;
1285
1286         for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) {
1287                 if (_route->slaved_to (*v)) {
1288                         if (!label.empty()) {
1289                                 label += ' ';
1290                         }
1291                         label += PBD::to_string ((*v)->number(), std::dec);
1292                 }
1293         }
1294
1295         if (label.empty()) {
1296                 label = _("-vca-");
1297                 vca_button->set_active_state (Gtkmm2ext::Off);
1298         } else {
1299                 vca_button->set_active_state (Gtkmm2ext::ExplicitActive);
1300         }
1301
1302         vca_button->set_text (label);
1303 }
1304
1305 void
1306 RouteUI::route_rec_enable_changed ()
1307 {
1308         blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
1309         update_monitoring_display ();
1310 }
1311
1312 void
1313 RouteUI::session_rec_enable_changed ()
1314 {
1315         blink_rec_display(true);  //this lets the button change "immediately" rather than wait for the next blink
1316         update_monitoring_display ();
1317 }
1318
1319 void
1320 RouteUI::blink_rec_display (bool blinkOn)
1321 {
1322         if (!rec_enable_button || !_route) {
1323                 return;
1324         }
1325
1326         if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1327                 return;
1328         }
1329
1330         if (!is_track()) {
1331                 return;
1332         }
1333
1334         if (track()->rec_enable_control()->get_value()) {
1335                 switch (_session->record_status ()) {
1336                 case Session::Recording:
1337                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1338                         break;
1339
1340                 case Session::Disabled:
1341                 case Session::Enabled:
1342                         if (UIConfiguration::instance().get_blink_rec_arm()) {
1343                                 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1344                         } else {
1345                                 rec_enable_button->set_active_state ( ImplicitActive );
1346                         }
1347                         break;
1348                 }
1349
1350                 if (step_edit_item) {
1351                         step_edit_item->set_sensitive (false);
1352                 }
1353
1354         } else {
1355                 rec_enable_button->unset_active_state ();
1356
1357                 if (step_edit_item) {
1358                         step_edit_item->set_sensitive (true);
1359                 }
1360         }
1361
1362         check_rec_enable_sensitivity ();
1363 }
1364
1365 void
1366 RouteUI::build_solo_menu (void)
1367 {
1368         using namespace Menu_Helpers;
1369
1370         solo_menu = new Menu;
1371         solo_menu->set_name ("ArdourContextMenu");
1372         MenuList& items = solo_menu->items();
1373         Gtk::CheckMenuItem* check;
1374
1375         check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1376         check->set_active (_route->solo_isolate_control()->solo_isolated());
1377         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1378         items.push_back (CheckMenuElem(*check));
1379         solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1380         check->show_all();
1381
1382         check = new Gtk::CheckMenuItem(_("Solo Safe"));
1383         check->set_active (_route->solo_safe_control()->solo_safe());
1384         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1385         items.push_back (CheckMenuElem(*check));
1386         solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1387         check->show_all();
1388
1389         //items.push_back (SeparatorElem());
1390         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1391
1392 }
1393
1394 void
1395 RouteUI::build_mute_menu(void)
1396 {
1397         using namespace Menu_Helpers;
1398
1399         mute_menu = new Menu;
1400         mute_menu->set_name ("ArdourContextMenu");
1401
1402         MenuList& items = mute_menu->items();
1403
1404         pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1405         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1406         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1407         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1408         pre_fader_mute_check->show_all();
1409
1410         post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1411         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1412         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1413         items.push_back (CheckMenuElem(*post_fader_mute_check));
1414         post_fader_mute_check->show_all();
1415
1416         listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1417         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1418         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1419         items.push_back (CheckMenuElem(*listen_mute_check));
1420         listen_mute_check->show_all();
1421
1422         main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1423         init_mute_menu(MuteMaster::Main, main_mute_check);
1424         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1425         items.push_back (CheckMenuElem(*main_mute_check));
1426         main_mute_check->show_all();
1427
1428         //items.push_back (SeparatorElem());
1429         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1430
1431         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1432 }
1433
1434 void
1435 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1436 {
1437         check->set_active (_route->mute_control()->mute_points() & mp);
1438 }
1439
1440 void
1441 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1442 {
1443         if (check->get_active()) {
1444                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() | mp));
1445         } else {
1446                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() & ~mp));
1447         }
1448 }
1449
1450 void
1451 RouteUI::muting_change ()
1452 {
1453         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1454
1455         bool yn;
1456         MuteMaster::MutePoint current = _route->mute_control()->mute_points ();
1457
1458         yn = (current & MuteMaster::PreFader);
1459
1460         if (pre_fader_mute_check->get_active() != yn) {
1461                 pre_fader_mute_check->set_active (yn);
1462         }
1463
1464         yn = (current & MuteMaster::PostFader);
1465
1466         if (post_fader_mute_check->get_active() != yn) {
1467                 post_fader_mute_check->set_active (yn);
1468         }
1469
1470         yn = (current & MuteMaster::Listen);
1471
1472         if (listen_mute_check->get_active() != yn) {
1473                 listen_mute_check->set_active (yn);
1474         }
1475
1476         yn = (current & MuteMaster::Main);
1477
1478         if (main_mute_check->get_active() != yn) {
1479                 main_mute_check->set_active (yn);
1480         }
1481 }
1482
1483 bool
1484 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1485 {
1486         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1487                 return true;
1488         }
1489
1490         bool view = solo_isolated_led->active_state();
1491         bool model = _route->solo_isolate_control()->solo_isolated();
1492
1493         /* called BEFORE the view has changed */
1494
1495         if (ev->button == 1) {
1496                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1497
1498                         if (model) {
1499                                 /* disable isolate for all routes */
1500                                 DisplaySuspender ds;
1501                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Route::solo_isolate_control), 0.0, Controllable::NoGroup);
1502                         } else {
1503                                 /* enable isolate for all routes */
1504                                 DisplaySuspender ds;
1505                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Route::solo_isolate_control), 1.0, Controllable::NoGroup);
1506                         }
1507
1508                 } else {
1509
1510                         if (model == view) {
1511
1512                                 /* flip just this route */
1513
1514                                 boost::shared_ptr<RouteList> rl (new RouteList);
1515                                 rl->push_back (_route);
1516                                 DisplaySuspender ds;
1517                                 _session->set_controls (route_list_to_control_list (rl, &Route::solo_isolate_control), view ? 0.0 : 1.0, Controllable::NoGroup);
1518                         }
1519                 }
1520         }
1521
1522         return false;
1523 }
1524
1525 bool
1526 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1527 {
1528         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1529                 return true;
1530         }
1531
1532         bool view = solo_safe_led->active_state();
1533         bool model = _route->solo_safe_control()->solo_safe();
1534
1535         if (ev->button == 1) {
1536                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1537                         boost::shared_ptr<RouteList> rl (_session->get_routes());
1538                         if (model) {
1539                                 /* disable solo safe for all routes */
1540                                 DisplaySuspender ds;
1541                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1542                                         (*i)->solo_safe_control()->set_value (0.0, Controllable::NoGroup);
1543                                 }
1544                         } else {
1545                                 /* enable solo safe for all routes */
1546                                 DisplaySuspender ds;
1547                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1548                                         (*i)->solo_safe_control()->set_value (1.0, Controllable::NoGroup);
1549                                 }
1550                         }
1551                 }
1552                 else {
1553                         if (model == view) {
1554                                 /* flip just this route */
1555                                 _route->solo_safe_control()->set_value (view ? 0.0 : 1.0, Controllable::NoGroup);
1556                         }
1557                 }
1558         }
1559
1560         return false;
1561 }
1562
1563 void
1564 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1565 {
1566         bool view = check->get_active();
1567         bool model = _route->solo_isolate_control()->solo_isolated();
1568
1569         /* called AFTER the view has changed */
1570
1571         if (model != view) {
1572                 _route->solo_isolate_control()->set_value (view ? 1.0 : 0.0, Controllable::UseGroup);
1573         }
1574 }
1575
1576 void
1577 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1578 {
1579         _route->solo_safe_control()->set_value (check->get_active() ? 1.0 : 0.0, Controllable::UseGroup);
1580 }
1581
1582 /** Ask the user to choose a colour, and then apply that color to my route
1583  */
1584 void
1585 RouteUI::choose_color ()
1586 {
1587         bool picked;
1588         Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1589
1590         if (picked) {
1591                 set_color(color);
1592         }
1593 }
1594
1595 /** Set the route's own color.  This may not be used for display if
1596  *  the route is in a group which shares its color with its routes.
1597  */
1598 void
1599 RouteUI::set_color (const Gdk::Color & c)
1600 {
1601         /* leave _color alone in the group case so that tracks can retain their
1602          * own pre-group colors.
1603          */
1604
1605         char buf[64];
1606         _color = c;
1607         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1608
1609         /* note: we use the route state ID here so that color is the same for both
1610            the time axis view and the mixer strip
1611         */
1612
1613         gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1614         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1615 }
1616
1617 /** @return GUI state ID for things that are common to the route in all its representations */
1618 string
1619 RouteUI::route_state_id () const
1620 {
1621         return string_compose (X_("route %1"), _route->id().to_s());
1622 }
1623
1624 int
1625 RouteUI::set_color_from_route ()
1626 {
1627         const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1628
1629         if (str.empty()) {
1630                 return 1;
1631         }
1632
1633         int r, g, b;
1634
1635         sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1636
1637         _color.set_red (r);
1638         _color.set_green (g);
1639         _color.set_blue (b);
1640
1641         return 0;
1642 }
1643
1644 /** @return true if this name should be used for the route, otherwise false */
1645 bool
1646 RouteUI::verify_new_route_name (const std::string& name)
1647 {
1648         if (name.find (':') == string::npos) {
1649                 return true;
1650         }
1651
1652         MessageDialog colon_msg (
1653                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1654                 false, MESSAGE_QUESTION, BUTTONS_NONE
1655                 );
1656
1657         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1658         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1659
1660         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1661 }
1662
1663 void
1664 RouteUI::route_rename ()
1665 {
1666         ArdourPrompter name_prompter (true);
1667         string result;
1668         bool done = false;
1669
1670         if (is_track()) {
1671                 name_prompter.set_title (_("Rename Track"));
1672         } else {
1673                 name_prompter.set_title (_("Rename Bus"));
1674         }
1675         name_prompter.set_prompt (_("New name:"));
1676         name_prompter.set_initial_text (_route->name());
1677         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1678         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1679         name_prompter.show_all ();
1680
1681         while (!done) {
1682                 switch (name_prompter.run ()) {
1683                 case Gtk::RESPONSE_ACCEPT:
1684                         name_prompter.get_result (result);
1685                         name_prompter.hide ();
1686                         if (result.length()) {
1687                                 if (verify_new_route_name (result)) {
1688                                         _route->set_name (result);
1689                                         done = true;
1690                                 } else {
1691                                         /* back to name prompter */
1692                                 }
1693
1694                         } else {
1695                                 /* nothing entered, just get out of here */
1696                                 done = true;
1697                         }
1698                         break;
1699                 default:
1700                         done = true;
1701                         break;
1702                 }
1703         }
1704
1705         return;
1706
1707 }
1708
1709 void
1710 RouteUI::property_changed (const PropertyChange& what_changed)
1711 {
1712         if (what_changed.contains (ARDOUR::Properties::name)) {
1713                 name_label.set_text (_route->name());
1714         }
1715 }
1716
1717 void
1718 RouteUI::toggle_comment_editor ()
1719 {
1720 //      if (ignore_toggle) {
1721 //              return;
1722 //      }
1723
1724         if (comment_window && comment_window->is_visible ()) {
1725                 comment_window->hide ();
1726         } else {
1727                 open_comment_editor ();
1728         }
1729 }
1730
1731
1732 void
1733 RouteUI::open_comment_editor ()
1734 {
1735         if (comment_window == 0) {
1736                 setup_comment_editor ();
1737         }
1738
1739         string title;
1740         title = _route->name();
1741         title += _(": comment editor");
1742
1743         comment_window->set_title (title);
1744         comment_window->present();
1745 }
1746
1747 void
1748 RouteUI::setup_comment_editor ()
1749 {
1750         comment_window = new ArdourWindow (""); // title will be reset to show route
1751         comment_window->set_skip_taskbar_hint (true);
1752         comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1753         comment_window->set_default_size (400, 200);
1754
1755         comment_area = manage (new TextView());
1756         comment_area->set_name ("MixerTrackCommentArea");
1757         comment_area->set_wrap_mode (WRAP_WORD);
1758         comment_area->set_editable (true);
1759         comment_area->get_buffer()->set_text (_route->comment());
1760         comment_area->show ();
1761
1762         comment_window->add (*comment_area);
1763 }
1764
1765 void
1766 RouteUI::comment_changed ()
1767 {
1768         ignore_comment_edit = true;
1769         if (comment_area) {
1770                 comment_area->get_buffer()->set_text (_route->comment());
1771         }
1772         ignore_comment_edit = false;
1773 }
1774
1775 void
1776 RouteUI::comment_editor_done_editing ()
1777 {
1778         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1779
1780         string const str = comment_area->get_buffer()->get_text();
1781         if (str == _route->comment ()) {
1782                 return;
1783         }
1784
1785         _route->set_comment (str, this);
1786 }
1787
1788 void
1789 RouteUI::set_route_active (bool a, bool apply_to_selection)
1790 {
1791         if (apply_to_selection) {
1792                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1793         } else {
1794                 _route->set_active (a, this);
1795         }
1796 }
1797
1798 void
1799 RouteUI::duplicate_selected_routes ()
1800 {
1801         ARDOUR_UI::instance()->start_duplicate_routes();
1802 }
1803
1804 void
1805 RouteUI::toggle_denormal_protection ()
1806 {
1807         if (denormal_menu_item) {
1808
1809                 bool x;
1810
1811                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1812
1813                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1814                         _route->set_denormal_protection (x);
1815                 }
1816         }
1817 }
1818
1819 void
1820 RouteUI::denormal_protection_changed ()
1821 {
1822         if (denormal_menu_item) {
1823                 denormal_menu_item->set_active (_route->denormal_protection());
1824         }
1825 }
1826
1827 void
1828 RouteUI::disconnect_input ()
1829 {
1830         _route->input()->disconnect (this);
1831 }
1832
1833 void
1834 RouteUI::disconnect_output ()
1835 {
1836         _route->output()->disconnect (this);
1837 }
1838
1839 bool
1840 RouteUI::is_track () const
1841 {
1842         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1843 }
1844
1845 boost::shared_ptr<Track>
1846 RouteUI::track() const
1847 {
1848         return boost::dynamic_pointer_cast<Track>(_route);
1849 }
1850
1851 bool
1852 RouteUI::is_audio_track () const
1853 {
1854         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1855 }
1856
1857 boost::shared_ptr<AudioTrack>
1858 RouteUI::audio_track() const
1859 {
1860         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1861 }
1862
1863 bool
1864 RouteUI::is_midi_track () const
1865 {
1866         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1867 }
1868
1869 boost::shared_ptr<MidiTrack>
1870 RouteUI::midi_track() const
1871 {
1872         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1873 }
1874
1875 bool
1876 RouteUI::has_audio_outputs () const
1877 {
1878         return (_route->n_outputs().n_audio() > 0);
1879 }
1880
1881 string
1882 RouteUI::name() const
1883 {
1884         return _route->name();
1885 }
1886
1887 void
1888 RouteUI::map_frozen ()
1889 {
1890         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1891
1892         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1893
1894         if (at) {
1895                 check_rec_enable_sensitivity ();
1896         }
1897 }
1898
1899 void
1900 RouteUI::adjust_latency ()
1901 {
1902         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1903 }
1904
1905 bool
1906 RouteUI::process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir)
1907 {
1908         std::string path;
1909         std::string safe_name;
1910         std::string name;
1911
1912         prompter.get_result (name, true);
1913
1914         safe_name = legalize_for_path (name);
1915         safe_name += template_suffix;
1916
1917         path = Glib::build_filename (dir, safe_name);
1918
1919         if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1920                 bool overwrite = overwrite_file_dialog (prompter,
1921                                                         _("Confirm Template Overwrite"),
1922                                                         _("A template already exists with that name. Do you want to overwrite it?"));
1923
1924                 if (!overwrite) {
1925                         return false;
1926                 }
1927         }
1928
1929         _route->save_as_template (path, name);
1930
1931         return true;
1932 }
1933
1934 void
1935 RouteUI::save_as_template ()
1936 {
1937         std::string dir;
1938
1939         dir = ARDOUR::user_route_template_directory ();
1940
1941         if (g_mkdir_with_parents (dir.c_str(), 0755)) {
1942                 error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg;
1943                 return;
1944         }
1945
1946         ArdourPrompter prompter (true); // modal
1947
1948         prompter.set_title (_("Save As Template"));
1949         prompter.set_prompt (_("Template name:"));
1950         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1951
1952         bool finished = false;
1953         while (!finished) {
1954                 switch (prompter.run()) {
1955                 case RESPONSE_ACCEPT:
1956                         finished = process_save_template_prompter (prompter, dir);
1957                         break;
1958                 default:
1959                         finished = true;
1960                         break;
1961                 }
1962         }
1963 }
1964
1965 void
1966 RouteUI::check_rec_enable_sensitivity ()
1967 {
1968         if (!rec_enable_button) {
1969                 assert (0); // This should not happen
1970                 return;
1971         }
1972         if (!_session->writable()) {
1973                 rec_enable_button->set_sensitive (false);
1974                 return;
1975         }
1976
1977         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1978                 rec_enable_button->set_sensitive (false);
1979         } else if (is_audio_track ()  && track()->freeze_state() == AudioTrack::Frozen) {
1980                 rec_enable_button->set_sensitive (false);
1981         } else {
1982                 rec_enable_button->set_sensitive (true);
1983         }
1984         if (_route && _route->record_safe ()) {
1985                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
1986         } else {
1987                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() & ~Gtkmm2ext::Insensitive));
1988         }
1989         update_monitoring_display ();
1990 }
1991
1992 void
1993 RouteUI::parameter_changed (string const & p)
1994 {
1995         /* this handles RC and per-session parameter changes */
1996
1997         if (p == "disable-disarm-during-roll") {
1998                 check_rec_enable_sensitivity ();
1999         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
2000                 set_button_names ();
2001         } else if (p == "auto-input") {
2002                 update_monitoring_display ();
2003         } else if (p == "blink-rec-arm") {
2004                 if (UIConfiguration::instance().get_blink_rec_arm()) {
2005                         rec_blink_connection.disconnect ();
2006                         rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
2007                 } else {
2008                         rec_blink_connection.disconnect ();
2009                         RouteUI::blink_rec_display(false);
2010                 }
2011         }
2012 }
2013
2014 void
2015 RouteUI::step_gain_up ()
2016 {
2017         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), Controllable::UseGroup);
2018 }
2019
2020 void
2021 RouteUI::page_gain_up ()
2022 {
2023         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), Controllable::UseGroup);
2024 }
2025
2026 void
2027 RouteUI::step_gain_down ()
2028 {
2029         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), Controllable::UseGroup);
2030 }
2031
2032 void
2033 RouteUI::page_gain_down ()
2034 {
2035         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), Controllable::UseGroup);
2036 }
2037
2038 void
2039 RouteUI::open_remote_control_id_dialog ()
2040 {
2041         ArdourDialog dialog (_("Remote Control ID"));
2042         SpinButton* spin = 0;
2043
2044         dialog.get_vbox()->set_border_width (18);
2045
2046         if (Config->get_remote_model() == UserOrdered) {
2047                 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
2048
2049                 HBox* hbox = manage (new HBox);
2050                 hbox->set_spacing (6);
2051                 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
2052                 spin = manage (new SpinButton);
2053                 spin->set_digits (0);
2054                 spin->set_increments (1, 10);
2055                 spin->set_range (0, limit);
2056                 spin->set_value (_route->remote_control_id());
2057                 hbox->pack_start (*spin);
2058                 dialog.get_vbox()->pack_start (*hbox);
2059
2060                 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
2061                 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
2062         } else {
2063                 Label* l = manage (new Label());
2064                 if (_route->is_master() || _route->is_monitor()) {
2065                         l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
2066                                                          "The remote control ID of %3 cannot be changed."),
2067                                                        Gtkmm2ext::markup_escape_text (_route->name()),
2068                                                        _route->remote_control_id(),
2069                                                        (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
2070                 } else {
2071                         l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
2072                                                          "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
2073                                                          "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
2074                                                        (is_track() ? _("track") : _("bus")),
2075                                                        _route->remote_control_id(),
2076                                                        "<span size=\"small\" style=\"italic\">",
2077                                                        "</span>",
2078                                                        Gtkmm2ext::markup_escape_text (_route->name()),
2079                                                        PROGRAM_NAME));
2080                 }
2081                 dialog.get_vbox()->pack_start (*l);
2082                 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
2083         }
2084
2085         dialog.show_all ();
2086         int const r = dialog.run ();
2087
2088         if (r == RESPONSE_ACCEPT && spin) {
2089                 _route->set_remote_control_id (spin->get_value_as_int ());
2090         }
2091 }
2092
2093 void
2094 RouteUI::setup_invert_buttons ()
2095 {
2096         /* remove old invert buttons */
2097         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
2098                 _invert_button_box.remove (**i);
2099         }
2100
2101         _invert_buttons.clear ();
2102
2103         if (!_route || !_route->input()) {
2104                 return;
2105         }
2106
2107         uint32_t const N = _route->input()->n_ports().n_audio ();
2108
2109         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2110
2111         for (uint32_t i = 0; i < to_add; ++i) {
2112                 ArdourButton* b = manage (new ArdourButton);
2113                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2114                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2115
2116                 b->set_name (X_("invert button"));
2117                 if (to_add == 1) {
2118                         if (N > 1) {
2119                                 b->set_text (string_compose (X_("Ø (%1)"), N));
2120                         } else {
2121                                 b->set_text (X_("Ø"));
2122                         }
2123                 } else {
2124                         b->set_text (string_compose (X_("Ø%1"), i + 1));
2125                 }
2126
2127                 if (N <= _max_invert_buttons) {
2128                         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));
2129                 } else {
2130                         UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2131                 }
2132
2133                 _invert_buttons.push_back (b);
2134                 _invert_button_box.pack_start (*b);
2135         }
2136
2137         _invert_button_box.set_spacing (1);
2138         _invert_button_box.show_all ();
2139 }
2140
2141 void
2142 RouteUI::set_invert_button_state ()
2143 {
2144         uint32_t const N = _route->input()->n_ports().n_audio();
2145         if (N > _max_invert_buttons) {
2146
2147                 /* One button for many channels; explicit active if all channels are inverted,
2148                    implicit active if some are, off if none are.
2149                 */
2150
2151                 ArdourButton* b = _invert_buttons.front ();
2152
2153                 if (_route->phase_control()->count() == _route->phase_control()->size()) {
2154                         b->set_active_state (Gtkmm2ext::ExplicitActive);
2155                 } else if (_route->phase_control()->any()) {
2156                         b->set_active_state (Gtkmm2ext::ImplicitActive);
2157                 } else {
2158                         b->set_active_state (Gtkmm2ext::Off);
2159                 }
2160
2161         } else {
2162
2163                 /* One button per channel; just set active */
2164
2165                 int j = 0;
2166                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2167                         (*i)->set_active (_route->phase_control()->inverted (j));
2168                 }
2169
2170         }
2171 }
2172
2173 bool
2174 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2175 {
2176         if (ev->button == 1 && i < _invert_buttons.size()) {
2177                 uint32_t const N = _route->input()->n_ports().n_audio ();
2178                 if (N <= _max_invert_buttons) {
2179                         /* left-click inverts phase so long as we have a button per channel */
2180                         _route->phase_control()->set_phase_invert (i, !_invert_buttons[i]->get_active());
2181                         return false;
2182                 }
2183         }
2184         return false;
2185 }
2186
2187
2188 bool
2189 RouteUI::invert_press (GdkEventButton* ev)
2190 {
2191         using namespace Menu_Helpers;
2192
2193         uint32_t const N = _route->input()->n_ports().n_audio();
2194         if (N <= _max_invert_buttons && ev->button != 3) {
2195                 /* If we have an invert button per channel, we only pop
2196                    up a menu on right-click; left click is handled
2197                    on release.
2198                 */
2199                 return false;
2200         }
2201
2202         delete _invert_menu;
2203         _invert_menu = new Menu;
2204         _invert_menu->set_name ("ArdourContextMenu");
2205         MenuList& items = _invert_menu->items ();
2206
2207         for (uint32_t i = 0; i < N; ++i) {
2208                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2209                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2210                 ++_i_am_the_modifier;
2211                 e->set_active (_route->phase_control()->inverted (i));
2212                 --_i_am_the_modifier;
2213         }
2214
2215         _invert_menu->popup (0, ev->time);
2216
2217         return true;
2218 }
2219
2220 void
2221 RouteUI::invert_menu_toggled (uint32_t c)
2222 {
2223         if (_i_am_the_modifier) {
2224                 return;
2225         }
2226
2227
2228         _route->phase_control()->set_phase_invert (c, !_route->phase_control()->inverted (c));
2229 }
2230
2231 void
2232 RouteUI::set_invert_sensitive (bool yn)
2233 {
2234         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2235                 (*b)->set_sensitive (yn);
2236         }
2237 }
2238
2239 void
2240 RouteUI::request_redraw ()
2241 {
2242         if (_route) {
2243                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2244         }
2245 }
2246
2247 /** The Route's gui_changed signal has been emitted */
2248 void
2249 RouteUI::route_gui_changed (string what_changed)
2250 {
2251         if (what_changed == "color") {
2252                 if (set_color_from_route () == 0) {
2253                         route_color_changed ();
2254                 }
2255         }
2256 }
2257
2258 void
2259 RouteUI::track_mode_changed (void)
2260 {
2261         assert(is_track());
2262         switch (track()->mode()) {
2263                 case ARDOUR::NonLayered:
2264                 case ARDOUR::Normal:
2265                         rec_enable_button->set_icon (ArdourIcon::RecButton);
2266                         break;
2267                 case ARDOUR::Destructive:
2268                         rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2269                         break;
2270         }
2271         rec_enable_button->queue_draw();
2272 }
2273
2274 /** @return the color that this route should use; it maybe its own,
2275     or it maybe that of its route group.
2276 */
2277 Gdk::Color
2278 RouteUI::color () const
2279 {
2280         RouteGroup* g = _route->route_group ();
2281
2282         if (g && g->is_color()) {
2283                 Gdk::Color c;
2284                 set_color_from_rgba (c, GroupTabs::group_color (g));
2285                 return c;
2286         }
2287
2288         return _color;
2289 }
2290
2291 void
2292 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2293 {
2294         _showing_sends_to = send_to;
2295         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2296 }
2297
2298 void
2299 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2300 {
2301         if (_route == send_to) {
2302                 show_sends_button->set_active (true);
2303                 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2304         } else {
2305                 show_sends_button->set_active (false);
2306                 send_blink_connection.disconnect ();
2307         }
2308 }
2309
2310 RouteGroup*
2311 RouteUI::route_group() const
2312 {
2313         return _route->route_group();
2314 }
2315
2316
2317 RoutePinWindowProxy::RoutePinWindowProxy(std::string const &name, boost::shared_ptr<ARDOUR::Route> route)
2318         : WM::ProxyBase (name, string())
2319         , _route (boost::weak_ptr<Route> (route))
2320 {
2321         route->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&RoutePinWindowProxy::route_going_away, this), gui_context());
2322 }
2323
2324 RoutePinWindowProxy::~RoutePinWindowProxy()
2325 {
2326         _window = 0;
2327 }
2328
2329 ARDOUR::SessionHandlePtr*
2330 RoutePinWindowProxy::session_handle ()
2331 {
2332         ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2333         if (aw) { return aw; }
2334         return 0;
2335 }
2336
2337 Gtk::Window*
2338 RoutePinWindowProxy::get (bool create)
2339 {
2340         boost::shared_ptr<Route> r = _route.lock ();
2341         if (!r) {
2342                 return 0;
2343         }
2344
2345         if (!_window) {
2346                 if (!create) {
2347                         return 0;
2348                 }
2349                 _window = new PluginPinDialog (r);
2350                 ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2351                 if (aw) {
2352                         aw->set_session (_session);
2353                 }
2354                 _window->show_all ();
2355         }
2356         return _window;
2357 }
2358
2359 void
2360 RoutePinWindowProxy::route_going_away ()
2361 {
2362         delete _window;
2363         _window = 0;
2364         WM::Manager::instance().remove (this);
2365         going_away_connection.disconnect();
2366 }
2367
2368 void
2369 RouteUI::maybe_add_route_print_mgr ()
2370 {
2371         if (_route->pinmgr_proxy ()) {
2372                 return;
2373         }
2374         RoutePinWindowProxy* wp = new RoutePinWindowProxy (
2375                         string_compose ("RPM-%1", _route->id()), _route);
2376         wp->set_session (_session);
2377
2378         const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
2379         if (ui_xml) {
2380                 wp->set_state (*ui_xml, 0);
2381         }
2382
2383 #if 0
2384         void* existing_ui = _route->pinmgr_proxy ();
2385         if (existing_ui) {
2386                 wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
2387         }
2388 #endif
2389         _route->set_pingmgr_proxy (wp);
2390
2391         WM::Manager::instance().register_window (wp);
2392 }
2393
2394 void
2395 RouteUI::manage_pins ()
2396 {
2397         RoutePinWindowProxy* proxy = _route->pinmgr_proxy ();
2398         if (proxy) {
2399                 proxy->get (true);
2400                 proxy->present();
2401         }
2402 }