ee66bf4c903c7069edc1310d297ece92b8271fe0
[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 <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/stop_signal.h>
22 #include <gtkmm2ext/choice.h>
23 #include <gtkmm2ext/doi.h>
24 #include <gtkmm2ext/bindable_button.h>
25 #include <gtkmm2ext/barcontroller.h>
26 #include <gtkmm2ext/gtk_ui.h>
27
28 #include "ardour/route_group.h"
29 #include "ardour/dB.h"
30 #include "pbd/memento_command.h"
31 #include "pbd/stacktrace.h"
32 #include "pbd/controllable.h"
33 #include "pbd/enumwriter.h"
34
35 #include "ardour_ui.h"
36 #include "editor.h"
37 #include "route_ui.h"
38 #include "keyboard.h"
39 #include "utils.h"
40 #include "prompter.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
46 #include "route_time_axis.h"
47
48 #include "ardour/route.h"
49 #include "ardour/event_type_map.h"
50 #include "ardour/session.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/audio_track.h"
53 #include "ardour/midi_track.h"
54 #include "ardour/template_utils.h"
55 #include "ardour/filename_extensions.h"
56 #include "ardour/directory_names.h"
57 #include "ardour/profile.h"
58
59 #include "i18n.h"
60 using namespace Gtk;
61 using namespace Gtkmm2ext;
62 using namespace ARDOUR;
63 using namespace PBD;
64
65 RouteUI::RouteUI (ARDOUR::Session* sess)
66         : AxisView(sess)
67 {
68         init ();
69 }
70
71 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session* sess)
72         : AxisView(sess)
73 {
74         init ();
75         set_route (rt);
76 }
77
78 RouteUI::~RouteUI()
79 {
80         _route.reset (); /* drop reference to route, so that it can be cleaned up */
81         route_connections.drop_connections ();
82
83         delete solo_menu;
84         delete mute_menu;
85         delete sends_menu;
86 }
87
88 void
89 RouteUI::init ()
90 {
91         self_destruct = true;
92         xml_node = 0;
93         mute_menu = 0;
94         solo_menu = 0;
95         sends_menu = 0;
96         pre_fader_mute_check = 0;
97         post_fader_mute_check = 0;
98         listen_mute_check = 0;
99         main_mute_check = 0;
100         solo_safe_check = 0;
101         solo_isolated_check = 0;
102         ignore_toggle = false;
103         _solo_release = 0;
104         _mute_release = 0;
105         route_active_menu_item = 0;
106         denormal_menu_item = 0;
107         multiple_mute_change = false;
108         multiple_solo_change = false;
109
110         invert_button = manage (new BindableToggleButton ());
111         // mute_button->set_self_managed (true);
112         invert_button->set_name ("InvertButton");
113         invert_button->add (invert_button_label);
114         invert_button_label.show ();
115         UI::instance()->set_tip (invert_button, _("Invert (Phase reverse) this track"), "");
116
117         mute_button = manage (new BindableToggleButton ());
118         // mute_button->set_self_managed (true);
119         mute_button->set_name ("MuteButton");
120         mute_button->add (mute_button_label);
121         mute_button_label.show ();
122         UI::instance()->set_tip (mute_button, _("Mute this track"), "");
123
124         solo_button = manage (new BindableToggleButton ());
125         // solo_button->set_self_managed (true);
126         solo_button->set_name ("SoloButton");
127         solo_button->add (solo_button_label);
128         solo_button_label.show ();
129         UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
130         solo_button->set_no_show_all (true);
131
132         rec_enable_button = manage (new BindableToggleButton ());
133         rec_enable_button->set_name ("RecordEnableButton");
134         // rec_enable_button->set_self_managed (true);
135         rec_enable_button->add (rec_enable_button_label);
136         rec_enable_button_label.show ();
137         UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
138
139         show_sends_button = manage (new BindableToggleButton (""));
140         show_sends_button->set_name ("SendAlert");
141         // show_sends_button->set_self_managed (true);
142         UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
143
144         _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
145         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
146         _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
147
148         Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
149
150         rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
151         rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
152
153         show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
154         show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
155
156         solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
157         solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
158         mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
159         mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
160         invert_button->signal_toggled().connect (sigc::mem_fun(*this, &RouteUI::invert_toggled), false);
161
162 }
163
164 void
165 RouteUI::reset ()
166 {
167         route_connections.drop_connections ();
168
169         delete solo_menu;
170         solo_menu = 0;
171
172         delete mute_menu;
173         mute_menu = 0;
174
175         if (xml_node) {
176                 /* do not delete the node - its owned by the route */
177                 xml_node = 0;
178         }
179
180         route_active_menu_item = 0;
181         denormal_menu_item = 0;
182 }
183
184 void
185 RouteUI::self_delete ()
186 {
187         /* This may be called from a non-GUI thread. Keep it safe */
188
189         delete_when_idle (this);
190 }
191
192 void
193 RouteUI::set_route (boost::shared_ptr<Route> rp)
194 {
195         reset ();
196
197         _route = rp;
198
199         if (set_color_from_route()) {
200                 set_color (unique_random_color());
201         }
202
203         if (self_destruct) {
204                 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
205         }
206         
207         mute_button->set_controllable (_route->mute_control());
208         solo_button->set_controllable (_route->solo_control());
209
210         _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
211         _route->mute_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::mute_changed, this, _1), gui_context());
212         _route->solo_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::solo_changed, this, _1), gui_context());
213         _route->solo_safe_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::solo_changed, this, _1), gui_context());
214         _route->listen_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::listen_changed, this, _1), gui_context());
215         _route->solo_isolated_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::solo_changed, this, _1), gui_context());
216         _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
217         _route->PropertyChanged.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::property_changed, this, _1), gui_context());
218
219         if (_session->writable() && is_track()) {
220                 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
221
222                 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
223
224                 rec_enable_button->show();
225                 rec_enable_button->set_controllable (t->rec_enable_control());
226
227                 update_rec_display ();
228         }
229
230         mute_button->unset_flags (Gtk::CAN_FOCUS);
231         solo_button->unset_flags (Gtk::CAN_FOCUS);
232
233         mute_button->show();
234         invert_button->show ();
235
236         if (_route->is_monitor()) {
237                 solo_button->hide ();
238         } else {
239                 solo_button->show();
240         }
241
242         map_frozen ();
243 }
244
245 void
246 RouteUI::invert_toggled ()
247 {
248         cerr << this << " button state = " << invert_button->get_active() << " PI = " << _route->phase_invert() << endl;
249         _route->set_phase_invert (invert_button->get_active());
250 }
251
252 void
253 RouteUI::polarity_changed ()
254 {
255         if (!_route) {
256                 return;
257         }
258         
259         if (_route->phase_invert()) {
260                 invert_button->set_active (true);
261         } else {
262                 invert_button->set_active (false);
263         }
264 }
265
266 bool
267 RouteUI::mute_press (GdkEventButton* ev)
268 {
269         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
270                 return true;
271         }
272
273         multiple_mute_change = false;
274
275         if (!ignore_toggle) {
276
277                 if (Keyboard::is_context_menu_event (ev)) {
278
279                         if (mute_menu == 0){
280                                 build_mute_menu();
281                         }
282
283                         mute_menu->popup(0,ev->time);
284
285                 } else {
286
287                         if (Keyboard::is_button2_event (ev)) {
288                                 // Primary-button2 click is the midi binding click
289                                 // button2-click is "momentary"
290
291
292                                 if (mute_button->on_button_press_event (ev)) {
293                                         return true;
294                                 }
295
296                                 _mute_release = new SoloMuteRelease (_route->muted ());
297                         }
298
299                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
300
301                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
302
303                                         if (_mute_release) {
304                                                 _mute_release->routes = _session->get_routes ();
305                                         }
306
307                                         _session->set_mute (_session->get_routes(), !_route->muted());
308
309                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
310
311                                         /* Primary-button1 applies change to the mix group even if it is not active
312                                            NOTE: Primary-button2 is MIDI learn.
313                                         */
314
315                                         if (ev->button == 1 && _route->route_group()) {
316                                                 if (_mute_release) {
317                                                         _mute_release->routes = _session->get_routes ();
318                                                 }
319                                                                 
320                                                 _session->set_mute (_session->get_routes(), !_route->muted(), Session::rt_cleanup, true);
321                                         }
322
323                                 } else {
324
325                                         /* plain click applies change to this route */
326                                         
327                                         boost::shared_ptr<RouteList> rl (new RouteList);
328                                         rl->push_back (_route);
329
330                                         if (_mute_release) {
331                                                 _mute_release->routes = rl;
332                                         }
333
334                                         _session->set_mute (rl, !_route->muted());
335
336                                 }
337                         }
338                 }
339
340         }
341
342         return true;
343 }
344
345 bool
346 RouteUI::mute_release (GdkEventButton*)
347 {
348         if (!ignore_toggle) {
349                 if (_mute_release){
350                         _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
351                         delete _mute_release;
352                         _mute_release = 0;
353                 }
354         }
355
356         return true;
357 }
358
359 bool
360 RouteUI::solo_press(GdkEventButton* ev)
361 {
362         /* ignore double/triple clicks */
363
364         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
365                 return true;
366         }
367         
368         multiple_solo_change = false;
369
370         if (!ignore_toggle) {
371                 
372                 if (Keyboard::is_context_menu_event (ev)) {
373                         
374                         if (solo_menu == 0) {
375                                 build_solo_menu ();
376                         }
377                         
378                         solo_menu->popup (1, ev->time);
379                         
380                 } else {
381                         
382                         if (Keyboard::is_button2_event (ev)) {
383                                 
384                                 // Primary-button2 click is the midi binding click
385                                 // button2-click is "momentary"
386                                 
387                                 if (solo_button->on_button_press_event (ev)) {
388                                         return true;
389                                 }
390
391                                 _solo_release = new SoloMuteRelease (_route->soloed());
392                         }
393                         
394                         if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
395                                 
396                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
397                                         
398                                         /* Primary-Tertiary-click applies change to all routes */
399
400                                         if (_solo_release) {
401                                                 _solo_release->routes = _session->get_routes ();
402                                         }
403                                         
404                                         if (Config->get_solo_control_is_listen_control()) {
405                                                 _session->set_listen (_session->get_routes(), !_route->listening(),  Session::rt_cleanup, true);
406                                         } else {
407                                                 _session->set_solo (_session->get_routes(), !_route->soloed(),  Session::rt_cleanup, true);
408                                         }
409                                         
410                                 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
411                                         
412                                         // Primary-Secondary-click: exclusively solo this track
413
414                                         if (_solo_release) {
415                                                 _solo_release->exclusive = true;
416
417                                                 boost::shared_ptr<RouteList> routes = _session->get_routes();
418
419                                                 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
420                                                         if ((*i)->soloed ()) {
421                                                                 _solo_release->routes_on->push_back (*i);
422                                                         } else {
423                                                                 _solo_release->routes_off->push_back (*i);
424                                                         }
425                                                 }
426                                         }
427                                         
428                                         if (Config->get_solo_control_is_listen_control()) {
429                                                 /* ??? we need a just_one_listen() method */
430                                         } else {
431                                                 _session->set_just_one_solo (_route, true);
432                                         }
433
434                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
435                                         
436                                         // shift-click: toggle solo isolated status
437                                         
438                                         _route->set_solo_isolated (!_route->solo_isolated(), this);
439                                         delete _solo_release;
440                                         _solo_release = 0;
441                                         
442                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
443                                         
444                                         /* Primary-button1: solo mix group.
445                                            NOTE: Primary-button2 is MIDI learn.
446                                         */
447                                         
448                                         if (ev->button == 1 && _route->route_group()) {
449
450                                                 if (_solo_release) {
451                                                         _solo_release->routes = _route->route_group()->route_list();
452                                                 }
453                                         
454                                                 if (Config->get_solo_control_is_listen_control()) {
455                                                         _session->set_listen (_route->route_group()->route_list(), !_route->listening(),  Session::rt_cleanup, true);
456                                                 } else {
457                                                         _session->set_solo (_route->route_group()->route_list(), !_route->soloed(),  Session::rt_cleanup, true);
458                                                 }
459                                         }
460                                         
461                                 } else {
462                                         
463                                         /* click: solo this route */
464                                         
465                                         boost::shared_ptr<RouteList> rl (new RouteList);
466                                         rl->push_back (route());
467
468                                         if (_solo_release) {
469                                                 _solo_release->routes = rl;
470                                         }
471
472                                         if (Config->get_solo_control_is_listen_control()) {
473                                                 _session->set_listen (rl, !_route->listening());
474                                         } else {
475                                                 _session->set_solo (rl, !_route->soloed());
476                                         }
477                                 }
478                         }
479                 }
480         }
481
482         return true;
483 }
484
485 bool
486 RouteUI::solo_release (GdkEventButton*)
487 {
488         if (!ignore_toggle) {
489                 
490                 if (_solo_release) {
491
492                         if (_solo_release->exclusive) {
493
494                         } else {
495                                 if (Config->get_solo_control_is_listen_control()) {
496                                         _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
497                                 } else {
498                                         _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
499                                 }
500                         }
501
502                         delete _solo_release;
503                         _solo_release = 0;
504                 }
505         }
506
507         return true;
508 }
509
510 bool
511 RouteUI::rec_enable_press(GdkEventButton* ev)
512 {
513         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
514                 return true;
515         }
516
517         if (!_session->engine().connected()) {
518                 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
519                 msg.run ();
520                 return true;
521         }
522
523         if (!ignore_toggle && is_track() && rec_enable_button) {
524
525                 if (Keyboard::is_button2_event (ev)) {
526
527                         // do nothing on midi sigc::bind event
528                         return rec_enable_button->on_button_press_event (ev);
529
530                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
531
532                         _session->set_record_enable (_session->get_routes(), !rec_enable_button->get_active());
533
534                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
535
536                         /* Primary-button1 applies change to the route group (even if it is not active)
537                            NOTE: Primary-button2 is MIDI learn.
538                         */
539                         if (ev->button == 1 && _route->route_group()) {
540                                 _session->set_record_enable (_route->route_group()->route_list(), !rec_enable_button->get_active(), Session::rt_cleanup, true);
541                         }
542
543                 } else if (Keyboard::is_context_menu_event (ev)) {
544
545                         /* do this on release */
546
547                 } else {
548
549                         boost::shared_ptr<RouteList> rl (new RouteList);
550                         rl->push_back (route());
551                         _session->set_record_enable (rl, !rec_enable_button->get_active());
552                 }
553         }
554
555         return true;
556 }
557
558 bool
559 RouteUI::rec_enable_release (GdkEventButton*)
560 {
561         return true;
562 }
563
564 void
565 RouteUI::build_sends_menu ()
566 {
567         using namespace Menu_Helpers;
568
569         sends_menu = new Menu;
570         sends_menu->set_name ("ArdourContextMenu");
571         MenuList& items = sends_menu->items();
572
573         items.push_back (MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader)));
574         items.push_back (MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader)));
575         items.push_back (MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader)));
576         items.push_back (MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader)));
577         items.push_back (MenuElem(_("Copy track gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
578         items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
579         items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
580
581 }
582
583 void
584 RouteUI::create_sends (Placement p)
585 {
586         _session->globally_add_internal_sends (_route, p);
587 }
588
589 void
590 RouteUI::create_selected_sends (Placement p)
591 {
592         boost::shared_ptr<RouteList> rlist (new RouteList);
593         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
594
595         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
596                 RouteTimeAxisView* rtv;
597                 RouteUI* rui;
598                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
599                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
600                                 if (boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
601                                         rlist->push_back (rui->route());
602                                 }
603                         }
604                 }
605         }
606         
607         _session->add_internal_sends (_route, p, rlist);
608 }
609
610 void
611 RouteUI::set_sends_gain_from_track ()
612 {
613         _session->globally_set_send_gains_from_track (_route);
614 }
615
616 void
617 RouteUI::set_sends_gain_to_zero ()
618 {
619         _session->globally_set_send_gains_to_zero (_route);
620 }
621
622 void
623 RouteUI::set_sends_gain_to_unity ()
624 {
625         _session->globally_set_send_gains_to_unity (_route);
626 }
627
628 bool
629 RouteUI::show_sends_press(GdkEventButton* ev)
630 {
631         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
632                 return true;
633         }
634
635         if (!ignore_toggle && !is_track() && show_sends_button) {
636
637                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
638
639                         // do nothing on midi sigc::bind event
640                         return false;
641
642                 } else if (Keyboard::is_context_menu_event (ev)) {
643
644                         if (sends_menu == 0) {
645                                 build_sends_menu ();
646                         }
647
648                         sends_menu->popup (0, ev->time);
649
650                 } else {
651
652                         /* change button state */
653
654                         show_sends_button->set_active (!show_sends_button->get_active());
655
656                         /* start blinking */
657
658                         if (show_sends_button->get_active()) {
659                                 /* show sends to this bus */
660                                 MixerStrip::SwitchIO (_route);
661                                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun(*this, &RouteUI::send_blink));
662                         } else {
663                                 /* everybody back to normal */
664                                 send_blink_connection.disconnect ();
665                                 MixerStrip::SwitchIO (boost::shared_ptr<Route>());
666                         }
667
668                 }
669         }
670
671         return true;
672 }
673
674 bool
675 RouteUI::show_sends_release (GdkEventButton*)
676 {
677         return true;
678 }
679
680 void
681 RouteUI::send_blink (bool onoff)
682 {
683         if (!show_sends_button) {
684                 return;
685         }
686
687         if (onoff) {
688                 show_sends_button->set_state (STATE_ACTIVE);
689         } else {
690                 show_sends_button->set_state (STATE_NORMAL);
691         }
692 }
693
694 void
695 RouteUI::solo_changed(void* /*src*/)
696 {
697         Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&RouteUI::update_solo_display, this));
698 }
699
700
701 void
702 RouteUI::listen_changed(void* /*src*/)
703 {
704         Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&RouteUI::update_solo_display, this));
705 }
706
707 int
708 RouteUI::solo_visual_state (boost::shared_ptr<Route> r)
709 {
710         if (r->is_master() || r->is_monitor()) {
711                 return 0;
712         }
713         
714         if (Config->get_solo_control_is_listen_control()) {
715
716                 if (r->listening()) {
717                         return 1;
718                 } else {
719                         return 0;
720                 }
721
722         } 
723         
724         if (r->soloed()) {
725                 return 1;
726         } else {
727                 return 0;
728         }
729 }
730
731 int
732 RouteUI::solo_visual_state_with_isolate (boost::shared_ptr<Route> r)
733 {
734         if (r->is_master() || r->is_monitor()) {
735                 return 0;
736         }
737         
738         if (Config->get_solo_control_is_listen_control()) {
739
740                 if (r->listening()) {
741                         return 1;
742                 } else {
743                         return 0;
744                 }
745
746         } 
747         
748         if (r->solo_isolated()) {
749                 return 2;
750         } else if (r->soloed()) {
751                 if (!r->self_soloed()) {
752                         return 3;
753                 } else {
754                         return 1;
755                 }
756         } else {
757                 return 0;
758         }
759 }
760
761 int
762 RouteUI::solo_isolate_visual_state (boost::shared_ptr<Route> r)
763 {
764         if (r->is_master() || r->is_monitor()) {
765                 return 0;
766         }
767         
768         if (r->solo_isolated()) {
769                 return 1;
770         } else {
771                 return 0;
772         }
773 }
774
775 int
776 RouteUI::solo_safe_visual_state (boost::shared_ptr<Route> r)
777 {
778         if (r->is_master() || r->is_monitor()) {
779                 return 0;
780         }
781         
782         if (r->solo_safe()) {
783                 return 1;
784         } else {
785                 return 0;
786         }
787 }
788
789 void
790 RouteUI::update_solo_display ()
791 {
792         bool x;
793
794         if (Config->get_solo_control_is_listen_control()) {
795
796                 if (solo_button->get_active() != (x = _route->listening())) {
797                         ignore_toggle = true;
798                         solo_button->set_active(x);
799                         ignore_toggle = false;
800                 }
801
802         } else {
803
804                 if (solo_button->get_active() != (x = _route->soloed())) {
805                         ignore_toggle = true;
806                         solo_button->set_active (x);
807                         ignore_toggle = false;
808                 }
809
810         }
811
812         bool yn = _route->solo_safe ();
813
814         if (solo_safe_check && solo_safe_check->get_active() != yn) {
815                 solo_safe_check->set_active (yn);
816         }
817
818         yn = _route->solo_isolated ();
819
820         if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
821                 solo_isolated_check->set_active (yn);
822         }
823
824         set_button_names ();
825
826         solo_button->set_visual_state (solo_visual_state_with_isolate (_route));
827 }
828
829 void
830 RouteUI::solo_changed_so_update_mute ()
831 {
832         update_mute_display ();
833 }
834
835 void
836 RouteUI::mute_changed(void* /*src*/)
837 {
838         update_mute_display ();
839 }
840
841 int
842 RouteUI::mute_visual_state (Session* s, boost::shared_ptr<Route> r)
843 {
844         if (r->is_master() || r->is_monitor()) {
845                 return 0;
846         }
847         
848         if (Config->get_show_solo_mutes()) {
849                 
850                 if (r->muted ()) {
851                         /* full mute */
852                         return 2;
853                 } else if (s->soloing() && !r->soloed() && !r->solo_isolated()) {
854                         /* mute-because-not-soloed */
855                         return 1;
856                 } else {
857                         /* no mute at all */
858                         return 0;
859                 }
860
861         } else {
862
863                 if (r->muted()) {
864                         /* full mute */
865                         return 2;
866                 } else {
867                         /* no mute at all */
868                         return 0;
869                 }
870         }
871
872         return 0;
873 }
874
875 void
876 RouteUI::update_mute_display ()
877 {
878         if (!_route) {
879                 return;
880         }
881
882         bool model = _route->muted();
883         bool view = mute_button->get_active();
884
885         /* first make sure the button's "depressed" visual
886            is correct.
887         */
888
889         if (model != view) {
890                 ignore_toggle = true;
891                 mute_button->set_active (model);
892                 ignore_toggle = false;
893         }
894
895         mute_button->set_visual_state (mute_visual_state (_session, _route));
896 }
897
898 void
899 RouteUI::route_rec_enable_changed ()
900 {
901         Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&RouteUI::update_rec_display, this));
902 }
903
904 void
905 RouteUI::session_rec_enable_changed ()
906 {
907         update_rec_display ();
908 }
909
910 void
911 RouteUI::update_rec_display ()
912 {
913         if (!rec_enable_button || !_route) {
914                 return;
915         }
916                         
917         bool model = _route->record_enabled();
918         bool view = rec_enable_button->get_active();
919
920         /* first make sure the button's "depressed" visual
921            is correct.
922         */
923
924         if (model != view) {
925                 ignore_toggle = true;
926                 rec_enable_button->set_active (model);
927                 ignore_toggle = false;
928         }
929
930         /* now make sure its color state is correct */
931
932         if (model) {
933
934                 switch (_session->record_status ()) {
935                 case Session::Recording:
936                         rec_enable_button->set_visual_state (1);
937                         break;
938
939                 case Session::Disabled:
940                 case Session::Enabled:
941                         rec_enable_button->set_visual_state (2);
942                         break;
943
944                 }
945
946         } else {
947                 rec_enable_button->set_visual_state (0);
948         }
949
950         check_rec_enable_sensitivity ();
951 }
952
953 void
954 RouteUI::build_solo_menu (void)
955 {
956         using namespace Menu_Helpers;
957
958         solo_menu = new Menu;
959         solo_menu->set_name ("ArdourContextMenu");
960         MenuList& items = solo_menu->items();
961         CheckMenuItem* check;
962
963         check = new CheckMenuItem(_("Solo Isolate"));
964         check->set_active (_route->solo_isolated());
965         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
966         items.push_back (CheckMenuElem(*check));
967         solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
968         check->show_all();
969
970         check = new CheckMenuItem(_("Solo Safe"));
971         check->set_active (_route->solo_safe());
972         check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
973         items.push_back (CheckMenuElem(*check));
974         solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
975         check->show_all();
976
977         //items.push_back (SeparatorElem());
978         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
979
980 }
981
982 void
983 RouteUI::build_mute_menu(void)
984 {
985         using namespace Menu_Helpers;
986
987         mute_menu = new Menu;
988         mute_menu->set_name ("ArdourContextMenu");
989
990         MenuList& items = mute_menu->items();
991
992         pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
993         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
994         pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
995         items.push_back (CheckMenuElem(*pre_fader_mute_check));
996         pre_fader_mute_check->show_all();
997
998         post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
999         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1000         post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1001         items.push_back (CheckMenuElem(*post_fader_mute_check));
1002         post_fader_mute_check->show_all();
1003
1004         listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1005         init_mute_menu(MuteMaster::Listen, listen_mute_check);
1006         listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1007         items.push_back (CheckMenuElem(*listen_mute_check));
1008         listen_mute_check->show_all();
1009
1010         main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1011         init_mute_menu(MuteMaster::Main, main_mute_check);
1012         main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1013         items.push_back (CheckMenuElem(*main_mute_check));
1014         main_mute_check->show_all();
1015
1016         //items.push_back (SeparatorElem());
1017         // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1018
1019         _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1020 }
1021
1022 void
1023 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1024 {
1025         check->set_active (_route->mute_points() & mp);
1026 }
1027
1028 void
1029 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1030 {
1031         if (check->get_active()) {
1032                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1033         } else {
1034                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1035         }
1036 }
1037
1038 void
1039 RouteUI::muting_change ()
1040 {
1041         ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1042
1043         bool yn;
1044         MuteMaster::MutePoint current = _route->mute_points ();
1045
1046         yn = (current & MuteMaster::PreFader);
1047
1048         if (pre_fader_mute_check->get_active() != yn) {
1049                 pre_fader_mute_check->set_active (yn);
1050         }
1051
1052         yn = (current & MuteMaster::PostFader);
1053
1054         if (post_fader_mute_check->get_active() != yn) {
1055                 post_fader_mute_check->set_active (yn);
1056         }
1057
1058         yn = (current & MuteMaster::Listen);
1059
1060         if (listen_mute_check->get_active() != yn) {
1061                 listen_mute_check->set_active (yn);
1062         }
1063
1064         yn = (current & MuteMaster::Main);
1065
1066         if (main_mute_check->get_active() != yn) {
1067                 main_mute_check->set_active (yn);
1068         }
1069 }
1070
1071 void
1072 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1073 {
1074         _route->set_solo_isolated (check->get_active(), this);
1075 }
1076
1077 void
1078 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1079 {
1080         _route->set_solo_safe (check->get_active(), this);
1081 }
1082
1083 bool
1084 RouteUI::choose_color()
1085 {
1086         bool picked;
1087         Gdk::Color color;
1088
1089         color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
1090
1091         if (picked) {
1092                 set_color (color);
1093         }
1094
1095         return picked;
1096 }
1097
1098 void
1099 RouteUI::set_color (const Gdk::Color & c)
1100 {
1101         char buf[64];
1102
1103         _color = c;
1104
1105         ensure_xml_node ();
1106         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1107         xml_node->add_property ("color", buf);
1108
1109         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1110 }
1111
1112
1113 void
1114 RouteUI::ensure_xml_node ()
1115 {
1116         if (xml_node == 0) {
1117                 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
1118                         xml_node = new XMLNode ("GUI");
1119                         _route->add_extra_xml (*xml_node);
1120                 }
1121         }
1122 }
1123
1124 XMLNode*
1125 RouteUI::get_automation_child_xml_node (Evoral::Parameter param)
1126 {
1127         ensure_xml_node ();
1128
1129         XMLNodeList kids = xml_node->children();
1130         XMLNodeConstIterator iter;
1131
1132         const string sym = ARDOUR::EventTypeMap::instance().to_symbol(param);
1133
1134         for (iter = kids.begin(); iter != kids.end(); ++iter) {
1135                 if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
1136                         XMLProperty* type = (*iter)->property("automation-id");
1137                         if (type && type->value() == sym)
1138                                 return *iter;
1139                 }
1140         }
1141
1142         // Didn't find it, make a new one
1143         XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
1144         child->add_property("automation-id", sym);
1145         xml_node->add_child_nocopy (*child);
1146
1147         return child;
1148 }
1149
1150 int
1151 RouteUI::set_color_from_route ()
1152 {
1153         XMLProperty *prop;
1154
1155         RouteUI::ensure_xml_node ();
1156
1157         if ((prop = xml_node->property ("color")) != 0) {
1158                 int r, g, b;
1159                 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
1160                 _color.set_red(r);
1161                 _color.set_green(g);
1162                 _color.set_blue(b);
1163                 return 0;
1164         }
1165         return 1;
1166 }
1167
1168 void
1169 RouteUI::remove_this_route ()
1170 {
1171         vector<string> choices;
1172         string prompt;
1173
1174         if (is_track()) {
1175                 prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n(this cannot be undone)"), _route->name());
1176         } else {
1177                 prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n(this cannot be undone)"), _route->name());
1178         }
1179
1180         choices.push_back (_("No, do nothing."));
1181         choices.push_back (_("Yes, remove it."));
1182
1183         string title;
1184         if (is_track()) {
1185                 title = _("Remove track");
1186         } else {
1187                 title = _("Remove bus");
1188         }
1189
1190         Choice prompter (title, prompt, choices);
1191
1192         if (prompter.run () == 1) {
1193                 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1194         }
1195 }
1196
1197 gint
1198 RouteUI::idle_remove_this_route (RouteUI *rui)
1199 {
1200         rui->_session->remove_route (rui->_route);
1201         return false;
1202 }
1203
1204 void
1205 RouteUI::route_rename ()
1206 {
1207         ArdourPrompter name_prompter (true);
1208         string result;
1209         name_prompter.set_prompt (_("New Name: "));
1210         name_prompter.set_initial_text (_route->name());
1211         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1212         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1213         name_prompter.show_all ();
1214
1215         switch (name_prompter.run ()) {
1216
1217         case Gtk::RESPONSE_ACCEPT:
1218         name_prompter.get_result (result);
1219         if (result.length()) {
1220                         _route->set_name (result);
1221                 }
1222                 break;
1223         }
1224
1225         return;
1226
1227 }
1228
1229 void
1230 RouteUI::property_changed (const PropertyChange& what_changed)
1231 {
1232         if (what_changed.contains (ARDOUR::Properties::name)) {
1233                 name_label.set_text (_route->name());
1234         }
1235 }
1236
1237 void
1238 RouteUI::toggle_route_active ()
1239 {
1240         bool yn;
1241
1242         if (route_active_menu_item) {
1243                 if (route_active_menu_item->get_active() != (yn = _route->active())) {
1244                         _route->set_active (!yn);
1245                 }
1246         }
1247 }
1248
1249 void
1250 RouteUI::route_active_changed ()
1251 {
1252         if (route_active_menu_item) {
1253                 Gtkmm2ext::UI::instance()->call_slot (invalidator (*this), boost::bind (&CheckMenuItem::set_active, route_active_menu_item, _route->active()));
1254         }
1255 }
1256
1257
1258 void
1259 RouteUI::toggle_denormal_protection ()
1260 {
1261         if (denormal_menu_item) {
1262
1263                 bool x;
1264
1265                 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1266
1267                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1268                         _route->set_denormal_protection (x);
1269                 }
1270         }
1271 }
1272
1273 void
1274 RouteUI::denormal_protection_changed ()
1275 {
1276         if (denormal_menu_item) {
1277                 denormal_menu_item->set_active (_route->denormal_protection());
1278         }
1279 }
1280
1281 void
1282 RouteUI::disconnect_input ()
1283 {
1284         _route->input()->disconnect (this);
1285 }
1286
1287 void
1288 RouteUI::disconnect_output ()
1289 {
1290         _route->output()->disconnect (this);
1291 }
1292
1293 bool
1294 RouteUI::is_track () const
1295 {
1296         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1297 }
1298
1299 boost::shared_ptr<Track>
1300 RouteUI::track() const
1301 {
1302         return boost::dynamic_pointer_cast<Track>(_route);
1303 }
1304
1305 bool
1306 RouteUI::is_audio_track () const
1307 {
1308         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1309 }
1310
1311 boost::shared_ptr<AudioTrack>
1312 RouteUI::audio_track() const
1313 {
1314         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1315 }
1316
1317 bool
1318 RouteUI::is_midi_track () const
1319 {
1320         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1321 }
1322
1323 boost::shared_ptr<MidiTrack>
1324 RouteUI::midi_track() const
1325 {
1326         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1327 }
1328
1329 string
1330 RouteUI::name() const
1331 {
1332         return _route->name();
1333 }
1334
1335 void
1336 RouteUI::map_frozen ()
1337 {
1338         ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1339
1340         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1341
1342         if (at) {
1343                 switch (at->freeze_state()) {
1344                 case AudioTrack::Frozen:
1345                         rec_enable_button->set_sensitive (false);
1346                         break;
1347                 default:
1348                         rec_enable_button->set_sensitive (true);
1349                         break;
1350                 }
1351         }
1352 }
1353
1354 void
1355 RouteUI::adjust_latency ()
1356 {
1357         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1358 }
1359
1360 void
1361 RouteUI::save_as_template ()
1362 {
1363         sys::path path;
1364         Glib::ustring safe_name;
1365         string name;
1366
1367         path = ARDOUR::user_route_template_directory ();
1368
1369         if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1370                 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1371                 return;
1372         }
1373
1374         Prompter p (true); // modal
1375
1376         p.set_prompt (_("Template name:"));
1377         switch (p.run()) {
1378         case RESPONSE_ACCEPT:
1379                 break;
1380         default:
1381                 return;
1382         }
1383
1384         p.hide ();
1385         p.get_result (name, true);
1386
1387         safe_name = legalize_for_path (name);
1388         safe_name += template_suffix;
1389
1390         path /= safe_name;
1391
1392         _route->save_as_template (path.to_string(), name);
1393 }
1394
1395 void
1396 RouteUI::check_rec_enable_sensitivity ()
1397 {
1398         if (_session->transport_rolling() && rec_enable_button->get_active() && Config->get_disable_disarm_during_roll()) {
1399                 rec_enable_button->set_sensitive (false);
1400         } else {
1401                 rec_enable_button->set_sensitive (true);
1402         }
1403 }
1404
1405 void
1406 RouteUI::parameter_changed (string const & p)
1407 {
1408         if (p == "disable-disarm-during-roll") {
1409                 check_rec_enable_sensitivity ();
1410         } else if (p == "solo-control-is-listen-control") {
1411                 set_button_names ();
1412         } else if (p == "listen-position") {
1413                 set_button_names ();
1414         }
1415 }
1416
1417 void
1418 RouteUI::step_gain_up ()
1419 {
1420         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1421 }
1422
1423 void
1424 RouteUI::page_gain_up ()
1425 {
1426         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1427 }
1428
1429 void
1430 RouteUI::step_gain_down ()
1431 {
1432         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1433 }
1434
1435 void
1436 RouteUI::page_gain_down ()
1437 {
1438         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1439 }
1440
1441 void
1442 RouteUI::open_remote_control_id_dialog ()
1443 {
1444         ArdourDialog dialog (_("Remote Control ID"));
1445
1446         uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1447
1448         HBox* hbox = manage (new HBox);
1449         hbox->set_spacing (6);
1450         hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1451         SpinButton* spin = manage (new SpinButton);
1452         spin->set_digits (0);
1453         spin->set_increments (1, 10);
1454         spin->set_range (0, limit);
1455         spin->set_value (_route->remote_control_id());
1456         hbox->pack_start (*spin);
1457         dialog.get_vbox()->pack_start (*hbox);
1458
1459         dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1460         dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1461
1462         dialog.show_all ();
1463         int const r = dialog.run ();
1464
1465         if (r == RESPONSE_ACCEPT) {
1466                 _route->set_remote_control_id (spin->get_value_as_int ());
1467         }
1468 }