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