4559058b8d4b4b420859edfdb9b7a1e648729b7a
[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/audio_diskstream.h>
38
39 #include "i18n.h"
40 using namespace sigc;
41 using namespace Gtk;
42 using namespace Gtkmm2ext;
43 using namespace ARDOUR;
44 using namespace PBD;
45
46
47 RouteUI::RouteUI (ARDOUR::Route& rt, ARDOUR::Session& sess, const char* m_name,
48                   const char* s_name, const char* r_name)
49     : AxisView(sess),
50           _route(rt),
51           mute_button(0),
52           solo_button(0),
53           rec_enable_button(0)
54 {
55         xml_node = 0;
56         mute_menu = 0;
57         solo_menu = 0;
58         remote_control_menu = 0;
59         ignore_toggle = false;
60         wait_for_release = false;
61         route_active_menu_item = 0;
62
63         if (set_color_from_route()) {
64                 set_color (unique_random_color());
65         }
66
67         _route.GoingAway.connect (mem_fun (*this, &RouteUI::route_removed));
68         _route.active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
69
70         mute_button = manage (new BindableToggleButton (& _route.midi_mute_control(), m_name ));
71         mute_button->set_bind_button_state (2, GDK_CONTROL_MASK);
72         solo_button = manage (new BindableToggleButton (& _route.midi_solo_control(), s_name ));
73         solo_button->set_bind_button_state (2, GDK_CONTROL_MASK);
74
75         if (is_audio_track()) {
76                 AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
77
78                 get_diskstream()->record_enable_changed.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
79
80                 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
81
82                 rec_enable_button = manage (new BindableToggleButton (& at->midi_rec_enable_control(), r_name ));
83                 rec_enable_button->set_bind_button_state (2, GDK_CONTROL_MASK);
84
85         } else {
86                 rec_enable_button = manage (new BindableToggleButton (0, r_name ));
87         }
88         
89         mute_button->unset_flags (Gtk::CAN_FOCUS);
90         solo_button->unset_flags (Gtk::CAN_FOCUS);
91         rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
92
93         /* map the current state */
94
95         update_rec_display ();
96         map_frozen ();
97 }
98
99 RouteUI::~RouteUI()
100 {
101         delete mute_menu;
102 }
103
104 gint
105 RouteUI::mute_press(GdkEventButton* ev)
106 {
107         if (!ignore_toggle) {
108
109                 if (Keyboard::is_context_menu_event (ev)) {
110
111                         if (mute_menu == 0){
112                                 build_mute_menu();
113                         }
114
115                         mute_menu->popup(0,0);
116
117                 } else {
118
119                         if (ev->button == 2) {
120                                 // ctrl-button2 click is the midi binding click
121                                 // button2-click is "momentary"
122                                 
123                                 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
124                                         wait_for_release = true;
125                                 }
126                         }
127
128                         if (ev->button == 1 || ev->button == 2) {
129
130                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
131
132                                         /* ctrl-shift-click applies change to all routes */
133
134                                         _session.begin_reversible_command (_("mute change"));
135                                         _session.add_undo (_session.global_mute_memento(this));
136                                         _session.set_all_mute (!_route.muted());
137                                         _session.add_redo_no_execute (_session.global_mute_memento(this));
138                                         _session.commit_reversible_command ();
139
140                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
141
142                                         /* ctrl-click applies change to the mix group.
143                                            ctrl-button2 is MIDI learn.
144                                         */
145
146                                         if (ev->button == 1) {
147                                                 set_mix_group_mute (_route, !_route.muted());
148                                         }
149                                         
150                                 } else {
151
152                                         /* plain click applies change to this route */
153
154                                         reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route.muted(), this);
155                                 }
156                         }
157                 }
158
159         }
160
161         return true;
162 }
163
164 gint
165 RouteUI::mute_release(GdkEventButton* ev)
166 {
167         if (!ignore_toggle) {
168                 if (wait_for_release){
169                         wait_for_release = false;
170                         // undo the last op
171                         // because the press was the last undoable thing we did
172                         _session.undo (1U);
173                 }
174         }
175         return true;
176 }
177
178 gint
179 RouteUI::solo_press(GdkEventButton* ev)
180 {
181         if (!ignore_toggle) {
182
183                 if (Keyboard::is_context_menu_event (ev)) {
184                         
185                         if (solo_menu == 0) {
186                                 build_solo_menu ();
187                         }
188
189                         solo_menu->popup (1, 0);
190
191                 } else {
192
193                         if (ev->button == 2) {
194
195                                 // ctrl-button2 click is the midi binding click
196                                 // button2-click is "momentary"
197                                 
198                                 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
199                                         wait_for_release = true;
200                                 }
201                         }
202
203                         if (ev->button == 1 || ev->button == 2) {
204
205                                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
206
207                                         /* ctrl-shift-click applies change to all routes */
208
209                                         _session.begin_reversible_command (_("solo change"));
210                                         _session.add_undo (_session.global_solo_memento(this));
211                                         _session.set_all_solo (!_route.soloed());
212                                         _session.add_redo_no_execute (_session.global_solo_memento(this));
213                                         _session.commit_reversible_command ();
214                                         
215                                 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
216
217                                         // ctrl-alt-click: exclusively solo this track, not a toggle */
218
219                                         _session.begin_reversible_command (_("solo change"));
220                                         _session.add_undo (_session.global_solo_memento(this));
221                                         _session.set_all_solo (false);
222                                         _route.set_solo (true, this);
223                                         _session.add_redo_no_execute (_session.global_solo_memento(this));
224                                         _session.commit_reversible_command ();
225
226                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
227
228                                         // shift-click: set this route to solo safe
229
230                                         _route.set_solo_safe (!_route.solo_safe(), this);
231                                         wait_for_release = false;
232
233                                 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
234
235                                         /* ctrl-click: solo mix group.
236                                            ctrl-button2 is MIDI learn.
237                                         */
238
239                                         if (ev->button == 1) {
240                                                 set_mix_group_solo (_route, !_route.soloed());
241                                         }
242
243                                 } else {
244
245                                         /* click: solo this route */
246
247                                         reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route.soloed(), this);
248                                 }
249                         }
250                 }
251         }
252
253         return true;
254 }
255
256 gint
257 RouteUI::solo_release(GdkEventButton* ev)
258 {
259         if (!ignore_toggle) {
260                 if (wait_for_release) {
261                         wait_for_release = false;
262                         // undo the last op
263                         // because the press was the last undoable thing we did
264
265                         _session.undo (1U);
266                 }
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         rc_items.push_back (RadioMenuElem (rc_group, _("None")));
438         if (_route.remote_control_id() == 0) {
439                 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
440                 rc_active->set_active ();
441         }
442                 
443         for (uint32_t i = 1; i < limit; ++i) {
444                 snprintf (buf, sizeof (buf), "%u", i);
445                 rc_items.push_back (RadioMenuElem (rc_group, buf));
446                 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
447                 if (_route.remote_control_id() == i) {
448                         rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
449                         rc_active->set_active ();
450                 }
451                 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
452         }
453 }
454
455 void
456 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
457 {
458         /* this is called when the radio menu item is toggled, and so 
459            is actually invoked twice per menu selection. we only
460            care about the invocation for the item that was being
461            marked active.
462         */
463
464         if (item->get_active()) {
465                 _route.set_remote_control_id (id);
466         }
467 }
468
469 void
470 RouteUI::build_solo_menu (void)
471 {
472         using namespace Menu_Helpers;
473         
474         solo_menu = new Menu;
475         solo_menu->set_name ("ArdourContextMenu");
476         MenuList& items = solo_menu->items();
477         CheckMenuItem* check;
478
479         check = new CheckMenuItem(_("Solo-safe"));
480         check->set_active (_route.solo_safe());
481         check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
482         _route.solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
483         items.push_back (CheckMenuElem(*check));
484         check->show_all();
485
486         items.push_back (SeparatorElem());
487         items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
488         
489 }
490
491 void
492 RouteUI::build_mute_menu(void)
493 {
494         using namespace Menu_Helpers;
495         
496         mute_menu = new Menu;
497         mute_menu->set_name ("ArdourContextMenu");
498         MenuList& items = mute_menu->items();
499         CheckMenuItem* check;
500         
501         check = new CheckMenuItem(_("Pre Fader"));
502         init_mute_menu(PRE_FADER, check);
503         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
504         _route.pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
505         items.push_back (CheckMenuElem(*check));
506         check->show_all();
507
508         check = new CheckMenuItem(_("Post Fader"));
509         init_mute_menu(POST_FADER, check);
510         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
511         _route.post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
512         items.push_back (CheckMenuElem(*check));
513         check->show_all();
514         
515         check = new CheckMenuItem(_("Control Outs"));
516         init_mute_menu(CONTROL_OUTS, check);
517         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
518         _route.control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
519         items.push_back (CheckMenuElem(*check));
520         check->show_all();
521
522         check = new CheckMenuItem(_("Main Outs"));
523         init_mute_menu(MAIN_OUTS, check);
524         check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
525         _route.main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
526         items.push_back (CheckMenuElem(*check));
527         check->show_all();
528
529         items.push_back (SeparatorElem());
530         items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
531 }
532
533 void
534 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
535 {
536         if (_route.get_mute_config (type)) {
537                 check->set_active (true);
538         }
539 }
540
541 void
542 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
543 {
544         _route.set_mute_config(type, check->get_active(), this);
545 }
546
547 void
548 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
549 {
550         _route.set_solo_safe (check->get_active(), this);
551 }
552
553 void
554 RouteUI::set_mix_group_solo(Route& route, bool yn)
555 {
556         RouteGroup* mix_group;
557
558         if((mix_group = route.mix_group()) != 0){
559                 _session.begin_reversible_command (_("mix group solo  change"));
560                 _session.add_undo (_session.global_solo_memento (this));
561                 mix_group->apply(&Route::set_solo, yn, this);
562                 _session.add_redo_no_execute (_session.global_solo_memento(this));
563                 _session.commit_reversible_command ();
564         } else {
565                 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route.soloed(), this);
566         }
567 }
568
569 void
570 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
571 {
572         _session.begin_reversible_command (name);
573         _session.add_undo (bind (mem_fun (_route, func), !yn, (void *) arg));
574         _session.add_redo (bind (mem_fun (_route, func), yn, (void *) arg));
575         _session.commit_reversible_command ();
576 }
577
578 void
579 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
580 {
581         _session.begin_reversible_command (name);
582         _session.add_undo (bind (mem_fun (*audio_track(), func), !yn, (void *) arg));
583         _session.add_redo (bind (mem_fun (*audio_track(), func), yn, (void *) arg));
584         _session.commit_reversible_command ();
585 }
586
587 void
588 RouteUI::set_mix_group_mute(Route& route, bool yn)
589 {
590         RouteGroup* mix_group;
591
592         if((mix_group = route.mix_group()) != 0){
593                 _session.begin_reversible_command (_("mix group mute change"));
594                 _session.add_undo (_session.global_mute_memento (this));
595                 mix_group->apply(&Route::set_mute, yn, this);
596                 _session.add_redo_no_execute (_session.global_mute_memento(this));
597                 _session.commit_reversible_command ();
598         } else {
599                 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route.muted(), this);
600         }
601 }
602
603 void
604 RouteUI::set_mix_group_rec_enable(Route& route, bool yn)
605 {
606         RouteGroup* mix_group;
607
608         if((mix_group = route.mix_group()) != 0){
609                 _session.begin_reversible_command (_("mix group rec-enable change"));
610                 _session.add_undo (_session.global_record_enable_memento (this));
611                 mix_group->apply (&Route::set_record_enable, yn, this);
612                 _session.add_redo_no_execute (_session.global_record_enable_memento(this));
613                 _session.commit_reversible_command ();
614         } else {
615                 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route.record_enabled(), this);
616         }
617 }
618
619
620 bool
621 RouteUI::choose_color()
622 {
623         bool picked;
624         Gdk::Color color;
625
626         color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
627
628         if (picked) {
629                 set_color (color);
630         }
631
632         return picked;
633 }
634
635 void
636 RouteUI::set_color (const Gdk::Color & c)
637 {
638         char buf[64];
639         
640         _color = c;
641         
642         ensure_xml_node ();
643         snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
644         xml_node->add_property ("color", buf);
645
646          _route.gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
647 }
648
649
650 void
651 RouteUI::ensure_xml_node ()
652 {
653         if (xml_node == 0) {
654                 if ((xml_node = _route.extra_xml ("GUI")) == 0) {
655                         xml_node = new XMLNode ("GUI");
656                         _route.add_extra_xml (*xml_node);
657                 }
658         }
659 }
660
661 XMLNode*
662 RouteUI::get_child_xml_node (const string & childname)
663 {
664         XMLNode* child;
665
666         ensure_xml_node ();
667         
668         
669         if ((child = find_named_node (*xml_node, childname)) == 0) {
670                 child = new XMLNode (childname);
671                 xml_node->add_child_nocopy (*child);
672         }
673
674         return child;
675 }
676
677 int
678 RouteUI::set_color_from_route ()
679 {
680         XMLProperty *prop;
681         
682         RouteUI::ensure_xml_node ();
683
684         if ((prop = xml_node->property ("color")) != 0) {
685                 int r, g, b;
686                 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
687                 _color.set_red(r);
688                 _color.set_green(g);
689                 _color.set_blue(b);
690                 return 0;
691         } 
692         return 1;
693 }
694
695 void
696 RouteUI::remove_this_route ()
697 {
698         vector<string> choices;
699         string prompt;
700
701         if (is_audio_track()) {
702                 prompt  = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n(cannot be undone)"), _route.name());
703         } else {
704                 prompt  = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route.name());
705         }
706
707         choices.push_back (_("No, do nothing."));
708         choices.push_back (_("Yes, remove it."));
709
710         Choice prompter (prompt, choices);
711
712         if (prompter.run () == 1) {
713                 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
714         }
715 }
716
717 gint
718 RouteUI::idle_remove_this_route (RouteUI *rui)
719 {
720         rui->_session.remove_route (rui->_route);
721         return FALSE;
722 }
723
724 void
725 RouteUI::route_removed ()
726 {
727         ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::route_removed));
728         
729         delete this;
730 }
731
732 void
733 RouteUI::route_rename ()
734 {
735         ArdourPrompter name_prompter (true);
736         string result;
737         name_prompter.set_prompt (_("New Name: "));
738         name_prompter.set_initial_text (_route.name());
739         name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
740         name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
741         name_prompter.show_all ();
742
743         switch (name_prompter.run ()) {
744
745         case Gtk::RESPONSE_ACCEPT:
746         name_prompter.get_result (result);
747         if (result.length()) {
748                         _route.set_name (result, this);
749                 }       
750                 break;
751         }
752
753         return;
754   
755 }
756
757 void
758 RouteUI::name_changed (void *src)
759 {
760         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
761
762         name_label.set_text (_route.name());
763 }
764
765 void
766 RouteUI::toggle_route_active ()
767 {
768         bool yn;
769
770         if (route_active_menu_item) {
771                 if (route_active_menu_item->get_active() != (yn = _route.active())) {
772                         _route.set_active (!yn);
773                 }
774         }
775 }
776
777 void
778 RouteUI::route_active_changed ()
779 {
780         if (route_active_menu_item) {
781                 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route.active()));
782         }
783 }
784
785 void
786 RouteUI::toggle_polarity ()
787 {
788         if (polarity_menu_item) {
789
790                 bool x;
791
792                 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
793                 
794                 if ((x = polarity_menu_item->get_active()) != _route.phase_invert()) {
795                         _route.set_phase_invert (x, this);
796                         if (x) {
797                                 name_label.set_text (X_("Ø ") + name_label.get_text());
798                         } else {
799                                 name_label.set_text (_route.name());
800                         }
801                 }
802         }
803 }
804
805 void
806 RouteUI::polarity_changed ()
807 {
808         /* no signal for this yet */
809 }
810
811 void
812 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
813 {
814         bool yn = _route.solo_safe ();
815
816         if (check->get_active() != yn) {
817                 check->set_active (yn);
818         }
819 }
820 void
821 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
822 {
823         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
824         
825         bool yn = _route.get_mute_config(PRE_FADER);
826         if (check->get_active() != yn) {
827                 check->set_active (yn);
828         }
829 }
830
831 void
832 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
833 {
834         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
835         
836         bool yn = _route.get_mute_config(POST_FADER);
837         if (check->get_active() != yn) {
838                 check->set_active (yn);
839         }
840 }
841
842 void
843 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
844 {
845         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
846         
847         bool yn = _route.get_mute_config(CONTROL_OUTS);
848         if (check->get_active() != yn) {
849                 check->set_active (yn);
850         }
851 }
852
853 void
854 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
855 {
856         ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
857         
858         bool yn = _route.get_mute_config(MAIN_OUTS);
859         if (check->get_active() != yn) {
860                 check->set_active (yn);
861         }
862 }
863
864 void
865 RouteUI::disconnect_input ()
866 {
867         _route.disconnect_inputs (this);
868 }
869
870 void
871 RouteUI::disconnect_output ()
872 {
873         _route.disconnect_outputs (this);
874 }
875
876 bool
877 RouteUI::is_audio_track () const
878 {
879         return dynamic_cast<AudioTrack*>(&_route) != 0;
880 }
881
882 AudioDiskstream*
883 RouteUI::get_diskstream () const
884 {
885         AudioTrack *at;
886
887         if ((at = dynamic_cast<AudioTrack*>(&_route)) != 0) {
888                 return &at->disk_stream();
889         } else {
890                 return 0;
891         }
892 }
893
894 AudioTrack*
895 RouteUI::audio_track() const
896 {
897         return dynamic_cast<AudioTrack*>(&_route);
898 }
899 string
900 RouteUI::name() const
901 {
902         return _route.name();
903 }
904
905 void
906 RouteUI::map_frozen ()
907 {
908         ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
909
910         AudioTrack* at = dynamic_cast<AudioTrack*>(&_route);
911
912         if (at) {
913                 switch (at->freeze_state()) {
914                 case AudioTrack::Frozen:
915                         rec_enable_button->set_sensitive (false);
916                         break;
917                 default:
918                         rec_enable_button->set_sensitive (true);
919                         break;
920                 }
921         }
922 }