2 Copyright (C) 2002-2006 Paul Davis
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.
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.
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.
21 #include <gtkmm2ext/gtk_ui.h>
22 #include <gtkmm2ext/stop_signal.h>
23 #include <gtkmm2ext/choice.h>
24 #include <gtkmm2ext/doi.h>
25 #include <gtkmm2ext/bindable_button.h>
27 #include <ardour/route_group.h>
28 #include <pbd/memento_command.h>
29 #include <pbd/stacktrace.h>
30 #include <pbd/shiva.h>
36 #include "gui_thread.h"
38 #include <ardour/route.h>
39 #include <ardour/session.h>
40 #include <ardour/audioengine.h>
41 #include <ardour/audio_track.h>
42 #include <ardour/audio_diskstream.h>
43 #include <ardour/midi_track.h>
44 #include <ardour/midi_diskstream.h>
49 using namespace Gtkmm2ext;
50 using namespace ARDOUR;
53 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
54 const char* s_name, const char* r_name)
64 remote_control_menu = 0;
65 ignore_toggle = false;
66 wait_for_release = false;
67 route_active_menu_item = 0;
69 if (set_color_from_route()) {
70 set_color (unique_random_color());
73 new Shiva<Route,RouteUI> (*_route, *this);
75 _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
77 mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
78 solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
80 // mute_button->unset_flags (Gtk::CAN_FOCUS);
81 // solo_button->unset_flags (Gtk::CAN_FOCUS);
83 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
84 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
85 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
88 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
90 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
92 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
94 rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
95 rec_enable_button->unset_flags (Gtk::CAN_FOCUS);
97 update_rec_display ();
100 mute_button->unset_flags (Gtk::CAN_FOCUS);
101 solo_button->unset_flags (Gtk::CAN_FOCUS);
103 /* map the current state */
110 GoingAway (); /* EMIT SIGNAL */
115 RouteUI::mute_press(GdkEventButton* ev)
117 if (!ignore_toggle) {
119 if (Keyboard::is_context_menu_event (ev)) {
125 mute_menu->popup(0,ev->time);
129 if (ev->button == 2) {
130 // ctrl-button2 click is the midi binding click
131 // button2-click is "momentary"
133 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
134 wait_for_release = true;
140 if (ev->button == 1 || ev->button == 2) {
142 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
144 /* ctrl-shift-click applies change to all routes */
146 _session.begin_reversible_command (_("mute change"));
147 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
148 _session.set_all_mute (!_route->muted());
150 _session.add_command(cmd);
151 _session.commit_reversible_command ();
153 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
155 /* ctrl-click applies change to the mix group.
156 ctrl-button2 is MIDI learn.
159 if (ev->button == 1) {
160 set_mix_group_mute (_route, !_route->muted());
165 /* plain click applies change to this route */
167 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
178 RouteUI::mute_release(GdkEventButton* ev)
180 if (!ignore_toggle) {
181 if (wait_for_release){
182 wait_for_release = false;
184 // because the press was the last undoable thing we did
192 RouteUI::solo_press(GdkEventButton* ev)
194 if (!ignore_toggle) {
196 if (Keyboard::is_context_menu_event (ev)) {
198 if (solo_menu == 0) {
202 solo_menu->popup (1, ev->time);
206 if (ev->button == 2) {
208 // ctrl-button2 click is the midi binding click
209 // button2-click is "momentary"
211 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
212 wait_for_release = true;
218 if (ev->button == 1 || ev->button == 2) {
220 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
222 /* ctrl-shift-click applies change to all routes */
224 _session.begin_reversible_command (_("solo change"));
225 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
226 _session.set_all_solo (!_route->soloed());
228 _session.add_command (cmd);
229 _session.commit_reversible_command ();
231 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
233 // ctrl-alt-click: exclusively solo this track, not a toggle */
235 _session.begin_reversible_command (_("solo change"));
236 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
237 _session.set_all_solo (false);
238 _route->set_solo (true, this);
240 _session.add_command(cmd);
241 _session.commit_reversible_command ();
243 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
245 // shift-click: set this route to solo safe
247 _route->set_solo_safe (!_route->solo_safe(), this);
248 wait_for_release = false;
250 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
252 /* ctrl-click: solo mix group.
253 ctrl-button2 is MIDI learn.
256 if (ev->button == 1) {
257 set_mix_group_solo (_route, !_route->soloed());
262 /* click: solo this route */
264 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
274 RouteUI::solo_release(GdkEventButton* ev)
276 if (!ignore_toggle) {
277 if (wait_for_release) {
278 wait_for_release = false;
280 // because the press was the last undoable thing we did
290 RouteUI::rec_enable_press(GdkEventButton* ev)
292 if (!_session.engine().connected()) {
293 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
298 if (!ignore_toggle && is_track() && rec_enable_button) {
300 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
301 // do nothing on midi bind event
303 else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
305 _session.begin_reversible_command (_("rec-enable change"));
306 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
308 if (rec_enable_button->get_active()) {
309 _session.record_disenable_all ();
311 _session.record_enable_all ();
315 _session.add_command(cmd);
316 _session.commit_reversible_command ();
318 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
320 set_mix_group_rec_enable (_route, !_route->record_enabled());
324 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
326 ignore_toggle = true;
327 rec_enable_button->set_active(track()->record_enabled());
328 ignore_toggle = false;
331 stop_signal (*rec_enable_button, "button-press-event");
338 RouteUI::solo_changed(void* src)
340 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
344 RouteUI::update_solo_display ()
348 if (solo_button->get_active() != (x = _route->soloed())){
349 ignore_toggle = true;
350 solo_button->set_active(x);
351 ignore_toggle = false;
356 if (_route->solo_safe()){
357 solo_button->set_name(safe_solo_button_name());
359 solo_button->set_name(solo_button_name());
364 RouteUI::mute_changed(void* src)
366 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
370 RouteUI::update_mute_display ()
374 if (mute_button->get_active() != (x = _route->muted())){
375 ignore_toggle = true;
376 mute_button->set_active(x);
377 ignore_toggle = false;
382 RouteUI::route_rec_enable_changed ()
384 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
388 RouteUI::session_rec_enable_changed ()
390 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
394 RouteUI::update_rec_display ()
396 bool model = _route->record_enabled();
397 bool view = rec_enable_button->get_active();
399 /* first make sure the button's "depressed" visual
404 ignore_toggle = true;
405 rec_enable_button->set_active (model);
406 ignore_toggle = false;
409 /* now make sure its color state is correct */
413 switch (_session.record_status ()) {
414 case Session::Disabled:
415 case Session::Enabled:
416 if (rec_enable_button->get_state() != Gtk::STATE_ACTIVE) {
417 rec_enable_button->set_state (Gtk::STATE_ACTIVE);
421 case Session::Recording:
422 if (rec_enable_button->get_state() != Gtk::STATE_SELECTED) {
423 rec_enable_button->set_state (Gtk::STATE_SELECTED);
429 if (rec_enable_button->get_state() != Gtk::STATE_NORMAL) {
430 rec_enable_button->set_state (Gtk::STATE_NORMAL);
436 RouteUI::build_remote_control_menu ()
438 remote_control_menu = manage (new Menu);
439 refresh_remote_control_menu ();
443 RouteUI::refresh_remote_control_menu ()
445 using namespace Menu_Helpers;
447 RadioMenuItem::Group rc_group;
448 CheckMenuItem* rc_active;
449 uint32_t limit = _session.ntracks();
452 MenuList& rc_items = remote_control_menu->items();
455 /* note that this menu list starts at zero, not 1, because zero
456 is a valid, if useless, ID.
459 limit += 4; /* leave some breathing room */
461 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
462 if (_route->remote_control_id() == 0) {
463 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
464 rc_active->set_active ();
467 for (uint32_t i = 1; i < limit; ++i) {
468 snprintf (buf, sizeof (buf), "%u", i);
469 rc_items.push_back (RadioMenuElem (rc_group, buf));
470 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
471 if (_route->remote_control_id() == i) {
472 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
473 rc_active->set_active ();
475 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
480 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
482 /* this is called when the radio menu item is toggled, and so
483 is actually invoked twice per menu selection. we only
484 care about the invocation for the item that was being
488 if (item->get_active()) {
489 _route->set_remote_control_id (id);
494 RouteUI::build_solo_menu (void)
496 using namespace Menu_Helpers;
498 solo_menu = new Menu;
499 solo_menu->set_name ("ArdourContextMenu");
500 MenuList& items = solo_menu->items();
501 CheckMenuItem* check;
503 check = new CheckMenuItem(_("Solo-safe"));
504 check->set_active (_route->solo_safe());
505 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
506 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
507 items.push_back (CheckMenuElem(*check));
510 //items.push_back (SeparatorElem());
511 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
516 RouteUI::build_mute_menu(void)
518 using namespace Menu_Helpers;
520 mute_menu = new Menu;
521 mute_menu->set_name ("ArdourContextMenu");
522 MenuList& items = mute_menu->items();
523 CheckMenuItem* check;
525 check = new CheckMenuItem(_("Pre Fader"));
526 init_mute_menu(PRE_FADER, check);
527 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
528 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
529 items.push_back (CheckMenuElem(*check));
532 check = new CheckMenuItem(_("Post Fader"));
533 init_mute_menu(POST_FADER, check);
534 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
535 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
536 items.push_back (CheckMenuElem(*check));
539 check = new CheckMenuItem(_("Control Outs"));
540 init_mute_menu(CONTROL_OUTS, check);
541 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
542 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
543 items.push_back (CheckMenuElem(*check));
546 check = new CheckMenuItem(_("Main Outs"));
547 init_mute_menu(MAIN_OUTS, check);
548 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
549 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
550 items.push_back (CheckMenuElem(*check));
553 //items.push_back (SeparatorElem());
554 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
558 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
560 if (_route->get_mute_config (type)) {
561 check->set_active (true);
566 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
568 _route->set_mute_config(type, check->get_active(), this);
572 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
574 _route->set_solo_safe (check->get_active(), this);
578 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
580 RouteGroup* mix_group;
582 if((mix_group = route->mix_group()) != 0){
583 _session.begin_reversible_command (_("mix group solo change"));
584 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
585 mix_group->apply(&Route::set_solo, yn, this);
587 _session.add_command (cmd);
588 _session.commit_reversible_command ();
590 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
595 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
597 _session.begin_reversible_command (name);
598 XMLNode &before = _route->get_state();
599 bind(mem_fun(*_route, func), yn, arg)();
600 XMLNode &after = _route->get_state();
601 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
602 _session.commit_reversible_command ();
606 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
608 _session.begin_reversible_command (name);
609 XMLNode &before = track()->get_state();
610 bind (mem_fun (*track(), func), yn, arg)();
611 XMLNode &after = track()->get_state();
612 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
613 _session.commit_reversible_command ();
617 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
619 RouteGroup* mix_group;
621 if((mix_group = route->mix_group()) != 0){
622 _session.begin_reversible_command (_("mix group mute change"));
623 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
624 mix_group->apply(&Route::set_mute, yn, this);
626 _session.add_command(cmd);
627 _session.commit_reversible_command ();
629 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
634 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
636 RouteGroup* mix_group;
638 if((mix_group = route->mix_group()) != 0){
639 _session.begin_reversible_command (_("mix group rec-enable change"));
640 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
641 mix_group->apply (&Route::set_record_enable, yn, this);
643 _session.add_command(cmd);
644 _session.commit_reversible_command ();
646 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
652 RouteUI::choose_color()
657 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
667 RouteUI::set_color (const Gdk::Color & c)
674 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
675 xml_node->add_property ("color", buf);
677 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
682 RouteUI::ensure_xml_node ()
685 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
686 xml_node = new XMLNode ("GUI");
687 _route->add_extra_xml (*xml_node);
693 RouteUI::get_child_xml_node (const string & childname)
700 if ((child = find_named_node (*xml_node, childname)) == 0) {
701 child = new XMLNode (childname);
702 xml_node->add_child_nocopy (*child);
709 RouteUI::set_color_from_route ()
713 RouteUI::ensure_xml_node ();
715 if ((prop = xml_node->property ("color")) != 0) {
717 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
727 RouteUI::remove_this_route ()
729 vector<string> choices;
733 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());
735 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
738 choices.push_back (_("No, do nothing."));
739 choices.push_back (_("Yes, remove it."));
741 Choice prompter (prompt, choices);
743 if (prompter.run () == 1) {
744 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
749 RouteUI::idle_remove_this_route (RouteUI *rui)
751 rui->_session.remove_route (rui->_route);
756 RouteUI::route_rename ()
758 ArdourPrompter name_prompter (true);
760 name_prompter.set_prompt (_("New Name: "));
761 name_prompter.set_initial_text (_route->name());
762 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
763 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
764 name_prompter.show_all ();
766 switch (name_prompter.run ()) {
768 case Gtk::RESPONSE_ACCEPT:
769 name_prompter.get_result (result);
770 if (result.length()) {
771 _route->set_name (result, this);
781 RouteUI::name_changed (void *src)
783 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
785 name_label.set_text (_route->name());
789 RouteUI::toggle_route_active ()
793 if (route_active_menu_item) {
794 if (route_active_menu_item->get_active() != (yn = _route->active())) {
795 _route->set_active (!yn);
801 RouteUI::route_active_changed ()
803 if (route_active_menu_item) {
804 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
809 RouteUI::toggle_polarity ()
811 if (polarity_menu_item) {
815 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
817 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
818 _route->set_phase_invert (x, this);
820 name_label.set_text (X_("Ø ") + name_label.get_text());
822 name_label.set_text (_route->name());
829 RouteUI::polarity_changed ()
831 /* no signal for this yet */
835 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
837 bool yn = _route->solo_safe ();
839 if (check->get_active() != yn) {
840 check->set_active (yn);
844 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
846 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
848 bool yn = _route->get_mute_config(PRE_FADER);
849 if (check->get_active() != yn) {
850 check->set_active (yn);
855 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
857 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
859 bool yn = _route->get_mute_config(POST_FADER);
860 if (check->get_active() != yn) {
861 check->set_active (yn);
866 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
868 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
870 bool yn = _route->get_mute_config(CONTROL_OUTS);
871 if (check->get_active() != yn) {
872 check->set_active (yn);
877 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
879 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
881 bool yn = _route->get_mute_config(MAIN_OUTS);
882 if (check->get_active() != yn) {
883 check->set_active (yn);
888 RouteUI::disconnect_input ()
890 _route->disconnect_inputs (this);
894 RouteUI::disconnect_output ()
896 _route->disconnect_outputs (this);
900 RouteUI::is_track () const
902 return dynamic_cast<Track*>(_route.get()) != 0;
906 RouteUI::track() const
908 return dynamic_cast<Track*>(_route.get());
912 RouteUI::is_audio_track () const
914 return dynamic_cast<AudioTrack*>(_route.get()) != 0;
918 RouteUI::audio_track() const
920 return dynamic_cast<AudioTrack*>(_route.get());
924 RouteUI::is_midi_track () const
926 return dynamic_cast<MidiTrack*>(_route.get()) != 0;
930 RouteUI::midi_track() const
932 return dynamic_cast<MidiTrack*>(_route.get());
935 boost::shared_ptr<Diskstream>
936 RouteUI::get_diskstream () const
938 boost::shared_ptr<Track> t;
940 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
941 return t->diskstream();
943 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
948 RouteUI::name() const
950 return _route->name();
954 RouteUI::map_frozen ()
956 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
958 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
961 switch (at->freeze_state()) {
962 case AudioTrack::Frozen:
963 rec_enable_button->set_sensitive (false);
966 rec_enable_button->set_sensitive (true);