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 (ev->type == GDK_2BUTTON_PRESS) {
131 if (!ignore_toggle) {
133 if (Keyboard::is_context_menu_event (ev)) {
139 mute_menu->popup(0,ev->time);
143 if (ev->button == 2) {
144 // Primary-button2 click is the midi binding click
145 // button2-click is "momentary"
147 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
148 wait_for_release = true;
154 if (ev->button == 1 || ev->button == 2) {
156 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
158 /* Primary-Tertiary-click applies change to all routes */
160 _session.begin_reversible_command (_("mute change"));
161 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
162 _session.set_all_mute (!_route->muted());
164 _session.add_command(cmd);
165 _session.commit_reversible_command ();
167 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
169 /* Primary-button1 applies change to the mix group.
170 NOTE: Primary-button2 is MIDI learn.
173 if (ev->button == 1) {
174 set_mix_group_mute (_route, !_route->muted());
179 /* plain click applies change to this route */
181 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
192 RouteUI::mute_release(GdkEventButton* ev)
194 if (!ignore_toggle) {
195 if (wait_for_release){
196 wait_for_release = false;
198 // because the press was the last undoable thing we did
206 RouteUI::solo_press(GdkEventButton* ev)
208 /* ignore double clicks */
210 if (ev->type == GDK_2BUTTON_PRESS) {
214 if (!ignore_toggle) {
216 if (Keyboard::is_context_menu_event (ev)) {
218 if (solo_menu == 0) {
222 solo_menu->popup (1, ev->time);
226 if (ev->button == 2) {
228 // Primary-button2 click is the midi binding click
229 // button2-click is "momentary"
231 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
232 wait_for_release = true;
238 if (ev->button == 1 || ev->button == 2) {
240 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
242 /* Primary-Tertiary-click applies change to all routes */
244 _session.begin_reversible_command (_("solo change"));
245 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
246 _session.set_all_solo (!_route->soloed());
248 _session.add_command (cmd);
249 _session.commit_reversible_command ();
251 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
253 // Primary-Secondary-click: exclusively solo this track, not a toggle */
255 _session.begin_reversible_command (_("solo change"));
256 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
257 _session.set_all_solo (false);
258 _route->set_solo (true, this);
260 _session.add_command(cmd);
261 _session.commit_reversible_command ();
263 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
265 // shift-click: set this route to solo safe
267 _route->set_solo_safe (!_route->solo_safe(), this);
268 wait_for_release = false;
270 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
272 /* Primary-button1: solo mix group.
273 NOTE: Primary-button2 is MIDI learn.
276 if (ev->button == 1) {
277 set_mix_group_solo (_route, !_route->soloed());
282 /* click: solo this route */
283 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
293 RouteUI::solo_release(GdkEventButton* ev)
295 if (!ignore_toggle) {
296 if (wait_for_release) {
297 wait_for_release = false;
299 // because the press was the last undoable thing we did
309 RouteUI::rec_enable_press(GdkEventButton* ev)
311 if (ev->type == GDK_2BUTTON_PRESS) {
315 if (!_session.engine().connected()) {
316 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
321 if (!ignore_toggle && is_track() && rec_enable_button) {
323 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
325 // do nothing on midi bind event
328 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
330 _session.begin_reversible_command (_("rec-enable change"));
331 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
333 if (rec_enable_button->get_active()) {
334 _session.record_disenable_all ();
336 _session.record_enable_all ();
340 _session.add_command(cmd);
341 _session.commit_reversible_command ();
343 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
345 /* Primary-button1 applies change to the mix group.
346 NOTE: Primary-button2 is MIDI learn.
349 set_mix_group_rec_enable (_route, !_route->record_enabled());
353 reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
361 RouteUI::rec_enable_release (GdkEventButton* ev)
367 RouteUI::solo_changed(void* src)
369 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
373 RouteUI::update_solo_display ()
376 vector<Gdk::Color> fg_colors;
379 if (solo_button->get_active() != (x = _route->soloed())){
380 ignore_toggle = true;
381 solo_button->set_active(x);
382 ignore_toggle = false;
385 if (_route->solo_safe()) {
386 solo_button->set_visual_state (2);
387 } else if (_route->soloed()) {
388 solo_button->set_visual_state (1);
390 solo_button->set_visual_state (0);
395 RouteUI::solo_changed_so_update_mute ()
397 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
401 RouteUI::mute_changed(void* src)
403 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
407 RouteUI::update_mute_display ()
409 bool model = _route->muted();
410 bool view = mute_button->get_active();
412 /* first make sure the button's "depressed" visual
417 ignore_toggle = true;
418 mute_button->set_active (model);
419 ignore_toggle = false;
422 /* now attend to visual state */
424 if (Config->get_show_solo_mutes()) {
425 if (_route->muted()) {
426 mute_button->set_visual_state (2);
427 } else if (!_route->soloed() && _route->solo_muted()) {
429 mute_button->set_visual_state (1);
431 mute_button->set_visual_state (0);
434 if (_route->muted()) {
435 mute_button->set_visual_state (2);
437 mute_button->set_visual_state (0);
444 RouteUI::route_rec_enable_changed ()
446 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
450 RouteUI::session_rec_enable_changed ()
452 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
456 RouteUI::update_rec_display ()
458 bool model = _route->record_enabled();
459 bool view = rec_enable_button->get_active();
461 /* first make sure the button's "depressed" visual
466 ignore_toggle = true;
467 rec_enable_button->set_active (model);
468 ignore_toggle = false;
471 /* now make sure its color state is correct */
475 switch (_session.record_status ()) {
476 case Session::Recording:
477 rec_enable_button->set_visual_state (1);
480 case Session::Disabled:
481 case Session::Enabled:
482 rec_enable_button->set_visual_state (2);
488 rec_enable_button->set_visual_state (0);
493 RouteUI::build_remote_control_menu ()
495 remote_control_menu = manage (new Menu);
496 refresh_remote_control_menu ();
500 RouteUI::refresh_remote_control_menu ()
502 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
504 // only refresh the menu if it has been instantiated
506 if (remote_control_menu == 0) {
510 using namespace Menu_Helpers;
512 RadioMenuItem::Group rc_group;
513 CheckMenuItem* rc_active;
514 uint32_t limit = _session.ntracks() + _session.nbusses();
517 MenuList& rc_items = remote_control_menu->items();
520 /* note that this menu list starts at zero, not 1, because zero
521 is a valid, if useless, ID.
524 limit += 4; /* leave some breathing room */
526 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
527 if (_route->remote_control_id() == 0) {
528 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
529 rc_active->set_active ();
532 for (uint32_t i = 1; i < limit; ++i) {
533 snprintf (buf, sizeof (buf), "%u", i);
534 rc_items.push_back (RadioMenuElem (rc_group, buf));
535 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
536 if (_route->remote_control_id() == i) {
537 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
538 rc_active->set_active ();
540 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
545 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
547 /* this is called when the radio menu item is toggled, and so
548 is actually invoked twice per menu selection. we only
549 care about the invocation for the item that was being
553 if (item->get_active()) {
554 _route->set_remote_control_id (id);
559 RouteUI::build_solo_menu (void)
561 using namespace Menu_Helpers;
563 solo_menu = new Menu;
564 solo_menu->set_name ("ArdourContextMenu");
565 MenuList& items = solo_menu->items();
566 CheckMenuItem* check;
568 check = new CheckMenuItem(_("Solo-safe"));
569 check->set_active (_route->solo_safe());
570 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
571 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
572 items.push_back (CheckMenuElem(*check));
575 //items.push_back (SeparatorElem());
576 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
581 RouteUI::build_mute_menu(void)
583 using namespace Menu_Helpers;
585 mute_menu = new Menu;
586 mute_menu->set_name ("ArdourContextMenu");
587 MenuList& items = mute_menu->items();
588 CheckMenuItem* check;
590 check = new CheckMenuItem(_("Pre Fader"));
591 init_mute_menu(PRE_FADER, check);
592 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
593 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
594 items.push_back (CheckMenuElem(*check));
597 check = new CheckMenuItem(_("Post Fader"));
598 init_mute_menu(POST_FADER, check);
599 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
600 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
601 items.push_back (CheckMenuElem(*check));
604 check = new CheckMenuItem(_("Control Outs"));
605 init_mute_menu(CONTROL_OUTS, check);
606 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
607 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
608 items.push_back (CheckMenuElem(*check));
611 check = new CheckMenuItem(_("Main Outs"));
612 init_mute_menu(MAIN_OUTS, check);
613 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
614 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
615 items.push_back (CheckMenuElem(*check));
618 //items.push_back (SeparatorElem());
619 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
623 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
625 if (_route->get_mute_config (type)) {
626 check->set_active (true);
631 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
633 _route->set_mute_config(type, check->get_active(), this);
637 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
639 _route->set_solo_safe (check->get_active(), this);
643 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
645 RouteGroup* mix_group;
647 if((mix_group = route->mix_group()) != 0){
648 _session.begin_reversible_command (_("mix group solo change"));
649 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
650 mix_group->apply(&Route::set_solo, yn, this);
652 _session.add_command (cmd);
653 _session.commit_reversible_command ();
655 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
660 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
662 _session.begin_reversible_command (name);
663 XMLNode &before = _route->get_state();
664 bind(mem_fun(*_route, func), yn, arg)();
665 XMLNode &after = _route->get_state();
666 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
667 _session.commit_reversible_command ();
671 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
673 _session.begin_reversible_command (name);
674 XMLNode &before = audio_track()->get_state();
675 bind (mem_fun (*audio_track(), func), yn, arg)();
676 XMLNode &after = audio_track()->get_state();
677 _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), &before, &after));
678 _session.commit_reversible_command ();
682 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
684 RouteGroup* mix_group;
686 if((mix_group = route->mix_group()) != 0){
687 _session.begin_reversible_command (_("mix group mute change"));
688 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
689 mix_group->apply(&Route::set_mute, yn, this);
691 _session.add_command(cmd);
692 _session.commit_reversible_command ();
694 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
699 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
701 RouteGroup* mix_group;
703 if((mix_group = route->mix_group()) != 0){
704 _session.begin_reversible_command (_("mix group rec-enable change"));
705 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
706 mix_group->apply (&Route::set_record_enable, yn, this);
708 _session.add_command(cmd);
709 _session.commit_reversible_command ();
711 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
717 RouteUI::choose_color()
722 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
732 RouteUI::set_color (const Gdk::Color & c)
739 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
740 xml_node->add_property ("color", buf);
742 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
747 RouteUI::ensure_xml_node ()
750 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
751 xml_node = new XMLNode ("GUI");
752 _route->add_extra_xml (*xml_node);
758 RouteUI::get_child_xml_node (const string & childname)
765 if ((child = find_named_node (*xml_node, childname)) == 0) {
766 child = new XMLNode (childname);
767 xml_node->add_child_nocopy (*child);
774 RouteUI::set_color_from_route ()
778 RouteUI::ensure_xml_node ();
780 if ((prop = xml_node->property ("color")) != 0) {
782 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
792 RouteUI::remove_this_route ()
794 vector<string> choices;
798 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());
800 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
803 choices.push_back (_("No, do nothing."));
804 choices.push_back (_("Yes, remove it."));
806 Choice prompter (prompt, choices);
808 if (prompter.run () == 1) {
809 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
814 RouteUI::idle_remove_this_route (RouteUI *rui)
816 rui->_session.remove_route (rui->_route);
821 RouteUI::route_rename ()
823 ArdourPrompter name_prompter (true);
825 name_prompter.set_prompt (_("New Name: "));
826 name_prompter.set_initial_text (_route->name());
827 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
828 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
829 name_prompter.show_all ();
831 switch (name_prompter.run ()) {
833 case Gtk::RESPONSE_ACCEPT:
834 name_prompter.get_result (result);
835 if (result.length()) {
836 _route->set_name (result, this);
846 RouteUI::name_changed (void *src)
848 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
850 name_label.set_text (_route->name());
854 RouteUI::toggle_route_active ()
858 if (route_active_menu_item) {
859 if (route_active_menu_item->get_active() != (yn = _route->active())) {
860 _route->set_active (!yn);
866 RouteUI::route_active_changed ()
868 if (route_active_menu_item) {
869 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
874 RouteUI::toggle_polarity ()
876 if (polarity_menu_item) {
880 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
882 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
883 _route->set_phase_invert (x, this);
885 name_label.set_text (X_("Ø ") + name_label.get_text());
887 name_label.set_text (_route->name());
894 RouteUI::polarity_changed ()
896 /* no signal for this yet */
900 RouteUI::toggle_denormal_protection ()
902 if (denormal_menu_item) {
906 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
908 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
909 _route->set_denormal_protection (x, this);
915 RouteUI::denormal_protection_changed ()
917 /* no signal for this yet */
922 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
924 bool yn = _route->solo_safe ();
926 if (check->get_active() != yn) {
927 check->set_active (yn);
931 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
933 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
935 bool yn = _route->get_mute_config(PRE_FADER);
936 if (check->get_active() != yn) {
937 check->set_active (yn);
942 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
944 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
946 bool yn = _route->get_mute_config(POST_FADER);
947 if (check->get_active() != yn) {
948 check->set_active (yn);
953 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
955 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
957 bool yn = _route->get_mute_config(CONTROL_OUTS);
958 if (check->get_active() != yn) {
959 check->set_active (yn);
964 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
966 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
968 bool yn = _route->get_mute_config(MAIN_OUTS);
969 if (check->get_active() != yn) {
970 check->set_active (yn);
975 RouteUI::disconnect_input ()
977 _route->disconnect_inputs (this);
981 RouteUI::disconnect_output ()
983 _route->disconnect_outputs (this);
987 RouteUI::is_track () const
989 return boost::dynamic_pointer_cast<Track>(_route) != 0;
992 boost::shared_ptr<Track>
993 RouteUI::track() const
995 return boost::dynamic_pointer_cast<Track>(_route);
999 RouteUI::is_audio_track () const
1001 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1004 boost::shared_ptr<AudioTrack>
1005 RouteUI::audio_track() const
1007 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1010 boost::shared_ptr<Diskstream>
1011 RouteUI::get_diskstream () const
1013 boost::shared_ptr<Track> t;
1015 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1016 return t->diskstream();
1018 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1023 RouteUI::name() const
1025 return _route->name();
1029 RouteUI::map_frozen ()
1031 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1033 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1036 switch (at->freeze_state()) {
1037 case AudioTrack::Frozen:
1038 rec_enable_button->set_sensitive (false);
1041 rec_enable_button->set_sensitive (true);