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