drastic, deep and wide changes to make RouteGroup use boost::shared_ptr<Route> and...
[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 #if 0
266                                         /* Primary-Tertiary-click applies change to all routes */
267
268                                         _session.begin_reversible_command (_("mute change"));
269                                         Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
270                                         _session.set_mute (!_route->muted());
271                                         cmd->mark();
272                                         _session.add_command(cmd);
273                                         _session.commit_reversible_command ();
274                                         multiple_mute_change = true;
275 #endif
276
277                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
278
279 #if 0
280                                         /* Primary-button1 applies change to the mix group.
281                                            NOTE: Primary-button2 is MIDI learn.
282                                         */
283
284                                         if (ev->button == 1) {
285                                                 set_route_group_mute (_route, !_route->muted());
286                                         }
287 #endif
288
289                                 } else {
290
291 #if 0
292                                         /* plain click applies change to this route */
293                                         if (wait_for_release) {
294                                                 _route->set_mute (!_route->muted(), this);
295                                         } else {
296                                                 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
297                                         }
298 #endif
299                                 }
300                         }
301                 }
302
303         }
304
305         return true;
306 }
307
308 bool
309 RouteUI::mute_release(GdkEventButton*)
310 {
311         if (!ignore_toggle) {
312                 if (wait_for_release){
313                         wait_for_release = false;
314                         if (multiple_mute_change) {
315                                 multiple_mute_change = false;
316                                 // undo the last op
317                                 // because the press was the last undoable thing we did
318                                 _session.undo (1U);
319                         } else {
320                                 _route->set_mute (!_route->muted(), this);
321                         }
322                 }
323         }
324         return true;
325 }
326
327 void
328 RouteUI::post_solo_cleanup (SessionEvent* ev, bool was_not_latched)
329 {
330         ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::post_solo_cleanup), ev, was_not_latched));
331
332         delete ev;
333         
334         if (was_not_latched) {
335                 Config->set_solo_latched (false);
336         }
337 }       
338
339 bool
340 RouteUI::solo_press(GdkEventButton* ev)
341 {
342         /* ignore double/triple clicks */
343
344         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
345                 return true;
346         }
347
348         if (Config->get_solo_control_is_listen_control()) {
349
350                 _route->set_listen (!_route->listening(), this);
351
352         } else {
353
354                 multiple_solo_change = false;
355                 if (!ignore_toggle) {
356
357                         if (Keyboard::is_context_menu_event (ev)) {
358
359                                 if (solo_menu == 0) {
360                                         build_solo_menu ();
361                                 }
362
363                                 solo_menu->popup (1, ev->time);
364
365                         } else {
366
367                                 if (Keyboard::is_button2_event (ev)) {
368
369                                         // Primary-button2 click is the midi binding click
370                                         // button2-click is "momentary"
371
372                                         if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
373                                                 wait_for_release = true;
374                                         } else {
375                                                 return false;
376                                         }
377                                 }
378
379                                 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
380
381                                         if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
382
383                                                 /* Primary-Tertiary-click applies change to all routes */
384                                                 bool was_not_latched = false;
385
386                                                 if (!Config->get_solo_latched ()) {
387                                                         was_not_latched = true;
388                                                         /*
389                                                           XXX it makes no sense to solo all tracks if we're
390                                                           not in latched mode, but doing nothing feels like a bug,
391                                                           so do it anyway
392                                                         */
393                                                         Config->set_solo_latched (true);
394                                                 }
395
396                                                 SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
397                                                 ev->rt_slot =   bind (sigc::mem_fun (_session, &Session::set_solo), _session.get_routes(), !_route->soloed());
398                                                 ev->rt_return = bind (sigc::mem_fun (*this, &RouteUI::post_solo_cleanup), was_not_latched);
399                                                 
400                                                 _session.queue_event (ev);
401
402                                         } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
403
404                                                 // Primary-Secondary-click: exclusively solo this track, not a toggle */
405                                                 
406                                                 //boost::shared_ptr<RouteList> rl (new RouteList);
407                                                 //rl->push_back (route());
408
409                                                 //SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
410                                                 // ev->rt_slot =  bind (sigc::mem_fun (_session, &Session::set_just_one_solo), rl, true);
411                                                 //ev->rt_return = sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup);
412                                                 
413                                                 //_session.queue_event (ev);
414
415                                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
416
417                                                 // shift-click: toggle solo isolated status
418
419                                                 _route->set_solo_isolated (!_route->solo_isolated(), this);
420                                                 wait_for_release = false;
421
422                                         } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
423
424 #if 0
425                                                 /* Primary-button1: solo mix group.
426                                                    NOTE: Primary-button2 is MIDI learn.
427                                                 */
428
429                                                 if (ev->button == 1) {
430                                                         queue_route_group_op (RouteGroup::Solo, &Session::set_all_solo, !_route->soloed());
431                                                 }
432 #endif
433
434
435                                         } else {
436
437                                                 /* click: solo this route */
438
439                                                 boost::shared_ptr<RouteList> rl (new RouteList);
440                                                 rl->push_back (route());
441                                                 
442                                                 SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
443                                                 ev->rt_slot =   bind (sigc::mem_fun (_session, &Session::set_solo), rl, !rec_enable_button->get_active());
444                                                 ev->rt_return = sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup);
445                                                 
446                                                 _session.queue_event (ev);
447                                         }
448                                 }
449                         }
450                 }
451         }
452
453         return true;
454 }
455
456 bool
457 RouteUI::solo_release(GdkEventButton*)
458 {
459         if (!ignore_toggle) {
460                 if (wait_for_release) {
461                         wait_for_release = false;
462                         if (multiple_solo_change) {
463                                 multiple_solo_change = false;
464                                 // undo the last op
465                                 // because the press was the last undoable thing we did
466                                 _session.undo (1U);
467                         } else {
468                                 // we don't use "undo the last op"
469                                 // here because its expensive for the GUI
470                                 _route->set_solo (!_route->soloed(), this);
471                         }
472                 }
473         }
474
475         return true;
476 }
477
478 void
479 RouteUI::post_rtop_cleanup (SessionEvent* ev)
480 {
481         ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::post_rtop_cleanup), ev));
482         delete ev;
483 }
484
485 void
486 RouteUI::post_group_rtop_cleanup (SessionEvent* ev, RouteGroup* rg, RouteGroup::Property prop)
487 {
488         ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::post_group_rtop_cleanup), ev, rg, prop));
489         delete ev;
490         rg->set_property (prop, false);
491 }
492
493 void
494 RouteUI::queue_route_group_op (RouteGroup::Property prop, void (Session::*session_method)(boost::shared_ptr<RouteList>, bool), bool yn)
495 {
496         RouteGroup* rg = _route->route_group();
497         bool prop_was_active;
498
499         if (rg) {
500                 prop_was_active = rg->active_property (prop);
501                 rg->set_property (prop, true);
502         } else {
503                 prop_was_active = false;
504         }
505
506         /* we will queue the op for just this route, but because its route group now has the relevant property marked active,
507            the operation will apply to the whole group (if there is a group)
508         */
509         
510         boost::shared_ptr<RouteList> rl (new RouteList);
511         rl->push_back (route());
512         
513         SessionEvent* ev = new SessionEvent (SessionEvent::RealTimeOperation, SessionEvent::Add, SessionEvent::Immediate, 0, 0.0);
514         ev->rt_slot =   bind (sigc::mem_fun (_session, session_method), rl, yn);
515         if (rg && !prop_was_active) {
516                 ev->rt_return = bind (sigc::mem_fun (*this, &RouteUI::post_group_rtop_cleanup), rg, prop);
517         } else {
518                 ev->rt_return = sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup);
519         }
520         
521         _session.queue_event (ev);
522 }
523
524 bool
525 RouteUI::rec_enable_press(GdkEventButton* ev)
526 {
527         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
528                 return true;
529         }
530
531         if (!_session.engine().connected()) {
532                 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
533                 msg.run ();
534                 return true;
535         }
536
537         if (!ignore_toggle && is_track() && rec_enable_button) {
538
539                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
540
541                         // do nothing on midi bind event
542                         return false;
543
544                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
545
546 #if 0                   
547                         _session.set_record_enable (_session.get_route(), !rec_enable_button->get_active(), sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup));
548 #endif
549
550                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
551
552                         /* Primary-button1 applies change to the route group (even if it is not active)
553                            NOTE: Primary-button2 is MIDI learn.
554                         */
555 #if 0                   
556                         if (ev->button == 1 && _route->route_group()) {
557                                 _session.set_record_enable (_route->route_group(), !rec_enable_button->get_active(),
558                                 queue_route_group_op (RouteGroup::RecEnable, &Session::set_record_enable, 
559                         }
560 #endif
561
562                 } else if (Keyboard::is_context_menu_event (ev)) {
563
564                         /* do this on release */
565
566                 } else {
567
568 #if 0
569                         boost::shared_ptr<RouteList> rl (new RouteList);
570                         rl->push_back (route());
571                         _session.set_record_enable (rl, !rec_enable_button->get_active(), sigc::mem_fun (*this, &RouteUI::post_rtop_cleanup));
572 #endif
573                 }
574         }
575
576         return true;
577 }
578
579 bool
580 RouteUI::rec_enable_release (GdkEventButton*)
581 {
582         return true;
583 }
584
585 void
586 RouteUI::build_sends_menu ()
587 {
588         using namespace Menu_Helpers;
589
590         sends_menu = new Menu;
591         sends_menu->set_name ("ArdourContextMenu");
592         MenuList& items = sends_menu->items();
593
594         items.push_back (MenuElem(_("Assign all tracks (prefader)"), bind (mem_fun (*this, &RouteUI::create_sends), PreFader)));
595         items.push_back (MenuElem(_("Assign all tracks (postfader)"), bind (mem_fun (*this, &RouteUI::create_sends), PostFader)));
596         items.push_back (MenuElem(_("Assign selected tracks (prefader)"), bind (mem_fun (*this, &RouteUI::create_selected_sends), PreFader)));
597         items.push_back (MenuElem(_("Assign selected tracks (postfader)"), bind (mem_fun (*this, &RouteUI::create_selected_sends), PostFader)));
598         items.push_back (MenuElem(_("Copy track gains to sends"), mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
599         items.push_back (MenuElem(_("Set sends gain to -inf"), mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
600         items.push_back (MenuElem(_("Set sends gain to 0dB"), mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
601
602 }
603
604 void
605 RouteUI::create_sends (Placement p)
606 {
607         _session.globally_add_internal_sends (_route, p);
608 }
609
610 void
611 RouteUI::create_selected_sends (Placement p)
612 {
613         boost::shared_ptr<RouteList> rlist (new RouteList);
614         TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
615
616         for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
617                 RouteTimeAxisView* rtv;
618                 RouteUI* rui;
619                 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
620                         if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
621                                 if (boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
622                                         rlist->push_back (rui->route());
623                                 }
624                         }
625                 }
626         }
627         
628         _session.add_internal_sends (_route, p, rlist);
629 }
630
631 void
632 RouteUI::set_sends_gain_from_track ()
633 {
634         _session.globally_set_send_gains_from_track (_route);
635 }
636
637 void
638 RouteUI::set_sends_gain_to_zero ()
639 {
640         _session.globally_set_send_gains_to_zero (_route);
641 }
642
643 void
644 RouteUI::set_sends_gain_to_unity ()
645 {
646         _session.globally_set_send_gains_to_unity (_route);
647 }
648
649 bool
650 RouteUI::show_sends_press(GdkEventButton* ev)
651 {
652         if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
653                 return true;
654         }
655
656         if (!ignore_toggle && !is_track() && show_sends_button) {
657
658                 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
659
660                         // do nothing on midi bind event
661                         return false;
662
663                 } else if (Keyboard::is_context_menu_event (ev)) {
664
665                         if (sends_menu == 0) {
666                                 build_sends_menu ();
667                         }
668
669                         sends_menu->popup (0, ev->time);
670
671                 } else {
672
673                         /* change button state */
674
675                         show_sends_button->set_active (!show_sends_button->get_active());
676
677                         /* start blinking */
678
679                         if (show_sends_button->get_active()) {
680                                 /* show sends to this bus */
681                                 MixerStrip::SwitchIO (_route);
682                                 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (mem_fun(*this, &RouteUI::send_blink));
683                         } else {
684                                 /* everybody back to normal */
685                                 send_blink_connection.disconnect ();
686                                 MixerStrip::SwitchIO (boost::shared_ptr<Route>());
687                         }
688
689                 }
690         }
691
692         return true;
693 }
694
695 bool
696 RouteUI::show_sends_release (GdkEventButton*)
697 {
698         return true;
699 }
700
701 void
702 RouteUI::send_blink (bool onoff)
703 {
704         if (!show_sends_button) {
705                 return;
706         }
707
708         if (onoff) {
709                 show_sends_button->set_state (STATE_ACTIVE);
710         } else {
711                 show_sends_button->set_state (STATE_NORMAL);
712         }
713 }
714
715 void
716 RouteUI::solo_changed(void* /*src*/)
717 {
718         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
719 }
720
721
722 void
723 RouteUI::listen_changed(void* /*src*/)
724 {
725         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
726 }
727
728 int
729 RouteUI::solo_visual_state (boost::shared_ptr<Route> r)
730 {
731         if (Config->get_solo_control_is_listen_control()) {
732
733                 if (r->listening()) {
734                         return 1;
735                 } else {
736                         return 0;
737                 }
738
739         } else {
740
741                 if (r->solo_isolated()) {
742                         return 2;
743                 } else if (r->soloed()) {
744                         return 1;
745                 } else {
746                         return 0;
747                 }
748         }
749
750         return 0;
751 }
752
753 void
754 RouteUI::update_solo_display ()
755 {
756         bool x;
757         
758         if (Config->get_solo_control_is_listen_control()) {
759
760                 if (solo_button->get_active() != (x = _route->listening())) {
761                         ignore_toggle = true;
762                         solo_button->set_active(x);
763                         ignore_toggle = false;
764                 }
765
766         } else {
767
768                 if (solo_button->get_active() != (x = _route->soloed())) {
769                         ignore_toggle = true;
770                         solo_button->set_active (x);
771                         ignore_toggle = false;
772                 }
773
774         }
775
776         solo_button->set_visual_state (solo_visual_state (_route));
777 }
778
779 void
780 RouteUI::solo_changed_so_update_mute ()
781 {
782         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
783 }
784
785 void
786 RouteUI::mute_changed(void* /*src*/)
787 {
788         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
789 }
790
791 int
792 RouteUI::mute_visual_state (Session& s, boost::shared_ptr<Route> r)
793 {
794         if (Config->get_show_solo_mutes()) {
795                 
796                 if (r->muted ()) {
797                         /* full mute */
798                         return 2;
799                 } else if (s.soloing() && !r->soloed() && !r->solo_isolated()) {
800                         /* mute-because-not-soloed */
801                         return 1;
802                 } else {
803                         /* no mute at all */
804                         return 0;
805                 }
806
807         } else {
808
809                 if (r->muted()) {
810                         /* full mute */
811                         return 2;
812                 } else {
813                         /* no mute at all */
814                         return 0;
815                 }
816         }
817
818         return 0;
819 }
820
821 void
822 RouteUI::update_mute_display ()
823 {
824         bool model = _route->muted();
825         bool view = mute_button->get_active();
826
827         /* first make sure the button's "depressed" visual
828            is correct.
829         */
830
831         if (model != view) {
832                 ignore_toggle = true;
833                 mute_button->set_active (model);
834                 ignore_toggle = false;
835         }
836
837         mute_button->set_visual_state (mute_visual_state (_session, _route));
838 }
839
840 void
841 RouteUI::route_rec_enable_changed ()
842 {
843         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
844 }
845
846 void
847 RouteUI::session_rec_enable_changed ()
848 {
849         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
850 }
851
852 void
853 RouteUI::update_rec_display ()
854 {
855         bool model = _route->record_enabled();
856         bool view = rec_enable_button->get_active();
857
858         /* first make sure the button's "depressed" visual
859            is correct.
860         */
861
862         if (model != view) {
863                 ignore_toggle = true;
864                 rec_enable_button->set_active (model);
865                 ignore_toggle = false;
866         }
867
868         /* now make sure its color state is correct */
869
870         if (model) {
871
872                 switch (_session.record_status ()) {
873                 case Session::Recording:
874                         rec_enable_button->set_visual_state (1);
875                         break;
876
877                 case Session::Disabled:
878                 case Session::Enabled:
879                         rec_enable_button->set_visual_state (2);
880                         break;
881
882                 }
883
884         } else {
885                 rec_enable_button->set_visual_state (0);
886         }
887
888         check_rec_enable_sensitivity ();
889 }
890
891 void
892 RouteUI::build_solo_menu (void)
893 {
894         using namespace Menu_Helpers;
895
896         solo_menu = new Menu;
897         solo_menu->set_name ("ArdourContextMenu");
898         MenuList& items = solo_menu->items();
899         CheckMenuItem* check;
900
901         check = new CheckMenuItem(_("Solo Isolate"));
902         check->set_active (_route->solo_isolated());
903         check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
904         _route->solo_isolated_changed.connect(bind (mem_fun (*this, &RouteUI::solo_isolated_toggle), check));
905         items.push_back (CheckMenuElem(*check));
906         check->show_all();
907
908         check = new CheckMenuItem(_("Solo Safe"));
909         check->set_active (_route->solo_safe());
910         check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
911         _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
912         items.push_back (CheckMenuElem(*check));
913         check->show_all();
914
915         //items.push_back (SeparatorElem());
916         // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
917
918 }
919
920 void
921 RouteUI::build_mute_menu(void)
922 {
923         using namespace Menu_Helpers;
924
925         mute_menu = new Menu;
926         mute_menu->set_name ("ArdourContextMenu");
927
928         MenuList& items = mute_menu->items();
929
930         pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
931         init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
932         pre_fader_mute_check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
933         items.push_back (CheckMenuElem(*pre_fader_mute_check));
934         pre_fader_mute_check->show_all();
935
936         post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
937         init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
938         post_fader_mute_check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
939         items.push_back (CheckMenuElem(*post_fader_mute_check));
940         post_fader_mute_check->show_all();
941
942         listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
943         init_mute_menu(MuteMaster::Listen, listen_mute_check);
944         listen_mute_check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
945         items.push_back (CheckMenuElem(*listen_mute_check));
946         listen_mute_check->show_all();
947
948         main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
949         init_mute_menu(MuteMaster::Main, main_mute_check);
950         main_mute_check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
951         items.push_back (CheckMenuElem(*main_mute_check));
952         main_mute_check->show_all();
953
954         //items.push_back (SeparatorElem());
955         // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
956
957         _route->mute_points_changed.connect (mem_fun (*this, &RouteUI::muting_change));
958 }
959
960 void
961 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
962 {
963         check->set_active (_route->mute_points() & mp);
964 }
965
966 void
967 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
968 {
969         if (check->get_active()) {
970                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
971         } else {
972                 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
973         }
974 }
975
976 void
977 RouteUI::muting_change ()
978 {
979         ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::muting_change));
980
981         bool yn;
982         MuteMaster::MutePoint current = _route->mute_points ();
983
984         yn = (current & MuteMaster::PreFader);
985
986         if (pre_fader_mute_check->get_active() != yn) {
987                 pre_fader_mute_check->set_active (yn);
988         }
989
990         yn = (current & MuteMaster::PostFader);
991
992         if (post_fader_mute_check->get_active() != yn) {
993                 post_fader_mute_check->set_active (yn);
994         }
995
996         yn = (current & MuteMaster::Listen);
997
998         if (listen_mute_check->get_active() != yn) {
999                 listen_mute_check->set_active (yn);
1000         }
1001
1002         yn = (current & MuteMaster::Main);
1003
1004         if (main_mute_check->get_active() != yn) {
1005                 main_mute_check->set_active (yn);
1006         }
1007 }
1008
1009 void
1010 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1011 {
1012         _route->set_solo_isolated (check->get_active(), this);
1013 }
1014
1015 void
1016 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1017 {
1018         _route->set_solo_safe (check->get_active(), this);
1019 }
1020
1021 void
1022 RouteUI::set_route_group_solo(boost::shared_ptr<Route> route, bool yn)
1023 {
1024         RouteGroup* route_group;
1025
1026         if((route_group = route->route_group()) != 0){
1027                 _session.begin_reversible_command (_("mix group solo  change"));
1028                 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
1029                 route_group->apply(&Route::set_solo, yn, this);
1030                 cmd->mark();
1031                 _session.add_command (cmd);
1032                 _session.commit_reversible_command ();
1033         } else {
1034                 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
1035         }
1036 }
1037
1038 void
1039 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
1040 {
1041         _session.begin_reversible_command (name);
1042         XMLNode &before = _route->get_state();
1043         bind(mem_fun(*_route, func), yn, arg)();
1044         XMLNode &after = _route->get_state();
1045         _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
1046         _session.commit_reversible_command ();
1047 }
1048
1049 void
1050 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
1051 {
1052         _session.begin_reversible_command (name);
1053         XMLNode &before = track()->get_state();
1054         bind (mem_fun (*track(), func), yn, arg)();
1055         XMLNode &after = track()->get_state();
1056         _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
1057         _session.commit_reversible_command ();
1058 }
1059
1060 void
1061 RouteUI::set_route_group_mute(boost::shared_ptr<Route> route, bool yn)
1062 {
1063         RouteGroup* route_group;
1064
1065         if((route_group = route->route_group()) != 0){
1066                 _session.begin_reversible_command (_("mix group mute change"));
1067                 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
1068                 route_group->apply(&Route::set_mute, yn, this);
1069                 cmd->mark();
1070                 _session.add_command(cmd);
1071                 _session.commit_reversible_command ();
1072         } else {
1073                 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
1074         }
1075 }
1076
1077 void
1078 RouteUI::set_route_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
1079 {
1080         RouteGroup* route_group;
1081
1082         if((route_group = route->route_group()) != 0){
1083                 _session.begin_reversible_command (_("mix group rec-enable change"));
1084                 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
1085                 route_group->apply (&Route::set_record_enable, yn, this);
1086                 cmd->mark();
1087                 _session.add_command(cmd);
1088                 _session.commit_reversible_command ();
1089         } else {
1090                 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
1091         }
1092 }
1093
1094
1095 bool
1096 RouteUI::choose_color()
1097 {
1098         bool picked;
1099         Gdk::Color color;
1100
1101         color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
1102
1103         if (picked) {
1104                 set_color (color);
1105         }
1106
1107         return picked;
1108 }
1109
1110 void
1111 RouteUI::set_color (const Gdk::Color & c)
1112 {
1113         char buf[64];
1114
1115         _color = c;
1116
1117         ensure_xml_node ();
1118         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1119         xml_node->add_property ("color", buf);
1120
1121         _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1122 }
1123
1124
1125 void
1126 RouteUI::ensure_xml_node ()
1127 {
1128         if (xml_node == 0) {
1129                 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
1130                         xml_node = new XMLNode ("GUI");
1131                         _route->add_extra_xml (*xml_node);
1132                 }
1133         }
1134 }
1135
1136 XMLNode*
1137 RouteUI::get_automation_child_xml_node (Evoral::Parameter param)
1138 {
1139         ensure_xml_node ();
1140
1141         XMLNodeList kids = xml_node->children();
1142         XMLNodeConstIterator iter;
1143
1144         const string sym = ARDOUR::EventTypeMap::instance().to_symbol(param);
1145
1146         for (iter = kids.begin(); iter != kids.end(); ++iter) {
1147                 if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
1148                         XMLProperty* type = (*iter)->property("automation-id");
1149                         if (type && type->value() == sym)
1150                                 return *iter;
1151                 }
1152         }
1153
1154         // Didn't find it, make a new one
1155         XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
1156         child->add_property("automation-id", sym);
1157         xml_node->add_child_nocopy (*child);
1158
1159         return child;
1160 }
1161
1162 int
1163 RouteUI::set_color_from_route ()
1164 {
1165         XMLProperty *prop;
1166
1167         RouteUI::ensure_xml_node ();
1168
1169         if ((prop = xml_node->property ("color")) != 0) {
1170                 int r, g, b;
1171                 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
1172                 _color.set_red(r);
1173                 _color.set_green(g);
1174                 _color.set_blue(b);
1175                 return 0;
1176         }
1177         return 1;
1178 }
1179
1180 void
1181 RouteUI::remove_this_route ()
1182 {
1183         vector<string> choices;
1184         string prompt;
1185
1186         if (is_track()) {
1187                 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());
1188         } else {
1189                 prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
1190         }
1191
1192         choices.push_back (_("No, do nothing."));
1193         choices.push_back (_("Yes, remove it."));
1194
1195         Choice prompter (prompt, choices);
1196
1197         if (prompter.run () == 1) {
1198                 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1199         }
1200 }
1201
1202 gint
1203 RouteUI::idle_remove_this_route (RouteUI *rui)
1204 {
1205         rui->_session.remove_route (rui->_route);
1206         return false;
1207 }
1208
1209 void
1210 RouteUI::route_rename ()
1211 {
1212         ArdourPrompter name_prompter (true);
1213         string result;
1214         name_prompter.set_prompt (_("New Name: "));
1215         name_prompter.set_initial_text (_route->name());
1216         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1217         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1218         name_prompter.show_all ();
1219
1220         switch (name_prompter.run ()) {
1221
1222         case Gtk::RESPONSE_ACCEPT:
1223         name_prompter.get_result (result);
1224         if (result.length()) {
1225                         _route->set_name (result);
1226                 }
1227                 break;
1228         }
1229
1230         return;
1231
1232 }
1233
1234 void
1235 RouteUI::name_changed ()
1236 {
1237         ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
1238
1239         name_label.set_text (_route->name());
1240 }
1241
1242 void
1243 RouteUI::toggle_route_active ()
1244 {
1245         bool yn;
1246
1247         if (route_active_menu_item) {
1248                 if (route_active_menu_item->get_active() != (yn = _route->active())) {
1249                         _route->set_active (!yn);
1250                 }
1251         }
1252 }
1253
1254 void
1255 RouteUI::route_active_changed ()
1256 {
1257         if (route_active_menu_item) {
1258                 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
1259         }
1260 }
1261
1262 void
1263 RouteUI::toggle_polarity ()
1264 {
1265         if (polarity_menu_item) {
1266
1267                 bool x;
1268
1269                 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
1270
1271                 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
1272                         _route->set_phase_invert (x);
1273                         if (x) {
1274                                 name_label.set_text (X_("Ø ") + name_label.get_text());
1275                         } else {
1276                                 name_label.set_text (_route->name());
1277                         }
1278                 }
1279         }
1280 }
1281
1282 void
1283 RouteUI::polarity_changed ()
1284 {
1285         if (_route->phase_invert()) {
1286                 name_label.set_text (X_("Ø ") + name_label.get_text());
1287         } else {
1288                 name_label.set_text (_route->name());
1289         }
1290 }
1291
1292 void
1293 RouteUI::toggle_denormal_protection ()
1294 {
1295         if (denormal_menu_item) {
1296
1297                 bool x;
1298
1299                 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
1300
1301                 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1302                         _route->set_denormal_protection (x);
1303                 }
1304         }
1305 }
1306
1307 void
1308 RouteUI::denormal_protection_changed ()
1309 {
1310         if (denormal_menu_item) {
1311                 denormal_menu_item->set_active (_route->denormal_protection());
1312         }
1313 }
1314
1315 void
1316 RouteUI::solo_isolated_toggle(void* /*src*/, Gtk::CheckMenuItem* check)
1317 {
1318         bool yn = _route->solo_isolated ();
1319
1320         if (check->get_active() != yn) {
1321                 check->set_active (yn);
1322         }
1323 }
1324
1325
1326 void
1327 RouteUI::solo_safe_toggle(void* /*src*/, Gtk::CheckMenuItem* check)
1328 {
1329         bool yn = _route->solo_safe ();
1330
1331         if (check->get_active() != yn) {
1332                 check->set_active (yn);
1333         }
1334 }
1335
1336 void
1337 RouteUI::disconnect_input ()
1338 {
1339         _route->input()->disconnect (this);
1340 }
1341
1342 void
1343 RouteUI::disconnect_output ()
1344 {
1345         _route->output()->disconnect (this);
1346 }
1347
1348 bool
1349 RouteUI::is_track () const
1350 {
1351         return boost::dynamic_pointer_cast<Track>(_route) != 0;
1352 }
1353
1354 boost::shared_ptr<Track>
1355 RouteUI::track() const
1356 {
1357         return boost::dynamic_pointer_cast<Track>(_route);
1358 }
1359
1360 bool
1361 RouteUI::is_audio_track () const
1362 {
1363         return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1364 }
1365
1366 boost::shared_ptr<AudioTrack>
1367 RouteUI::audio_track() const
1368 {
1369         return boost::dynamic_pointer_cast<AudioTrack>(_route);
1370 }
1371
1372 bool
1373 RouteUI::is_midi_track () const
1374 {
1375         return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1376 }
1377
1378 boost::shared_ptr<MidiTrack>
1379 RouteUI::midi_track() const
1380 {
1381         return boost::dynamic_pointer_cast<MidiTrack>(_route);
1382 }
1383
1384 boost::shared_ptr<Diskstream>
1385 RouteUI::get_diskstream () const
1386 {
1387         boost::shared_ptr<Track> t;
1388
1389         if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1390                 return t->diskstream();
1391         } else {
1392                 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1393         }
1394 }
1395
1396 string
1397 RouteUI::name() const
1398 {
1399         return _route->name();
1400 }
1401
1402 void
1403 RouteUI::map_frozen ()
1404 {
1405         ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1406
1407         AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1408
1409         if (at) {
1410                 switch (at->freeze_state()) {
1411                 case AudioTrack::Frozen:
1412                         rec_enable_button->set_sensitive (false);
1413                         break;
1414                 default:
1415                         rec_enable_button->set_sensitive (true);
1416                         break;
1417                 }
1418         }
1419 }
1420
1421 void
1422 RouteUI::adjust_latency ()
1423 {
1424         LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session.frame_rate(), _session.engine().frames_per_cycle());
1425 }
1426
1427 void
1428 RouteUI::save_as_template ()
1429 {
1430         sys::path path;
1431         Glib::ustring safe_name;
1432         string name;
1433
1434         path = ARDOUR::user_route_template_directory ();
1435
1436         if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1437                 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1438                 return;
1439         }
1440
1441         Prompter p (true); // modal
1442
1443         p.set_prompt (_("Template name:"));
1444         switch (p.run()) {
1445         case RESPONSE_ACCEPT:
1446                 break;
1447         default:
1448                 return;
1449         }
1450
1451         p.hide ();
1452         p.get_result (name, true);
1453
1454         safe_name = legalize_for_path (name);
1455         safe_name += template_suffix;
1456
1457         path /= safe_name;
1458
1459         _route->save_as_template (path.to_string(), name);
1460 }
1461
1462 void
1463 RouteUI::check_rec_enable_sensitivity ()
1464 {
1465         if (_session.transport_rolling() && rec_enable_button->get_active() && Config->get_disable_disarm_during_roll()) {
1466                 rec_enable_button->set_sensitive (false);
1467         } else {
1468                 rec_enable_button->set_sensitive (true);
1469         }
1470 }
1471
1472 void
1473 RouteUI::parameter_changed (string const & p)
1474 {
1475         ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::parameter_changed), p));
1476
1477         if (p == "disable-disarm-during-roll") {
1478                 check_rec_enable_sensitivity ();
1479         } else if (p == "solo-control-is-listen-control") {
1480                 set_button_names ();
1481         } else if (p == "listen-position") {
1482                 set_button_names ();
1483         }
1484 }
1485
1486 void
1487 RouteUI::step_gain_up ()
1488 {
1489         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1490 }
1491
1492 void
1493 RouteUI::page_gain_up ()
1494 {
1495         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1496 }
1497
1498 void
1499 RouteUI::step_gain_down ()
1500 {
1501         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1502 }
1503
1504 void
1505 RouteUI::page_gain_down ()
1506 {
1507         _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1508 }
1509
1510 void
1511 RouteUI::open_remote_control_id_dialog ()
1512 {
1513         ArdourDialog dialog (_("Remote Control ID"));
1514
1515         uint32_t const limit = _session.ntracks() + _session.nbusses () + 4;
1516
1517         HBox* hbox = manage (new HBox);
1518         hbox->set_spacing (6);
1519         hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1520         SpinButton* spin = manage (new SpinButton);
1521         spin->set_digits (0);
1522         spin->set_increments (1, 10);
1523         spin->set_range (0, limit);
1524         spin->set_value (_route->remote_control_id());
1525         hbox->pack_start (*spin);
1526         dialog.get_vbox()->pack_start (*hbox);
1527
1528         dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1529         dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1530
1531         dialog.show_all ();
1532         int const r = dialog.run ();
1533
1534         if (r == RESPONSE_ACCEPT) {
1535                 _route->set_remote_control_id (spin->get_value_as_int ());
1536         }
1537 }