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