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