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