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