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