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>
25 #include <gtkmm2ext/barcontroller.h>
27 #include <ardour/route_group.h>
28 #include <pbd/memento_command.h>
29 #include <pbd/stacktrace.h>
30 #include <pbd/shiva.h>
31 #include <pbd/controllable.h>
37 #include "gui_thread.h"
38 #include "ardour_dialog.h"
39 #include "latency_gui.h"
40 #include "automation_time_axis.h"
42 #include <ardour/route.h>
43 #include <ardour/session.h>
44 #include <ardour/audioengine.h>
45 #include <ardour/audio_track.h>
46 #include <ardour/audio_diskstream.h>
47 #include <ardour/midi_track.h>
48 #include <ardour/midi_diskstream.h>
53 using namespace Gtkmm2ext;
54 using namespace ARDOUR;
57 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
58 const char* s_name, const char* r_name)
68 remote_control_menu = 0;
69 ignore_toggle = false;
70 wait_for_release = false;
71 route_active_menu_item = 0;
72 was_solo_safe = false;
73 polarity_menu_item = 0;
74 denormal_menu_item = 0;
76 if (set_color_from_route()) {
77 set_color (unique_random_color());
80 new PairedShiva<Route,RouteUI> (*_route, *this);
82 _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
84 mute_button = manage (new BindableToggleButton (*_route->mute_control().get(), m_name ));
85 mute_button->set_self_managed (true);
87 solo_button = manage (new BindableToggleButton (*_route->solo_control().get(), s_name ));
88 solo_button->set_self_managed (true);
90 mute_button->set_name ("MuteButton");
91 solo_button->set_name ("SoloButton");
93 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
94 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
95 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
97 /* when solo changes, update mute state too, in case the user wants us to display it */
99 _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
102 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
104 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
106 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
108 rec_enable_button = manage (new BindableToggleButton (*t->rec_enable_control().get(), r_name ));
109 rec_enable_button->set_name ("RecordEnableButton");
110 rec_enable_button->set_self_managed (true);
112 update_rec_display ();
115 mute_button->unset_flags (Gtk::CAN_FOCUS);
116 solo_button->unset_flags (Gtk::CAN_FOCUS);
118 _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
120 /* map the current state */
127 GoingAway (); /* EMIT SIGNAL */
132 RouteUI::mute_press(GdkEventButton* ev)
134 if (!ignore_toggle) {
136 if (Keyboard::is_context_menu_event (ev)) {
142 mute_menu->popup(0,ev->time);
146 if (ev->button == 2) {
147 // ctrl-button2 click is the midi binding click
148 // button2-click is "momentary"
150 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
151 wait_for_release = true;
157 if (ev->button == 1 || ev->button == 2) {
159 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
161 /* ctrl-shift-click applies change to all routes */
163 _session.begin_reversible_command (_("mute change"));
164 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
165 _session.set_all_mute (!_route->muted());
167 _session.add_command(cmd);
168 _session.commit_reversible_command ();
170 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
172 /* ctrl-click applies change to the mix group.
173 ctrl-button2 is MIDI learn.
176 if (ev->button == 1) {
177 set_mix_group_mute (_route, !_route->muted());
182 /* plain click applies change to this route */
184 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
195 RouteUI::mute_release(GdkEventButton* ev)
197 if (!ignore_toggle) {
198 if (wait_for_release){
199 wait_for_release = false;
201 // because the press was the last undoable thing we did
209 RouteUI::solo_press(GdkEventButton* ev)
211 if (!ignore_toggle) {
213 if (Keyboard::is_context_menu_event (ev)) {
215 if (solo_menu == 0) {
219 solo_menu->popup (1, ev->time);
223 if (ev->button == 2) {
225 // ctrl-button2 click is the midi binding click
226 // button2-click is "momentary"
228 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
229 wait_for_release = true;
235 if (ev->button == 1 || ev->button == 2) {
237 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
239 /* ctrl-shift-click applies change to all routes */
241 _session.begin_reversible_command (_("solo change"));
242 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
243 _session.set_all_solo (!_route->soloed());
245 _session.add_command (cmd);
246 _session.commit_reversible_command ();
248 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
250 // ctrl-alt-click: exclusively solo this track, not a toggle */
252 _session.begin_reversible_command (_("solo change"));
253 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
254 _session.set_all_solo (false);
255 _route->set_solo (true, this);
257 _session.add_command(cmd);
258 _session.commit_reversible_command ();
260 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
262 // shift-click: set this route to solo safe
264 _route->set_solo_safe (!_route->solo_safe(), this);
265 wait_for_release = false;
267 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
269 /* ctrl-click: solo mix group.
270 ctrl-button2 is MIDI learn.
273 if (ev->button == 1) {
274 set_mix_group_solo (_route, !_route->soloed());
279 /* click: solo this route */
281 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
291 RouteUI::solo_release(GdkEventButton* ev)
293 if (!ignore_toggle) {
294 if (wait_for_release) {
295 wait_for_release = false;
297 // because the press was the last undoable thing we did
307 RouteUI::rec_enable_press(GdkEventButton* ev)
309 if (!_session.engine().connected()) {
310 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
315 if (!ignore_toggle && is_track() && rec_enable_button) {
317 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
319 // do nothing on midi bind event
321 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
323 _session.begin_reversible_command (_("rec-enable change"));
324 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
326 if (rec_enable_button->get_active()) {
327 _session.record_disenable_all ();
329 _session.record_enable_all ();
333 _session.add_command(cmd);
334 _session.commit_reversible_command ();
336 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
338 set_mix_group_rec_enable (_route, !_route->record_enabled());
342 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
350 RouteUI::rec_enable_release (GdkEventButton* ev)
356 RouteUI::solo_changed(void* src)
358 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
362 RouteUI::update_solo_display ()
365 vector<Gdk::Color> fg_colors;
368 if (solo_button->get_active() != (x = _route->soloed())){
369 ignore_toggle = true;
370 solo_button->set_active(x);
371 ignore_toggle = false;
374 if (_route->solo_safe()) {
375 solo_button->set_visual_state (2);
376 } else if (_route->soloed()) {
377 solo_button->set_visual_state (1);
379 solo_button->set_visual_state (0);
384 RouteUI::solo_changed_so_update_mute ()
386 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
390 RouteUI::mute_changed(void* src)
392 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
396 RouteUI::update_mute_display ()
398 bool model = _route->muted();
399 bool view = mute_button->get_active();
401 /* first make sure the button's "depressed" visual
406 ignore_toggle = true;
407 mute_button->set_active (model);
408 ignore_toggle = false;
411 /* now attend to visual state */
413 if (Config->get_show_solo_mutes()) {
414 if (_route->muted()) {
415 mute_button->set_visual_state (2);
416 } else if (!_route->soloed() && _route->solo_muted()) {
418 mute_button->set_visual_state (1);
420 mute_button->set_visual_state (0);
423 if (_route->muted()) {
424 mute_button->set_visual_state (2);
426 mute_button->set_visual_state (0);
433 RouteUI::route_rec_enable_changed ()
435 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
439 RouteUI::session_rec_enable_changed ()
441 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
445 RouteUI::update_rec_display ()
447 bool model = _route->record_enabled();
448 bool view = rec_enable_button->get_active();
450 /* first make sure the button's "depressed" visual
455 ignore_toggle = true;
456 rec_enable_button->set_active (model);
457 ignore_toggle = false;
460 /* now make sure its color state is correct */
464 switch (_session.record_status ()) {
465 case Session::Recording:
466 rec_enable_button->set_visual_state (1);
469 case Session::Disabled:
470 case Session::Enabled:
471 rec_enable_button->set_visual_state (2);
477 rec_enable_button->set_visual_state (0);
482 RouteUI::build_remote_control_menu ()
484 remote_control_menu = manage (new Menu);
485 refresh_remote_control_menu ();
489 RouteUI::refresh_remote_control_menu ()
491 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
493 // only refresh the menu if it has been instantiated
495 if (remote_control_menu == 0) {
499 using namespace Menu_Helpers;
501 RadioMenuItem::Group rc_group;
502 CheckMenuItem* rc_active;
503 uint32_t limit = _session.ntracks() + _session.nbusses();
506 MenuList& rc_items = remote_control_menu->items();
509 /* note that this menu list starts at zero, not 1, because zero
510 is a valid, if useless, ID.
513 limit += 4; /* leave some breathing room */
515 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
516 if (_route->remote_control_id() == 0) {
517 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
518 rc_active->set_active ();
521 for (uint32_t i = 1; i < limit; ++i) {
522 snprintf (buf, sizeof (buf), "%u", i);
523 rc_items.push_back (RadioMenuElem (rc_group, buf));
524 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
525 if (_route->remote_control_id() == i) {
526 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
527 rc_active->set_active ();
529 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
534 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
536 /* this is called when the radio menu item is toggled, and so
537 is actually invoked twice per menu selection. we only
538 care about the invocation for the item that was being
542 if (item->get_active()) {
543 _route->set_remote_control_id (id);
548 RouteUI::build_solo_menu (void)
550 using namespace Menu_Helpers;
552 solo_menu = new Menu;
553 solo_menu->set_name ("ArdourContextMenu");
554 MenuList& items = solo_menu->items();
555 CheckMenuItem* check;
557 check = new CheckMenuItem(_("Solo-safe"));
558 check->set_active (_route->solo_safe());
559 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
560 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
561 items.push_back (CheckMenuElem(*check));
564 //items.push_back (SeparatorElem());
565 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
570 RouteUI::build_mute_menu(void)
572 using namespace Menu_Helpers;
574 mute_menu = new Menu;
575 mute_menu->set_name ("ArdourContextMenu");
576 MenuList& items = mute_menu->items();
577 CheckMenuItem* check;
579 check = new CheckMenuItem(_("Pre Fader"));
580 init_mute_menu(PRE_FADER, check);
581 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
582 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
583 items.push_back (CheckMenuElem(*check));
586 check = new CheckMenuItem(_("Post Fader"));
587 init_mute_menu(POST_FADER, check);
588 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
589 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
590 items.push_back (CheckMenuElem(*check));
593 check = new CheckMenuItem(_("Control Outs"));
594 init_mute_menu(CONTROL_OUTS, check);
595 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
596 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
597 items.push_back (CheckMenuElem(*check));
600 check = new CheckMenuItem(_("Main Outs"));
601 init_mute_menu(MAIN_OUTS, check);
602 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
603 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
604 items.push_back (CheckMenuElem(*check));
607 //items.push_back (SeparatorElem());
608 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
612 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
614 if (_route->get_mute_config (type)) {
615 check->set_active (true);
620 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
622 _route->set_mute_config(type, check->get_active(), this);
626 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
628 _route->set_solo_safe (check->get_active(), this);
632 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
634 RouteGroup* mix_group;
636 if((mix_group = route->mix_group()) != 0){
637 _session.begin_reversible_command (_("mix group solo change"));
638 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
639 mix_group->apply(&Route::set_solo, yn, this);
641 _session.add_command (cmd);
642 _session.commit_reversible_command ();
644 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
649 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
651 _session.begin_reversible_command (name);
652 XMLNode &before = _route->get_state();
653 bind(mem_fun(*_route, func), yn, arg)();
654 XMLNode &after = _route->get_state();
655 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
656 _session.commit_reversible_command ();
660 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
662 _session.begin_reversible_command (name);
663 XMLNode &before = track()->get_state();
664 bind (mem_fun (*track(), func), yn, arg)();
665 XMLNode &after = track()->get_state();
666 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
667 _session.commit_reversible_command ();
671 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
673 RouteGroup* mix_group;
675 if((mix_group = route->mix_group()) != 0){
676 _session.begin_reversible_command (_("mix group mute change"));
677 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
678 mix_group->apply(&Route::set_mute, yn, this);
680 _session.add_command(cmd);
681 _session.commit_reversible_command ();
683 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
688 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
690 RouteGroup* mix_group;
692 if((mix_group = route->mix_group()) != 0){
693 _session.begin_reversible_command (_("mix group rec-enable change"));
694 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
695 mix_group->apply (&Route::set_record_enable, yn, this);
697 _session.add_command(cmd);
698 _session.commit_reversible_command ();
700 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
706 RouteUI::choose_color()
711 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
721 RouteUI::set_color (const Gdk::Color & c)
728 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
729 xml_node->add_property ("color", buf);
731 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
736 RouteUI::ensure_xml_node ()
739 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
740 xml_node = new XMLNode ("GUI");
741 _route->add_extra_xml (*xml_node);
747 RouteUI::get_automation_child_xml_node (Parameter param)
751 XMLNodeList kids = xml_node->children();
752 XMLNodeConstIterator iter;
754 for (iter = kids.begin(); iter != kids.end(); ++iter) {
755 if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
756 XMLProperty* type = (*iter)->property("automation-id");
757 if (type && type->value() == param.to_string())
762 // Didn't find it, make a new one
763 XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
764 child->add_property("automation-id", param.to_string());
765 xml_node->add_child_nocopy (*child);
771 RouteUI::set_color_from_route ()
775 RouteUI::ensure_xml_node ();
777 if ((prop = xml_node->property ("color")) != 0) {
779 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
789 RouteUI::remove_this_route ()
791 vector<string> choices;
795 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());
797 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
800 choices.push_back (_("No, do nothing."));
801 choices.push_back (_("Yes, remove it."));
803 Choice prompter (prompt, choices);
805 if (prompter.run () == 1) {
806 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
811 RouteUI::idle_remove_this_route (RouteUI *rui)
813 rui->_session.remove_route (rui->_route);
818 RouteUI::route_rename ()
820 ArdourPrompter name_prompter (true);
822 name_prompter.set_prompt (_("New Name: "));
823 name_prompter.set_initial_text (_route->name());
824 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
825 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
826 name_prompter.show_all ();
828 switch (name_prompter.run ()) {
830 case Gtk::RESPONSE_ACCEPT:
831 name_prompter.get_result (result);
832 if (result.length()) {
833 _route->set_name (result);
843 RouteUI::name_changed ()
845 ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
847 name_label.set_text (_route->name());
851 RouteUI::toggle_route_active ()
855 if (route_active_menu_item) {
856 if (route_active_menu_item->get_active() != (yn = _route->active())) {
857 _route->set_active (!yn);
863 RouteUI::route_active_changed ()
865 if (route_active_menu_item) {
866 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
871 RouteUI::toggle_polarity ()
873 if (polarity_menu_item) {
877 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
879 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
880 _route->set_phase_invert (x, this);
882 name_label.set_text (X_("Ø ") + name_label.get_text());
884 name_label.set_text (_route->name());
891 RouteUI::polarity_changed ()
893 /* no signal for this yet */
897 RouteUI::toggle_denormal_protection ()
899 if (denormal_menu_item) {
903 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
905 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
906 _route->set_denormal_protection (x, this);
912 RouteUI::denormal_protection_changed ()
914 /* no signal for this yet */
919 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
921 bool yn = _route->solo_safe ();
923 if (check->get_active() != yn) {
924 check->set_active (yn);
928 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
930 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
932 bool yn = _route->get_mute_config(PRE_FADER);
933 if (check->get_active() != yn) {
934 check->set_active (yn);
939 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
941 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
943 bool yn = _route->get_mute_config(POST_FADER);
944 if (check->get_active() != yn) {
945 check->set_active (yn);
950 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
952 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
954 bool yn = _route->get_mute_config(CONTROL_OUTS);
955 if (check->get_active() != yn) {
956 check->set_active (yn);
961 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
963 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
965 bool yn = _route->get_mute_config(MAIN_OUTS);
966 if (check->get_active() != yn) {
967 check->set_active (yn);
972 RouteUI::disconnect_input ()
974 _route->disconnect_inputs (this);
978 RouteUI::disconnect_output ()
980 _route->disconnect_outputs (this);
984 RouteUI::is_track () const
986 return boost::dynamic_pointer_cast<Track>(_route) != 0;
989 boost::shared_ptr<Track>
990 RouteUI::track() const
992 return boost::dynamic_pointer_cast<Track>(_route);
996 RouteUI::is_audio_track () const
998 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1001 boost::shared_ptr<AudioTrack>
1002 RouteUI::audio_track() const
1004 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1008 RouteUI::is_midi_track () const
1010 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1013 boost::shared_ptr<MidiTrack>
1014 RouteUI::midi_track() const
1016 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1019 boost::shared_ptr<Diskstream>
1020 RouteUI::get_diskstream () const
1022 boost::shared_ptr<Track> t;
1024 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1025 return t->diskstream();
1027 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1032 RouteUI::name() const
1034 return _route->name();
1038 RouteUI::map_frozen ()
1040 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1042 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1045 switch (at->freeze_state()) {
1046 case AudioTrack::Frozen:
1047 rec_enable_button->set_sensitive (false);
1050 rec_enable_button->set_sensitive (true);
1057 RouteUI::adjust_latency ()
1059 LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());