2 Copyright (C) 2002-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <gtkmm2ext/gtk_ui.h>
22 #include <gtkmm2ext/stop_signal.h>
23 #include <gtkmm2ext/choice.h>
24 #include <gtkmm2ext/doi.h>
25 #include <gtkmm2ext/bindable_button.h>
27 #include <ardour/route_group.h>
28 #include <pbd/memento_command.h>
29 #include <pbd/stacktrace.h>
30 #include <pbd/shiva.h>
36 #include "gui_thread.h"
38 #include <ardour/route.h>
39 #include <ardour/session.h>
40 #include <ardour/audioengine.h>
41 #include <ardour/audio_track.h>
42 #include <ardour/audio_diskstream.h>
47 using namespace Gtkmm2ext;
48 using namespace ARDOUR;
51 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
52 const char* s_name, const char* r_name)
62 remote_control_menu = 0;
63 ignore_toggle = false;
64 wait_for_release = false;
65 route_active_menu_item = 0;
66 was_solo_safe = false;
68 if (set_color_from_route()) {
69 set_color (unique_random_color());
72 new PairedShiva<Route,RouteUI> (*_route, *this);
74 _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
76 mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
77 solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
79 mute_button->set_name ("MuteButton");
80 solo_button->set_name ("SoloButton");
82 vector<Gdk::Color> colors;
85 /* mute+solo buttons get 2 color states, so add one here to supplement the existing one */
86 ::set_color(c, rgba_from_style (X_("MuteButton"), 0x7f, 0xff, 0x7f, 0, "bg", Gtk::STATE_ACTIVE, false ));
88 mute_button->set_colors (colors);
92 /* mute+solo buttons get 2 color states, so add one here to supplement the existing one */
93 ::set_color(c, rgba_from_style (X_("SoloButton"), 0x7f, 0xff, 0x7f, 0, "bg", Gtk::STATE_ACTIVE, false ));
95 solo_button->set_colors (colors);
97 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
98 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
99 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
101 update_solo_display ();
102 update_mute_display ();
105 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
107 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
109 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
111 rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
115 /* record button has 3 color states, so we set 2 extra here */
116 ::set_color(c, rgba_from_style (X_("TrackRecordEnableButton"), 0xff, 0, 0, 0, "bg", Gtk::STATE_SELECTED, false ));
117 colors.push_back (c);
119 ::set_color(c, rgba_from_style (X_("TrackRecordEnableButton"), 0xff, 0, 0, 0, "bg", Gtk::STATE_ACTIVE, false ));
120 colors.push_back (c);
122 rec_enable_button->set_colors (colors);
124 update_rec_display ();
127 /* map the current state */
134 GoingAway (); /* EMIT SIGNAL */
139 RouteUI::mute_press(GdkEventButton* ev)
141 if (!ignore_toggle) {
143 if (Keyboard::is_context_menu_event (ev)) {
149 mute_menu->popup(0,ev->time);
153 if (ev->button == 2) {
154 // ctrl-button2 click is the midi binding click
155 // button2-click is "momentary"
157 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
158 wait_for_release = true;
164 if (ev->button == 1 || ev->button == 2) {
166 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
168 /* ctrl-shift-click applies change to all routes */
170 _session.begin_reversible_command (_("mute change"));
171 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
172 _session.set_all_mute (!_route->muted());
174 _session.add_command(cmd);
175 _session.commit_reversible_command ();
177 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
179 /* ctrl-click applies change to the mix group.
180 ctrl-button2 is MIDI learn.
183 if (ev->button == 1) {
184 set_mix_group_mute (_route, !_route->muted());
189 /* plain click applies change to this route */
191 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
202 RouteUI::mute_release(GdkEventButton* ev)
204 if (!ignore_toggle) {
205 if (wait_for_release){
206 wait_for_release = false;
208 // because the press was the last undoable thing we did
216 RouteUI::solo_press(GdkEventButton* ev)
218 if (!ignore_toggle) {
220 if (Keyboard::is_context_menu_event (ev)) {
222 if (solo_menu == 0) {
226 solo_menu->popup (1, ev->time);
230 if (ev->button == 2) {
232 // ctrl-button2 click is the midi binding click
233 // button2-click is "momentary"
235 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
236 wait_for_release = true;
242 if (ev->button == 1 || ev->button == 2) {
244 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
246 /* ctrl-shift-click applies change to all routes */
248 _session.begin_reversible_command (_("solo change"));
249 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
250 _session.set_all_solo (!_route->soloed());
252 _session.add_command (cmd);
253 _session.commit_reversible_command ();
255 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
257 // ctrl-alt-click: exclusively solo this track, not a toggle */
259 _session.begin_reversible_command (_("solo change"));
260 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
261 _session.set_all_solo (false);
262 _route->set_solo (true, this);
264 _session.add_command(cmd);
265 _session.commit_reversible_command ();
267 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
269 // shift-click: set this route to solo safe
271 _route->set_solo_safe (!_route->solo_safe(), this);
272 wait_for_release = false;
274 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
276 /* ctrl-click: solo mix group.
277 ctrl-button2 is MIDI learn.
280 if (ev->button == 1) {
281 set_mix_group_solo (_route, !_route->soloed());
286 /* click: solo this route */
288 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
298 RouteUI::solo_release(GdkEventButton* ev)
300 if (!ignore_toggle) {
301 if (wait_for_release) {
302 wait_for_release = false;
304 // because the press was the last undoable thing we did
314 RouteUI::rec_enable_press(GdkEventButton* ev)
316 if (!_session.engine().connected()) {
317 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
322 if (!ignore_toggle && is_track() && rec_enable_button) {
324 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
325 // do nothing on midi bind event
327 else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
329 _session.begin_reversible_command (_("rec-enable change"));
330 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
332 if (rec_enable_button->get_active()) {
333 _session.record_disenable_all ();
335 _session.record_enable_all ();
339 _session.add_command(cmd);
340 _session.commit_reversible_command ();
342 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
344 set_mix_group_rec_enable (_route, !_route->record_enabled());
348 reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
350 ignore_toggle = true;
351 rec_enable_button->set_active(audio_track()->record_enabled());
352 ignore_toggle = false;
355 stop_signal (*rec_enable_button, "button-press-event");
362 RouteUI::solo_changed(void* src)
364 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
368 RouteUI::update_solo_display ()
371 vector<Gdk::Color> colors;
374 if (_route->solo_safe() != was_solo_safe){
376 if (_route->solo_safe()) {
378 ::set_color(c, rgba_from_style (safe_solo_button_name(), 0x7f, 0xff, 0x7f, 0, "bg", Gtk::STATE_ACTIVE, false ));
379 solo_button->set_name(safe_solo_button_name());
381 ::set_color(c, rgba_from_style (solo_button_name(), 0x7f, 0xff, 0x7f, 0, "bg", Gtk::STATE_ACTIVE, false ));
382 solo_button->set_name(solo_button_name());
385 colors.push_back (c);
386 solo_button->set_colors (colors);
388 was_solo_safe = !was_solo_safe;
391 if (solo_button->get_active() != (x = _route->soloed())){
392 ignore_toggle = true;
393 solo_button->set_active(x);
394 ignore_toggle = false;
400 RouteUI::mute_changed(void* src)
402 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
406 RouteUI::update_mute_display ()
410 if (mute_button->get_active() != (x = _route->muted())){
411 ignore_toggle = true;
412 mute_button->set_active(x);
413 ignore_toggle = false;
418 RouteUI::route_rec_enable_changed ()
420 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
424 RouteUI::session_rec_enable_changed ()
426 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
430 RouteUI::update_rec_display ()
432 bool model = _route->record_enabled();
433 bool view = rec_enable_button->get_active();
435 /* first make sure the button's "depressed" visual
440 ignore_toggle = true;
441 rec_enable_button->set_active (model);
442 ignore_toggle = false;
445 /* now make sure its color state is correct */
449 switch (_session.record_status ()) {
450 case Session::Disabled:
451 case Session::Enabled:
452 if (rec_enable_button->get_state() != Gtk::STATE_ACTIVE) {
453 rec_enable_button->set_state (Gtk::STATE_ACTIVE);
457 case Session::Recording:
458 if (rec_enable_button->get_state() != Gtk::STATE_SELECTED) {
459 rec_enable_button->set_state (Gtk::STATE_SELECTED);
465 if (rec_enable_button->get_state() != Gtk::STATE_NORMAL) {
466 rec_enable_button->set_state (Gtk::STATE_NORMAL);
472 RouteUI::build_remote_control_menu ()
474 remote_control_menu = manage (new Menu);
475 refresh_remote_control_menu ();
479 RouteUI::refresh_remote_control_menu ()
481 using namespace Menu_Helpers;
483 RadioMenuItem::Group rc_group;
484 CheckMenuItem* rc_active;
485 uint32_t limit = _session.ntracks() + _session.nbusses();
488 MenuList& rc_items = remote_control_menu->items();
491 /* note that this menu list starts at zero, not 1, because zero
492 is a valid, if useless, ID.
495 limit += 4; /* leave some breathing room */
497 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
498 if (_route->remote_control_id() == 0) {
499 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
500 rc_active->set_active ();
503 for (uint32_t i = 1; i < limit; ++i) {
504 snprintf (buf, sizeof (buf), "%u", i);
505 rc_items.push_back (RadioMenuElem (rc_group, buf));
506 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
507 if (_route->remote_control_id() == i) {
508 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
509 rc_active->set_active ();
511 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
516 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
518 /* this is called when the radio menu item is toggled, and so
519 is actually invoked twice per menu selection. we only
520 care about the invocation for the item that was being
524 if (item->get_active()) {
525 _route->set_remote_control_id (id);
530 RouteUI::build_solo_menu (void)
532 using namespace Menu_Helpers;
534 solo_menu = new Menu;
535 solo_menu->set_name ("ArdourContextMenu");
536 MenuList& items = solo_menu->items();
537 CheckMenuItem* check;
539 check = new CheckMenuItem(_("Solo-safe"));
540 check->set_active (_route->solo_safe());
541 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
542 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
543 items.push_back (CheckMenuElem(*check));
546 //items.push_back (SeparatorElem());
547 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
552 RouteUI::build_mute_menu(void)
554 using namespace Menu_Helpers;
556 mute_menu = new Menu;
557 mute_menu->set_name ("ArdourContextMenu");
558 MenuList& items = mute_menu->items();
559 CheckMenuItem* check;
561 check = new CheckMenuItem(_("Pre Fader"));
562 init_mute_menu(PRE_FADER, check);
563 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
564 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
565 items.push_back (CheckMenuElem(*check));
568 check = new CheckMenuItem(_("Post Fader"));
569 init_mute_menu(POST_FADER, check);
570 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
571 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
572 items.push_back (CheckMenuElem(*check));
575 check = new CheckMenuItem(_("Control Outs"));
576 init_mute_menu(CONTROL_OUTS, check);
577 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
578 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
579 items.push_back (CheckMenuElem(*check));
582 check = new CheckMenuItem(_("Main Outs"));
583 init_mute_menu(MAIN_OUTS, check);
584 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
585 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
586 items.push_back (CheckMenuElem(*check));
589 //items.push_back (SeparatorElem());
590 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
594 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
596 if (_route->get_mute_config (type)) {
597 check->set_active (true);
602 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
604 _route->set_mute_config(type, check->get_active(), this);
608 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
610 _route->set_solo_safe (check->get_active(), this);
614 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
616 RouteGroup* mix_group;
618 if((mix_group = route->mix_group()) != 0){
619 _session.begin_reversible_command (_("mix group solo change"));
620 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
621 mix_group->apply(&Route::set_solo, yn, this);
623 _session.add_command (cmd);
624 _session.commit_reversible_command ();
626 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
631 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
633 _session.begin_reversible_command (name);
634 XMLNode &before = _route->get_state();
635 bind(mem_fun(*_route, func), yn, arg)();
636 XMLNode &after = _route->get_state();
637 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
638 _session.commit_reversible_command ();
642 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
644 _session.begin_reversible_command (name);
645 XMLNode &before = audio_track()->get_state();
646 bind (mem_fun (*audio_track(), func), yn, arg)();
647 XMLNode &after = audio_track()->get_state();
648 _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), &before, &after));
649 _session.commit_reversible_command ();
653 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
655 RouteGroup* mix_group;
657 if((mix_group = route->mix_group()) != 0){
658 _session.begin_reversible_command (_("mix group mute change"));
659 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
660 mix_group->apply(&Route::set_mute, yn, this);
662 _session.add_command(cmd);
663 _session.commit_reversible_command ();
665 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
670 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
672 RouteGroup* mix_group;
674 if((mix_group = route->mix_group()) != 0){
675 _session.begin_reversible_command (_("mix group rec-enable change"));
676 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
677 mix_group->apply (&Route::set_record_enable, yn, this);
679 _session.add_command(cmd);
680 _session.commit_reversible_command ();
682 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
688 RouteUI::choose_color()
693 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
703 RouteUI::set_color (const Gdk::Color & c)
710 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
711 xml_node->add_property ("color", buf);
713 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
718 RouteUI::ensure_xml_node ()
721 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
722 xml_node = new XMLNode ("GUI");
723 _route->add_extra_xml (*xml_node);
729 RouteUI::get_child_xml_node (const string & childname)
736 if ((child = find_named_node (*xml_node, childname)) == 0) {
737 child = new XMLNode (childname);
738 xml_node->add_child_nocopy (*child);
745 RouteUI::set_color_from_route ()
749 RouteUI::ensure_xml_node ();
751 if ((prop = xml_node->property ("color")) != 0) {
753 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
763 RouteUI::remove_this_route ()
765 vector<string> choices;
769 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());
771 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
774 choices.push_back (_("No, do nothing."));
775 choices.push_back (_("Yes, remove it."));
777 Choice prompter (prompt, choices);
779 if (prompter.run () == 1) {
780 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
785 RouteUI::idle_remove_this_route (RouteUI *rui)
787 rui->_session.remove_route (rui->_route);
792 RouteUI::route_rename ()
794 ArdourPrompter name_prompter (true);
796 name_prompter.set_prompt (_("New Name: "));
797 name_prompter.set_initial_text (_route->name());
798 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
799 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
800 name_prompter.show_all ();
802 switch (name_prompter.run ()) {
804 case Gtk::RESPONSE_ACCEPT:
805 name_prompter.get_result (result);
806 if (result.length()) {
807 _route->set_name (result, this);
817 RouteUI::name_changed (void *src)
819 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
821 name_label.set_text (_route->name());
825 RouteUI::toggle_route_active ()
829 if (route_active_menu_item) {
830 if (route_active_menu_item->get_active() != (yn = _route->active())) {
831 _route->set_active (!yn);
837 RouteUI::route_active_changed ()
839 if (route_active_menu_item) {
840 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
845 RouteUI::toggle_polarity ()
847 if (polarity_menu_item) {
851 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
853 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
854 _route->set_phase_invert (x, this);
856 name_label.set_text (X_("Ø ") + name_label.get_text());
858 name_label.set_text (_route->name());
865 RouteUI::polarity_changed ()
867 /* no signal for this yet */
871 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
873 bool yn = _route->solo_safe ();
875 if (check->get_active() != yn) {
876 check->set_active (yn);
880 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
882 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
884 bool yn = _route->get_mute_config(PRE_FADER);
885 if (check->get_active() != yn) {
886 check->set_active (yn);
891 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
893 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
895 bool yn = _route->get_mute_config(POST_FADER);
896 if (check->get_active() != yn) {
897 check->set_active (yn);
902 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
904 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
906 bool yn = _route->get_mute_config(CONTROL_OUTS);
907 if (check->get_active() != yn) {
908 check->set_active (yn);
913 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
915 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
917 bool yn = _route->get_mute_config(MAIN_OUTS);
918 if (check->get_active() != yn) {
919 check->set_active (yn);
924 RouteUI::disconnect_input ()
926 _route->disconnect_inputs (this);
930 RouteUI::disconnect_output ()
932 _route->disconnect_outputs (this);
936 RouteUI::is_track () const
938 return dynamic_cast<Track*>(_route.get()) != 0;
942 RouteUI::track() const
944 return dynamic_cast<Track*>(_route.get());
948 RouteUI::is_audio_track () const
950 return dynamic_cast<AudioTrack*>(_route.get()) != 0;
954 RouteUI::audio_track() const
956 return dynamic_cast<AudioTrack*>(_route.get());
959 boost::shared_ptr<Diskstream>
960 RouteUI::get_diskstream () const
962 boost::shared_ptr<Track> t;
964 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
965 return t->diskstream();
967 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
972 RouteUI::name() const
974 return _route->name();
978 RouteUI::map_frozen ()
980 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
982 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
985 switch (at->freeze_state()) {
986 case AudioTrack::Frozen:
987 rec_enable_button->set_sensitive (false);
990 rec_enable_button->set_sensitive (true);