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