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 (ev->type == GDK_2BUTTON_PRESS) {
142 if (!ignore_toggle) {
144 if (Keyboard::is_context_menu_event (ev)) {
150 mute_menu->popup(0,ev->time);
154 if (ev->button == 2) {
155 // Primary-button2 click is the midi binding click
156 // button2-click is "momentary"
158 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
159 wait_for_release = true;
165 if (ev->button == 1 || ev->button == 2) {
167 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
169 /* Primary-Tertiary-click applies change to all routes */
171 _session.begin_reversible_command (_("mute change"));
172 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
173 _session.set_all_mute (!_route->muted());
175 _session.add_command(cmd);
176 _session.commit_reversible_command ();
178 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
180 /* Primary-button1 applies change to the mix group.
181 NOTE: Primary-button2 is MIDI learn.
184 if (ev->button == 1) {
185 set_mix_group_mute (_route, !_route->muted());
190 /* plain click applies change to this route */
192 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
203 RouteUI::mute_release(GdkEventButton* ev)
205 if (!ignore_toggle) {
206 if (wait_for_release){
207 wait_for_release = false;
209 // because the press was the last undoable thing we did
217 RouteUI::solo_press(GdkEventButton* ev)
219 /* ignore double clicks */
221 if (ev->type == GDK_2BUTTON_PRESS) {
225 if (!ignore_toggle) {
227 if (Keyboard::is_context_menu_event (ev)) {
229 if (solo_menu == 0) {
233 solo_menu->popup (1, ev->time);
237 if (ev->button == 2) {
239 // Primary-button2 click is the midi binding click
240 // button2-click is "momentary"
242 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
243 wait_for_release = true;
249 if (ev->button == 1 || ev->button == 2) {
251 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
253 /* Primary-Tertiary-click applies change to all routes */
255 _session.begin_reversible_command (_("solo change"));
256 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
257 _session.set_all_solo (!_route->soloed());
259 _session.add_command (cmd);
260 _session.commit_reversible_command ();
262 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
264 // Primary-Secondary-click: exclusively solo this track, not a toggle */
266 _session.begin_reversible_command (_("solo change"));
267 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
268 _session.set_all_solo (false);
269 _route->set_solo (true, this);
271 _session.add_command(cmd);
272 _session.commit_reversible_command ();
274 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
276 // shift-click: set this route to solo safe
278 _route->set_solo_safe (!_route->solo_safe(), this);
279 wait_for_release = false;
281 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
283 /* Primary-button1: solo mix group.
284 NOTE: Primary-button2 is MIDI learn.
287 if (ev->button == 1) {
288 set_mix_group_solo (_route, !_route->soloed());
293 /* click: solo this route */
294 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
304 RouteUI::solo_release(GdkEventButton* ev)
306 if (!ignore_toggle) {
307 if (wait_for_release) {
308 wait_for_release = false;
310 // because the press was the last undoable thing we did
320 RouteUI::rec_enable_press(GdkEventButton* ev)
322 if (ev->type == GDK_2BUTTON_PRESS) {
326 if (!_session.engine().connected()) {
327 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
332 if (!ignore_toggle && is_track() && rec_enable_button) {
334 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
336 // do nothing on midi bind event
339 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
341 _session.begin_reversible_command (_("rec-enable change"));
342 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
344 if (rec_enable_button->get_active()) {
345 _session.record_disenable_all ();
347 _session.record_enable_all ();
351 _session.add_command(cmd);
352 _session.commit_reversible_command ();
354 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
356 /* Primary-button1 applies change to the mix group.
357 NOTE: Primary-button2 is MIDI learn.
360 set_mix_group_rec_enable (_route, !_route->record_enabled());
364 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
372 RouteUI::rec_enable_release (GdkEventButton* ev)
378 RouteUI::solo_changed(void* src)
380 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
384 RouteUI::update_solo_display ()
387 vector<Gdk::Color> fg_colors;
390 if (solo_button->get_active() != (x = _route->soloed())){
391 ignore_toggle = true;
392 solo_button->set_active(x);
393 ignore_toggle = false;
396 if (_route->solo_safe()) {
397 solo_button->set_visual_state (2);
398 } else if (_route->soloed()) {
399 solo_button->set_visual_state (1);
401 solo_button->set_visual_state (0);
406 RouteUI::solo_changed_so_update_mute ()
408 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
412 RouteUI::mute_changed(void* src)
414 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
418 RouteUI::update_mute_display ()
420 bool model = _route->muted();
421 bool view = mute_button->get_active();
423 /* first make sure the button's "depressed" visual
428 ignore_toggle = true;
429 mute_button->set_active (model);
430 ignore_toggle = false;
433 /* now attend to visual state */
435 if (Config->get_show_solo_mutes()) {
436 if (_route->muted()) {
437 mute_button->set_visual_state (2);
438 } else if (!_route->soloed() && _route->solo_muted()) {
440 mute_button->set_visual_state (1);
442 mute_button->set_visual_state (0);
445 if (_route->muted()) {
446 mute_button->set_visual_state (2);
448 mute_button->set_visual_state (0);
455 RouteUI::route_rec_enable_changed ()
457 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
461 RouteUI::session_rec_enable_changed ()
463 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
467 RouteUI::update_rec_display ()
469 bool model = _route->record_enabled();
470 bool view = rec_enable_button->get_active();
472 /* first make sure the button's "depressed" visual
477 ignore_toggle = true;
478 rec_enable_button->set_active (model);
479 ignore_toggle = false;
482 /* now make sure its color state is correct */
486 switch (_session.record_status ()) {
487 case Session::Recording:
488 rec_enable_button->set_visual_state (1);
491 case Session::Disabled:
492 case Session::Enabled:
493 rec_enable_button->set_visual_state (2);
499 rec_enable_button->set_visual_state (0);
504 RouteUI::build_remote_control_menu ()
506 remote_control_menu = manage (new Menu);
507 refresh_remote_control_menu ();
511 RouteUI::refresh_remote_control_menu ()
513 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
515 // only refresh the menu if it has been instantiated
517 if (remote_control_menu == 0) {
521 using namespace Menu_Helpers;
523 RadioMenuItem::Group rc_group;
524 CheckMenuItem* rc_active;
525 uint32_t limit = _session.ntracks() + _session.nbusses();
528 MenuList& rc_items = remote_control_menu->items();
531 /* note that this menu list starts at zero, not 1, because zero
532 is a valid, if useless, ID.
535 limit += 4; /* leave some breathing room */
537 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
538 if (_route->remote_control_id() == 0) {
539 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
540 rc_active->set_active ();
543 for (uint32_t i = 1; i < limit; ++i) {
544 snprintf (buf, sizeof (buf), "%u", i);
545 rc_items.push_back (RadioMenuElem (rc_group, buf));
546 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
547 if (_route->remote_control_id() == i) {
548 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
549 rc_active->set_active ();
551 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
556 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
558 /* this is called when the radio menu item is toggled, and so
559 is actually invoked twice per menu selection. we only
560 care about the invocation for the item that was being
564 if (item->get_active()) {
565 _route->set_remote_control_id (id);
570 RouteUI::build_solo_menu (void)
572 using namespace Menu_Helpers;
574 solo_menu = new Menu;
575 solo_menu->set_name ("ArdourContextMenu");
576 MenuList& items = solo_menu->items();
577 CheckMenuItem* check;
579 check = new CheckMenuItem(_("Solo-safe"));
580 check->set_active (_route->solo_safe());
581 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
582 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
583 items.push_back (CheckMenuElem(*check));
586 //items.push_back (SeparatorElem());
587 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
592 RouteUI::build_mute_menu(void)
594 using namespace Menu_Helpers;
596 mute_menu = new Menu;
597 mute_menu->set_name ("ArdourContextMenu");
598 MenuList& items = mute_menu->items();
599 CheckMenuItem* check;
601 check = new CheckMenuItem(_("Pre Fader"));
602 init_mute_menu(PRE_FADER, check);
603 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
604 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
605 items.push_back (CheckMenuElem(*check));
608 check = new CheckMenuItem(_("Post Fader"));
609 init_mute_menu(POST_FADER, check);
610 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
611 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
612 items.push_back (CheckMenuElem(*check));
615 check = new CheckMenuItem(_("Control Outs"));
616 init_mute_menu(CONTROL_OUTS, check);
617 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
618 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
619 items.push_back (CheckMenuElem(*check));
622 check = new CheckMenuItem(_("Main Outs"));
623 init_mute_menu(MAIN_OUTS, check);
624 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
625 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
626 items.push_back (CheckMenuElem(*check));
629 //items.push_back (SeparatorElem());
630 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
634 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
636 if (_route->get_mute_config (type)) {
637 check->set_active (true);
642 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
644 _route->set_mute_config(type, check->get_active(), this);
648 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
650 _route->set_solo_safe (check->get_active(), this);
654 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
656 RouteGroup* mix_group;
658 if((mix_group = route->mix_group()) != 0){
659 _session.begin_reversible_command (_("mix group solo change"));
660 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
661 mix_group->apply(&Route::set_solo, yn, this);
663 _session.add_command (cmd);
664 _session.commit_reversible_command ();
666 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
671 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
673 _session.begin_reversible_command (name);
674 XMLNode &before = _route->get_state();
675 bind(mem_fun(*_route, func), yn, arg)();
676 XMLNode &after = _route->get_state();
677 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
678 _session.commit_reversible_command ();
682 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
684 _session.begin_reversible_command (name);
685 XMLNode &before = track()->get_state();
686 bind (mem_fun (*track(), func), yn, arg)();
687 XMLNode &after = track()->get_state();
688 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
689 _session.commit_reversible_command ();
693 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
695 RouteGroup* mix_group;
697 if((mix_group = route->mix_group()) != 0){
698 _session.begin_reversible_command (_("mix group mute change"));
699 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
700 mix_group->apply(&Route::set_mute, yn, this);
702 _session.add_command(cmd);
703 _session.commit_reversible_command ();
705 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
710 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
712 RouteGroup* mix_group;
714 if((mix_group = route->mix_group()) != 0){
715 _session.begin_reversible_command (_("mix group rec-enable change"));
716 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
717 mix_group->apply (&Route::set_record_enable, yn, this);
719 _session.add_command(cmd);
720 _session.commit_reversible_command ();
722 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
728 RouteUI::choose_color()
733 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
743 RouteUI::set_color (const Gdk::Color & c)
750 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
751 xml_node->add_property ("color", buf);
753 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
758 RouteUI::ensure_xml_node ()
761 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
762 xml_node = new XMLNode ("GUI");
763 _route->add_extra_xml (*xml_node);
769 RouteUI::get_automation_child_xml_node (Parameter param)
773 XMLNodeList kids = xml_node->children();
774 XMLNodeConstIterator iter;
776 for (iter = kids.begin(); iter != kids.end(); ++iter) {
777 if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
778 XMLProperty* type = (*iter)->property("automation-id");
779 if (type && type->value() == param.to_string())
784 // Didn't find it, make a new one
785 XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
786 child->add_property("automation-id", param.to_string());
787 xml_node->add_child_nocopy (*child);
793 RouteUI::set_color_from_route ()
797 RouteUI::ensure_xml_node ();
799 if ((prop = xml_node->property ("color")) != 0) {
801 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
811 RouteUI::remove_this_route ()
813 vector<string> choices;
817 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());
819 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
822 choices.push_back (_("No, do nothing."));
823 choices.push_back (_("Yes, remove it."));
825 Choice prompter (prompt, choices);
827 if (prompter.run () == 1) {
828 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
833 RouteUI::idle_remove_this_route (RouteUI *rui)
835 rui->_session.remove_route (rui->_route);
840 RouteUI::route_rename ()
842 ArdourPrompter name_prompter (true);
844 name_prompter.set_prompt (_("New Name: "));
845 name_prompter.set_initial_text (_route->name());
846 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
847 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
848 name_prompter.show_all ();
850 switch (name_prompter.run ()) {
852 case Gtk::RESPONSE_ACCEPT:
853 name_prompter.get_result (result);
854 if (result.length()) {
855 _route->set_name (result);
865 RouteUI::name_changed ()
867 ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
869 name_label.set_text (_route->name());
873 RouteUI::toggle_route_active ()
877 if (route_active_menu_item) {
878 if (route_active_menu_item->get_active() != (yn = _route->active())) {
879 _route->set_active (!yn);
885 RouteUI::route_active_changed ()
887 if (route_active_menu_item) {
888 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
893 RouteUI::toggle_polarity ()
895 if (polarity_menu_item) {
899 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
901 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
902 _route->set_phase_invert (x, this);
904 name_label.set_text (X_("Ø ") + name_label.get_text());
906 name_label.set_text (_route->name());
913 RouteUI::polarity_changed ()
915 /* no signal for this yet */
919 RouteUI::toggle_denormal_protection ()
921 if (denormal_menu_item) {
925 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
927 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
928 _route->set_denormal_protection (x, this);
934 RouteUI::denormal_protection_changed ()
936 /* no signal for this yet */
941 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
943 bool yn = _route->solo_safe ();
945 if (check->get_active() != yn) {
946 check->set_active (yn);
950 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
952 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
954 bool yn = _route->get_mute_config(PRE_FADER);
955 if (check->get_active() != yn) {
956 check->set_active (yn);
961 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
963 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
965 bool yn = _route->get_mute_config(POST_FADER);
966 if (check->get_active() != yn) {
967 check->set_active (yn);
972 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
974 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
976 bool yn = _route->get_mute_config(CONTROL_OUTS);
977 if (check->get_active() != yn) {
978 check->set_active (yn);
983 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
985 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
987 bool yn = _route->get_mute_config(MAIN_OUTS);
988 if (check->get_active() != yn) {
989 check->set_active (yn);
994 RouteUI::disconnect_input ()
996 _route->disconnect_inputs (this);
1000 RouteUI::disconnect_output ()
1002 _route->disconnect_outputs (this);
1006 RouteUI::is_track () const
1008 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1011 boost::shared_ptr<Track>
1012 RouteUI::track() const
1014 return boost::dynamic_pointer_cast<Track>(_route);
1018 RouteUI::is_audio_track () const
1020 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1023 boost::shared_ptr<AudioTrack>
1024 RouteUI::audio_track() const
1026 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1030 RouteUI::is_midi_track () const
1032 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1035 boost::shared_ptr<MidiTrack>
1036 RouteUI::midi_track() const
1038 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1041 boost::shared_ptr<Diskstream>
1042 RouteUI::get_diskstream () const
1044 boost::shared_ptr<Track> t;
1046 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1047 return t->diskstream();
1049 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1054 RouteUI::name() const
1056 return _route->name();
1060 RouteUI::map_frozen ()
1062 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1064 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1067 switch (at->freeze_state()) {
1068 case AudioTrack::Frozen:
1069 rec_enable_button->set_sensitive (false);
1072 rec_enable_button->set_sensitive (true);
1079 RouteUI::adjust_latency ()
1081 LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());