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