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