remove two minor leftovers from last commit
[ardour.git] / gtk2_ardour / route_ui.cc
1 /*
2     Copyright (C) 2002 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     $Id$
19 */
20
21 #include <gtkmm2ext/gtk_ui.h>
22 #include <gtkmm2ext/stop_signal.h>
23 #include <gtkmm2ext/choice.h>
24 #include <gtkmm2ext/bindable_button.h>
25 #include <gtkmm2ext/doi.h>
26
27 #include <ardour/route_group.h>
28
29 #include "route_ui.h"
30 #include "keyboard.h"
31 #include "utils.h"
32 #include "prompter.h"
33 #include "gui_thread.h"
34
35 #include <ardour/route.h>
36 #include <ardour/audio_track.h>
37 #include <ardour/diskstream.h>
38
39 #include "i18n.h"
40 using namespace sigc;
41 using namespace Gtk;
42 using namespace Gtkmm2ext;
43 using namespace ARDOUR;
44
45
46 RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name,
47                   const char* s_name, const char* r_name)
48     : AxisView(sess),
49           _route(rt),
50           mute_button(0),
51           solo_button(0),
52           rec_enable_button(0)
53 {
54         xml_node = 0;
55         mute_menu = 0;
56         solo_menu = 0;
57         remote_control_menu = 0;
58         ignore_toggle = false;
59         wait_for_release = false;
60         route_active_menu_item = 0;
61
62         if (set_color_from_route()) {
63                 set_color (unique_random_color());
64         }
65
66         _route.GoingAway.connect (mem_fun (*this, &RouteUI::route_removed));
67         _route.active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
68
69         mute_button = manage (new BindableToggleButton (& _route.midi_mute_control(), m_name ));
70         mute_button->set_bind_button_state (2, GDK_CONTROL_MASK);
71         solo_button = manage (new BindableToggleButton (& _route.midi_solo_control(), s_name ));
72         solo_button->set_bind_button_state (2, GDK_CONTROL_MASK);
73
74         if (is_audio_track()) {
75                 AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
76
77                 get_diskstream()->record_enable_changed.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
78
79                 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
80
81                 rec_enable_button = manage (new BindableToggleButton (& at->midi_rec_enable_control(), r_name ));
82                 rec_enable_button->set_bind_button_state (2, GDK_CONTROL_MASK);
83
84         } else {
85                 rec_enable_button = manage (new BindableToggleButton (0, r_name ));
86         }
87         
88         mute_button->unset_flags (Gtk::CAN_FOCUS);
89         solo_button->unset_flags (Gtk::CAN_FOCUS);
90         rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
91
92         /* map the current state */
93
94         update_rec_display ();
95         map_frozen ();
96 }
97
98 RouteUI::~RouteUI()
99 {
100         delete mute_menu;
101 }
102
103 gint
104 RouteUI::mute_press(GdkEventButton* ev)
105 {
106         if (!ignore_toggle) {
107
108                 if (Keyboard::is_context_menu_event (ev)) {
109
110                         if (mute_menu == 0){
111                                 build_mute_menu();
112                         }
113
114                         mute_menu->popup(0,0);
115
116                 } else {
117
118                         if (ev->button == 2) {
119                                 // ctrl-button2 click is the midi binding click
120                                 // button2-click is "momentary"
121                                 
122                                 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
123                                         wait_for_release = true;
124                                 }
125                         }
126
127                         if (ev->button == 1 || ev->button == 2) {
128
129                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
130
131                                         /* ctrl-shift-click applies change to all routes */
132
133                                         _session.begin_reversible_command (_("mute change"));
134                                         _session.add_undo (_session.global_mute_memento(this));
135                                         _session.set_all_mute (!_route.muted());
136                                         _session.add_redo_no_execute (_session.global_mute_memento(this));
137                                         _session.commit_reversible_command ();
138
139                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
140
141                                         /* ctrl-click applies change to the mix group.
142                                            ctrl-button2 is MIDI learn.
143                                         */
144
145                                         if (ev->button == 1) {
146                                                 set_mix_group_mute (_route, !_route.muted());
147                                         }
148                                         
149                                 } else {
150
151                                         /* plain click applies change to this route */
152
153                                         reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route.muted(), this);
154                                 }
155                         }
156                 }
157
158         }
159
160         return true;
161 }
162
163 gint
164 RouteUI::mute_release(GdkEventButton* ev)
165 {
166         if (!ignore_toggle) {
167                 if (wait_for_release){
168                         wait_for_release = false;
169                         // undo the last op
170                         // because the press was the last undoable thing we did
171                         _session.undo (1U);
172                 }
173         }
174         return true;
175 }
176
177 gint
178 RouteUI::solo_press(GdkEventButton* ev)
179 {
180         if (!ignore_toggle) {
181
182                 if (Keyboard::is_context_menu_event (ev)) {
183                         
184                         if (solo_menu == 0) {
185                                 build_solo_menu ();
186                         }
187
188                         solo_menu->popup (1, 0);
189
190                 } else {
191
192                         if (ev->button == 2) {
193
194                                 // ctrl-button2 click is the midi binding click
195                                 // button2-click is "momentary"
196                                 
197                                 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
198                                         wait_for_release = true;
199                                 }
200                         }
201
202                         if (ev->button == 1 || ev->button == 2) {
203
204                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
205
206                                         /* ctrl-shift-click applies change to all routes */
207
208                                         _session.begin_reversible_command (_("solo change"));
209                                         _session.add_undo (_session.global_solo_memento(this));
210                                         _session.set_all_solo (!_route.soloed());
211                                         _session.add_redo_no_execute (_session.global_solo_memento(this));
212                                         _session.commit_reversible_command ();
213                                         
214                                 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
215
216                                         // ctrl-alt-click: exclusively solo this track, not a toggle */
217
218                                         _session.begin_reversible_command (_("solo change"));
219                                         _session.add_undo (_session.global_solo_memento(this));
220                                         _session.set_all_solo (false);
221                                         _route.set_solo (true, this);
222                                         _session.add_redo_no_execute (_session.global_solo_memento(this));
223                                         _session.commit_reversible_command ();
224
225                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
226
227                                         // shift-click: set this route to solo safe
228
229                                         _route.set_solo_safe (!_route.solo_safe(), this);
230                                         wait_for_release = false;
231
232                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
233
234                                         /* ctrl-click: solo mix group.
235                                            ctrl-button2 is MIDI learn.
236                                         */
237
238                                         if (ev->button == 1) {
239                                                 set_mix_group_solo (_route, !_route.soloed());
240                                         }
241
242                                 } else {
243
244                                         /* click: solo this route */
245
246                                         reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route.soloed(), this);
247                                 }
248                         }
249                 }
250         }
251
252         return stop_signal (*solo_button, "button-press-event");
253 }
254
255 gint
256 RouteUI::solo_release(GdkEventButton* ev)
257 {
258         if(!ignore_toggle){
259                 if (wait_for_release){
260                         wait_for_release = false;
261                         // undo the last op
262                         // because the press was the last undoable thing we did
263
264                         _session.undo (1U);
265
266                         stop_signal (*solo_button, "button-release-event");
267                 }
268         }
269         return TRUE;
270 }
271
272 gint
273 RouteUI::rec_enable_press(GdkEventButton* ev)
274 {
275         if (!ignore_toggle && is_audio_track()) {
276
277                 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
278                         // do nothing on midi bind event
279                 }
280                 else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
281
282                         _session.begin_reversible_command (_("rec-enable change"));
283                         _session.add_undo (_session.global_record_enable_memento(this));
284
285                         if (rec_enable_button->get_active()) {
286                                 _session.record_disenable_all ();
287                         } else {
288                                 _session.record_enable_all ();
289                         }
290
291                         _session.add_redo_no_execute (_session.global_record_enable_memento(this));
292                         _session.commit_reversible_command ();
293
294                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
295
296                         set_mix_group_rec_enable (_route, !_route.record_enabled());
297
298                 } else {
299
300                         reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
301
302                         ignore_toggle = true;
303                         rec_enable_button->set_active(audio_track()->record_enabled());
304                         ignore_toggle = false;
305                 }
306                 
307                 stop_signal (*rec_enable_button, "button-press-event");
308         }
309
310         return TRUE;
311 }
312
313 void
314 RouteUI::solo_changed(void* src)
315 {
316         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
317 }
318
319 void
320 RouteUI::update_solo_display ()
321 {
322         bool x;
323
324         if (solo_button->get_active() != (x = _route.soloed())){
325                 ignore_toggle = true;
326                 solo_button->set_active(x);
327                 ignore_toggle = false;
328         }
329         
330         /* show solo safe */
331
332         if (_route.solo_safe()){
333                 solo_button->set_name(safe_solo_button_name());
334         } else {
335                 solo_button->set_name(solo_button_name());
336         }
337 }
338
339 void
340 RouteUI::mute_changed(void* src)
341 {
342         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
343 }
344
345 void
346 RouteUI::update_mute_display ()
347 {
348         bool x;
349
350         if (mute_button->get_active() != (x = _route.muted())){
351                 ignore_toggle = true;
352                 mute_button->set_active(x);
353                 ignore_toggle = false;
354         }
355 }
356
357 void
358 RouteUI::route_rec_enable_changed (void *src)
359 {
360         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
361 }
362
363 void
364 RouteUI::session_rec_enable_changed ()
365 {
366         Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
367 }
368
369 void
370 RouteUI::update_rec_display ()
371 {
372         bool model = _route.record_enabled();
373         bool view = rec_enable_button->get_active();
374
375         /* first make sure the button's "depressed" visual
376            is correct.
377         */
378         
379         if (model != view) {
380                 ignore_toggle = true;
381                 rec_enable_button->set_active (model);
382                 ignore_toggle = false;
383         }
384
385         /* now make sure its color state is correct */
386
387         if (model) {
388
389                 switch (_session.record_status ()) {
390                 case Session::Disabled:
391                 case Session::Enabled:
392                         if (rec_enable_button->get_state() != Gtk::STATE_ACTIVE) {
393                                 rec_enable_button->set_state (Gtk::STATE_ACTIVE);
394                         }
395                         break;
396
397                 case Session::Recording:
398                         if (rec_enable_button->get_state() != Gtk::STATE_SELECTED) {
399                                 rec_enable_button->set_state (Gtk::STATE_SELECTED);
400                         }
401                         break;
402                 }
403
404         } else {
405                 if (rec_enable_button->get_state() != Gtk::STATE_NORMAL) {
406                         rec_enable_button->set_state (Gtk::STATE_NORMAL);
407                 }
408         }
409 }
410
411 void
412 RouteUI::build_remote_control_menu ()
413 {
414         remote_control_menu = manage (new Menu);
415         refresh_remote_control_menu ();
416 }
417
418 void
419 RouteUI::refresh_remote_control_menu ()
420 {
421         using namespace Menu_Helpers;
422
423         RadioMenuItem::Group rc_group;
424         CheckMenuItem* rc_active;
425         uint32_t limit = _session.ntracks();
426         char buf[32];
427
428         MenuList& rc_items = remote_control_menu->items();
429         rc_items.clear ();
430
431         /* note that this menu list starts at zero, not 1, because zero
432            is a valid, if useless, ID.
433         */
434
435         limit += 4; /* leave some breathing room */
436         
437         for (uint32_t i = 0; i < limit; ++i) {
438                 snprintf (buf, sizeof (buf), "%u", i);
439                 rc_items.push_back (RadioMenuElem (rc_group, buf));
440                 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
441                 if (_route.remote_control_id() == i) {
442                         rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
443                         rc_active->set_active ();
444                 }
445                 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
446         }
447 }
448
449 void
450 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
451 {
452         /* this is called when the radio menu item is toggled, and so 
453            is actually invoked twice per menu selection. we only
454            care about the invocation for the item that was being
455            marked active.
456         */
457
458         if (item->get_active()) {
459                 _route.set_remote_control_id (id);
460         }
461 }
462
463 void
464 RouteUI::build_solo_menu (void)
465 {
466         using namespace Menu_Helpers;
467         
468         solo_menu = new Menu;
469         solo_menu->set_name ("ArdourContextMenu");
470         MenuList& items = solo_menu->items();
471         CheckMenuItem* check;
472
473         check = new CheckMenuItem(_("Solo-safe"));
474         check->set_active (_route.solo_safe());
475         check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
476         _route.solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
477         items.push_back (CheckMenuElem(*check));
478         check->show_all();
479
480         items.push_back (SeparatorElem());
481         items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
482         
483 }
484
485 void
486 RouteUI::build_mute_menu(void)
487 {
488         using namespace Menu_Helpers;
489         
490         mute_menu = new Menu;
491         mute_menu->set_name ("ArdourContextMenu");
492         MenuList& items = mute_menu->items();
493         CheckMenuItem* check;
494         
495         check = new CheckMenuItem(_("Pre Fader"));
496         init_mute_menu(PRE_FADER, check);
497         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
498         _route.pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
499         items.push_back (CheckMenuElem(*check));
500         check->show_all();
501
502         check = new CheckMenuItem(_("Post Fader"));
503         init_mute_menu(POST_FADER, check);
504         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
505         _route.post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
506         items.push_back (CheckMenuElem(*check));
507         check->show_all();
508         
509         check = new CheckMenuItem(_("Control Outs"));
510         init_mute_menu(CONTROL_OUTS, check);
511         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
512         _route.control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
513         items.push_back (CheckMenuElem(*check));
514         check->show_all();
515
516         check = new CheckMenuItem(_("Main Outs"));
517         init_mute_menu(MAIN_OUTS, check);
518         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
519         _route.main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
520         items.push_back (CheckMenuElem(*check));
521         check->show_all();
522
523         items.push_back (SeparatorElem());
524         items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
525 }
526
527 void
528 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
529 {
530         if (_route.get_mute_config (type)) {
531                 check->set_active (true);
532         }
533 }
534
535 void
536 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
537 {
538         _route.set_mute_config(type, check->get_active(), this);
539 }
540
541 void
542 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
543 {
544         _route.set_solo_safe (check->get_active(), this);
545 }
546
547 void
548 RouteUI::set_mix_group_solo(Route& route, bool yn)
549 {
550         RouteGroup* mix_group;
551
552         if((mix_group = route.mix_group()) != 0){
553                 _session.begin_reversible_command (_("mix group solo  change"));
554                 _session.add_undo (_session.global_solo_memento (this));
555                 mix_group->apply(&Route::set_solo, yn, this);
556                 _session.add_redo_no_execute (_session.global_solo_memento(this));
557                 _session.commit_reversible_command ();
558         } else {
559                 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route.soloed(), this);
560         }
561 }
562
563 void
564 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
565 {
566         _session.begin_reversible_command (name);
567         _session.add_undo (bind (mem_fun (_route, func), !yn, (void *) arg));
568         _session.add_redo (bind (mem_fun (_route, func), yn, (void *) arg));
569         _session.commit_reversible_command ();
570 }
571
572 void
573 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
574 {
575         _session.begin_reversible_command (name);
576         _session.add_undo (bind (mem_fun (*audio_track(), func), !yn, (void *) arg));
577         _session.add_redo (bind (mem_fun (*audio_track(), func), yn, (void *) arg));
578         _session.commit_reversible_command ();
579 }
580
581 void
582 RouteUI::set_mix_group_mute(Route& route, bool yn)
583 {
584         RouteGroup* mix_group;
585
586         if((mix_group = route.mix_group()) != 0){
587                 _session.begin_reversible_command (_("mix group mute change"));
588                 _session.add_undo (_session.global_mute_memento (this));
589                 mix_group->apply(&Route::set_mute, yn, this);
590                 _session.add_redo_no_execute (_session.global_mute_memento(this));
591                 _session.commit_reversible_command ();
592         } else {
593                 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route.muted(), this);
594         }
595 }
596
597 void
598 RouteUI::set_mix_group_rec_enable(Route& route, bool yn)
599 {
600         RouteGroup* mix_group;
601
602         if((mix_group = route.mix_group()) != 0){
603                 _session.begin_reversible_command (_("mix group rec-enable change"));
604                 _session.add_undo (_session.global_record_enable_memento (this));
605                 mix_group->apply (&Route::set_record_enable, yn, this);
606                 _session.add_redo_no_execute (_session.global_record_enable_memento(this));
607                 _session.commit_reversible_command ();
608         } else {
609                 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route.record_enabled(), this);
610         }
611 }
612
613
614 bool
615 RouteUI::choose_color()
616 {
617         bool picked;
618         Gdk::Color color;
619
620         color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
621
622         if (picked) {
623                 set_color (color);
624         }
625
626         return picked;
627 }
628
629 void
630 RouteUI::set_color (const Gdk::Color & c)
631 {
632         char buf[64];
633         
634         _color = c;
635         
636         ensure_xml_node ();
637         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
638         xml_node->add_property ("color", buf);
639
640          _route.gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
641 }
642
643
644 void
645 RouteUI::ensure_xml_node ()
646 {
647         if (xml_node == 0) {
648                 if ((xml_node = _route.extra_xml ("GUI")) == 0) {
649                         xml_node = new XMLNode ("GUI");
650                         _route.add_extra_xml (*xml_node);
651                 }
652         }
653 }
654
655 XMLNode*
656 RouteUI::get_child_xml_node (const string & childname)
657 {
658         XMLNode* child;
659
660         ensure_xml_node ();
661         
662         
663         if ((child = find_named_node (*xml_node, childname)) == 0) {
664                 child = new XMLNode (childname);
665                 xml_node->add_child_nocopy (*child);
666         }
667
668         return child;
669 }
670
671 int
672 RouteUI::set_color_from_route ()
673 {
674         XMLProperty *prop;
675         
676         RouteUI::ensure_xml_node ();
677
678         if ((prop = xml_node->property ("color")) != 0) {
679                 int r, g, b;
680                 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
681                 _color.set_red(r);
682                 _color.set_green(g);
683                 _color.set_blue(b);
684                 return 0;
685         } 
686         return 1;
687 }
688
689 void
690 RouteUI::remove_this_route ()
691 {
692         vector<string> choices;
693         string prompt;
694
695         if (is_audio_track()) {
696                 prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route.name());
697         } else {
698                 prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route.name());
699         }
700
701         choices.push_back (_("Yes, remove it."));
702         choices.push_back (_("No, do nothing."));
703
704         Choice prompter (prompt, choices);
705
706         prompter.chosen.connect(sigc::ptr_fun(Gtk::Main::quit));
707         prompter.show_all ();
708
709         Gtk::Main::run ();
710
711         if (prompter.get_choice() == 0) {
712           Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
713         }
714 }
715
716 gint
717 RouteUI::idle_remove_this_route (RouteUI *rui)
718 {
719         rui->_session.remove_route (rui->_route);
720         return FALSE;
721 }
722
723 void
724 RouteUI::route_removed ()
725 {
726         ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::route_removed));
727         
728         delete this;
729 }
730
731 void
732 RouteUI::route_rename ()
733 {
734         ArdourPrompter name_prompter (true);
735         string result;
736         name_prompter.set_prompt (_("new name: "));
737         name_prompter.set_initial_text (_route.name());
738         name_prompter.show_all ();
739
740         switch (name_prompter.run ()) {
741
742         case Gtk::RESPONSE_ACCEPT:
743         name_prompter.get_result (result);
744         if (result.length()) {
745                         _route.set_name (result, this);
746                 }       
747                 break;
748         }
749
750         return;
751   
752 }
753
754 void
755 RouteUI::name_changed (void *src)
756 {
757         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
758         
759         name_label.set_text (_route.name());
760 }
761
762 void
763 RouteUI::toggle_route_active ()
764 {
765         bool yn;
766
767         if (route_active_menu_item) {
768                 if (route_active_menu_item->get_active() != (yn = _route.active())) {
769                         _route.set_active (!yn);
770                 }
771         }
772 }
773
774 void
775 RouteUI::route_active_changed ()
776 {
777         if (route_active_menu_item) {
778                 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route.active()));
779         }
780 }
781
782 void
783 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
784 {
785         bool yn = _route.solo_safe ();
786
787         if (check->get_active() != yn) {
788                 check->set_active (yn);
789         }
790 }
791 void
792 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
793 {
794         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
795         
796         bool yn = _route.get_mute_config(PRE_FADER);
797         if (check->get_active() != yn) {
798                 check->set_active (yn);
799         }
800 }
801
802 void
803 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
804 {
805         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
806         
807         bool yn = _route.get_mute_config(POST_FADER);
808         if (check->get_active() != yn) {
809                 check->set_active (yn);
810         }
811 }
812
813 void
814 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
815 {
816         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
817         
818         bool yn = _route.get_mute_config(CONTROL_OUTS);
819         if (check->get_active() != yn) {
820                 check->set_active (yn);
821         }
822 }
823
824 void
825 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
826 {
827         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
828         
829         bool yn = _route.get_mute_config(MAIN_OUTS);
830         if (check->get_active() != yn) {
831                 check->set_active (yn);
832         }
833 }
834
835 void
836 RouteUI::disconnect_input ()
837 {
838         _route.disconnect_inputs (this);
839 }
840
841 void
842 RouteUI::disconnect_output ()
843 {
844         _route.disconnect_outputs (this);
845 }
846
847 bool
848 RouteUI::is_audio_track () const
849 {
850         return dynamic_cast<AudioTrack*>(&_route) != 0;
851 }
852
853 DiskStream*
854 RouteUI::get_diskstream () const
855 {
856         AudioTrack *at;
857
858         if ((at = dynamic_cast<AudioTrack*>(&_route)) != 0) {
859                 return &at->disk_stream();
860         } else {
861                 return 0;
862         }
863 }
864
865 AudioTrack*
866 RouteUI::audio_track() const
867 {
868         return dynamic_cast<AudioTrack*>(&_route);
869 }
870 string
871 RouteUI::name() const
872 {
873         return _route.name();
874 }
875
876 void
877 RouteUI::map_frozen ()
878 {
879         ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
880
881         AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
882
883         if (at) {
884                 switch (at->freeze_state()) {
885                 case AudioTrack::Frozen:
886                         rec_enable_button->set_sensitive (false);
887                         break;
888                 default:
889                         rec_enable_button->set_sensitive (true);
890                         break;
891                 }
892         }
893 }
894