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 rec_enable_button->show();
113 update_rec_display ();
116 mute_button->unset_flags (Gtk::CAN_FOCUS);
117 solo_button->unset_flags (Gtk::CAN_FOCUS);
122 _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
124 /* map the current state */
131 GoingAway (); /* EMIT SIGNAL */
136 RouteUI::mute_press(GdkEventButton* ev)
138 if (!ignore_toggle) {
140 if (Keyboard::is_context_menu_event (ev)) {
146 mute_menu->popup(0,ev->time);
150 if (ev->button == 2) {
151 // ctrl-button2 click is the midi binding click
152 // button2-click is "momentary"
154 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
155 wait_for_release = true;
161 if (ev->button == 1 || ev->button == 2) {
163 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
165 /* ctrl-shift-click applies change to all routes */
167 _session.begin_reversible_command (_("mute change"));
168 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
169 _session.set_all_mute (!_route->muted());
171 _session.add_command(cmd);
172 _session.commit_reversible_command ();
174 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
176 /* ctrl-click applies change to the mix group.
177 ctrl-button2 is MIDI learn.
180 if (ev->button == 1) {
181 set_mix_group_mute (_route, !_route->muted());
186 /* plain click applies change to this route */
188 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
199 RouteUI::mute_release(GdkEventButton* ev)
201 if (!ignore_toggle) {
202 if (wait_for_release){
203 wait_for_release = false;
205 // because the press was the last undoable thing we did
213 RouteUI::solo_press(GdkEventButton* ev)
215 if (!ignore_toggle) {
217 if (Keyboard::is_context_menu_event (ev)) {
219 if (solo_menu == 0) {
223 solo_menu->popup (1, ev->time);
227 if (ev->button == 2) {
229 // ctrl-button2 click is the midi binding click
230 // button2-click is "momentary"
232 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
233 wait_for_release = true;
239 if (ev->button == 1 || ev->button == 2) {
241 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
243 /* ctrl-shift-click applies change to all routes */
245 _session.begin_reversible_command (_("solo change"));
246 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
247 _session.set_all_solo (!_route->soloed());
249 _session.add_command (cmd);
250 _session.commit_reversible_command ();
252 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
254 // ctrl-alt-click: exclusively solo this track, not a toggle */
256 _session.begin_reversible_command (_("solo change"));
257 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
258 _session.set_all_solo (false);
259 _route->set_solo (true, this);
261 _session.add_command(cmd);
262 _session.commit_reversible_command ();
264 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
266 // shift-click: set this route to solo safe
268 _route->set_solo_safe (!_route->solo_safe(), this);
269 wait_for_release = false;
271 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
273 /* ctrl-click: solo mix group.
274 ctrl-button2 is MIDI learn.
277 if (ev->button == 1) {
278 set_mix_group_solo (_route, !_route->soloed());
283 /* click: solo this route */
285 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
295 RouteUI::solo_release(GdkEventButton* ev)
297 if (!ignore_toggle) {
298 if (wait_for_release) {
299 wait_for_release = false;
301 // because the press was the last undoable thing we did
311 RouteUI::rec_enable_press(GdkEventButton* ev)
313 if (!_session.engine().connected()) {
314 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
319 if (!ignore_toggle && is_track() && rec_enable_button) {
321 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
323 // do nothing on midi bind event
325 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
327 _session.begin_reversible_command (_("rec-enable change"));
328 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
330 if (rec_enable_button->get_active()) {
331 _session.record_disenable_all ();
333 _session.record_enable_all ();
337 _session.add_command(cmd);
338 _session.commit_reversible_command ();
340 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
342 set_mix_group_rec_enable (_route, !_route->record_enabled());
346 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
354 RouteUI::rec_enable_release (GdkEventButton* ev)
360 RouteUI::solo_changed(void* src)
362 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
366 RouteUI::update_solo_display ()
369 vector<Gdk::Color> fg_colors;
372 if (solo_button->get_active() != (x = _route->soloed())){
373 ignore_toggle = true;
374 solo_button->set_active(x);
375 ignore_toggle = false;
378 if (_route->solo_safe()) {
379 solo_button->set_visual_state (2);
380 } else if (_route->soloed()) {
381 solo_button->set_visual_state (1);
383 solo_button->set_visual_state (0);
388 RouteUI::solo_changed_so_update_mute ()
390 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
394 RouteUI::mute_changed(void* src)
396 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
400 RouteUI::update_mute_display ()
402 bool model = _route->muted();
403 bool view = mute_button->get_active();
405 /* first make sure the button's "depressed" visual
410 ignore_toggle = true;
411 mute_button->set_active (model);
412 ignore_toggle = false;
415 /* now attend to visual state */
417 if (Config->get_show_solo_mutes()) {
418 if (_route->muted()) {
419 mute_button->set_visual_state (2);
420 } else if (!_route->soloed() && _route->solo_muted()) {
422 mute_button->set_visual_state (1);
424 mute_button->set_visual_state (0);
427 if (_route->muted()) {
428 mute_button->set_visual_state (2);
430 mute_button->set_visual_state (0);
437 RouteUI::route_rec_enable_changed ()
439 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
443 RouteUI::session_rec_enable_changed ()
445 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
449 RouteUI::update_rec_display ()
451 bool model = _route->record_enabled();
452 bool view = rec_enable_button->get_active();
454 /* first make sure the button's "depressed" visual
459 ignore_toggle = true;
460 rec_enable_button->set_active (model);
461 ignore_toggle = false;
464 /* now make sure its color state is correct */
468 switch (_session.record_status ()) {
469 case Session::Recording:
470 rec_enable_button->set_visual_state (1);
473 case Session::Disabled:
474 case Session::Enabled:
475 rec_enable_button->set_visual_state (2);
481 rec_enable_button->set_visual_state (0);
486 RouteUI::build_remote_control_menu ()
488 remote_control_menu = manage (new Menu);
489 refresh_remote_control_menu ();
493 RouteUI::refresh_remote_control_menu ()
495 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
497 // only refresh the menu if it has been instantiated
499 if (remote_control_menu == 0) {
503 using namespace Menu_Helpers;
505 RadioMenuItem::Group rc_group;
506 CheckMenuItem* rc_active;
507 uint32_t limit = _session.ntracks() + _session.nbusses();
510 MenuList& rc_items = remote_control_menu->items();
513 /* note that this menu list starts at zero, not 1, because zero
514 is a valid, if useless, ID.
517 limit += 4; /* leave some breathing room */
519 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
520 if (_route->remote_control_id() == 0) {
521 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
522 rc_active->set_active ();
525 for (uint32_t i = 1; i < limit; ++i) {
526 snprintf (buf, sizeof (buf), "%u", i);
527 rc_items.push_back (RadioMenuElem (rc_group, buf));
528 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
529 if (_route->remote_control_id() == i) {
530 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
531 rc_active->set_active ();
533 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
538 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
540 /* this is called when the radio menu item is toggled, and so
541 is actually invoked twice per menu selection. we only
542 care about the invocation for the item that was being
546 if (item->get_active()) {
547 _route->set_remote_control_id (id);
552 RouteUI::build_solo_menu (void)
554 using namespace Menu_Helpers;
556 solo_menu = new Menu;
557 solo_menu->set_name ("ArdourContextMenu");
558 MenuList& items = solo_menu->items();
559 CheckMenuItem* check;
561 check = new CheckMenuItem(_("Solo-safe"));
562 check->set_active (_route->solo_safe());
563 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
564 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
565 items.push_back (CheckMenuElem(*check));
568 //items.push_back (SeparatorElem());
569 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
574 RouteUI::build_mute_menu(void)
576 using namespace Menu_Helpers;
578 mute_menu = new Menu;
579 mute_menu->set_name ("ArdourContextMenu");
580 MenuList& items = mute_menu->items();
581 CheckMenuItem* check;
583 check = new CheckMenuItem(_("Pre Fader"));
584 init_mute_menu(PRE_FADER, check);
585 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
586 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
587 items.push_back (CheckMenuElem(*check));
590 check = new CheckMenuItem(_("Post Fader"));
591 init_mute_menu(POST_FADER, check);
592 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
593 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
594 items.push_back (CheckMenuElem(*check));
597 check = new CheckMenuItem(_("Control Outs"));
598 init_mute_menu(CONTROL_OUTS, check);
599 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
600 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
601 items.push_back (CheckMenuElem(*check));
604 check = new CheckMenuItem(_("Main Outs"));
605 init_mute_menu(MAIN_OUTS, check);
606 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
607 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
608 items.push_back (CheckMenuElem(*check));
611 //items.push_back (SeparatorElem());
612 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
616 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
618 if (_route->get_mute_config (type)) {
619 check->set_active (true);
624 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
626 _route->set_mute_config(type, check->get_active(), this);
630 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
632 _route->set_solo_safe (check->get_active(), this);
636 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
638 RouteGroup* mix_group;
640 if((mix_group = route->mix_group()) != 0){
641 _session.begin_reversible_command (_("mix group solo change"));
642 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
643 mix_group->apply(&Route::set_solo, yn, this);
645 _session.add_command (cmd);
646 _session.commit_reversible_command ();
648 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
653 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
655 _session.begin_reversible_command (name);
656 XMLNode &before = _route->get_state();
657 bind(mem_fun(*_route, func), yn, arg)();
658 XMLNode &after = _route->get_state();
659 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
660 _session.commit_reversible_command ();
664 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
666 _session.begin_reversible_command (name);
667 XMLNode &before = track()->get_state();
668 bind (mem_fun (*track(), func), yn, arg)();
669 XMLNode &after = track()->get_state();
670 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
671 _session.commit_reversible_command ();
675 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
677 RouteGroup* mix_group;
679 if((mix_group = route->mix_group()) != 0){
680 _session.begin_reversible_command (_("mix group mute change"));
681 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
682 mix_group->apply(&Route::set_mute, yn, this);
684 _session.add_command(cmd);
685 _session.commit_reversible_command ();
687 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
692 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
694 RouteGroup* mix_group;
696 if((mix_group = route->mix_group()) != 0){
697 _session.begin_reversible_command (_("mix group rec-enable change"));
698 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
699 mix_group->apply (&Route::set_record_enable, yn, this);
701 _session.add_command(cmd);
702 _session.commit_reversible_command ();
704 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
710 RouteUI::choose_color()
715 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
725 RouteUI::set_color (const Gdk::Color & c)
732 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
733 xml_node->add_property ("color", buf);
735 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
740 RouteUI::ensure_xml_node ()
743 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
744 xml_node = new XMLNode ("GUI");
745 _route->add_extra_xml (*xml_node);
751 RouteUI::get_automation_child_xml_node (Parameter param)
755 XMLNodeList kids = xml_node->children();
756 XMLNodeConstIterator iter;
758 for (iter = kids.begin(); iter != kids.end(); ++iter) {
759 if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
760 XMLProperty* type = (*iter)->property("automation-id");
761 if (type && type->value() == param.to_string())
766 // Didn't find it, make a new one
767 XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
768 child->add_property("automation-id", param.to_string());
769 xml_node->add_child_nocopy (*child);
775 RouteUI::set_color_from_route ()
779 RouteUI::ensure_xml_node ();
781 if ((prop = xml_node->property ("color")) != 0) {
783 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
793 RouteUI::remove_this_route ()
795 vector<string> choices;
799 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());
801 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
804 choices.push_back (_("No, do nothing."));
805 choices.push_back (_("Yes, remove it."));
807 Choice prompter (prompt, choices);
809 if (prompter.run () == 1) {
810 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
815 RouteUI::idle_remove_this_route (RouteUI *rui)
817 rui->_session.remove_route (rui->_route);
822 RouteUI::route_rename ()
824 ArdourPrompter name_prompter (true);
826 name_prompter.set_prompt (_("New Name: "));
827 name_prompter.set_initial_text (_route->name());
828 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
829 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
830 name_prompter.show_all ();
832 switch (name_prompter.run ()) {
834 case Gtk::RESPONSE_ACCEPT:
835 name_prompter.get_result (result);
836 if (result.length()) {
837 _route->set_name (result);
847 RouteUI::name_changed ()
849 ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
851 name_label.set_text (_route->name());
855 RouteUI::toggle_route_active ()
859 if (route_active_menu_item) {
860 if (route_active_menu_item->get_active() != (yn = _route->active())) {
861 _route->set_active (!yn);
867 RouteUI::route_active_changed ()
869 if (route_active_menu_item) {
870 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
875 RouteUI::toggle_polarity ()
877 if (polarity_menu_item) {
881 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
883 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
884 _route->set_phase_invert (x, this);
886 name_label.set_text (X_("Ø ") + name_label.get_text());
888 name_label.set_text (_route->name());
895 RouteUI::polarity_changed ()
897 /* no signal for this yet */
901 RouteUI::toggle_denormal_protection ()
903 if (denormal_menu_item) {
907 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
909 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
910 _route->set_denormal_protection (x, this);
916 RouteUI::denormal_protection_changed ()
918 /* no signal for this yet */
923 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
925 bool yn = _route->solo_safe ();
927 if (check->get_active() != yn) {
928 check->set_active (yn);
932 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
934 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
936 bool yn = _route->get_mute_config(PRE_FADER);
937 if (check->get_active() != yn) {
938 check->set_active (yn);
943 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
945 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
947 bool yn = _route->get_mute_config(POST_FADER);
948 if (check->get_active() != yn) {
949 check->set_active (yn);
954 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
956 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
958 bool yn = _route->get_mute_config(CONTROL_OUTS);
959 if (check->get_active() != yn) {
960 check->set_active (yn);
965 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
967 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
969 bool yn = _route->get_mute_config(MAIN_OUTS);
970 if (check->get_active() != yn) {
971 check->set_active (yn);
976 RouteUI::disconnect_input ()
978 _route->disconnect_inputs (this);
982 RouteUI::disconnect_output ()
984 _route->disconnect_outputs (this);
988 RouteUI::is_track () const
990 return boost::dynamic_pointer_cast<Track>(_route) != 0;
993 boost::shared_ptr<Track>
994 RouteUI::track() const
996 return boost::dynamic_pointer_cast<Track>(_route);
1000 RouteUI::is_audio_track () const
1002 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1005 boost::shared_ptr<AudioTrack>
1006 RouteUI::audio_track() const
1008 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1012 RouteUI::is_midi_track () const
1014 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1017 boost::shared_ptr<MidiTrack>
1018 RouteUI::midi_track() const
1020 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1023 boost::shared_ptr<Diskstream>
1024 RouteUI::get_diskstream () const
1026 boost::shared_ptr<Track> t;
1028 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1029 return t->diskstream();
1031 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1036 RouteUI::name() const
1038 return _route->name();
1042 RouteUI::map_frozen ()
1044 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1046 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1049 switch (at->freeze_state()) {
1050 case AudioTrack::Frozen:
1051 rec_enable_button->set_sensitive (false);
1054 rec_enable_button->set_sensitive (true);
1061 RouteUI::adjust_latency ()
1063 LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());