Use const wherever you can
[ardour.git] / gtk2_ardour / route_ui.cc
1 /*
2     Copyright (C) 2002-2006 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <map>
21 #include <boost/algorithm/string.hpp>
22
23 #include <gtkmm/stock.h>
24
25 #include "pbd/memento_command.h"
26 #include "pbd/stacktrace.h"
27 #include "pbd/controllable.h"
28 #include "pbd/enumwriter.h"
29
30 #include "ardour/dB.h"
31 #include "ardour/route_group.h"
32 #include "ardour/solo_isolate_control.h"
33 #include "ardour/vca.h"
34 #include "ardour/vca_manager.h"
35 #include "ardour/audio_track.h"
36 #include "ardour/audio_port.h"
37 #include "ardour/audioengine.h"
38 #include "ardour/filename_extensions.h"
39 #include "ardour/midi_track.h"
40 #include "ardour/monitor_control.h"
41 #include "ardour/internal_send.h"
42 #include "ardour/panner_shell.h"
43 #include "ardour/profile.h"
44 #include "ardour/phase_control.h"
45 #include "ardour/send.h"
46 #include "ardour/route.h"
47 #include "ardour/session.h"
48 #include "ardour/template_utils.h"
49
50 #include "gtkmm2ext/gtk_ui.h"
51 #include "gtkmm2ext/doi.h"
52 #include "gtkmm2ext/gtk_ui.h"
53 #include "gtkmm2ext/utils.h"
54
55 #include "widgets/ardour_button.h"
56 #include "widgets/binding_proxy.h"
57 #include "widgets/prompter.h"
58
59 #include "ardour_dialog.h"
60 #include "ardour_ui.h"
61 #include "automation_time_axis.h"
62 #include "editor.h"
63 #include "group_tabs.h"
64 #include "gui_object.h"
65 #include "gui_thread.h"
66 #include "keyboard.h"
67 #include "latency_gui.h"
68 #include "mixer_strip.h"
69 #include "plugin_pin_dialog.h"
70 #include "rgb_macros.h"
71 #include "route_time_axis.h"
72 #include "route_ui.h"
73 #include "save_template_dialog.h"
74 #include "timers.h"
75 #include "ui_config.h"
76 #include "utils.h"
77
78 #include "pbd/i18n.h"
79
80 using namespace Gtk;
81 using namespace Gtkmm2ext;
82 using namespace ARDOUR;
83 using namespace ARDOUR_UI_UTILS;
84 using namespace ArdourWidgets;
85 using namespace PBD;
86 using namespace std;
87
88 uint32_t RouteUI::_max_invert_buttons = 3;
89 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
90 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
91 std::string RouteUI::program_port_prefix;
92
93 RouteUI::RouteUI (ARDOUR::Session* sess)
94         : monitor_input_button (0)
95         , monitor_disk_button (0)
96         , mute_menu(0)
97         , solo_menu(0)
98         , sends_menu(0)
99         , record_menu(0)
100         , comment_window(0)
101         , comment_area(0)
102         , input_selector (0)
103         , output_selector (0)
104         , _invert_menu(0)
105 {
106         if (program_port_prefix.empty()) {
107                 // compare to gtk2_ardour/port_group.cc
108                 string lpn (PROGRAM_NAME);
109                 boost::to_lower (lpn);
110                 program_port_prefix = lpn + ":"; // e.g. "ardour:"
111         }
112
113         if (sess) {
114                 init ();
115         }
116 }
117
118 RouteUI::~RouteUI()
119 {
120         if (_route) {
121                 ARDOUR_UI::instance()->gui_object_state->remove_node (route_state_id());
122         }
123
124         _route.reset (); /* drop reference to route, so that it can be cleaned up */
125         route_connections.drop_connections ();
126
127         delete solo_menu;
128         delete mute_menu;
129         delete sends_menu;
130         delete record_menu;
131         delete comment_window;
132         delete input_selector;
133         delete output_selector;
134         delete monitor_input_button;
135         delete monitor_disk_button;
136         delete _invert_menu;
137
138         send_blink_connection.disconnect ();
139         rec_blink_connection.disconnect ();
140 }
141
142 void
143 RouteUI::init ()
144 {
145         self_destruct = true;
146         mute_menu = 0;
147         solo_menu = 0;
148         sends_menu = 0;
149         record_menu = 0;
150         _invert_menu = 0;
151         pre_fader_mute_check = 0;
152         post_fader_mute_check = 0;
153         listen_mute_check = 0;
154         main_mute_check = 0;
155         solo_safe_check = 0;
156         solo_isolated_check = 0;
157         solo_isolated_led = 0;
158         solo_safe_led = 0;
159         _solo_release = 0;
160         _mute_release = 0;
161         denormal_menu_item = 0;
162         step_edit_item = 0;
163         rec_safe_item = 0;
164         multiple_mute_change = false;
165         multiple_solo_change = false;
166         _i_am_the_modifier = 0;
167
168         input_selector = 0;
169         output_selector = 0;
170
171         setup_invert_buttons ();
172
173         mute_button = manage (new ArdourButton);
174         mute_button->set_name ("mute button");
175         UI::instance()->set_tip (mute_button, _("Mute this track"), "");
176
177         solo_button = manage (new ArdourButton);
178         solo_button->set_name ("solo button");
179         UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
180         solo_button->set_no_show_all (true);
181
182         rec_enable_button = manage (new ArdourButton);
183         rec_enable_button->set_name ("record enable button");
184         rec_enable_button->set_icon (ArdourIcon::RecButton);
185         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
186
187         if (UIConfiguration::instance().get_blink_rec_arm()) {
188                 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
189         }
190
191         show_sends_button = manage (new ArdourButton);
192         show_sends_button->set_name ("send alert button");
193         UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
194
195         monitor_input_button = new ArdourButton (ArdourButton::default_elements);
196         monitor_input_button->set_name ("monitor button");
197         monitor_input_button->set_text (_("In"));
198         UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
199         monitor_input_button->set_no_show_all (true);
200
201         monitor_disk_button = new ArdourButton (ArdourButton::default_elements);
202         monitor_disk_button->set_name ("monitor button");
203         monitor_disk_button->set_text (_("Disk"));
204         UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
205         monitor_disk_button->set_no_show_all (true);
206
207         _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
208         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
209         _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
210
211         _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
212         Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
213         UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (this, &RouteUI::parameter_changed));
214
215         rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
216         rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
217
218         show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
219         show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
220
221         solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
222         solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
223         mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
224         mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
225
226         monitor_input_button->set_distinct_led_click (false);
227         monitor_disk_button->set_distinct_led_click (false);
228
229         monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
230         monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
231
232         monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
233         monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
234
235         BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
236 }
237
238 void
239 RouteUI::reset ()
240 {
241         route_connections.drop_connections ();
242
243         delete solo_menu;
244         solo_menu = 0;
245
246         delete mute_menu;
247         mute_menu = 0;
248
249         _color_picker.reset ();
250
251         denormal_menu_item = 0;
252 }
253
254 void
255 RouteUI::self_delete ()
256 {
257         delete this;
258 }
259
260 void
261 RouteUI::set_route (boost::shared_ptr<Route> rp)
262 {
263         reset ();
264
265         _route = rp;
266
267         if ( !_route->presentation_info().color_set() ) {
268                 /* deal with older 4.x color, which was stored in the GUI object state */
269
270                 string p = ARDOUR_UI::instance()->gui_object_state->get_string (route_state_id(), X_("color"));
271
272                 if (!p.empty()) {
273
274                         /* old v4.x or earlier session. Use this information */
275
276                         int red, green, blue;
277                         char colon;
278
279                         stringstream ss (p);
280
281                         /* old color format version was:
282
283                            16bit value for red:16 bit value for green:16 bit value for blue
284
285                            decode to rgb ..
286                         */
287
288                         ss >> red;
289                         ss >> colon;
290                         ss >> green;
291                         ss >> colon;
292                         ss >> blue;
293
294                         red >>= 2;
295                         green >>= 2;
296                         blue >>= 2;
297
298                         _route->presentation_info().set_color (RGBA_TO_UINT (red, green, blue, 255));
299                 }
300         }
301
302         if (set_color_from_route()) {
303                 set_color (gdk_color_to_rgba (AxisView::unique_random_color ()));
304         }
305
306         if (self_destruct) {
307                 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
308         }
309
310         delete input_selector;
311         input_selector = 0;
312
313         delete output_selector;
314         output_selector = 0;
315
316         mute_button->set_controllable (_route->mute_control());
317         solo_button->set_controllable (_route->solo_control());
318
319         _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
320
321         _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this), gui_context());
322
323         _route->mute_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context());
324         _route->solo_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
325         _route->solo_safe_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
326         _route->solo_isolate_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
327         _route->phase_control()->Changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
328         _route->fan_out.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::fan_out, this, true, true), gui_context());
329
330         if (is_track()) {
331                 track()->FreezeChange.connect (*this, invalidator (*this), boost::bind (&RouteUI::map_frozen, this), gui_context());
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 (_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                 /* Primary-Tertiary-click applies change to all routes */
920                 rl = _session->get_routes ();
921                 _session->set_controls (route_list_to_control_list (rl, &Stripable::monitoring_control), (double) mc, Controllable::NoGroup);
922         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
923                 /* Primary-click overrides group */
924                 rl.reset (new RouteList);
925                 rl->push_back (route());
926                 _session->set_controls (route_list_to_control_list (rl, &Stripable::monitoring_control), (double) mc, Controllable::InverseGroup);
927         } else {
928                 rl.reset (new RouteList);
929                 rl->push_back (route());
930                 _session->set_controls (route_list_to_control_list (rl, &Stripable::monitoring_control), (double) mc, Controllable::UseGroup);
931         }
932
933         return false;
934 }
935
936 void
937 RouteUI::build_record_menu ()
938 {
939         if (!record_menu) {
940                 record_menu = new Menu;
941                 record_menu->set_name ("ArdourContextMenu");
942                 using namespace Menu_Helpers;
943                 MenuList& items = record_menu->items();
944
945                 items.push_back (CheckMenuElem (_("Rec-Safe"), sigc::mem_fun (*this, &RouteUI::toggle_rec_safe)));
946                 rec_safe_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
947
948                 if (is_midi_track()) {
949                         items.push_back (SeparatorElem());
950                         items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
951                         step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
952                 }
953         }
954
955         if (step_edit_item) {
956                 if (track()->rec_enable_control()->get_value()) {
957                         step_edit_item->set_sensitive (false);
958                 }
959                 step_edit_item->set_active (midi_track()->step_editing());
960         }
961         if (rec_safe_item) {
962                 rec_safe_item->set_sensitive (!_route->rec_enable_control()->get_value());
963                 rec_safe_item->set_active (_route->rec_safe_control()->get_value());
964         }
965 }
966
967 void
968 RouteUI::toggle_step_edit ()
969 {
970         if (!is_midi_track() || track()->rec_enable_control()->get_value()) {
971                 return;
972         }
973
974         midi_track()->set_step_editing (step_edit_item->get_active());
975 }
976
977 void
978 RouteUI::toggle_rec_safe ()
979 {
980         boost::shared_ptr<AutomationControl> rs = _route->rec_safe_control();
981
982         if (!rs) {
983                 return;
984         }
985
986         /* This check is made inside the control too, but dong it here can't
987          * hurt.
988          */
989
990         if (_route->rec_enable_control()->get_value()) {
991                 return;
992         }
993
994         rs->set_value (rec_safe_item->get_active (), Controllable::UseGroup);
995 }
996
997 void
998 RouteUI::step_edit_changed (bool yn)
999 {
1000         if (yn) {
1001                 if (rec_enable_button) {
1002                         rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1003                 }
1004
1005                 start_step_editing ();
1006
1007                 if (step_edit_item) {
1008                         step_edit_item->set_active (true);
1009                 }
1010
1011         } else {
1012
1013                 if (rec_enable_button) {
1014                         rec_enable_button->unset_active_state ();
1015                 }
1016
1017                 stop_step_editing ();
1018
1019                 if (step_edit_item) {
1020                         step_edit_item->set_active (false);
1021                 }
1022         }
1023 }
1024
1025 bool
1026 RouteUI::rec_enable_release (GdkEventButton* ev)
1027 {
1028         if (Keyboard::is_context_menu_event (ev)) {
1029                 build_record_menu ();
1030                 if (record_menu) {
1031                         record_menu->popup (1, ev->time);
1032                 }
1033                 return false;
1034         }
1035
1036         return false;
1037 }
1038
1039 void
1040 RouteUI::build_sends_menu ()
1041 {
1042         using namespace Menu_Helpers;
1043
1044         sends_menu = new Menu;
1045         sends_menu->set_name ("ArdourContextMenu");
1046         MenuList& items = sends_menu->items();
1047
1048         items.push_back (
1049                 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
1050                 );
1051
1052         items.push_back (
1053                 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
1054                 );
1055
1056         items.push_back (
1057                 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
1058                 );
1059
1060         items.push_back (
1061                 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
1062                 );
1063
1064         items.push_back (
1065                 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
1066                 );
1067
1068         items.push_back (
1069                 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
1070
1071         items.push_back (
1072                 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
1073                 );
1074
1075         items.push_back (
1076                 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
1077                 );
1078
1079         items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
1080         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
1081         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
1082
1083 }
1084
1085 void
1086 RouteUI::create_sends (Placement p, bool include_buses)
1087 {
1088         _session->globally_add_internal_sends (_route, p, include_buses);
1089 }
1090
1091 void
1092 RouteUI::create_selected_sends (Placement p, bool include_buses)
1093 {
1094         boost::shared_ptr<RouteList> rlist (new RouteList);
1095         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
1096
1097         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
1098                 RouteTimeAxisView* rtv;
1099                 RouteUI* rui;
1100                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1101                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1102                                 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1103                                         rlist->push_back (rui->route());
1104                                 }
1105                         }
1106                 }
1107         }
1108
1109         _session->add_internal_sends (_route, p, rlist);
1110 }
1111
1112 void
1113 RouteUI::set_sends_gain_from_track ()
1114 {
1115         _session->globally_set_send_gains_from_track (_route);
1116 }
1117
1118 void
1119 RouteUI::set_sends_gain_to_zero ()
1120 {
1121         _session->globally_set_send_gains_to_zero (_route);
1122 }
1123
1124 void
1125 RouteUI::set_sends_gain_to_unity ()
1126 {
1127         _session->globally_set_send_gains_to_unity (_route);
1128 }
1129
1130 bool
1131 RouteUI::show_sends_press(GdkEventButton* ev)
1132 {
1133         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1134                 return true;
1135         }
1136
1137         if (!is_track() && show_sends_button) {
1138
1139                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1140
1141                         // do nothing on midi sigc::bind event
1142                         return false;
1143
1144                 } else if (Keyboard::is_context_menu_event (ev)) {
1145
1146                         if (sends_menu == 0) {
1147                                 build_sends_menu ();
1148                         }
1149
1150                         sends_menu->popup (0, ev->time);
1151
1152                 } else {
1153
1154                         boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1155
1156                         if (s == _route) {
1157                                 set_showing_sends_to (boost::shared_ptr<Route> ());
1158                         } else {
1159                                 set_showing_sends_to (_route);
1160                         }
1161                 }
1162         }
1163
1164         return true;
1165 }
1166
1167 bool
1168 RouteUI::show_sends_release (GdkEventButton*)
1169 {
1170         return true;
1171 }
1172
1173 void
1174 RouteUI::send_blink (bool onoff)
1175 {
1176         if (!show_sends_button) {
1177                 return;
1178         }
1179
1180         if (onoff) {
1181                 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1182         } else {
1183                 show_sends_button->unset_active_state ();
1184         }
1185 }
1186
1187 Gtkmm2ext::ActiveState
1188 RouteUI::solo_active_state (boost::shared_ptr<Stripable> s)
1189 {
1190         boost::shared_ptr<SoloControl> sc = s->solo_control();
1191
1192         if (!sc) {
1193                 return Gtkmm2ext::Off;
1194         }
1195
1196         if (!sc->can_solo()) {
1197                 return Gtkmm2ext::Off;
1198         }
1199
1200
1201         if (sc->self_soloed()) {
1202                 return Gtkmm2ext::ExplicitActive;
1203         } else if (sc->soloed_by_others()) {
1204                 return Gtkmm2ext::ImplicitActive;
1205         } else {
1206                 return Gtkmm2ext::Off;
1207         }
1208 }
1209
1210 Gtkmm2ext::ActiveState
1211 RouteUI::solo_isolate_active_state (boost::shared_ptr<Stripable> s)
1212 {
1213         boost::shared_ptr<SoloIsolateControl> sc = s->solo_isolate_control();
1214
1215         if (!sc) {
1216                 return Gtkmm2ext::Off;
1217         }
1218
1219         if (s->is_master() || s->is_monitor()) {
1220                 return Gtkmm2ext::Off;
1221         }
1222
1223         if (sc->solo_isolated()) {
1224                 return Gtkmm2ext::ExplicitActive;
1225         } else {
1226                 return Gtkmm2ext::Off;
1227         }
1228 }
1229
1230 Gtkmm2ext::ActiveState
1231 RouteUI::solo_safe_active_state (boost::shared_ptr<Stripable> s)
1232 {
1233         boost::shared_ptr<SoloSafeControl> sc = s->solo_safe_control();
1234
1235         if (!sc) {
1236                 return Gtkmm2ext::Off;
1237         }
1238
1239         if (s->is_master() || s->is_monitor()) {
1240                 return Gtkmm2ext::Off;
1241         }
1242
1243         if (sc->solo_safe()) {
1244                 return Gtkmm2ext::ExplicitActive;
1245         } else {
1246                 return Gtkmm2ext::Off;
1247         }
1248 }
1249
1250 void
1251 RouteUI::update_solo_display ()
1252 {
1253         bool yn = _route->solo_safe_control()->solo_safe ();
1254
1255         if (solo_safe_check && solo_safe_check->get_active() != yn) {
1256                 solo_safe_check->set_active (yn);
1257         }
1258
1259         yn = _route->solo_isolate_control()->solo_isolated ();
1260
1261         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1262                 solo_isolated_check->set_active (yn);
1263         }
1264
1265         set_button_names ();
1266
1267         if (solo_isolated_led) {
1268                 if (_route->solo_isolate_control()->solo_isolated()) {
1269                         solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1270                 } else {
1271                         solo_isolated_led->unset_active_state ();
1272                 }
1273         }
1274
1275         if (solo_safe_led) {
1276                 if (_route->solo_safe_control()->solo_safe()) {
1277                         solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1278                 } else {
1279                         solo_safe_led->unset_active_state ();
1280                 }
1281         }
1282
1283         solo_button->set_active_state (solo_active_state (_route));
1284
1285         /* some changes to solo status can affect mute display, so catch up
1286          */
1287
1288         update_mute_display ();
1289 }
1290
1291 void
1292 RouteUI::solo_changed_so_update_mute ()
1293 {
1294         update_mute_display ();
1295 }
1296
1297 ActiveState
1298 RouteUI::mute_active_state (Session*, boost::shared_ptr<Stripable> s)
1299 {
1300         boost::shared_ptr<MuteControl> mc = s->mute_control();
1301
1302         if (s->is_monitor()) {
1303                 return Gtkmm2ext::Off;
1304         }
1305
1306         if (!mc) {
1307                 return Gtkmm2ext::Off;
1308         }
1309
1310         if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1311
1312                 if (mc->muted_by_self ()) {
1313                         /* full mute */
1314                         return Gtkmm2ext::ExplicitActive;
1315                 } else if (mc->muted_by_others_soloing () || mc->muted_by_masters ()) {
1316                         /* this will reflect both solo mutes AND master mutes */
1317                         return Gtkmm2ext::ImplicitActive;
1318                 } else {
1319                         /* no mute at all */
1320                         return Gtkmm2ext::Off;
1321                 }
1322
1323         } else {
1324
1325                 if (mc->muted_by_self()) {
1326                         /* full mute */
1327                         return Gtkmm2ext::ExplicitActive;
1328                 } else if (mc->muted_by_masters ()) {
1329                         /* this shows only master mutes, not mute-by-others-soloing */
1330                         return Gtkmm2ext::ImplicitActive;
1331                 } else {
1332                         /* no mute at all */
1333                         return Gtkmm2ext::Off;
1334                 }
1335         }
1336
1337         return ActiveState(0);
1338 }
1339
1340 void
1341 RouteUI::update_mute_display ()
1342 {
1343         if (!_route) {
1344                 return;
1345         }
1346
1347         mute_button->set_active_state (mute_active_state (_session, _route));
1348 }
1349
1350
1351 void
1352 RouteUI::route_rec_enable_changed ()
1353 {
1354         blink_rec_display (true);  //this lets the button change "immediately" rather than wait for the next blink
1355 }
1356
1357 void
1358 RouteUI::session_rec_enable_changed ()
1359 {
1360         blink_rec_display (true);  //this lets the button change "immediately" rather than wait for the next blink
1361 }
1362
1363 void
1364 RouteUI::blink_rec_display (bool blinkOn)
1365 {
1366         if (!rec_enable_button || !_route) {
1367                 return;
1368         }
1369
1370         if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1371                 return;
1372         }
1373
1374         if (!is_track()) {
1375                 return;
1376         }
1377
1378         if (track()->rec_enable_control()->get_value()) {
1379                 switch (_session->record_status ()) {
1380                         case Session::Recording:
1381                                 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1382                                 break;
1383
1384                         case Session::Disabled:
1385                         case Session::Enabled:
1386                                 if (UIConfiguration::instance().get_blink_rec_arm()) {
1387                                         rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1388                                 } else {
1389                                         rec_enable_button->set_active_state ( ImplicitActive );
1390                                 }
1391                                 break;
1392                 }
1393
1394                 if (step_edit_item) {
1395                         step_edit_item->set_sensitive (false);
1396                 }
1397
1398         } else {
1399                 rec_enable_button->unset_active_state ();
1400
1401                 if (step_edit_item) {
1402                         step_edit_item->set_sensitive (true);
1403                 }
1404         }
1405
1406         check_rec_enable_sensitivity ();
1407 }
1408
1409 void
1410 RouteUI::build_solo_menu (void)
1411 {
1412         using namespace Menu_Helpers;
1413
1414         solo_menu = new Menu;
1415         solo_menu->set_name ("ArdourContextMenu");
1416         MenuList& items = solo_menu->items();
1417         Gtk::CheckMenuItem* check;
1418
1419         check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1420         check->set_active (_route->solo_isolate_control()->solo_isolated());
1421         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1422         items.push_back (CheckMenuElem(*check));
1423         solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1424         check->show_all();
1425
1426         check = new Gtk::CheckMenuItem(_("Solo Safe"));
1427         check->set_active (_route->solo_safe_control()->solo_safe());
1428         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1429         items.push_back (CheckMenuElem(*check));
1430         solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1431         check->show_all();
1432 }
1433
1434 void
1435 RouteUI::build_mute_menu(void)
1436 {
1437         using namespace Menu_Helpers;
1438
1439         mute_menu = new Menu;
1440         mute_menu->set_name ("ArdourContextMenu");
1441
1442         MenuList& items = mute_menu->items();
1443
1444         pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1445         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1446         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1447         items.push_back (CheckMenuElem(*pre_fader_mute_check));
1448         pre_fader_mute_check->show_all();
1449
1450         post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1451         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1452         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1453         items.push_back (CheckMenuElem(*post_fader_mute_check));
1454         post_fader_mute_check->show_all();
1455
1456         listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1457         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1458         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1459         items.push_back (CheckMenuElem(*listen_mute_check));
1460         listen_mute_check->show_all();
1461
1462         main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1463         init_mute_menu(MuteMaster::Main, main_mute_check);
1464         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1465         items.push_back (CheckMenuElem(*main_mute_check));
1466         main_mute_check->show_all();
1467
1468         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1469 }
1470
1471 void
1472 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1473 {
1474         check->set_active (_route->mute_control()->mute_points() & mp);
1475 }
1476
1477 void
1478 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1479 {
1480         if (check->get_active()) {
1481                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() | mp));
1482         } else {
1483                 _route->mute_control()->set_mute_points (MuteMaster::MutePoint (_route->mute_control()->mute_points() & ~mp));
1484         }
1485 }
1486
1487 void
1488 RouteUI::muting_change ()
1489 {
1490         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1491
1492         bool yn;
1493         MuteMaster::MutePoint current = _route->mute_control()->mute_points ();
1494
1495         yn = (current & MuteMaster::PreFader);
1496
1497         if (pre_fader_mute_check->get_active() != yn) {
1498                 pre_fader_mute_check->set_active (yn);
1499         }
1500
1501         yn = (current & MuteMaster::PostFader);
1502
1503         if (post_fader_mute_check->get_active() != yn) {
1504                 post_fader_mute_check->set_active (yn);
1505         }
1506
1507         yn = (current & MuteMaster::Listen);
1508
1509         if (listen_mute_check->get_active() != yn) {
1510                 listen_mute_check->set_active (yn);
1511         }
1512
1513         yn = (current & MuteMaster::Main);
1514
1515         if (main_mute_check->get_active() != yn) {
1516                 main_mute_check->set_active (yn);
1517         }
1518 }
1519
1520 bool
1521 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1522 {
1523         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1524                 return true;
1525         }
1526
1527         bool view = solo_isolated_led->active_state();
1528         bool model = _route->solo_isolate_control()->solo_isolated();
1529
1530         /* called BEFORE the view has changed */
1531
1532         if (ev->button == 1) {
1533                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1534
1535                         if (model) {
1536                                 /* disable isolate for all routes */
1537                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_isolate_control), 0.0, Controllable::NoGroup);
1538                         } else {
1539                                 /* enable isolate for all routes */
1540                                 _session->set_controls (route_list_to_control_list (_session->get_routes(), &Stripable::solo_isolate_control), 1.0, Controllable::NoGroup);
1541                         }
1542
1543                 } else {
1544
1545                         if (model == view) {
1546
1547                                 /* flip just this route */
1548
1549                                 boost::shared_ptr<RouteList> rl (new RouteList);
1550                                 rl->push_back (_route);
1551                                 _session->set_controls (route_list_to_control_list (rl, &Stripable::solo_isolate_control), view ? 0.0 : 1.0, Controllable::NoGroup);
1552                         }
1553                 }
1554         }
1555
1556         return false;
1557 }
1558
1559 bool
1560 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1561 {
1562         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1563                 return true;
1564         }
1565
1566         bool view = solo_safe_led->active_state();
1567         bool model = _route->solo_safe_control()->solo_safe();
1568
1569         if (ev->button == 1) {
1570                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1571                         boost::shared_ptr<RouteList> rl (_session->get_routes());
1572                         if (model) {
1573                                 /* disable solo safe for all routes */
1574                                 DisplaySuspender ds;
1575                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1576                                         (*i)->solo_safe_control()->set_value (0.0, Controllable::NoGroup);
1577                                 }
1578                         } else {
1579                                 /* enable solo safe for all routes */
1580                                 DisplaySuspender ds;
1581                                 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1582                                         (*i)->solo_safe_control()->set_value (1.0, Controllable::NoGroup);
1583                                 }
1584                         }
1585                 }
1586                 else {
1587                         if (model == view) {
1588                                 /* flip just this route */
1589                                 _route->solo_safe_control()->set_value (view ? 0.0 : 1.0, Controllable::NoGroup);
1590                         }
1591                 }
1592         }
1593
1594         return false;
1595 }
1596
1597 void
1598 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1599 {
1600         bool view = check->get_active();
1601         bool model = _route->solo_isolate_control()->solo_isolated();
1602
1603         /* called AFTER the view has changed */
1604
1605         if (model != view) {
1606                 _route->solo_isolate_control()->set_value (view ? 1.0 : 0.0, Controllable::UseGroup);
1607         }
1608 }
1609
1610 void
1611 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1612 {
1613         _route->solo_safe_control()->set_value (check->get_active() ? 1.0 : 0.0, Controllable::UseGroup);
1614 }
1615
1616 /** Ask the user to choose a colour, and then apply that color to my route */
1617 void
1618 RouteUI::choose_color ()
1619 {
1620         _color_picker.popup (_route);
1621 }
1622
1623 /** Set the route's own color.  This may not be used for display if
1624  *  the route is in a group which shares its color with its routes.
1625  */
1626 void
1627 RouteUI::set_color (uint32_t c)
1628 {
1629         _route->presentation_info().set_color (c);
1630 }
1631
1632 /** @return GUI state ID for things that are common to the route in all its representations */
1633 string
1634 RouteUI::route_state_id () const
1635 {
1636         return string_compose (X_("route %1"), _route->id().to_s());
1637 }
1638
1639 int
1640 RouteUI::set_color_from_route ()
1641 {
1642         if (_route->presentation_info().color_set()) {
1643                 return 0; /* nothing to do */
1644         }
1645
1646         return 1; /* pick a color */
1647 }
1648
1649 /** @return true if this name should be used for the route, otherwise false */
1650 bool
1651 RouteUI::verify_new_route_name (const std::string& name)
1652 {
1653         if (name.find (':') == string::npos) {
1654                 return true;
1655         }
1656
1657         MessageDialog colon_msg (
1658                 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1659                 false, MESSAGE_QUESTION, BUTTONS_NONE
1660                 );
1661
1662         colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1663         colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1664
1665         return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1666 }
1667
1668 void
1669 RouteUI::route_rename ()
1670 {
1671         ArdourWidgets::Prompter name_prompter (true);
1672         string result;
1673         bool done = false;
1674
1675         if (is_track()) {
1676                 name_prompter.set_title (_("Rename Track"));
1677         } else {
1678                 name_prompter.set_title (_("Rename Bus"));
1679         }
1680         name_prompter.set_prompt (_("New name:"));
1681         name_prompter.set_initial_text (_route->name());
1682         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1683         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1684         name_prompter.show_all ();
1685
1686         while (!done) {
1687                 switch (name_prompter.run ()) {
1688                 case Gtk::RESPONSE_ACCEPT:
1689                         name_prompter.get_result (result);
1690                         name_prompter.hide ();
1691                         if (result.length()) {
1692                                 if (verify_new_route_name (result)) {
1693                                         _route->set_name (result);
1694                                         done = true;
1695                                 } else {
1696                                         /* back to name prompter */
1697                                 }
1698
1699                         } else {
1700                                 /* nothing entered, just get out of here */
1701                                 done = true;
1702                         }
1703                         break;
1704                 default:
1705                         done = true;
1706                         break;
1707                 }
1708         }
1709
1710         return;
1711
1712 }
1713
1714 void
1715 RouteUI::toggle_comment_editor ()
1716 {
1717 //      if (ignore_toggle) {
1718 //              return;
1719 //      }
1720
1721         if (comment_window && comment_window->is_visible ()) {
1722                 comment_window->hide ();
1723         } else {
1724                 open_comment_editor ();
1725         }
1726 }
1727
1728
1729 void
1730 RouteUI::open_comment_editor ()
1731 {
1732         if (comment_window == 0) {
1733                 setup_comment_editor ();
1734         }
1735
1736         string title;
1737         title = _route->name();
1738         title += _(": comment editor");
1739
1740         comment_window->set_title (title);
1741         comment_window->present();
1742 }
1743
1744 void
1745 RouteUI::setup_comment_editor ()
1746 {
1747         comment_window = new ArdourWindow (""); // title will be reset to show route
1748         comment_window->set_skip_taskbar_hint (true);
1749         comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1750         comment_window->set_default_size (400, 200);
1751
1752         comment_area = manage (new TextView());
1753         comment_area->set_name ("MixerTrackCommentArea");
1754         comment_area->set_wrap_mode (WRAP_WORD);
1755         comment_area->set_editable (true);
1756         comment_area->get_buffer()->set_text (_route->comment());
1757         comment_area->show ();
1758
1759         comment_window->add (*comment_area);
1760 }
1761
1762 void
1763 RouteUI::comment_changed ()
1764 {
1765         ignore_comment_edit = true;
1766         if (comment_area) {
1767                 comment_area->get_buffer()->set_text (_route->comment());
1768         }
1769         ignore_comment_edit = false;
1770 }
1771
1772 void
1773 RouteUI::comment_editor_done_editing ()
1774 {
1775         ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1776
1777         string const str = comment_area->get_buffer()->get_text();
1778         if (str == _route->comment ()) {
1779                 return;
1780         }
1781
1782         _route->set_comment (str, this);
1783 }
1784
1785 void
1786 RouteUI::set_route_active (bool a, bool apply_to_selection)
1787 {
1788         if (apply_to_selection) {
1789                 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1790         } else {
1791                 _route->set_active (a, this);
1792         }
1793 }
1794
1795 void
1796 RouteUI::duplicate_selected_routes ()
1797 {
1798         ARDOUR_UI::instance()->start_duplicate_routes();
1799 }
1800
1801 void
1802 RouteUI::toggle_denormal_protection ()
1803 {
1804         if (denormal_menu_item) {
1805
1806                 bool x;
1807
1808                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1809
1810                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1811                         _route->set_denormal_protection (x);
1812                 }
1813         }
1814 }
1815
1816 void
1817 RouteUI::denormal_protection_changed ()
1818 {
1819         if (denormal_menu_item) {
1820                 denormal_menu_item->set_active (_route->denormal_protection());
1821         }
1822 }
1823
1824 void
1825 RouteUI::disconnect_input ()
1826 {
1827         _route->input()->disconnect (this);
1828 }
1829
1830 void
1831 RouteUI::disconnect_output ()
1832 {
1833         _route->output()->disconnect (this);
1834 }
1835
1836 bool
1837 RouteUI::is_track () const
1838 {
1839         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1840 }
1841
1842 boost::shared_ptr<Track>
1843 RouteUI::track() const
1844 {
1845         return boost::dynamic_pointer_cast<Track>(_route);
1846 }
1847
1848 bool
1849 RouteUI::is_audio_track () const
1850 {
1851         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1852 }
1853
1854 boost::shared_ptr<AudioTrack>
1855 RouteUI::audio_track() const
1856 {
1857         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1858 }
1859
1860 bool
1861 RouteUI::is_midi_track () const
1862 {
1863         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1864 }
1865
1866 boost::shared_ptr<MidiTrack>
1867 RouteUI::midi_track() const
1868 {
1869         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1870 }
1871
1872 bool
1873 RouteUI::has_audio_outputs () const
1874 {
1875         return (_route->n_outputs().n_audio() > 0);
1876 }
1877
1878 void
1879 RouteUI::map_frozen ()
1880 {
1881         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1882
1883         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1884
1885         if (at) {
1886                 check_rec_enable_sensitivity ();
1887         }
1888 }
1889
1890 void
1891 RouteUI::adjust_latency ()
1892 {
1893         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1894 }
1895
1896
1897 void
1898 RouteUI::save_as_template_dialog_response (int response, SaveTemplateDialog* d)
1899 {
1900         if (response == RESPONSE_ACCEPT) {
1901                 const string name = d->get_template_name ();
1902                 const string desc = d->get_description ();
1903                 const string path = Glib::build_filename(ARDOUR::user_route_template_directory (), name);
1904
1905                 if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) { /* file already exists. */
1906                         bool overwrite = overwrite_file_dialog (*d,
1907                                                                 _("Confirm Template Overwrite"),
1908                                                                 _("A template already exists with that name. Do you want to overwrite it?"));
1909
1910                         if (!overwrite) {
1911                                 d->show ();
1912                                 return;
1913                         }
1914                 }
1915                 _route->save_as_template (path, name, desc);
1916         }
1917
1918         delete d;
1919 }
1920
1921 void
1922 RouteUI::save_as_template ()
1923 {
1924         const std::string dir = ARDOUR::user_route_template_directory ();
1925
1926         if (g_mkdir_with_parents (dir.c_str(), 0755)) {
1927                 error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg;
1928                 return;
1929         }
1930
1931         SaveTemplateDialog* d = new SaveTemplateDialog (_route->name());
1932
1933         d->signal_response().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::save_as_template_dialog_response), d));
1934         d->show ();
1935 }
1936
1937 void
1938 RouteUI::check_rec_enable_sensitivity ()
1939 {
1940         if (!rec_enable_button) {
1941                 assert (0); // This should not happen
1942                 return;
1943         }
1944         if (!_session->writable()) {
1945                 rec_enable_button->set_sensitive (false);
1946                 return;
1947         }
1948
1949         if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1950                 rec_enable_button->set_sensitive (false);
1951         } else if (is_audio_track ()  && track()->freeze_state() == AudioTrack::Frozen) {
1952                 rec_enable_button->set_sensitive (false);
1953         } else {
1954                 rec_enable_button->set_sensitive (true);
1955         }
1956         if (_route && _route->rec_safe_control () && _route->rec_safe_control()->get_value()) {
1957                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() | Gtkmm2ext::Insensitive));
1958         } else {
1959                 rec_enable_button->set_visual_state (Gtkmm2ext::VisualState (solo_button->visual_state() & ~Gtkmm2ext::Insensitive));
1960         }
1961         update_monitoring_display ();
1962 }
1963
1964 void
1965 RouteUI::parameter_changed (string const & p)
1966 {
1967         /* this handles RC and per-session parameter changes */
1968
1969         if (p == "disable-disarm-during-roll") {
1970                 check_rec_enable_sensitivity ();
1971         } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1972                 set_button_names ();
1973         } else if (p == "session-monitoring") {
1974                 update_monitoring_display ();
1975         } else if (p == "auto-input") {
1976                 update_monitoring_display ();
1977         } else if (p == "blink-rec-arm") {
1978                 if (UIConfiguration::instance().get_blink_rec_arm()) {
1979                         rec_blink_connection.disconnect ();
1980                         rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1981                 } else {
1982                         rec_blink_connection.disconnect ();
1983                         RouteUI::blink_rec_display(false);
1984                 }
1985         }
1986 }
1987
1988 void
1989 RouteUI::setup_invert_buttons ()
1990 {
1991         /* remove old invert buttons */
1992         for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1993                 _invert_button_box.remove (**i);
1994         }
1995
1996         _invert_buttons.clear ();
1997
1998         if (!_route || !_route->input()) {
1999                 return;
2000         }
2001
2002         uint32_t const N = _route->input()->n_ports().n_audio ();
2003
2004         uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2005
2006         for (uint32_t i = 0; i < to_add; ++i) {
2007                 ArdourButton* b = manage (new ArdourButton);
2008                 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2009                 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2010
2011                 b->set_name (X_("invert button"));
2012                 if (to_add == 1) {
2013                         if (N > 1) {
2014                                 b->set_text (string_compose (X_("Ø (%1)"), N));
2015                         } else {
2016                                 b->set_text (X_("Ø"));
2017                         }
2018                 } else {
2019                         b->set_text (string_compose (X_("Ø%1"), i + 1));
2020                 }
2021
2022                 if (N <= _max_invert_buttons) {
2023                         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));
2024                 } else {
2025                         UI::instance()->set_tip (*b, _("Click to show a menu of channels to invert polarity"));
2026                 }
2027
2028                 _invert_buttons.push_back (b);
2029                 _invert_button_box.pack_start (*b);
2030         }
2031
2032         _invert_button_box.set_spacing (1);
2033         _invert_button_box.show_all ();
2034 }
2035
2036 void
2037 RouteUI::set_invert_button_state ()
2038 {
2039         uint32_t const N = _route->input()->n_ports().n_audio();
2040         if (N > _max_invert_buttons) {
2041
2042                 /* One button for many channels; explicit active if all channels are inverted,
2043                    implicit active if some are, off if none are.
2044                 */
2045
2046                 ArdourButton* b = _invert_buttons.front ();
2047
2048                 if (_route->phase_control()->count() == _route->phase_control()->size()) {
2049                         b->set_active_state (Gtkmm2ext::ExplicitActive);
2050                 } else if (_route->phase_control()->any()) {
2051                         b->set_active_state (Gtkmm2ext::ImplicitActive);
2052                 } else {
2053                         b->set_active_state (Gtkmm2ext::Off);
2054                 }
2055
2056         } else {
2057
2058                 /* One button per channel; just set active */
2059
2060                 int j = 0;
2061                 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2062                         (*i)->set_active (_route->phase_control()->inverted (j));
2063                 }
2064
2065         }
2066 }
2067
2068 bool
2069 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2070 {
2071         if (ev->button == 1 && i < _invert_buttons.size()) {
2072                 uint32_t const N = _route->input()->n_ports().n_audio ();
2073                 if (N <= _max_invert_buttons) {
2074                         /* left-click inverts phase so long as we have a button per channel */
2075                         _route->phase_control()->set_phase_invert (i, !_invert_buttons[i]->get_active());
2076                         return false;
2077                 }
2078         }
2079         return false;
2080 }
2081
2082
2083 bool
2084 RouteUI::invert_press (GdkEventButton* ev)
2085 {
2086         using namespace Menu_Helpers;
2087
2088         uint32_t const N = _route->input()->n_ports().n_audio();
2089         if (N <= _max_invert_buttons && ev->button != 3) {
2090                 /* If we have an invert button per channel, we only pop
2091                    up a menu on right-click; left click is handled
2092                    on release.
2093                 */
2094                 return false;
2095         }
2096
2097         delete _invert_menu;
2098         _invert_menu = new Menu;
2099         _invert_menu->set_name ("ArdourContextMenu");
2100         MenuList& items = _invert_menu->items ();
2101
2102         for (uint32_t i = 0; i < N; ++i) {
2103                 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2104                 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2105                 ++_i_am_the_modifier;
2106                 e->set_active (_route->phase_control()->inverted (i));
2107                 --_i_am_the_modifier;
2108         }
2109
2110         _invert_menu->popup (0, ev->time);
2111
2112         return true;
2113 }
2114
2115 void
2116 RouteUI::invert_menu_toggled (uint32_t c)
2117 {
2118         if (_i_am_the_modifier) {
2119                 return;
2120         }
2121
2122
2123         _route->phase_control()->set_phase_invert (c, !_route->phase_control()->inverted (c));
2124 }
2125
2126 void
2127 RouteUI::set_invert_sensitive (bool yn)
2128 {
2129         for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2130                 (*b)->set_sensitive (yn);
2131         }
2132 }
2133
2134 /** The Route's gui_changed signal has been emitted */
2135 void
2136 RouteUI::route_gui_changed (PropertyChange const& what_changed)
2137 {
2138         if (what_changed.contains (Properties::color)) {
2139                 if (set_color_from_route () == 0) {
2140                         route_color_changed ();
2141                 }
2142         }
2143 }
2144
2145 void
2146 RouteUI::track_mode_changed (void)
2147 {
2148         assert(is_track());
2149         switch (track()->mode()) {
2150                 case ARDOUR::NonLayered:
2151                 case ARDOUR::Normal:
2152                         rec_enable_button->set_icon (ArdourIcon::RecButton);
2153                         break;
2154                 case ARDOUR::Destructive:
2155                         rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2156                         break;
2157         }
2158         rec_enable_button->queue_draw();
2159 }
2160
2161 /** @return the color that this route should use; it maybe its own,
2162  *  or it maybe that of its route group.
2163  */
2164 Gdk::Color
2165 RouteUI::route_color () const
2166 {
2167         Gdk::Color c;
2168         RouteGroup* g = _route->route_group ();
2169         string p;
2170
2171         if (g && g->is_color()) {
2172                 set_color_from_rgba (c, GroupTabs::group_color (g));
2173         } else {
2174                 set_color_from_rgba (c, _route->presentation_info().color());
2175         }
2176
2177         return c;
2178 }
2179
2180 void
2181 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2182 {
2183         _showing_sends_to = send_to;
2184         BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2185 }
2186
2187 void
2188 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2189 {
2190         if (_route == send_to) {
2191                 show_sends_button->set_active (true);
2192                 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2193         } else {
2194                 show_sends_button->set_active (false);
2195                 send_blink_connection.disconnect ();
2196         }
2197 }
2198
2199 RouteGroup*
2200 RouteUI::route_group() const
2201 {
2202         return _route->route_group();
2203 }
2204
2205
2206 RoutePinWindowProxy::RoutePinWindowProxy(std::string const &name, boost::shared_ptr<ARDOUR::Route> route)
2207         : WM::ProxyBase (name, string())
2208         , _route (boost::weak_ptr<Route> (route))
2209 {
2210         route->DropReferences.connect (going_away_connection, MISSING_INVALIDATOR, boost::bind (&RoutePinWindowProxy::route_going_away, this), gui_context());
2211 }
2212
2213 RoutePinWindowProxy::~RoutePinWindowProxy()
2214 {
2215         _window = 0;
2216 }
2217
2218 ARDOUR::SessionHandlePtr*
2219 RoutePinWindowProxy::session_handle ()
2220 {
2221         ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2222         if (aw) { return aw; }
2223         return 0;
2224 }
2225
2226 Gtk::Window*
2227 RoutePinWindowProxy::get (bool create)
2228 {
2229         boost::shared_ptr<Route> r = _route.lock ();
2230         if (!r) {
2231                 return 0;
2232         }
2233
2234         if (!_window) {
2235                 if (!create) {
2236                         return 0;
2237                 }
2238                 _window = new PluginPinDialog (r);
2239                 ArdourWindow* aw = dynamic_cast<ArdourWindow*> (_window);
2240                 if (aw) {
2241                         aw->set_session (_session);
2242                 }
2243                 _window->show_all ();
2244         }
2245         return _window;
2246 }
2247
2248 void
2249 RoutePinWindowProxy::route_going_away ()
2250 {
2251         delete _window;
2252         _window = 0;
2253         WM::Manager::instance().remove (this);
2254         going_away_connection.disconnect();
2255         delete this;
2256 }
2257
2258 void
2259 RouteUI::maybe_add_route_print_mgr ()
2260 {
2261         if (_route->pinmgr_proxy ()) {
2262                 return;
2263         }
2264         RoutePinWindowProxy* wp = new RoutePinWindowProxy (
2265                         string_compose ("RPM-%1", _route->id()), _route);
2266         wp->set_session (_session);
2267
2268         const XMLNode* ui_xml = _session->extra_xml (X_("UI"));
2269         if (ui_xml) {
2270                 wp->set_state (*ui_xml, 0);
2271         }
2272
2273 #if 0
2274         void* existing_ui = _route->pinmgr_proxy ();
2275         if (existing_ui) {
2276                 wp->use_window (*(reinterpret_cast<Gtk::Window*>(existing_ui)));
2277         }
2278 #endif
2279         _route->set_pingmgr_proxy (wp);
2280
2281         WM::Manager::instance().register_window (wp);
2282 }
2283
2284 void
2285 RouteUI::manage_pins ()
2286 {
2287         RoutePinWindowProxy* proxy = _route->pinmgr_proxy ();
2288         if (proxy) {
2289                 proxy->get (true);
2290                 proxy->present();
2291         }
2292 }
2293
2294 void
2295 RouteUI::fan_out (bool to_busses, bool group)
2296 {
2297         DisplaySuspender ds;
2298         boost::shared_ptr<ARDOUR::Route> route = _route;
2299         boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (route->the_instrument ());
2300         assert (pi);
2301
2302         const uint32_t n_outputs = pi->output_streams ().n_audio ();
2303         if (route->n_outputs ().n_audio () != n_outputs) {
2304                 MessageDialog msg (string_compose (
2305                                         _("The Plugin's number of audio outputs ports (%1) does not match the Tracks's number of audio outputs (%2). Cannot fan out."),
2306                                         n_outputs, route->n_outputs ().n_audio ()));
2307                 msg.run ();
2308                 return;
2309         }
2310
2311 #define BUSNAME  pd.group_name + "(" + route->name () + ")"
2312
2313         /* count busses and channels/bus */
2314         boost::shared_ptr<Plugin> plugin = pi->plugin ();
2315         std::map<std::string, uint32_t> busnames;
2316         for (uint32_t p = 0; p < n_outputs; ++p) {
2317                 const Plugin::IOPortDescription& pd (plugin->describe_io_port (DataType::AUDIO, false, p));
2318                 std::string bn = BUSNAME;
2319                 busnames[bn]++;
2320         }
2321
2322         if (busnames.size () < 2) {
2323                 MessageDialog msg (_("Instrument has only 1 output bus. Nothing to fan out."));
2324                 msg.run ();
2325                 return;
2326         }
2327
2328         uint32_t outputs = 2;
2329         if (_session->master_out ()) {
2330                 outputs = std::max (outputs, _session->master_out ()->n_inputs ().n_audio ());
2331         }
2332
2333         route->output ()->disconnect (this);
2334         route->panner_shell ()->set_bypassed (true);
2335
2336         RouteList to_group;
2337         for (uint32_t p = 0; p < n_outputs; ++p) {
2338                 const Plugin::IOPortDescription& pd (plugin->describe_io_port (DataType::AUDIO, false, p));
2339                 std::string bn = BUSNAME;
2340                 boost::shared_ptr<Route> r = _session->route_by_name (bn);
2341                 if (!r) {
2342                         if (to_busses) {
2343                                 RouteList rl = _session->new_audio_route (busnames[bn], outputs, NULL, 1, bn, PresentationInfo::AudioBus, PresentationInfo::max_order);
2344                                 r = rl.front ();
2345                                 assert (r);
2346                         } else {
2347                                 list<boost::shared_ptr<AudioTrack> > tl =
2348                                         _session->new_audio_track (busnames[bn], outputs, NULL, 1, bn, PresentationInfo::max_order, Normal);
2349                                 r = tl.front ();
2350                                 assert (r);
2351
2352                                 boost::shared_ptr<ControlList> cl (new ControlList);
2353                                 cl->push_back (r->monitoring_control ());
2354                                 _session->set_controls (cl, (double) MonitorInput, Controllable::NoGroup);
2355                         }
2356                         r->input ()->disconnect (this);
2357                 }
2358                 to_group.push_back (r);
2359                 route->output ()->audio (p)->connect (r->input ()->audio (pd.group_channel).get());
2360         }
2361 #undef BUSNAME
2362
2363         if (group) {
2364                 RouteGroup* rg = NULL;
2365                 const std::list<RouteGroup*>& rgs (_session->route_groups ());
2366                 for (std::list<RouteGroup*>::const_iterator i = rgs.begin (); i != rgs.end (); ++i) {
2367                         if ((*i)->name () == pi->name ()) {
2368                                 rg = *i;
2369                                 break;
2370                         }
2371                 }
2372                 if (!rg) {
2373                         rg = new RouteGroup (*_session, pi->name ());
2374                         _session->add_route_group (rg);
2375                         rg->set_gain (false);
2376                 }
2377
2378                 GroupTabs::set_group_color (rg, route->presentation_info().color());
2379                 for (RouteList::const_iterator i = to_group.begin(); i != to_group.end(); ++i) {
2380                         rg->add (*i);
2381                 }
2382         }
2383 }
2384
2385 bool
2386 RouteUI::mark_hidden (bool yn)
2387 {
2388         if (yn != _route->presentation_info().hidden()) {
2389                 _route->presentation_info().set_hidden (yn);
2390                 return true; // things changed
2391         }
2392         return false;
2393 }
2394
2395 boost::shared_ptr<Stripable>
2396 RouteUI::stripable () const
2397 {
2398         return _route;
2399 }