Update color stripable color-picker(s)
[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                                         boost::shared_ptr<RouteList> routes = _session->get_routes();
638
639                                         for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
640                                                 if ((*i)->soloed ()) {
641                                                         _solo_release->routes_on->push_back (*i);
642                                                 } else {
643                                                         _solo_release->routes_off->push_back (*i);
644                                                 }
645                                         }
646                                 }
647
648                                 if (Config->get_solo_control_is_listen_control()) {
649                                         /* ??? we need a just_one_listen() method */
650                                 } else {
651                                         DisplaySuspender ds;
652                                         _route->solo_control()->set_value (1.0, Controllable::NoGroup);
653                                 }
654
655                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
656
657                                 // shift-click: toggle solo isolated status
658
659                                 _route->solo_isolate_control()->set_value (_route->solo_isolate_control()->get_value() ? 0.0 : 1.0, Controllable::UseGroup);
660                                 delete _solo_release;
661                                 _solo_release = 0;
662
663                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
664
665                                 /* Primary-button1: solo mix group.
666                                    NOTE: Primary-button2 is MIDI learn.
667                                 */
668
669                                 /* Primary-button1 applies change to the mix group even if it is not active
670                                    NOTE: Primary-button2 is MIDI learn.
671                                 */
672
673                                 boost::shared_ptr<RouteList> rl;
674
675                                 if (ev->button == 1) {
676
677                                         /* Primary-button1 inverts the implication of
678                                            the group being active. If the group is
679                                            active (for solo), then this modifier means
680                                            "do not apply to solo". If the group is
681                                            inactive (for mute), then this modifier
682                                            means "apply to route". This is all
683                                            accomplished by passing just the actual
684                                            route, along with the InverseGroup group
685                                            control disposition.
686
687                                            NOTE: Primary-button2 is MIDI learn.
688                                         */
689
690                                         rl.reset (new RouteList);
691                                         rl->push_back (_route);
692
693                                         if (_solo_release) {
694                                                 _solo_release->routes = rl;
695                                         }
696
697                                         _session->set_controls (route_list_to_control_list (rl, &Stripable::solo_control), !_route->self_soloed(), Controllable::InverseGroup);
698                                 }
699
700                                 delete _solo_release;
701                                 _solo_release = 0;
702
703                         } else {
704
705                                 /* click: solo this route */
706
707                                 boost::shared_ptr<RouteList> rl (new RouteList);
708                                 rl->push_back (route());
709
710                                 if (_solo_release) {
711                                         _solo_release->routes = rl;
712                                 }
713
714                                 _session->set_controls (route_list_to_control_list (rl, &Stripable::solo_control), !_route->self_soloed(), Controllable::UseGroup);
715                         }
716                 }
717         }
718
719         return false;
720 }
721
722 bool
723 RouteUI::solo_release (GdkEventButton* /*ev*/)
724 {
725         if (_solo_release) {
726
727                 if (_solo_release->exclusive) {
728
729                 } else {
730                         _session->set_controls (route_list_to_control_list (_solo_release->routes, &Stripable::solo_control), _solo_release->active ? 1.0 : 0.0, Controllable::UseGroup);
731                 }
732
733                 delete _solo_release;
734                 _solo_release = 0;
735         }
736
737         return false;
738 }
739
740 bool
741 RouteUI::rec_enable_press(GdkEventButton* ev)
742 {
743         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
744                 return true;
745         }
746
747         //if this is a binding action, let the ArdourButton handle it
748         if ( BindingProxy::is_bind_action(ev) )
749                 return false;
750
751         if (!_session->engine().connected()) {
752                 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
753                 msg.run ();
754                 return false;
755         }
756
757         if (is_midi_track()) {
758
759                 /* rec-enable button exits from step editing */
760
761                 if (midi_track()->step_editing()) {
762                         midi_track()->set_step_editing (false);
763                         return false;
764                 }
765         }
766
767         if (is_track() && rec_enable_button) {
768
769                 if (Keyboard::is_button2_event (ev)) {
770
771                         //rec arm does not have a momentary mode
772                         return false;
773
774                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
775
776                         _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::rec_enable_control), !track()->rec_enable_control()->get_value(), Controllable::NoGroup);
777
778                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
779
780                         /* Primary-button1 applies change to the route group (even if it is not active)
781                            NOTE: Primary-button2 is MIDI learn.
782                         */
783
784                         if (ev->button == 1) {
785
786                                 boost::shared_ptr<RouteList> rl;
787
788                                 rl.reset (new RouteList);
789                                 rl->push_back (_route);
790
791                                 _session->set_controls (route_list_to_control_list (rl, &Stripable::rec_enable_control), !track()->rec_enable_control()->get_value(), Controllable::InverseGroup);
792                         }
793
794                 } else if (Keyboard::is_context_menu_event (ev)) {
795
796                         /* do this on release */
797
798                 } else {
799
800                         boost::shared_ptr<Track> trk = track();
801                         trk->rec_enable_control()->set_value (!trk->rec_enable_control()->get_value(), Controllable::UseGroup);
802                 }
803         }
804
805         return false;
806 }
807
808 void
809 RouteUI::update_monitoring_display ()
810 {
811         if (!_route) {
812                 return;
813         }
814
815         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
816
817         if (!t) {
818                 return;
819         }
820
821         MonitorState ms = t->monitoring_state();
822
823         if (t->monitoring_control()->monitoring_choice() & MonitorInput) {
824                 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
825         } else {
826                 if (ms & MonitoringInput) {
827                         monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
828                 } else {
829                         monitor_input_button->unset_active_state ();
830                 }
831         }
832
833         if (t->monitoring_control()->monitoring_choice() & MonitorDisk) {
834                 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
835         } else {
836                 if (ms & MonitoringDisk) {
837                         monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
838                 } else {
839                         monitor_disk_button->unset_active_state ();
840                 }
841         }
842 }
843
844 bool
845 RouteUI::monitor_input_press(GdkEventButton*)
846 {
847         return false;
848 }
849
850 bool
851 RouteUI::monitor_input_release(GdkEventButton* ev)
852 {
853         return monitor_release (ev, MonitorInput);
854 }
855
856 bool
857 RouteUI::monitor_disk_press (GdkEventButton*)
858 {
859         return false;
860 }
861
862 bool
863 RouteUI::monitor_disk_release (GdkEventButton* ev)
864 {
865         return monitor_release (ev, MonitorDisk);
866 }
867
868 bool
869 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
870 {
871         if (ev->button != 1) {
872                 return false;
873         }
874
875         boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
876
877         if (!t) {
878                 return true;
879         }
880
881         MonitorChoice mc;
882         boost::shared_ptr<RouteList> rl;
883
884         /* XXX for now, monitoring choices are orthogonal. cue monitoring
885            will follow in 3.X but requires mixing the input and playback (disk)
886            signal together, which requires yet more buffers.
887         */
888
889         if (t->monitoring_control()->monitoring_choice() & monitor_choice) {
890                 mc = MonitorChoice (t->monitoring_control()->monitoring_choice() & ~monitor_choice);
891         } else {
892                 /* this line will change when the options are non-orthogonal */
893                 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
894                 mc = monitor_choice;
895         }
896
897         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
898                 rl = _session->get_routes ();
899
900         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
901                 if (_route->route_group() && _route->route_group()->is_monitoring()) {
902                         rl = _route->route_group()->route_list();
903                 } else {
904                         rl.reset (new RouteList);
905                         rl->push_back (route());
906                 }
907         } else {
908                 rl.reset (new RouteList);
909                 rl->push_back (route());
910         }
911
912         _session->set_controls (route_list_to_control_list (rl, &Stripable::monitoring_control), (double) mc, Controllable::UseGroup);
913
914         return false;
915 }
916
917 void
918 RouteUI::build_record_menu ()
919 {
920         if (!record_menu) {
921                 record_menu = new Menu;
922                 record_menu->set_name ("ArdourContextMenu");
923                 using namespace Menu_Helpers;
924                 MenuList& items = record_menu->items();
925
926                 items.push_back (CheckMenuElem (_("Rec-Safe"), sigc::mem_fun (*this, &RouteUI::toggle_rec_safe)));
927                 rec_safe_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
928
929                 if (is_midi_track()) {
930                         items.push_back (SeparatorElem());
931                         items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
932                         step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
933                 }
934         }
935
936         if (step_edit_item) {
937                 if (track()->rec_enable_control()->get_value()) {
938                         step_edit_item->set_sensitive (false);
939                 }
940                 step_edit_item->set_active (midi_track()->step_editing());
941         }
942         if (rec_safe_item) {
943                 rec_safe_item->set_sensitive (!_route->rec_enable_control()->get_value());
944                 rec_safe_item->set_active (_route->rec_safe_control()->get_value());
945         }
946 }
947
948 void
949 RouteUI::toggle_step_edit ()
950 {
951         if (!is_midi_track() || track()->rec_enable_control()->get_value()) {
952                 return;
953         }
954
955         midi_track()->set_step_editing (step_edit_item->get_active());
956 }
957
958 void
959 RouteUI::toggle_rec_safe ()
960 {
961         boost::shared_ptr<AutomationControl> rs = _route->rec_safe_control();
962
963         if (!rs) {
964                 return;
965         }
966
967         /* This check is made inside the control too, but dong it here can't
968          * hurt.
969          */
970
971         if (_route->rec_enable_control()->get_value()) {
972                 return;
973         }
974
975         rs->set_value (rec_safe_item->get_active (), Controllable::UseGroup);
976 }
977
978 void
979 RouteUI::step_edit_changed (bool yn)
980 {
981         if (yn) {
982                 if (rec_enable_button) {
983                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
984                 }
985
986                 start_step_editing ();
987
988                 if (step_edit_item) {
989                         step_edit_item->set_active (true);
990                 }
991
992         } else {
993
994                 if (rec_enable_button) {
995                         rec_enable_button->unset_active_state ();
996                 }
997
998                 stop_step_editing ();
999
1000                 if (step_edit_item) {
1001                         step_edit_item->set_active (false);
1002                 }
1003         }
1004 }
1005
1006 bool
1007 RouteUI::rec_enable_release (GdkEventButton* ev)
1008 {
1009         if (Keyboard::is_context_menu_event (ev)) {
1010                 build_record_menu ();
1011                 if (record_menu) {
1012                         record_menu->popup (1, ev->time);
1013                 }
1014                 return false;
1015         }
1016
1017         return false;
1018 }
1019
1020 void
1021 RouteUI::build_sends_menu ()
1022 {
1023         using namespace Menu_Helpers;
1024
1025         sends_menu = new Menu;
1026         sends_menu->set_name ("ArdourContextMenu");
1027         MenuList& items = sends_menu->items();
1028
1029         items.push_back (
1030                 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
1031                 );
1032
1033         items.push_back (
1034                 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
1035                 );
1036
1037         items.push_back (
1038                 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
1039                 );
1040
1041         items.push_back (
1042                 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
1043                 );
1044
1045         items.push_back (
1046                 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
1047                 );
1048
1049         items.push_back (
1050                 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
1051
1052         items.push_back (
1053                 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
1054                 );
1055
1056         items.push_back (
1057                 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
1058                 );
1059
1060         items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
1061         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
1062         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
1063
1064 }
1065
1066 void
1067 RouteUI::create_sends (Placement p, bool include_buses)
1068 {
1069         _session->globally_add_internal_sends (_route, p, include_buses);
1070 }
1071
1072 void
1073 RouteUI::create_selected_sends (Placement p, bool include_buses)
1074 {
1075         boost::shared_ptr<RouteList> rlist (new RouteList);
1076         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
1077
1078         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
1079                 RouteTimeAxisView* rtv;
1080                 RouteUI* rui;
1081                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1082                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1083                                 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1084                                         rlist->push_back (rui->route());
1085                                 }
1086                         }
1087                 }
1088         }
1089
1090         _session->add_internal_sends (_route, p, rlist);
1091 }
1092
1093 void
1094 RouteUI::set_sends_gain_from_track ()
1095 {
1096         _session->globally_set_send_gains_from_track (_route);
1097 }
1098
1099 void
1100 RouteUI::set_sends_gain_to_zero ()
1101 {
1102         _session->globally_set_send_gains_to_zero (_route);
1103 }
1104
1105 void
1106 RouteUI::set_sends_gain_to_unity ()
1107 {
1108         _session->globally_set_send_gains_to_unity (_route);
1109 }
1110
1111 bool
1112 RouteUI::show_sends_press(GdkEventButton* ev)
1113 {
1114         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1115                 return true;
1116         }
1117
1118         if (!is_track() && show_sends_button) {
1119
1120                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1121
1122                         // do nothing on midi sigc::bind event
1123                         return false;
1124
1125                 } else if (Keyboard::is_context_menu_event (ev)) {
1126
1127                         if (sends_menu == 0) {
1128                                 build_sends_menu ();
1129                         }
1130
1131                         sends_menu->popup (0, ev->time);
1132
1133                 } else {
1134
1135                         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1136
1137                         if (s == _route) {
1138                                 set_showing_sends_to (boost::shared_ptr<Route> ());
1139                         } else {
1140                                 set_showing_sends_to (_route);
1141                         }
1142                 }
1143         }
1144
1145         return true;
1146 }
1147
1148 bool
1149 RouteUI::show_sends_release (GdkEventButton*)
1150 {
1151         return true;
1152 }
1153
1154 void
1155 RouteUI::send_blink (bool onoff)
1156 {
1157         if (!show_sends_button) {
1158                 return;
1159         }
1160
1161         if (onoff) {
1162                 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1163         } else {
1164                 show_sends_button->unset_active_state ();
1165         }
1166 }
1167
1168 Gtkmm2ext::ActiveState
1169 RouteUI::solo_active_state (boost::shared_ptr<Stripable> s)
1170 {
1171         boost::shared_ptr<SoloControl> sc = s->solo_control();
1172
1173         if (!sc) {
1174                 return Gtkmm2ext::Off;
1175         }
1176
1177         if (!sc->can_solo()) {
1178                 return Gtkmm2ext::Off;
1179         }
1180
1181
1182         if (sc->self_soloed()) {
1183                 return Gtkmm2ext::ExplicitActive;
1184         } else if (sc->soloed_by_others()) {
1185                 return Gtkmm2ext::ImplicitActive;
1186         } else {
1187                 return Gtkmm2ext::Off;
1188         }
1189 }
1190
1191 Gtkmm2ext::ActiveState
1192 RouteUI::solo_isolate_active_state (boost::shared_ptr<Stripable> s)
1193 {
1194         boost::shared_ptr<SoloIsolateControl> sc = s->solo_isolate_control();
1195
1196         if (!sc) {
1197                 return Gtkmm2ext::Off;
1198         }
1199
1200         if (s->is_master() || s->is_monitor()) {
1201                 return Gtkmm2ext::Off;
1202         }
1203
1204         if (sc->solo_isolated()) {
1205                 return Gtkmm2ext::ExplicitActive;
1206         } else {
1207                 return Gtkmm2ext::Off;
1208         }
1209 }
1210
1211 Gtkmm2ext::ActiveState
1212 RouteUI::solo_safe_active_state (boost::shared_ptr<Stripable> s)
1213 {
1214         boost::shared_ptr<SoloSafeControl> sc = s->solo_safe_control();
1215
1216         if (!sc) {
1217                 return Gtkmm2ext::Off;
1218         }
1219
1220         if (s->is_master() || s->is_monitor()) {
1221                 return Gtkmm2ext::Off;
1222         }
1223
1224         if (sc->solo_safe()) {
1225                 return Gtkmm2ext::ExplicitActive;
1226         } else {
1227                 return Gtkmm2ext::Off;
1228         }
1229 }
1230
1231 void
1232 RouteUI::update_solo_display ()
1233 {
1234         bool yn = _route->solo_safe_control()->solo_safe ();
1235
1236         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1237                 solo_safe_check->set_active (yn);
1238         }
1239
1240         yn = _route->solo_isolate_control()->solo_isolated ();
1241
1242         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1243                 solo_isolated_check->set_active (yn);
1244         }
1245
1246         set_button_names ();
1247
1248         if (solo_isolated_led) {
1249                 if (_route->solo_isolate_control()->solo_isolated()) {
1250                         solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1251                 } else {
1252                         solo_isolated_led->unset_active_state ();
1253                 }
1254         }
1255
1256         if (solo_safe_led) {
1257                 if (_route->solo_safe_control()->solo_safe()) {
1258                         solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1259                 } else {
1260                         solo_safe_led->unset_active_state ();
1261                 }
1262         }
1263
1264         solo_button->set_active_state (solo_active_state (_route));
1265
1266         /* some changes to solo status can affect mute display, so catch up
1267          */
1268
1269         update_mute_display ();
1270 }
1271
1272 void
1273 RouteUI::solo_changed_so_update_mute ()
1274 {
1275         update_mute_display ();
1276 }
1277
1278 ActiveState
1279 RouteUI::mute_active_state (Session*, boost::shared_ptr<Stripable> s)
1280 {
1281         boost::shared_ptr<MuteControl> mc = s->mute_control();
1282
1283         if (s->is_monitor()) {
1284                 return Gtkmm2ext::Off;
1285         }
1286
1287         if (!mc) {
1288                 return Gtkmm2ext::Off;
1289         }
1290
1291         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1292
1293                 if (mc->muted_by_self ()) {
1294                         /* full mute */
1295                         return Gtkmm2ext::ExplicitActive;
1296                 } else if (mc->muted_by_others_soloing () || mc->muted_by_masters ()) {
1297                         /* this will reflect both solo mutes AND master mutes */
1298                         return Gtkmm2ext::ImplicitActive;
1299                 } else {
1300                         /* no mute at all */
1301                         return Gtkmm2ext::Off;
1302                 }
1303
1304         } else {
1305
1306                 if (mc->muted_by_self()) {
1307                         /* full mute */
1308                         return Gtkmm2ext::ExplicitActive;
1309                 } else if (mc->muted_by_masters ()) {
1310                         /* this shows only master mutes, not mute-by-others-soloing */
1311                         return Gtkmm2ext::ImplicitActive;
1312                 } else {
1313                         /* no mute at all */
1314                         return Gtkmm2ext::Off;
1315                 }
1316         }
1317
1318         return ActiveState(0);
1319 }
1320
1321 void
1322 RouteUI::update_mute_display ()
1323 {
1324         if (!_route) {
1325                 return;
1326         }
1327
1328         mute_button->set_active_state (mute_active_state (_session, _route));
1329 }
1330
1331
1332 void
1333 RouteUI::route_rec_enable_changed ()
1334 {
1335         blink_rec_display (true);  //this lets the button change "immediately" rather than wait for the next blink
1336 }
1337
1338 void
1339 RouteUI::session_rec_enable_changed ()
1340 {
1341         blink_rec_display (true);  //this lets the button change "immediately" rather than wait for the next blink
1342 }
1343
1344 void
1345 RouteUI::blink_rec_display (bool blinkOn)
1346 {
1347         if (!rec_enable_button || !_route) {
1348                 return;
1349         }
1350
1351         if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1352                 return;
1353         }
1354
1355         if (!is_track()) {
1356                 return;
1357         }
1358
1359         if (track()->rec_enable_control()->get_value()) {
1360                 switch (_session->record_status ()) {
1361                 case Session::Recording:
1362                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1363                         break;
1364
1365                 case Session::Disabled:
1366                 case Session::Enabled:
1367                         if (UIConfiguration::instance().get_blink_rec_arm()) {
1368                                 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1369                         } else {
1370                                 rec_enable_button->set_active_state ( ImplicitActive );
1371                         }
1372                         break;
1373                 }
1374
1375                 if (step_edit_item) {
1376                         step_edit_item->set_sensitive (false);
1377                 }
1378
1379         } else {
1380                 rec_enable_button->unset_active_state ();
1381
1382                 if (step_edit_item) {
1383                         step_edit_item->set_sensitive (true);
1384                 }
1385         }
1386
1387         check_rec_enable_sensitivity ();
1388 }
1389
1390 void
1391 RouteUI::build_solo_menu (void)
1392 {
1393         using namespace Menu_Helpers;
1394
1395         solo_menu = new Menu;
1396         solo_menu->set_name ("ArdourContextMenu");
1397         MenuList& items = solo_menu->items();
1398         Gtk::CheckMenuItem* check;
1399
1400         check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1401         check->set_active (_route->solo_isolate_control()->solo_isolated());
1402         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1403         items.push_back (CheckMenuElem(*check));
1404         solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1405         check->show_all();
1406
1407         check = new Gtk::CheckMenuItem(_("Solo Safe"));
1408         check->set_active (_route->solo_safe_control()->solo_safe());
1409         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1410         items.push_back (CheckMenuElem(*check));
1411         solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1412         check->show_all();
1413
1414         //items.push_back (SeparatorElem());
1415         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1416
1417 }
1418
1419 void
1420 RouteUI::build_mute_menu(void)
1421 {
1422         using namespace Menu_Helpers;
1423
1424         mute_menu = new Menu;
1425         mute_menu->set_name ("ArdourContextMenu");
1426
1427         MenuList& items = mute_menu->items();
1428
1429         pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1430         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1431         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1432         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1433         pre_fader_mute_check->show_all();
1434
1435         post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1436         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1437         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1438         items.push_back (CheckMenuElem(*post_fader_mute_check));
1439         post_fader_mute_check->show_all();
1440
1441         listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1442         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1443         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1444         items.push_back (CheckMenuElem(*listen_mute_check));
1445         listen_mute_check->show_all();
1446
1447         main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1448         init_mute_menu(MuteMaster::Main, main_mute_check);
1449         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1450         items.push_back (CheckMenuElem(*main_mute_check));
1451         main_mute_check->show_all();
1452
1453         //items.push_back (SeparatorElem());
1454         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1455
1456         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1457 }
1458
1459 void
1460 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1461 {
1462         check->set_active (_route->mute_control()->mute_points() & mp);
1463 }
1464
1465 void
1466 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1467 {
1468         if (check->get_active()) {
1469                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() | mp));
1470         } else {
1471                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() & ~mp));
1472         }
1473 }
1474
1475 void
1476 RouteUI::muting_change ()
1477 {
1478         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1479
1480         bool yn;
1481         MuteMaster::MutePoint current = _route->mute_control()->mute_points ();
1482
1483         yn = (current & MuteMaster::PreFader);
1484
1485         if (pre_fader_mute_check->get_active() != yn) {
1486                 pre_fader_mute_check->set_active (yn);
1487         }
1488
1489         yn = (current & MuteMaster::PostFader);
1490
1491         if (post_fader_mute_check->get_active() != yn) {
1492                 post_fader_mute_check->set_active (yn);
1493         }
1494
1495         yn = (current & MuteMaster::Listen);
1496
1497         if (listen_mute_check->get_active() != yn) {
1498                 listen_mute_check->set_active (yn);
1499         }
1500
1501         yn = (current & MuteMaster::Main);
1502
1503         if (main_mute_check->get_active() != yn) {
1504                 main_mute_check->set_active (yn);
1505         }
1506 }
1507
1508 bool
1509 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1510 {
1511         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1512                 return true;
1513         }
1514
1515         bool view = solo_isolated_led->active_state();
1516         bool model = _route->solo_isolate_control()->solo_isolated();
1517
1518         /* called BEFORE the view has changed */
1519
1520         if (ev->button == 1) {
1521                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1522
1523                         if (model) {
1524                                 /* disable isolate for all routes */
1525                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_isolate_control), 0.0, Controllable::NoGroup);
1526                         } else {
1527                                 /* enable isolate for all routes */
1528                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_isolate_control), 1.0, Controllable::NoGroup);
1529                         }
1530
1531                 } else {
1532
1533                         if (model == view) {
1534
1535                                 /* flip just this route */
1536
1537                                 boost::shared_ptr<RouteList> rl (new RouteList);
1538                                 rl->push_back (_route);
1539                                 _session->set_controls (route_list_to_control_list (rl, &Stripable::solo_isolate_control), view ? 0.0 : 1.0, Controllable::NoGroup);
1540                         }
1541                 }
1542         }
1543
1544         return false;
1545 }
1546
1547 bool
1548 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1549 {
1550         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1551                 return true;
1552         }
1553
1554         bool view = solo_safe_led->active_state();
1555         bool model = _route->solo_safe_control()->solo_safe();
1556
1557         if (ev->button == 1) {
1558                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1559                         boost::shared_ptr<RouteList> rl (_session->get_routes());
1560                         if (model) {
1561                                 /* disable solo safe for all routes */
1562                                 DisplaySuspender ds;
1563                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1564                                         (*i)->solo_safe_control()->set_value (0.0, Controllable::NoGroup);
1565                                 }
1566                         } else {
1567                                 /* enable solo safe for all routes */
1568                                 DisplaySuspender ds;
1569                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1570                                         (*i)->solo_safe_control()->set_value (1.0, Controllable::NoGroup);
1571                                 }
1572                         }
1573                 }
1574                 else {
1575                         if (model == view) {
1576                                 /* flip just this route */
1577                                 _route->solo_safe_control()->set_value (view ? 0.0 : 1.0, Controllable::NoGroup);
1578                         }
1579                 }
1580         }
1581
1582         return false;
1583 }
1584
1585 void
1586 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1587 {
1588         bool view = check->get_active();
1589         bool model = _route->solo_isolate_control()->solo_isolated();
1590
1591         /* called AFTER the view has changed */
1592
1593         if (model != view) {
1594                 _route->solo_isolate_control()->set_value (view ? 1.0 : 0.0, Controllable::UseGroup);
1595         }
1596 }
1597
1598 void
1599 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1600 {
1601         _route->solo_safe_control()->set_value (check->get_active() ? 1.0 : 0.0, Controllable::UseGroup);
1602 }
1603
1604 /** Ask the user to choose a colour, and then apply that color to my route
1605  */
1606 void
1607 RouteUI::choose_color ()
1608 {
1609         _color_picker.popup (_route);
1610 }
1611
1612 /** Set the route's own color.  This may not be used for display if
1613  *  the route is in a group which shares its color with its routes.
1614  */
1615 void
1616 RouteUI::set_color (uint32_t c)
1617 {
1618         _route->presentation_info().set_color (c);
1619 }
1620
1621 /** @return GUI state ID for things that are common to the route in all its representations */
1622 string
1623 RouteUI::route_state_id () const
1624 {
1625         return string_compose (X_("route %1"), _route->id().to_s());
1626 }
1627
1628 int
1629 RouteUI::set_color_from_route ()
1630 {
1631         if (_route->presentation_info().color_set()) {
1632                 return 0; /* nothing to do */
1633         }
1634
1635         return 1; /* pick a color */
1636 }
1637
1638 /** @return true if this name should be used for the route, otherwise false */
1639 bool
1640 RouteUI::verify_new_route_name (const std::string& name)
1641 {
1642         if (name.find (':') == string::npos) {
1643                 return true;
1644         }
1645
1646         MessageDialog colon_msg (
1647                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1648                 false, MESSAGE_QUESTION, BUTTONS_NONE
1649                 );
1650
1651         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1652         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1653
1654         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1655 }
1656
1657 void
1658 RouteUI::route_rename ()
1659 {
1660         ArdourPrompter name_prompter (true);
1661         string result;
1662         bool done = false;
1663
1664         if (is_track()) {
1665                 name_prompter.set_title (_("Rename Track"));
1666         } else {
1667                 name_prompter.set_title (_("Rename Bus"));
1668         }
1669         name_prompter.set_prompt (_("New name:"));
1670         name_prompter.set_initial_text (_route->name());
1671         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1672         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1673         name_prompter.show_all ();
1674
1675         while (!done) {
1676                 switch (name_prompter.run ()) {
1677                 case Gtk::RESPONSE_ACCEPT:
1678                         name_prompter.get_result (result);
1679                         name_prompter.hide ();
1680                         if (result.length()) {
1681                                 if (verify_new_route_name (result)) {
1682                                         _route->set_name (result);
1683                                         done = true;
1684                                 } else {
1685                                         /* back to name prompter */
1686                                 }
1687
1688                         } else {
1689                                 /* nothing entered, just get out of here */
1690                                 done = true;
1691                         }
1692                         break;
1693                 default:
1694                         done = true;
1695                         break;
1696                 }
1697         }
1698
1699         return;
1700
1701 }
1702
1703 void
1704 RouteUI::toggle_comment_editor ()
1705 {
1706 //      if (ignore_toggle) {
1707 //              return;
1708 //      }
1709
1710         if (comment_window && comment_window->is_visible ()) {
1711                 comment_window->hide ();
1712         } else {
1713                 open_comment_editor ();
1714         }
1715 }
1716
1717
1718 void
1719 RouteUI::open_comment_editor ()
1720 {
1721         if (comment_window == 0) {
1722                 setup_comment_editor ();
1723         }
1724
1725         string title;
1726         title = _route->name();
1727         title += _(": comment editor");
1728
1729         comment_window->set_title (title);
1730         comment_window->present();
1731 }
1732
1733 void
1734 RouteUI::setup_comment_editor ()
1735 {
1736         comment_window = new ArdourWindow (""); // title will be reset to show route
1737         comment_window->set_skip_taskbar_hint (true);
1738         comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1739         comment_window->set_default_size (400, 200);
1740
1741         comment_area = manage (new TextView());
1742         comment_area->set_name ("MixerTrackCommentArea");
1743         comment_area->set_wrap_mode (WRAP_WORD);
1744         comment_area->set_editable (true);
1745         comment_area->get_buffer()->set_text (_route->comment());
1746         comment_area->show ();
1747
1748         comment_window->add (*comment_area);
1749 }
1750
1751 void
1752 RouteUI::comment_changed ()
1753 {
1754         ignore_comment_edit = true;
1755         if (comment_area) {
1756                 comment_area->get_buffer()->set_text (_route->comment());
1757         }
1758         ignore_comment_edit = false;
1759 }
1760
1761 void
1762 RouteUI::comment_editor_done_editing ()
1763 {
1764         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1765
1766         string const str = comment_area->get_buffer()->get_text();
1767         if (str == _route->comment ()) {
1768                 return;
1769         }
1770
1771         _route->set_comment (str, this);
1772 }
1773
1774 void
1775 RouteUI::set_route_active (bool a, bool apply_to_selection)
1776 {
1777         if (apply_to_selection) {
1778                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1779         } else {
1780                 _route->set_active (a, this);
1781         }
1782 }
1783
1784 void
1785 RouteUI::duplicate_selected_routes ()
1786 {
1787         ARDOUR_UI::instance()->start_duplicate_routes();
1788 }
1789
1790 void
1791 RouteUI::toggle_denormal_protection ()
1792 {
1793         if (denormal_menu_item) {
1794
1795                 bool x;
1796
1797                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1798
1799                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1800                         _route->set_denormal_protection (x);
1801                 }
1802         }
1803 }
1804
1805 void
1806 RouteUI::denormal_protection_changed ()
1807 {
1808         if (denormal_menu_item) {
1809                 denormal_menu_item->set_active (_route->denormal_protection());
1810         }
1811 }
1812
1813 void
1814 RouteUI::disconnect_input ()
1815 {
1816         _route->input()->disconnect (this);
1817 }
1818
1819 void
1820 RouteUI::disconnect_output ()
1821 {
1822         _route->output()->disconnect (this);
1823 }
1824
1825 bool
1826 RouteUI::is_track () const
1827 {
1828         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1829 }
1830
1831 boost::shared_ptr<Track>
1832 RouteUI::track() const
1833 {
1834         return boost::dynamic_pointer_cast<Track>(_route);
1835 }
1836
1837 bool
1838 RouteUI::is_audio_track () const
1839 {
1840         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1841 }
1842
1843 boost::shared_ptr<AudioTrack>
1844 RouteUI::audio_track() const
1845 {
1846         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1847 }
1848
1849 bool
1850 RouteUI::is_midi_track () const
1851 {
1852         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1853 }
1854
1855 boost::shared_ptr<MidiTrack>
1856 RouteUI::midi_track() const
1857 {
1858         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1859 }
1860
1861 bool
1862 RouteUI::has_audio_outputs () const
1863 {
1864         return (_route->n_outputs().n_audio() > 0);
1865 }
1866
1867 void
1868 RouteUI::map_frozen ()
1869 {
1870         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1871
1872         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1873
1874         if (at) {
1875                 check_rec_enable_sensitivity ();
1876         }
1877 }
1878
1879 void
1880 RouteUI::adjust_latency ()
1881 {
1882         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1883 }
1884
1885 bool
1886 RouteUI::process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir)
1887 {
1888         std::string path;
1889         std::string safe_name;
1890         std::string name;
1891
1892         prompter.get_result (name, true);
1893
1894         safe_name = legalize_for_path (name);
1895         safe_name += template_suffix;
1896
1897         path = Glib::build_filename (dir, safe_name);
1898
1899         if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1900                 bool overwrite = overwrite_file_dialog (prompter,
1901                                                         _("Confirm Template Overwrite"),
1902                                                         _("A template already exists with that name. Do you want to overwrite it?"));
1903
1904                 if (!overwrite) {
1905                         return false;
1906                 }
1907         }
1908
1909         _route->save_as_template (path, name);
1910
1911         return true;
1912 }
1913
1914 void
1915 RouteUI::save_as_template ()
1916 {
1917         std::string dir;
1918
1919         dir = ARDOUR::user_route_template_directory ();
1920
1921         if (g_mkdir_with_parents (dir.c_str(), 0755)) {
1922                 error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg;
1923                 return;
1924         }
1925
1926         ArdourPrompter prompter (true); // modal
1927
1928         prompter.set_title (_("Save As Template"));
1929         prompter.set_prompt (_("Template name:"));
1930         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1931
1932         bool finished = false;
1933         while (!finished) {
1934                 switch (prompter.run()) {
1935                 case RESPONSE_ACCEPT:
1936                         finished = process_save_template_prompter (prompter, dir);
1937                         break;
1938                 default:
1939                         finished = true;
1940                         break;
1941                 }
1942         }
1943 }
1944
1945 void
1946 RouteUI::check_rec_enable_sensitivity ()
1947 {
1948         if (!rec_enable_button) {
1949                 assert (0); // This should not happen
1950                 return;
1951         }
1952         if (!_session->writable()) {
1953                 rec_enable_button->set_sensitive (false);
1954                 return;
1955         }
1956
1957         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1958                 rec_enable_button->set_sensitive (false);
1959         } else if (is_audio_track ()  && track()->freeze_state() == AudioTrack::Frozen) {
1960                 rec_enable_button->set_sensitive (false);
1961         } else {
1962                 rec_enable_button->set_sensitive (true);
1963         }
1964         if (_route && _route->rec_safe_control () && _route->rec_safe_control()->get_value()) {
1965                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
1966         } else {
1967                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() & ~Gtkmm2ext::Insensitive));
1968         }
1969         update_monitoring_display ();
1970 }
1971
1972 void
1973 RouteUI::parameter_changed (string const & p)
1974 {
1975         /* this handles RC and per-session parameter changes */
1976
1977         if (p == "disable-disarm-during-roll") {
1978                 check_rec_enable_sensitivity ();
1979         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1980                 set_button_names ();
1981         } else if (p == "session-monitoring") {
1982                 update_monitoring_display ();
1983         } else if (p == "auto-input") {
1984                 update_monitoring_display ();
1985         } else if (p == "blink-rec-arm") {
1986                 if (UIConfiguration::instance().get_blink_rec_arm()) {
1987                         rec_blink_connection.disconnect ();
1988                         rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1989                 } else {
1990                         rec_blink_connection.disconnect ();
1991                         RouteUI::blink_rec_display(false);
1992                 }
1993         }
1994 }
1995
1996 void
1997 RouteUI::step_gain_up ()
1998 {
1999         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), Controllable::UseGroup);
2000 }
2001
2002 void
2003 RouteUI::page_gain_up ()
2004 {
2005         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), Controllable::UseGroup);
2006 }
2007
2008 void
2009 RouteUI::step_gain_down ()
2010 {
2011         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), Controllable::UseGroup);
2012 }
2013
2014 void
2015 RouteUI::page_gain_down ()
2016 {
2017         _route->gain_control()->set_value (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), Controllable::UseGroup);
2018 }
2019
2020 void
2021 RouteUI::setup_invert_buttons ()
2022 {
2023         /* remove old invert buttons */
2024         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
2025                 _invert_button_box.remove (**i);
2026         }
2027
2028         _invert_buttons.clear ();
2029
2030         if (!_route || !_route->input()) {
2031                 return;
2032         }
2033
2034         uint32_t const N = _route->input()->n_ports().n_audio ();
2035
2036         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2037
2038         for (uint32_t i = 0; i < to_add; ++i) {
2039                 ArdourButton* b = manage (new ArdourButton);
2040                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2041                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2042
2043                 b->set_name (X_("invert button"));
2044                 if (to_add == 1) {
2045                         if (N > 1) {
2046                                 b->set_text (string_compose (X_("Ø (%1)"), N));
2047                         } else {
2048                                 b->set_text (X_("Ø"));
2049                         }
2050                 } else {
2051                         b->set_text (string_compose (X_("Ø%1"), i + 1));
2052                 }
2053
2054                 if (N <= _max_invert_buttons) {
2055                         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));
2056                 } else {
2057                         UI::instance()->set_tip (*b, _("Click to show a menu of channels to invert polarity"));
2058                 }
2059
2060                 _invert_buttons.push_back (b);
2061                 _invert_button_box.pack_start (*b);
2062         }
2063
2064         _invert_button_box.set_spacing (1);
2065         _invert_button_box.show_all ();
2066 }
2067
2068 void
2069 RouteUI::set_invert_button_state ()
2070 {
2071         uint32_t const N = _route->input()->n_ports().n_audio();
2072         if (N > _max_invert_buttons) {
2073
2074                 /* One button for many channels; explicit active if all channels are inverted,
2075                    implicit active if some are, off if none are.
2076                 */
2077
2078                 ArdourButton* b = _invert_buttons.front ();
2079
2080                 if (_route->phase_control()->count() == _route->phase_control()->size()) {
2081                         b->set_active_state (Gtkmm2ext::ExplicitActive);
2082                 } else if (_route->phase_control()->any()) {
2083                         b->set_active_state (Gtkmm2ext::ImplicitActive);
2084                 } else {
2085                         b->set_active_state (Gtkmm2ext::Off);
2086                 }
2087
2088         } else {
2089
2090                 /* One button per channel; just set active */
2091
2092                 int j = 0;
2093                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2094                         (*i)->set_active (_route->phase_control()->inverted (j));
2095                 }
2096
2097         }
2098 }
2099
2100 bool
2101 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2102 {
2103         if (ev->button == 1 && i < _invert_buttons.size()) {
2104                 uint32_t const N = _route->input()->n_ports().n_audio ();
2105                 if (N <= _max_invert_buttons) {
2106                         /* left-click inverts phase so long as we have a button per channel */
2107                         _route->phase_control()->set_phase_invert (i, !_invert_buttons[i]->get_active());
2108                         return false;
2109                 }
2110         }
2111         return false;
2112 }
2113
2114
2115 bool
2116 RouteUI::invert_press (GdkEventButton* ev)
2117 {
2118         using namespace Menu_Helpers;
2119
2120         uint32_t const N = _route->input()->n_ports().n_audio();
2121         if (N <= _max_invert_buttons && ev->button != 3) {
2122                 /* If we have an invert button per channel, we only pop
2123                    up a menu on right-click; left click is handled
2124                    on release.
2125                 */
2126                 return false;
2127         }
2128
2129         delete _invert_menu;
2130         _invert_menu = new Menu;
2131         _invert_menu->set_name ("ArdourContextMenu");
2132         MenuList& items = _invert_menu->items ();
2133
2134         for (uint32_t i = 0; i < N; ++i) {
2135                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2136                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2137                 ++_i_am_the_modifier;
2138                 e->set_active (_route->phase_control()->inverted (i));
2139                 --_i_am_the_modifier;
2140         }
2141
2142         _invert_menu->popup (0, ev->time);
2143
2144         return true;
2145 }
2146
2147 void
2148 RouteUI::invert_menu_toggled (uint32_t c)
2149 {
2150         if (_i_am_the_modifier) {
2151                 return;
2152         }
2153
2154
2155         _route->phase_control()->set_phase_invert (c, !_route->phase_control()->inverted (c));
2156 }
2157
2158 void
2159 RouteUI::set_invert_sensitive (bool yn)
2160 {
2161         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2162                 (*b)->set_sensitive (yn);
2163         }
2164 }
2165
2166 void
2167 RouteUI::request_redraw ()
2168 {
2169         if (_route) {
2170                 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2171         }
2172 }
2173
2174 /** The Route's gui_changed signal has been emitted */
2175 void
2176 RouteUI::route_gui_changed (PropertyChange const& what_changed)
2177 {
2178         if (what_changed.contains (Properties::color)) {
2179                 if (set_color_from_route () == 0) {
2180                         route_color_changed ();
2181                 }
2182         }
2183 }
2184
2185 void
2186 RouteUI::track_mode_changed (void)
2187 {
2188         assert(is_track());
2189         switch (track()->mode()) {
2190                 case ARDOUR::NonLayered:
2191                 case ARDOUR::Normal:
2192                         rec_enable_button->set_icon (ArdourIcon::RecButton);
2193                         break;
2194                 case ARDOUR::Destructive:
2195                         rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2196                         break;
2197         }
2198         rec_enable_button->queue_draw();
2199 }
2200
2201 /** @return the color that this route should use; it maybe its own,
2202     or it maybe that of its route group.
2203 */
2204
2205 Gdk::Color
2206 RouteUI::route_color () const
2207 {
2208         Gdk::Color c;
2209         RouteGroup* g = _route->route_group ();
2210         string p;
2211
2212         if (g && g->is_color()) {
2213                 set_color_from_rgba (c, GroupTabs::group_color (g));
2214         } else {
2215                 set_color_from_rgba (c, _route->presentation_info().color());
2216         }
2217
2218         return c;
2219 }
2220
2221 void
2222 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2223 {
2224         _showing_sends_to = send_to;
2225         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2226 }
2227
2228 void
2229 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2230 {
2231         if (_route == send_to) {
2232                 show_sends_button->set_active (true);
2233                 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2234         } else {
2235                 show_sends_button->set_active (false);
2236                 send_blink_connection.disconnect ();
2237         }
2238 }
2239
2240 RouteGroup*
2241 RouteUI::route_group() const
2242 {
2243         return _route->route_group();
2244 }
2245
2246
2247 RoutePinWindowProxy::RoutePinWindowProxy(std::string const &name, boost::shared_ptr<ARDOUR::Route> route)
2248         : WM::ProxyBase (name, string())
2249         , _route (boost::weak_ptr<Route> (route))
2250 {
2251         route->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&RoutePinWindowProxy::route_going_away, this), gui_context());
2252 }
2253
2254 RoutePinWindowProxy::~RoutePinWindowProxy()
2255 {
2256         _window = 0;
2257 }
2258
2259 ARDOUR::SessionHandlePtr*
2260 RoutePinWindowProxy::session_handle ()
2261 {
2262         ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2263         if (aw) { return aw; }
2264         return 0;
2265 }
2266
2267 Gtk::Window*
2268 RoutePinWindowProxy::get (bool create)
2269 {
2270         boost::shared_ptr<Route> r = _route.lock ();
2271         if (!r) {
2272                 return 0;
2273         }
2274
2275         if (!_window) {
2276                 if (!create) {
2277                         return 0;
2278                 }
2279                 _window = new PluginPinDialog (r);
2280                 ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2281                 if (aw) {
2282                         aw->set_session (_session);
2283                 }
2284                 _window->show_all ();
2285         }
2286         return _window;
2287 }
2288
2289 void
2290 RoutePinWindowProxy::route_going_away ()
2291 {
2292         delete _window;
2293         _window = 0;
2294         WM::Manager::instance().remove (this);
2295         going_away_connection.disconnect();
2296         delete this;
2297 }
2298
2299 void
2300 RouteUI::maybe_add_route_print_mgr ()
2301 {
2302         if (_route->pinmgr_proxy ()) {
2303                 return;
2304         }
2305         RoutePinWindowProxy* wp = new RoutePinWindowProxy (
2306                         string_compose ("RPM-%1", _route->id()), _route);
2307         wp->set_session (_session);
2308
2309         const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
2310         if (ui_xml) {
2311                 wp->set_state (*ui_xml, 0);
2312         }
2313
2314 #if 0
2315         void* existing_ui = _route->pinmgr_proxy ();
2316         if (existing_ui) {
2317                 wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
2318         }
2319 #endif
2320         _route->set_pingmgr_proxy (wp);
2321
2322         WM::Manager::instance().register_window (wp);
2323 }
2324
2325 void
2326 RouteUI::manage_pins ()
2327 {
2328         RoutePinWindowProxy* proxy = _route->pinmgr_proxy ();
2329         if (proxy) {
2330                 proxy->get (true);
2331                 proxy->present();
2332         }
2333 }
2334
2335 void
2336 RouteUI::fan_out (bool to_busses, bool group)
2337 {
2338         DisplaySuspender ds;
2339         boost::shared_ptr<ARDOUR::Route> route = _route;
2340         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (route->the_instrument ());
2341         assert (pi);
2342
2343         const uint32_t n_outputs = pi->output_streams ().n_audio ();
2344         if (route->n_outputs ().n_audio () != n_outputs) {
2345                 MessageDialog msg (string_compose (
2346                                         _("The Plugin's number of audio outputs ports (%1) does not match the Tracks's number of audio outputs (%2). Cannot fan out."),
2347                                         n_outputs, route->n_outputs ().n_audio ()));
2348                 msg.run ();
2349                 return;
2350         }
2351
2352 #define BUSNAME  pd.group_name + "(" + route->name () + ")"
2353
2354         /* count busses and channels/bus */
2355         boost::shared_ptr<Plugin> plugin = pi->plugin ();
2356         std::map<std::string, uint32_t> busnames;
2357         for (uint32_t p = 0; p < n_outputs; ++p) {
2358                 const Plugin::IOPortDescription& pd (plugin->describe_io_port (DataType::AUDIO, false, p));
2359                 std::string bn = BUSNAME;
2360                 busnames[bn]++;
2361         }
2362
2363         if (busnames.size () < 2) {
2364                 MessageDialog msg (_("Instrument has only 1 output bus. Nothing to fan out."));
2365                 msg.run ();
2366                 return;
2367         }
2368
2369         uint32_t outputs = 2;
2370         if (_session->master_out ()) {
2371                 outputs = std::max (outputs, _session->master_out ()->n_inputs ().n_audio ());
2372         }
2373
2374         route->output ()->disconnect (this);
2375         route->panner_shell ()->set_bypassed (true);
2376
2377         RouteList to_group;
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                 boost::shared_ptr<Route> r = _session->route_by_name (bn);
2382                 if (!r) {
2383                         if (to_busses) {
2384                                 RouteList rl = _session->new_audio_route (busnames[bn], outputs, NULL, 1, bn, PresentationInfo::AudioBus, PresentationInfo::max_order);
2385                                 r = rl.front ();
2386                                 assert (r);
2387                         } else {
2388                                 list<boost::shared_ptr<AudioTrack> > tl =
2389                                         _session->new_audio_track (busnames[bn], outputs, NULL, 1, bn, PresentationInfo::max_order, Normal);
2390                                 r = tl.front ();
2391                                 assert (r);
2392
2393                                 boost::shared_ptr<ControlList> cl (new ControlList);
2394                                 cl->push_back (r->monitoring_control ());
2395                                 _session->set_controls (cl, (double) MonitorInput, Controllable::NoGroup);
2396                         }
2397                         r->input ()->disconnect (this);
2398                 }
2399                 to_group.push_back (r);
2400                 route->output ()->audio (p)->connect (r->input ()->audio (pd.group_channel).get());
2401         }
2402 #undef BUSNAME
2403
2404         if (group) {
2405                 RouteGroup* rg = NULL;
2406                 const std::list<RouteGroup*>& rgs (_session->route_groups ());
2407                 for (std::list<RouteGroup*>::const_iterator i = rgs.begin (); i != rgs.end (); ++i) {
2408                         if ((*i)->name () == pi->name ()) {
2409                                 rg = *i;
2410                                 break;
2411                         }
2412                 }
2413                 if (!rg) {
2414                         rg = new RouteGroup (*_session, pi->name ());
2415                         _session->add_route_group (rg);
2416                         rg->set_gain (false);
2417                 }
2418
2419                 GroupTabs::set_group_color (rg, route->presentation_info().color());
2420                 for (RouteList::const_iterator i = to_group.begin(); i != to_group.end(); ++i) {
2421                         rg->add (*i);
2422                 }
2423         }
2424 }
2425
2426 bool
2427 RouteUI::mark_hidden (bool yn)
2428 {
2429         if (yn != _route->presentation_info().hidden()) {
2430                 _route->presentation_info().set_hidden (yn);
2431                 return true; // things changed
2432         }
2433         return false;
2434 }
2435
2436 boost::shared_ptr<Stripable>
2437 RouteUI::stripable () const
2438 {
2439         return _route;
2440 }
2441