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