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 // Primary-button2 click is the midi binding click
141 // button2-click is "momentary"
143 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
144 wait_for_release = true;
150 if (ev->button == 1 || ev->button == 2) {
152 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
154 /* Primary-Tertiary-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::PrimaryModifier)) {
165 /* Primary-button1 applies change to the mix group.
166 NOTE: Primary-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 // Primary-button2 click is the midi binding click
219 // button2-click is "momentary"
221 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
222 wait_for_release = true;
228 if (ev->button == 1 || ev->button == 2) {
230 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
232 /* Primary-Tertiary-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::PrimaryModifier|Keyboard::SecondaryModifier))) {
243 // Primary-Secondary-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::TertiaryModifier)) {
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::PrimaryModifier)) {
262 /* Primary-button1: solo mix group.
263 NOTE: Primary-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::PrimaryModifier)) {
312 // do nothing on midi bind event
315 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
317 _session.begin_reversible_command (_("rec-enable change"));
318 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
320 if (rec_enable_button->get_active()) {
321 _session.record_disenable_all ();
323 _session.record_enable_all ();
327 _session.add_command(cmd);
328 _session.commit_reversible_command ();
330 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
332 /* Primary-button1 applies change to the mix group.
333 NOTE: Primary-button2 is MIDI learn.
336 set_mix_group_rec_enable (_route, !_route->record_enabled());
340 reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
348 RouteUI::rec_enable_release (GdkEventButton* ev)
354 RouteUI::solo_changed(void* src)
356 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
360 RouteUI::update_solo_display ()
363 vector<Gdk::Color> fg_colors;
366 if (solo_button->get_active() != (x = _route->soloed())){
367 ignore_toggle = true;
368 solo_button->set_active(x);
369 ignore_toggle = false;
372 if (_route->solo_safe()) {
373 solo_button->set_visual_state (2);
374 } else if (_route->soloed()) {
375 solo_button->set_visual_state (1);
377 solo_button->set_visual_state (0);
382 RouteUI::solo_changed_so_update_mute ()
384 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
388 RouteUI::mute_changed(void* src)
390 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
394 RouteUI::update_mute_display ()
396 bool model = _route->muted();
397 bool view = mute_button->get_active();
399 /* first make sure the button's "depressed" visual
404 ignore_toggle = true;
405 mute_button->set_active (model);
406 ignore_toggle = false;
409 /* now attend to visual state */
411 if (Config->get_show_solo_mutes()) {
412 if (_route->muted()) {
413 mute_button->set_visual_state (2);
414 } else if (!_route->soloed() && _route->solo_muted()) {
416 mute_button->set_visual_state (1);
418 mute_button->set_visual_state (0);
421 if (_route->muted()) {
422 mute_button->set_visual_state (2);
424 mute_button->set_visual_state (0);
431 RouteUI::route_rec_enable_changed ()
433 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
437 RouteUI::session_rec_enable_changed ()
439 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
443 RouteUI::update_rec_display ()
445 bool model = _route->record_enabled();
446 bool view = rec_enable_button->get_active();
448 /* first make sure the button's "depressed" visual
453 ignore_toggle = true;
454 rec_enable_button->set_active (model);
455 ignore_toggle = false;
458 /* now make sure its color state is correct */
462 switch (_session.record_status ()) {
463 case Session::Recording:
464 rec_enable_button->set_visual_state (1);
467 case Session::Disabled:
468 case Session::Enabled:
469 rec_enable_button->set_visual_state (2);
475 rec_enable_button->set_visual_state (0);
480 RouteUI::build_remote_control_menu ()
482 remote_control_menu = manage (new Menu);
483 refresh_remote_control_menu ();
487 RouteUI::refresh_remote_control_menu ()
489 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
491 // only refresh the menu if it has been instantiated
493 if (remote_control_menu == 0) {
497 using namespace Menu_Helpers;
499 RadioMenuItem::Group rc_group;
500 CheckMenuItem* rc_active;
501 uint32_t limit = _session.ntracks() + _session.nbusses();
504 MenuList& rc_items = remote_control_menu->items();
507 /* note that this menu list starts at zero, not 1, because zero
508 is a valid, if useless, ID.
511 limit += 4; /* leave some breathing room */
513 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
514 if (_route->remote_control_id() == 0) {
515 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
516 rc_active->set_active ();
519 for (uint32_t i = 1; i < limit; ++i) {
520 snprintf (buf, sizeof (buf), "%u", i);
521 rc_items.push_back (RadioMenuElem (rc_group, buf));
522 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
523 if (_route->remote_control_id() == i) {
524 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
525 rc_active->set_active ();
527 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
532 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
534 /* this is called when the radio menu item is toggled, and so
535 is actually invoked twice per menu selection. we only
536 care about the invocation for the item that was being
540 if (item->get_active()) {
541 _route->set_remote_control_id (id);
546 RouteUI::build_solo_menu (void)
548 using namespace Menu_Helpers;
550 solo_menu = new Menu;
551 solo_menu->set_name ("ArdourContextMenu");
552 MenuList& items = solo_menu->items();
553 CheckMenuItem* check;
555 check = new CheckMenuItem(_("Solo-safe"));
556 check->set_active (_route->solo_safe());
557 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
558 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
559 items.push_back (CheckMenuElem(*check));
562 //items.push_back (SeparatorElem());
563 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
568 RouteUI::build_mute_menu(void)
570 using namespace Menu_Helpers;
572 mute_menu = new Menu;
573 mute_menu->set_name ("ArdourContextMenu");
574 MenuList& items = mute_menu->items();
575 CheckMenuItem* check;
577 check = new CheckMenuItem(_("Pre Fader"));
578 init_mute_menu(PRE_FADER, check);
579 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
580 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
581 items.push_back (CheckMenuElem(*check));
584 check = new CheckMenuItem(_("Post Fader"));
585 init_mute_menu(POST_FADER, check);
586 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
587 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
588 items.push_back (CheckMenuElem(*check));
591 check = new CheckMenuItem(_("Control Outs"));
592 init_mute_menu(CONTROL_OUTS, check);
593 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
594 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
595 items.push_back (CheckMenuElem(*check));
598 check = new CheckMenuItem(_("Main Outs"));
599 init_mute_menu(MAIN_OUTS, check);
600 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
601 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
602 items.push_back (CheckMenuElem(*check));
605 //items.push_back (SeparatorElem());
606 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
610 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
612 if (_route->get_mute_config (type)) {
613 check->set_active (true);
618 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
620 _route->set_mute_config(type, check->get_active(), this);
624 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
626 _route->set_solo_safe (check->get_active(), this);
630 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
632 RouteGroup* mix_group;
634 if((mix_group = route->mix_group()) != 0){
635 _session.begin_reversible_command (_("mix group solo change"));
636 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
637 mix_group->apply(&Route::set_solo, yn, this);
639 _session.add_command (cmd);
640 _session.commit_reversible_command ();
642 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
647 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
649 _session.begin_reversible_command (name);
650 XMLNode &before = _route->get_state();
651 bind(mem_fun(*_route, func), yn, arg)();
652 XMLNode &after = _route->get_state();
653 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
654 _session.commit_reversible_command ();
658 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
660 _session.begin_reversible_command (name);
661 XMLNode &before = audio_track()->get_state();
662 bind (mem_fun (*audio_track(), func), yn, arg)();
663 XMLNode &after = audio_track()->get_state();
664 _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), &before, &after));
665 _session.commit_reversible_command ();
669 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
671 RouteGroup* mix_group;
673 if((mix_group = route->mix_group()) != 0){
674 _session.begin_reversible_command (_("mix group mute change"));
675 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
676 mix_group->apply(&Route::set_mute, yn, this);
678 _session.add_command(cmd);
679 _session.commit_reversible_command ();
681 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
686 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
688 RouteGroup* mix_group;
690 if((mix_group = route->mix_group()) != 0){
691 _session.begin_reversible_command (_("mix group rec-enable change"));
692 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
693 mix_group->apply (&Route::set_record_enable, yn, this);
695 _session.add_command(cmd);
696 _session.commit_reversible_command ();
698 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
704 RouteUI::choose_color()
709 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
719 RouteUI::set_color (const Gdk::Color & c)
726 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
727 xml_node->add_property ("color", buf);
729 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
734 RouteUI::ensure_xml_node ()
737 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
738 xml_node = new XMLNode ("GUI");
739 _route->add_extra_xml (*xml_node);
745 RouteUI::get_child_xml_node (const string & childname)
752 if ((child = find_named_node (*xml_node, childname)) == 0) {
753 child = new XMLNode (childname);
754 xml_node->add_child_nocopy (*child);
761 RouteUI::set_color_from_route ()
765 RouteUI::ensure_xml_node ();
767 if ((prop = xml_node->property ("color")) != 0) {
769 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
779 RouteUI::remove_this_route ()
781 vector<string> choices;
785 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());
787 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
790 choices.push_back (_("No, do nothing."));
791 choices.push_back (_("Yes, remove it."));
793 Choice prompter (prompt, choices);
795 if (prompter.run () == 1) {
796 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
801 RouteUI::idle_remove_this_route (RouteUI *rui)
803 rui->_session.remove_route (rui->_route);
808 RouteUI::route_rename ()
810 ArdourPrompter name_prompter (true);
812 name_prompter.set_prompt (_("New Name: "));
813 name_prompter.set_initial_text (_route->name());
814 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
815 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
816 name_prompter.show_all ();
818 switch (name_prompter.run ()) {
820 case Gtk::RESPONSE_ACCEPT:
821 name_prompter.get_result (result);
822 if (result.length()) {
823 _route->set_name (result, this);
833 RouteUI::name_changed (void *src)
835 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
837 name_label.set_text (_route->name());
841 RouteUI::toggle_route_active ()
845 if (route_active_menu_item) {
846 if (route_active_menu_item->get_active() != (yn = _route->active())) {
847 _route->set_active (!yn);
853 RouteUI::route_active_changed ()
855 if (route_active_menu_item) {
856 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
861 RouteUI::toggle_polarity ()
863 if (polarity_menu_item) {
867 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
869 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
870 _route->set_phase_invert (x, this);
872 name_label.set_text (X_("Ø ") + name_label.get_text());
874 name_label.set_text (_route->name());
881 RouteUI::polarity_changed ()
883 /* no signal for this yet */
887 RouteUI::toggle_denormal_protection ()
889 if (denormal_menu_item) {
893 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
895 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
896 _route->set_denormal_protection (x, this);
902 RouteUI::denormal_protection_changed ()
904 /* no signal for this yet */
909 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
911 bool yn = _route->solo_safe ();
913 if (check->get_active() != yn) {
914 check->set_active (yn);
918 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
920 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
922 bool yn = _route->get_mute_config(PRE_FADER);
923 if (check->get_active() != yn) {
924 check->set_active (yn);
929 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
931 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
933 bool yn = _route->get_mute_config(POST_FADER);
934 if (check->get_active() != yn) {
935 check->set_active (yn);
940 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
942 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
944 bool yn = _route->get_mute_config(CONTROL_OUTS);
945 if (check->get_active() != yn) {
946 check->set_active (yn);
951 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
953 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
955 bool yn = _route->get_mute_config(MAIN_OUTS);
956 if (check->get_active() != yn) {
957 check->set_active (yn);
962 RouteUI::disconnect_input ()
964 _route->disconnect_inputs (this);
968 RouteUI::disconnect_output ()
970 _route->disconnect_outputs (this);
974 RouteUI::is_track () const
976 return boost::dynamic_pointer_cast<Track>(_route) != 0;
979 boost::shared_ptr<Track>
980 RouteUI::track() const
982 return boost::dynamic_pointer_cast<Track>(_route);
986 RouteUI::is_audio_track () const
988 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
991 boost::shared_ptr<AudioTrack>
992 RouteUI::audio_track() const
994 return boost::dynamic_pointer_cast<AudioTrack>(_route);
997 boost::shared_ptr<Diskstream>
998 RouteUI::get_diskstream () const
1000 boost::shared_ptr<Track> t;
1002 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1003 return t->diskstream();
1005 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1010 RouteUI::name() const
1012 return _route->name();
1016 RouteUI::map_frozen ()
1018 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1020 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1023 switch (at->freeze_state()) {
1024 case AudioTrack::Frozen:
1025 rec_enable_button->set_sensitive (false);
1028 rec_enable_button->set_sensitive (true);