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