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.
20 #include <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/stop_signal.h>
22 #include <gtkmm2ext/choice.h>
23 #include <gtkmm2ext/doi.h>
24 #include <gtkmm2ext/bindable_button.h>
26 #include <ardour/route_group.h>
27 #include <pbd/memento_command.h>
28 #include <pbd/stacktrace.h>
29 #include <pbd/shiva.h>
35 #include "gui_thread.h"
37 #include <ardour/route.h>
38 #include <ardour/session.h>
39 #include <ardour/audioengine.h>
40 #include <ardour/audio_track.h>
41 #include <ardour/audio_diskstream.h>
46 using namespace Gtkmm2ext;
47 using namespace ARDOUR;
50 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
51 const char* s_name, const char* r_name)
61 remote_control_menu = 0;
62 ignore_toggle = false;
63 wait_for_release = false;
64 route_active_menu_item = 0;
65 was_solo_safe = false;
66 polarity_menu_item = 0;
67 denormal_menu_item = 0;
69 if (set_color_from_route()) {
70 set_color (unique_random_color());
73 new PairedShiva<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 mute_button->set_self_managed (true);
80 solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
81 solo_button->set_self_managed (true);
83 mute_button->set_name ("MuteButton");
84 solo_button->set_name ("SoloButton");
86 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
87 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
88 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
90 /* when solo changes, update mute state too, in case the user wants us to display it */
92 _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
94 update_solo_display ();
95 update_mute_display ();
98 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
100 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
102 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
104 rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
105 rec_enable_button->set_name ("RecordEnableButton");
106 rec_enable_button->set_self_managed (true);
108 update_rec_display ();
111 _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
113 /* map the current state */
120 GoingAway (); /* EMIT SIGNAL */
125 RouteUI::mute_press(GdkEventButton* ev)
127 if (!ignore_toggle) {
129 if (Keyboard::is_context_menu_event (ev)) {
135 mute_menu->popup(0,ev->time);
139 if (ev->button == 2) {
140 // ctrl-button2 click is the midi binding click
141 // button2-click is "momentary"
143 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
144 wait_for_release = true;
150 if (ev->button == 1 || ev->button == 2) {
152 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
154 /* ctrl-shift-click applies change to all routes */
156 _session.begin_reversible_command (_("mute change"));
157 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
158 _session.set_all_mute (!_route->muted());
160 _session.add_command(cmd);
161 _session.commit_reversible_command ();
163 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
165 /* ctrl-click applies change to the mix group.
166 ctrl-button2 is MIDI learn.
169 if (ev->button == 1) {
170 set_mix_group_mute (_route, !_route->muted());
175 /* plain click applies change to this route */
177 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
188 RouteUI::mute_release(GdkEventButton* ev)
190 if (!ignore_toggle) {
191 if (wait_for_release){
192 wait_for_release = false;
194 // because the press was the last undoable thing we did
202 RouteUI::solo_press(GdkEventButton* ev)
204 if (!ignore_toggle) {
206 if (Keyboard::is_context_menu_event (ev)) {
208 if (solo_menu == 0) {
212 solo_menu->popup (1, ev->time);
216 if (ev->button == 2) {
218 // ctrl-button2 click is the midi binding click
219 // button2-click is "momentary"
221 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
222 wait_for_release = true;
228 if (ev->button == 1 || ev->button == 2) {
230 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
232 /* ctrl-shift-click applies change to all routes */
234 _session.begin_reversible_command (_("solo change"));
235 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
236 _session.set_all_solo (!_route->soloed());
238 _session.add_command (cmd);
239 _session.commit_reversible_command ();
241 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
243 // ctrl-alt-click: exclusively solo this track, not a toggle */
245 _session.begin_reversible_command (_("solo change"));
246 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
247 _session.set_all_solo (false);
248 _route->set_solo (true, this);
250 _session.add_command(cmd);
251 _session.commit_reversible_command ();
253 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
255 // shift-click: set this route to solo safe
257 _route->set_solo_safe (!_route->solo_safe(), this);
258 wait_for_release = false;
260 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
262 /* ctrl-click: solo mix group.
263 ctrl-button2 is MIDI learn.
266 if (ev->button == 1) {
267 set_mix_group_solo (_route, !_route->soloed());
272 /* click: solo this route */
274 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
284 RouteUI::solo_release(GdkEventButton* ev)
286 if (!ignore_toggle) {
287 if (wait_for_release) {
288 wait_for_release = false;
290 // because the press was the last undoable thing we did
300 RouteUI::rec_enable_press(GdkEventButton* ev)
302 if (!_session.engine().connected()) {
303 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
308 if (!ignore_toggle && is_track() && rec_enable_button) {
310 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
312 // do nothing on midi bind event
314 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
316 _session.begin_reversible_command (_("rec-enable change"));
317 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
319 if (rec_enable_button->get_active()) {
320 _session.record_disenable_all ();
322 _session.record_enable_all ();
326 _session.add_command(cmd);
327 _session.commit_reversible_command ();
329 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
331 set_mix_group_rec_enable (_route, !_route->record_enabled());
335 reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
343 RouteUI::rec_enable_release (GdkEventButton* ev)
349 RouteUI::solo_changed(void* src)
351 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
355 RouteUI::update_solo_display ()
358 vector<Gdk::Color> fg_colors;
361 if (solo_button->get_active() != (x = _route->soloed())){
362 ignore_toggle = true;
363 solo_button->set_active(x);
364 ignore_toggle = false;
367 if (_route->solo_safe()) {
368 solo_button->set_visual_state (2);
369 } else if (_route->soloed()) {
370 solo_button->set_visual_state (1);
372 solo_button->set_visual_state (0);
377 RouteUI::solo_changed_so_update_mute ()
379 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
383 RouteUI::mute_changed(void* src)
385 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
389 RouteUI::update_mute_display ()
391 bool model = _route->muted();
392 bool view = mute_button->get_active();
394 /* first make sure the button's "depressed" visual
399 ignore_toggle = true;
400 mute_button->set_active (model);
401 ignore_toggle = false;
404 /* now attend to visual state */
406 if (Config->get_show_solo_mutes()) {
407 if (_route->muted()) {
408 mute_button->set_visual_state (2);
409 } else if (!_route->soloed() && _route->solo_muted()) {
411 mute_button->set_visual_state (1);
413 mute_button->set_visual_state (0);
416 if (_route->muted()) {
417 mute_button->set_visual_state (2);
419 mute_button->set_visual_state (0);
426 RouteUI::route_rec_enable_changed ()
428 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
432 RouteUI::session_rec_enable_changed ()
434 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
438 RouteUI::update_rec_display ()
440 bool model = _route->record_enabled();
441 bool view = rec_enable_button->get_active();
443 /* first make sure the button's "depressed" visual
448 ignore_toggle = true;
449 rec_enable_button->set_active (model);
450 ignore_toggle = false;
453 /* now make sure its color state is correct */
457 switch (_session.record_status ()) {
458 case Session::Recording:
459 rec_enable_button->set_visual_state (1);
462 case Session::Disabled:
463 case Session::Enabled:
464 rec_enable_button->set_visual_state (2);
470 rec_enable_button->set_visual_state (0);
475 RouteUI::build_remote_control_menu ()
477 remote_control_menu = manage (new Menu);
478 refresh_remote_control_menu ();
482 RouteUI::refresh_remote_control_menu ()
484 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
486 // only refresh the menu if it has been instantiated
488 if (remote_control_menu == 0) {
492 using namespace Menu_Helpers;
494 RadioMenuItem::Group rc_group;
495 CheckMenuItem* rc_active;
496 uint32_t limit = _session.ntracks() + _session.nbusses();
499 MenuList& rc_items = remote_control_menu->items();
502 /* note that this menu list starts at zero, not 1, because zero
503 is a valid, if useless, ID.
506 limit += 4; /* leave some breathing room */
508 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
509 if (_route->remote_control_id() == 0) {
510 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
511 rc_active->set_active ();
514 for (uint32_t i = 1; i < limit; ++i) {
515 snprintf (buf, sizeof (buf), "%u", i);
516 rc_items.push_back (RadioMenuElem (rc_group, buf));
517 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
518 if (_route->remote_control_id() == i) {
519 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
520 rc_active->set_active ();
522 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
527 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
529 /* this is called when the radio menu item is toggled, and so
530 is actually invoked twice per menu selection. we only
531 care about the invocation for the item that was being
535 if (item->get_active()) {
536 _route->set_remote_control_id (id);
541 RouteUI::build_solo_menu (void)
543 using namespace Menu_Helpers;
545 solo_menu = new Menu;
546 solo_menu->set_name ("ArdourContextMenu");
547 MenuList& items = solo_menu->items();
548 CheckMenuItem* check;
550 check = new CheckMenuItem(_("Solo-safe"));
551 check->set_active (_route->solo_safe());
552 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
553 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
554 items.push_back (CheckMenuElem(*check));
557 //items.push_back (SeparatorElem());
558 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
563 RouteUI::build_mute_menu(void)
565 using namespace Menu_Helpers;
567 mute_menu = new Menu;
568 mute_menu->set_name ("ArdourContextMenu");
569 MenuList& items = mute_menu->items();
570 CheckMenuItem* check;
572 check = new CheckMenuItem(_("Pre Fader"));
573 init_mute_menu(PRE_FADER, check);
574 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
575 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
576 items.push_back (CheckMenuElem(*check));
579 check = new CheckMenuItem(_("Post Fader"));
580 init_mute_menu(POST_FADER, check);
581 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
582 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
583 items.push_back (CheckMenuElem(*check));
586 check = new CheckMenuItem(_("Control Outs"));
587 init_mute_menu(CONTROL_OUTS, check);
588 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
589 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
590 items.push_back (CheckMenuElem(*check));
593 check = new CheckMenuItem(_("Main Outs"));
594 init_mute_menu(MAIN_OUTS, check);
595 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
596 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
597 items.push_back (CheckMenuElem(*check));
600 //items.push_back (SeparatorElem());
601 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
605 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
607 if (_route->get_mute_config (type)) {
608 check->set_active (true);
613 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
615 _route->set_mute_config(type, check->get_active(), this);
619 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
621 _route->set_solo_safe (check->get_active(), this);
625 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
627 RouteGroup* mix_group;
629 if((mix_group = route->mix_group()) != 0){
630 _session.begin_reversible_command (_("mix group solo change"));
631 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
632 mix_group->apply(&Route::set_solo, yn, this);
634 _session.add_command (cmd);
635 _session.commit_reversible_command ();
637 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
642 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
644 _session.begin_reversible_command (name);
645 XMLNode &before = _route->get_state();
646 bind(mem_fun(*_route, func), yn, arg)();
647 XMLNode &after = _route->get_state();
648 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
649 _session.commit_reversible_command ();
653 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
655 _session.begin_reversible_command (name);
656 XMLNode &before = audio_track()->get_state();
657 bind (mem_fun (*audio_track(), func), yn, arg)();
658 XMLNode &after = audio_track()->get_state();
659 _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), &before, &after));
660 _session.commit_reversible_command ();
664 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
666 RouteGroup* mix_group;
668 if((mix_group = route->mix_group()) != 0){
669 _session.begin_reversible_command (_("mix group mute change"));
670 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
671 mix_group->apply(&Route::set_mute, yn, this);
673 _session.add_command(cmd);
674 _session.commit_reversible_command ();
676 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
681 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
683 RouteGroup* mix_group;
685 if((mix_group = route->mix_group()) != 0){
686 _session.begin_reversible_command (_("mix group rec-enable change"));
687 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
688 mix_group->apply (&Route::set_record_enable, yn, this);
690 _session.add_command(cmd);
691 _session.commit_reversible_command ();
693 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
699 RouteUI::choose_color()
704 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
714 RouteUI::set_color (const Gdk::Color & c)
721 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
722 xml_node->add_property ("color", buf);
724 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
729 RouteUI::ensure_xml_node ()
732 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
733 xml_node = new XMLNode ("GUI");
734 _route->add_extra_xml (*xml_node);
740 RouteUI::get_child_xml_node (const string & childname)
747 if ((child = find_named_node (*xml_node, childname)) == 0) {
748 child = new XMLNode (childname);
749 xml_node->add_child_nocopy (*child);
756 RouteUI::set_color_from_route ()
760 RouteUI::ensure_xml_node ();
762 if ((prop = xml_node->property ("color")) != 0) {
764 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
774 RouteUI::remove_this_route ()
776 vector<string> choices;
780 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());
782 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
785 choices.push_back (_("No, do nothing."));
786 choices.push_back (_("Yes, remove it."));
788 Choice prompter (prompt, choices);
790 if (prompter.run () == 1) {
791 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
796 RouteUI::idle_remove_this_route (RouteUI *rui)
798 rui->_session.remove_route (rui->_route);
803 RouteUI::route_rename ()
805 ArdourPrompter name_prompter (true);
807 name_prompter.set_prompt (_("New Name: "));
808 name_prompter.set_initial_text (_route->name());
809 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
810 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
811 name_prompter.show_all ();
813 switch (name_prompter.run ()) {
815 case Gtk::RESPONSE_ACCEPT:
816 name_prompter.get_result (result);
817 if (result.length()) {
818 _route->set_name (result, this);
828 RouteUI::name_changed (void *src)
830 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
832 name_label.set_text (_route->name());
836 RouteUI::toggle_route_active ()
840 if (route_active_menu_item) {
841 if (route_active_menu_item->get_active() != (yn = _route->active())) {
842 _route->set_active (!yn);
848 RouteUI::route_active_changed ()
850 if (route_active_menu_item) {
851 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
856 RouteUI::toggle_polarity ()
858 if (polarity_menu_item) {
862 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
864 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
865 _route->set_phase_invert (x, this);
867 name_label.set_text (X_("Ø ") + name_label.get_text());
869 name_label.set_text (_route->name());
876 RouteUI::polarity_changed ()
878 /* no signal for this yet */
882 RouteUI::toggle_denormal_protection ()
884 if (denormal_menu_item) {
888 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
890 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
891 _route->set_denormal_protection (x, this);
897 RouteUI::denormal_protection_changed ()
899 /* no signal for this yet */
904 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
906 bool yn = _route->solo_safe ();
908 if (check->get_active() != yn) {
909 check->set_active (yn);
913 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
915 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
917 bool yn = _route->get_mute_config(PRE_FADER);
918 if (check->get_active() != yn) {
919 check->set_active (yn);
924 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
926 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
928 bool yn = _route->get_mute_config(POST_FADER);
929 if (check->get_active() != yn) {
930 check->set_active (yn);
935 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
937 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
939 bool yn = _route->get_mute_config(CONTROL_OUTS);
940 if (check->get_active() != yn) {
941 check->set_active (yn);
946 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
948 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
950 bool yn = _route->get_mute_config(MAIN_OUTS);
951 if (check->get_active() != yn) {
952 check->set_active (yn);
957 RouteUI::disconnect_input ()
959 _route->disconnect_inputs (this);
963 RouteUI::disconnect_output ()
965 _route->disconnect_outputs (this);
969 RouteUI::is_track () const
971 return dynamic_cast<Track*>(_route.get()) != 0;
975 RouteUI::track() const
977 return dynamic_cast<Track*>(_route.get());
981 RouteUI::is_audio_track () const
983 return dynamic_cast<AudioTrack*>(_route.get()) != 0;
987 RouteUI::audio_track() const
989 return dynamic_cast<AudioTrack*>(_route.get());
992 boost::shared_ptr<Diskstream>
993 RouteUI::get_diskstream () const
995 boost::shared_ptr<Track> t;
997 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
998 return t->diskstream();
1000 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1005 RouteUI::name() const
1007 return _route->name();
1011 RouteUI::map_frozen ()
1013 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1015 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1018 switch (at->freeze_state()) {
1019 case AudioTrack::Frozen:
1020 rec_enable_button->set_sensitive (false);
1023 rec_enable_button->set_sensitive (true);