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>
42 #include <ardour/midi_track.h>
43 #include <ardour/midi_diskstream.h>
48 using namespace Gtkmm2ext;
49 using namespace ARDOUR;
52 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
53 const char* s_name, const char* r_name)
63 remote_control_menu = 0;
64 ignore_toggle = false;
65 wait_for_release = false;
66 route_active_menu_item = 0;
67 was_solo_safe = false;
68 polarity_menu_item = 0;
69 denormal_menu_item = 0;
71 if (set_color_from_route()) {
72 set_color (unique_random_color());
75 new PairedShiva<Route,RouteUI> (*_route, *this);
77 _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
79 mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
80 mute_button->set_self_managed (true);
82 solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
83 solo_button->set_self_managed (true);
85 mute_button->set_name ("MuteButton");
86 solo_button->set_name ("SoloButton");
88 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
89 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
90 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
92 /* when solo changes, update mute state too, in case the user wants us to display it */
94 _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
97 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
99 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
101 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
103 rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
104 rec_enable_button->set_name ("RecordEnableButton");
105 rec_enable_button->set_self_managed (true);
107 update_rec_display ();
110 mute_button->unset_flags (Gtk::CAN_FOCUS);
111 solo_button->unset_flags (Gtk::CAN_FOCUS);
113 _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
115 /* map the current state */
122 GoingAway (); /* EMIT SIGNAL */
127 RouteUI::mute_press(GdkEventButton* ev)
129 if (!ignore_toggle) {
131 if (Keyboard::is_context_menu_event (ev)) {
137 mute_menu->popup(0,ev->time);
141 if (ev->button == 2) {
142 // ctrl-button2 click is the midi binding click
143 // button2-click is "momentary"
145 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
146 wait_for_release = true;
152 if (ev->button == 1 || ev->button == 2) {
154 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
156 /* ctrl-shift-click applies change to all routes */
158 _session.begin_reversible_command (_("mute change"));
159 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
160 _session.set_all_mute (!_route->muted());
162 _session.add_command(cmd);
163 _session.commit_reversible_command ();
165 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
167 /* ctrl-click applies change to the mix group.
168 ctrl-button2 is MIDI learn.
171 if (ev->button == 1) {
172 set_mix_group_mute (_route, !_route->muted());
177 /* plain click applies change to this route */
179 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
190 RouteUI::mute_release(GdkEventButton* ev)
192 if (!ignore_toggle) {
193 if (wait_for_release){
194 wait_for_release = false;
196 // because the press was the last undoable thing we did
204 RouteUI::solo_press(GdkEventButton* ev)
206 if (!ignore_toggle) {
208 if (Keyboard::is_context_menu_event (ev)) {
210 if (solo_menu == 0) {
214 solo_menu->popup (1, ev->time);
218 if (ev->button == 2) {
220 // ctrl-button2 click is the midi binding click
221 // button2-click is "momentary"
223 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
224 wait_for_release = true;
230 if (ev->button == 1 || ev->button == 2) {
232 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
234 /* ctrl-shift-click applies change to all routes */
236 _session.begin_reversible_command (_("solo change"));
237 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
238 _session.set_all_solo (!_route->soloed());
240 _session.add_command (cmd);
241 _session.commit_reversible_command ();
243 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
245 // ctrl-alt-click: exclusively solo this track, not a toggle */
247 _session.begin_reversible_command (_("solo change"));
248 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
249 _session.set_all_solo (false);
250 _route->set_solo (true, this);
252 _session.add_command(cmd);
253 _session.commit_reversible_command ();
255 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
257 // shift-click: set this route to solo safe
259 _route->set_solo_safe (!_route->solo_safe(), this);
260 wait_for_release = false;
262 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
264 /* ctrl-click: solo mix group.
265 ctrl-button2 is MIDI learn.
268 if (ev->button == 1) {
269 set_mix_group_solo (_route, !_route->soloed());
274 /* click: solo this route */
276 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
286 RouteUI::solo_release(GdkEventButton* ev)
288 if (!ignore_toggle) {
289 if (wait_for_release) {
290 wait_for_release = false;
292 // because the press was the last undoable thing we did
302 RouteUI::rec_enable_press(GdkEventButton* ev)
304 if (!_session.engine().connected()) {
305 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
310 if (!ignore_toggle && is_track() && rec_enable_button) {
312 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
314 // do nothing on midi bind event
316 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
318 _session.begin_reversible_command (_("rec-enable change"));
319 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
321 if (rec_enable_button->get_active()) {
322 _session.record_disenable_all ();
324 _session.record_enable_all ();
328 _session.add_command(cmd);
329 _session.commit_reversible_command ();
331 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
333 set_mix_group_rec_enable (_route, !_route->record_enabled());
337 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
345 RouteUI::rec_enable_release (GdkEventButton* ev)
351 RouteUI::solo_changed(void* src)
353 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
357 RouteUI::update_solo_display ()
360 vector<Gdk::Color> fg_colors;
363 if (solo_button->get_active() != (x = _route->soloed())){
364 ignore_toggle = true;
365 solo_button->set_active(x);
366 ignore_toggle = false;
369 if (_route->solo_safe()) {
370 solo_button->set_visual_state (2);
371 } else if (_route->soloed()) {
372 solo_button->set_visual_state (1);
374 solo_button->set_visual_state (0);
379 RouteUI::solo_changed_so_update_mute ()
381 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
385 RouteUI::mute_changed(void* src)
387 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
391 RouteUI::update_mute_display ()
393 bool model = _route->muted();
394 bool view = mute_button->get_active();
396 /* first make sure the button's "depressed" visual
401 ignore_toggle = true;
402 mute_button->set_active (model);
403 ignore_toggle = false;
406 /* now attend to visual state */
408 if (Config->get_show_solo_mutes()) {
409 if (_route->muted()) {
410 mute_button->set_visual_state (2);
411 } else if (!_route->soloed() && _route->solo_muted()) {
413 mute_button->set_visual_state (1);
415 mute_button->set_visual_state (0);
418 if (_route->muted()) {
419 mute_button->set_visual_state (2);
421 mute_button->set_visual_state (0);
428 RouteUI::route_rec_enable_changed ()
430 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
434 RouteUI::session_rec_enable_changed ()
436 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
440 RouteUI::update_rec_display ()
442 bool model = _route->record_enabled();
443 bool view = rec_enable_button->get_active();
445 /* first make sure the button's "depressed" visual
450 ignore_toggle = true;
451 rec_enable_button->set_active (model);
452 ignore_toggle = false;
455 /* now make sure its color state is correct */
459 switch (_session.record_status ()) {
460 case Session::Recording:
461 rec_enable_button->set_visual_state (1);
464 case Session::Disabled:
465 case Session::Enabled:
466 rec_enable_button->set_visual_state (2);
472 rec_enable_button->set_visual_state (0);
477 RouteUI::build_remote_control_menu ()
479 remote_control_menu = manage (new Menu);
480 refresh_remote_control_menu ();
484 RouteUI::refresh_remote_control_menu ()
486 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
488 // only refresh the menu if it has been instantiated
490 if (remote_control_menu == 0) {
494 using namespace Menu_Helpers;
496 RadioMenuItem::Group rc_group;
497 CheckMenuItem* rc_active;
498 uint32_t limit = _session.ntracks() + _session.nbusses();
501 MenuList& rc_items = remote_control_menu->items();
504 /* note that this menu list starts at zero, not 1, because zero
505 is a valid, if useless, ID.
508 limit += 4; /* leave some breathing room */
510 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
511 if (_route->remote_control_id() == 0) {
512 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
513 rc_active->set_active ();
516 for (uint32_t i = 1; i < limit; ++i) {
517 snprintf (buf, sizeof (buf), "%u", i);
518 rc_items.push_back (RadioMenuElem (rc_group, buf));
519 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
520 if (_route->remote_control_id() == i) {
521 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
522 rc_active->set_active ();
524 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
529 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
531 /* this is called when the radio menu item is toggled, and so
532 is actually invoked twice per menu selection. we only
533 care about the invocation for the item that was being
537 if (item->get_active()) {
538 _route->set_remote_control_id (id);
543 RouteUI::build_solo_menu (void)
545 using namespace Menu_Helpers;
547 solo_menu = new Menu;
548 solo_menu->set_name ("ArdourContextMenu");
549 MenuList& items = solo_menu->items();
550 CheckMenuItem* check;
552 check = new CheckMenuItem(_("Solo-safe"));
553 check->set_active (_route->solo_safe());
554 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
555 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
556 items.push_back (CheckMenuElem(*check));
559 //items.push_back (SeparatorElem());
560 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
565 RouteUI::build_mute_menu(void)
567 using namespace Menu_Helpers;
569 mute_menu = new Menu;
570 mute_menu->set_name ("ArdourContextMenu");
571 MenuList& items = mute_menu->items();
572 CheckMenuItem* check;
574 check = new CheckMenuItem(_("Pre Fader"));
575 init_mute_menu(PRE_FADER, check);
576 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
577 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
578 items.push_back (CheckMenuElem(*check));
581 check = new CheckMenuItem(_("Post Fader"));
582 init_mute_menu(POST_FADER, check);
583 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
584 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
585 items.push_back (CheckMenuElem(*check));
588 check = new CheckMenuItem(_("Control Outs"));
589 init_mute_menu(CONTROL_OUTS, check);
590 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
591 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
592 items.push_back (CheckMenuElem(*check));
595 check = new CheckMenuItem(_("Main Outs"));
596 init_mute_menu(MAIN_OUTS, check);
597 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
598 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
599 items.push_back (CheckMenuElem(*check));
602 //items.push_back (SeparatorElem());
603 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
607 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
609 if (_route->get_mute_config (type)) {
610 check->set_active (true);
615 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
617 _route->set_mute_config(type, check->get_active(), this);
621 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
623 _route->set_solo_safe (check->get_active(), this);
627 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
629 RouteGroup* mix_group;
631 if((mix_group = route->mix_group()) != 0){
632 _session.begin_reversible_command (_("mix group solo change"));
633 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
634 mix_group->apply(&Route::set_solo, yn, this);
636 _session.add_command (cmd);
637 _session.commit_reversible_command ();
639 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
644 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
646 _session.begin_reversible_command (name);
647 XMLNode &before = _route->get_state();
648 bind(mem_fun(*_route, func), yn, arg)();
649 XMLNode &after = _route->get_state();
650 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
651 _session.commit_reversible_command ();
655 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
657 _session.begin_reversible_command (name);
658 XMLNode &before = track()->get_state();
659 bind (mem_fun (*track(), func), yn, arg)();
660 XMLNode &after = track()->get_state();
661 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
662 _session.commit_reversible_command ();
666 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
668 RouteGroup* mix_group;
670 if((mix_group = route->mix_group()) != 0){
671 _session.begin_reversible_command (_("mix group mute change"));
672 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
673 mix_group->apply(&Route::set_mute, yn, this);
675 _session.add_command(cmd);
676 _session.commit_reversible_command ();
678 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
683 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
685 RouteGroup* mix_group;
687 if((mix_group = route->mix_group()) != 0){
688 _session.begin_reversible_command (_("mix group rec-enable change"));
689 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
690 mix_group->apply (&Route::set_record_enable, yn, this);
692 _session.add_command(cmd);
693 _session.commit_reversible_command ();
695 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
701 RouteUI::choose_color()
706 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
716 RouteUI::set_color (const Gdk::Color & c)
723 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
724 xml_node->add_property ("color", buf);
726 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
731 RouteUI::ensure_xml_node ()
734 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
735 xml_node = new XMLNode ("GUI");
736 _route->add_extra_xml (*xml_node);
742 RouteUI::get_child_xml_node (const string & childname)
749 if ((child = find_named_node (*xml_node, childname)) == 0) {
750 child = new XMLNode (childname);
751 xml_node->add_child_nocopy (*child);
758 RouteUI::set_color_from_route ()
762 RouteUI::ensure_xml_node ();
764 if ((prop = xml_node->property ("color")) != 0) {
766 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
776 RouteUI::remove_this_route ()
778 vector<string> choices;
782 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());
784 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
787 choices.push_back (_("No, do nothing."));
788 choices.push_back (_("Yes, remove it."));
790 Choice prompter (prompt, choices);
792 if (prompter.run () == 1) {
793 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
798 RouteUI::idle_remove_this_route (RouteUI *rui)
800 rui->_session.remove_route (rui->_route);
805 RouteUI::route_rename ()
807 ArdourPrompter name_prompter (true);
809 name_prompter.set_prompt (_("New Name: "));
810 name_prompter.set_initial_text (_route->name());
811 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
812 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
813 name_prompter.show_all ();
815 switch (name_prompter.run ()) {
817 case Gtk::RESPONSE_ACCEPT:
818 name_prompter.get_result (result);
819 if (result.length()) {
820 _route->set_name (result);
830 RouteUI::name_changed ()
832 ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
834 name_label.set_text (_route->name());
838 RouteUI::toggle_route_active ()
842 if (route_active_menu_item) {
843 if (route_active_menu_item->get_active() != (yn = _route->active())) {
844 _route->set_active (!yn);
850 RouteUI::route_active_changed ()
852 if (route_active_menu_item) {
853 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
858 RouteUI::toggle_polarity ()
860 if (polarity_menu_item) {
864 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
866 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
867 _route->set_phase_invert (x, this);
869 name_label.set_text (X_("Ø ") + name_label.get_text());
871 name_label.set_text (_route->name());
878 RouteUI::polarity_changed ()
880 /* no signal for this yet */
884 RouteUI::toggle_denormal_protection ()
886 if (denormal_menu_item) {
890 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
892 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
893 _route->set_denormal_protection (x, this);
899 RouteUI::denormal_protection_changed ()
901 /* no signal for this yet */
906 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
908 bool yn = _route->solo_safe ();
910 if (check->get_active() != yn) {
911 check->set_active (yn);
915 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
917 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
919 bool yn = _route->get_mute_config(PRE_FADER);
920 if (check->get_active() != yn) {
921 check->set_active (yn);
926 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
928 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
930 bool yn = _route->get_mute_config(POST_FADER);
931 if (check->get_active() != yn) {
932 check->set_active (yn);
937 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
939 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
941 bool yn = _route->get_mute_config(CONTROL_OUTS);
942 if (check->get_active() != yn) {
943 check->set_active (yn);
948 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
950 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
952 bool yn = _route->get_mute_config(MAIN_OUTS);
953 if (check->get_active() != yn) {
954 check->set_active (yn);
959 RouteUI::disconnect_input ()
961 _route->disconnect_inputs (this);
965 RouteUI::disconnect_output ()
967 _route->disconnect_outputs (this);
971 RouteUI::is_track () const
973 return boost::dynamic_pointer_cast<Track>(_route) != 0;
976 boost::shared_ptr<Track>
977 RouteUI::track() const
979 return boost::dynamic_pointer_cast<Track>(_route);
983 RouteUI::is_audio_track () const
985 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
988 boost::shared_ptr<AudioTrack>
989 RouteUI::audio_track() const
991 return boost::dynamic_pointer_cast<AudioTrack>(_route);
995 RouteUI::is_midi_track () const
997 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1000 boost::shared_ptr<MidiTrack>
1001 RouteUI::midi_track() const
1003 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1006 boost::shared_ptr<Diskstream>
1007 RouteUI::get_diskstream () const
1009 boost::shared_ptr<Track> t;
1011 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1012 return t->diskstream();
1014 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1019 RouteUI::name() const
1021 return _route->name();
1025 RouteUI::map_frozen ()
1027 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1029 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1032 switch (at->freeze_state()) {
1033 case AudioTrack::Frozen:
1034 rec_enable_button->set_sensitive (false);
1037 rec_enable_button->set_sensitive (true);