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"
41 #include <ardour/route.h>
42 #include <ardour/session.h>
43 #include <ardour/audioengine.h>
44 #include <ardour/audio_track.h>
45 #include <ardour/audio_diskstream.h>
46 #include <ardour/midi_track.h>
47 #include <ardour/midi_diskstream.h>
52 using namespace Gtkmm2ext;
53 using namespace ARDOUR;
56 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
57 const char* s_name, const char* r_name)
67 remote_control_menu = 0;
68 ignore_toggle = false;
69 wait_for_release = false;
70 route_active_menu_item = 0;
71 was_solo_safe = false;
72 polarity_menu_item = 0;
73 denormal_menu_item = 0;
75 if (set_color_from_route()) {
76 set_color (unique_random_color());
79 new PairedShiva<Route,RouteUI> (*_route, *this);
81 _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
83 mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
84 mute_button->set_self_managed (true);
86 solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
87 solo_button->set_self_managed (true);
89 mute_button->set_name ("MuteButton");
90 solo_button->set_name ("SoloButton");
92 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
93 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
94 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
96 /* when solo changes, update mute state too, in case the user wants us to display it */
98 _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
101 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
103 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
105 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
107 rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
108 rec_enable_button->set_name ("RecordEnableButton");
109 rec_enable_button->set_self_managed (true);
111 update_rec_display ();
114 mute_button->unset_flags (Gtk::CAN_FOCUS);
115 solo_button->unset_flags (Gtk::CAN_FOCUS);
117 _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
119 /* map the current state */
126 GoingAway (); /* EMIT SIGNAL */
131 RouteUI::mute_press(GdkEventButton* ev)
133 if (!ignore_toggle) {
135 if (Keyboard::is_context_menu_event (ev)) {
141 mute_menu->popup(0,ev->time);
145 if (ev->button == 2) {
146 // ctrl-button2 click is the midi binding click
147 // button2-click is "momentary"
149 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
150 wait_for_release = true;
156 if (ev->button == 1 || ev->button == 2) {
158 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
160 /* ctrl-shift-click applies change to all routes */
162 _session.begin_reversible_command (_("mute change"));
163 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
164 _session.set_all_mute (!_route->muted());
166 _session.add_command(cmd);
167 _session.commit_reversible_command ();
169 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
171 /* ctrl-click applies change to the mix group.
172 ctrl-button2 is MIDI learn.
175 if (ev->button == 1) {
176 set_mix_group_mute (_route, !_route->muted());
181 /* plain click applies change to this route */
183 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
194 RouteUI::mute_release(GdkEventButton* ev)
196 if (!ignore_toggle) {
197 if (wait_for_release){
198 wait_for_release = false;
200 // because the press was the last undoable thing we did
208 RouteUI::solo_press(GdkEventButton* ev)
210 if (!ignore_toggle) {
212 if (Keyboard::is_context_menu_event (ev)) {
214 if (solo_menu == 0) {
218 solo_menu->popup (1, ev->time);
222 if (ev->button == 2) {
224 // ctrl-button2 click is the midi binding click
225 // button2-click is "momentary"
227 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
228 wait_for_release = true;
234 if (ev->button == 1 || ev->button == 2) {
236 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
238 /* ctrl-shift-click applies change to all routes */
240 _session.begin_reversible_command (_("solo change"));
241 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
242 _session.set_all_solo (!_route->soloed());
244 _session.add_command (cmd);
245 _session.commit_reversible_command ();
247 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
249 // ctrl-alt-click: exclusively solo this track, not a toggle */
251 _session.begin_reversible_command (_("solo change"));
252 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
253 _session.set_all_solo (false);
254 _route->set_solo (true, this);
256 _session.add_command(cmd);
257 _session.commit_reversible_command ();
259 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
261 // shift-click: set this route to solo safe
263 _route->set_solo_safe (!_route->solo_safe(), this);
264 wait_for_release = false;
266 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
268 /* ctrl-click: solo mix group.
269 ctrl-button2 is MIDI learn.
272 if (ev->button == 1) {
273 set_mix_group_solo (_route, !_route->soloed());
278 /* click: solo this route */
280 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
290 RouteUI::solo_release(GdkEventButton* ev)
292 if (!ignore_toggle) {
293 if (wait_for_release) {
294 wait_for_release = false;
296 // because the press was the last undoable thing we did
306 RouteUI::rec_enable_press(GdkEventButton* ev)
308 if (!_session.engine().connected()) {
309 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
314 if (!ignore_toggle && is_track() && rec_enable_button) {
316 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
318 // do nothing on midi bind event
320 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
322 _session.begin_reversible_command (_("rec-enable change"));
323 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
325 if (rec_enable_button->get_active()) {
326 _session.record_disenable_all ();
328 _session.record_enable_all ();
332 _session.add_command(cmd);
333 _session.commit_reversible_command ();
335 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
337 set_mix_group_rec_enable (_route, !_route->record_enabled());
341 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
349 RouteUI::rec_enable_release (GdkEventButton* ev)
355 RouteUI::solo_changed(void* src)
357 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
361 RouteUI::update_solo_display ()
364 vector<Gdk::Color> fg_colors;
367 if (solo_button->get_active() != (x = _route->soloed())){
368 ignore_toggle = true;
369 solo_button->set_active(x);
370 ignore_toggle = false;
373 if (_route->solo_safe()) {
374 solo_button->set_visual_state (2);
375 } else if (_route->soloed()) {
376 solo_button->set_visual_state (1);
378 solo_button->set_visual_state (0);
383 RouteUI::solo_changed_so_update_mute ()
385 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
389 RouteUI::mute_changed(void* src)
391 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
395 RouteUI::update_mute_display ()
397 bool model = _route->muted();
398 bool view = mute_button->get_active();
400 /* first make sure the button's "depressed" visual
405 ignore_toggle = true;
406 mute_button->set_active (model);
407 ignore_toggle = false;
410 /* now attend to visual state */
412 if (Config->get_show_solo_mutes()) {
413 if (_route->muted()) {
414 mute_button->set_visual_state (2);
415 } else if (!_route->soloed() && _route->solo_muted()) {
417 mute_button->set_visual_state (1);
419 mute_button->set_visual_state (0);
422 if (_route->muted()) {
423 mute_button->set_visual_state (2);
425 mute_button->set_visual_state (0);
432 RouteUI::route_rec_enable_changed ()
434 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
438 RouteUI::session_rec_enable_changed ()
440 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
444 RouteUI::update_rec_display ()
446 bool model = _route->record_enabled();
447 bool view = rec_enable_button->get_active();
449 /* first make sure the button's "depressed" visual
454 ignore_toggle = true;
455 rec_enable_button->set_active (model);
456 ignore_toggle = false;
459 /* now make sure its color state is correct */
463 switch (_session.record_status ()) {
464 case Session::Recording:
465 rec_enable_button->set_visual_state (1);
468 case Session::Disabled:
469 case Session::Enabled:
470 rec_enable_button->set_visual_state (2);
476 rec_enable_button->set_visual_state (0);
481 RouteUI::build_remote_control_menu ()
483 remote_control_menu = manage (new Menu);
484 refresh_remote_control_menu ();
488 RouteUI::refresh_remote_control_menu ()
490 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
492 // only refresh the menu if it has been instantiated
494 if (remote_control_menu == 0) {
498 using namespace Menu_Helpers;
500 RadioMenuItem::Group rc_group;
501 CheckMenuItem* rc_active;
502 uint32_t limit = _session.ntracks() + _session.nbusses();
505 MenuList& rc_items = remote_control_menu->items();
508 /* note that this menu list starts at zero, not 1, because zero
509 is a valid, if useless, ID.
512 limit += 4; /* leave some breathing room */
514 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
515 if (_route->remote_control_id() == 0) {
516 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
517 rc_active->set_active ();
520 for (uint32_t i = 1; i < limit; ++i) {
521 snprintf (buf, sizeof (buf), "%u", i);
522 rc_items.push_back (RadioMenuElem (rc_group, buf));
523 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
524 if (_route->remote_control_id() == i) {
525 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
526 rc_active->set_active ();
528 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
533 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
535 /* this is called when the radio menu item is toggled, and so
536 is actually invoked twice per menu selection. we only
537 care about the invocation for the item that was being
541 if (item->get_active()) {
542 _route->set_remote_control_id (id);
547 RouteUI::build_solo_menu (void)
549 using namespace Menu_Helpers;
551 solo_menu = new Menu;
552 solo_menu->set_name ("ArdourContextMenu");
553 MenuList& items = solo_menu->items();
554 CheckMenuItem* check;
556 check = new CheckMenuItem(_("Solo-safe"));
557 check->set_active (_route->solo_safe());
558 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
559 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
560 items.push_back (CheckMenuElem(*check));
563 //items.push_back (SeparatorElem());
564 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
569 RouteUI::build_mute_menu(void)
571 using namespace Menu_Helpers;
573 mute_menu = new Menu;
574 mute_menu->set_name ("ArdourContextMenu");
575 MenuList& items = mute_menu->items();
576 CheckMenuItem* check;
578 check = new CheckMenuItem(_("Pre Fader"));
579 init_mute_menu(PRE_FADER, check);
580 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
581 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
582 items.push_back (CheckMenuElem(*check));
585 check = new CheckMenuItem(_("Post Fader"));
586 init_mute_menu(POST_FADER, check);
587 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
588 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
589 items.push_back (CheckMenuElem(*check));
592 check = new CheckMenuItem(_("Control Outs"));
593 init_mute_menu(CONTROL_OUTS, check);
594 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
595 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
596 items.push_back (CheckMenuElem(*check));
599 check = new CheckMenuItem(_("Main Outs"));
600 init_mute_menu(MAIN_OUTS, check);
601 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
602 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
603 items.push_back (CheckMenuElem(*check));
606 //items.push_back (SeparatorElem());
607 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
611 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
613 if (_route->get_mute_config (type)) {
614 check->set_active (true);
619 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
621 _route->set_mute_config(type, check->get_active(), this);
625 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
627 _route->set_solo_safe (check->get_active(), this);
631 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
633 RouteGroup* mix_group;
635 if((mix_group = route->mix_group()) != 0){
636 _session.begin_reversible_command (_("mix group solo change"));
637 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
638 mix_group->apply(&Route::set_solo, yn, this);
640 _session.add_command (cmd);
641 _session.commit_reversible_command ();
643 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
648 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
650 _session.begin_reversible_command (name);
651 XMLNode &before = _route->get_state();
652 bind(mem_fun(*_route, func), yn, arg)();
653 XMLNode &after = _route->get_state();
654 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
655 _session.commit_reversible_command ();
659 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
661 _session.begin_reversible_command (name);
662 XMLNode &before = track()->get_state();
663 bind (mem_fun (*track(), func), yn, arg)();
664 XMLNode &after = track()->get_state();
665 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
666 _session.commit_reversible_command ();
670 RouteUI::set_mix_group_mute(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 mute change"));
676 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
677 mix_group->apply(&Route::set_mute, yn, this);
679 _session.add_command(cmd);
680 _session.commit_reversible_command ();
682 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
687 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
689 RouteGroup* mix_group;
691 if((mix_group = route->mix_group()) != 0){
692 _session.begin_reversible_command (_("mix group rec-enable change"));
693 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
694 mix_group->apply (&Route::set_record_enable, yn, this);
696 _session.add_command(cmd);
697 _session.commit_reversible_command ();
699 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
705 RouteUI::choose_color()
710 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
720 RouteUI::set_color (const Gdk::Color & c)
727 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
728 xml_node->add_property ("color", buf);
730 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
735 RouteUI::ensure_xml_node ()
738 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
739 xml_node = new XMLNode ("GUI");
740 _route->add_extra_xml (*xml_node);
746 RouteUI::get_child_xml_node (const string & childname)
753 if ((child = find_named_node (*xml_node, childname)) == 0) {
754 child = new XMLNode (childname);
755 xml_node->add_child_nocopy (*child);
762 RouteUI::set_color_from_route ()
766 RouteUI::ensure_xml_node ();
768 if ((prop = xml_node->property ("color")) != 0) {
770 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
780 RouteUI::remove_this_route ()
782 vector<string> choices;
786 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());
788 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
791 choices.push_back (_("No, do nothing."));
792 choices.push_back (_("Yes, remove it."));
794 Choice prompter (prompt, choices);
796 if (prompter.run () == 1) {
797 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
802 RouteUI::idle_remove_this_route (RouteUI *rui)
804 rui->_session.remove_route (rui->_route);
809 RouteUI::route_rename ()
811 ArdourPrompter name_prompter (true);
813 name_prompter.set_prompt (_("New Name: "));
814 name_prompter.set_initial_text (_route->name());
815 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
816 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
817 name_prompter.show_all ();
819 switch (name_prompter.run ()) {
821 case Gtk::RESPONSE_ACCEPT:
822 name_prompter.get_result (result);
823 if (result.length()) {
824 _route->set_name (result);
834 RouteUI::name_changed ()
836 ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
838 name_label.set_text (_route->name());
842 RouteUI::toggle_route_active ()
846 if (route_active_menu_item) {
847 if (route_active_menu_item->get_active() != (yn = _route->active())) {
848 _route->set_active (!yn);
854 RouteUI::route_active_changed ()
856 if (route_active_menu_item) {
857 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
862 RouteUI::toggle_polarity ()
864 if (polarity_menu_item) {
868 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
870 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
871 _route->set_phase_invert (x, this);
873 name_label.set_text (X_("Ø ") + name_label.get_text());
875 name_label.set_text (_route->name());
882 RouteUI::polarity_changed ()
884 /* no signal for this yet */
888 RouteUI::toggle_denormal_protection ()
890 if (denormal_menu_item) {
894 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
896 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
897 _route->set_denormal_protection (x, this);
903 RouteUI::denormal_protection_changed ()
905 /* no signal for this yet */
910 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
912 bool yn = _route->solo_safe ();
914 if (check->get_active() != yn) {
915 check->set_active (yn);
919 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
921 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
923 bool yn = _route->get_mute_config(PRE_FADER);
924 if (check->get_active() != yn) {
925 check->set_active (yn);
930 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
932 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
934 bool yn = _route->get_mute_config(POST_FADER);
935 if (check->get_active() != yn) {
936 check->set_active (yn);
941 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
943 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
945 bool yn = _route->get_mute_config(CONTROL_OUTS);
946 if (check->get_active() != yn) {
947 check->set_active (yn);
952 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
954 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
956 bool yn = _route->get_mute_config(MAIN_OUTS);
957 if (check->get_active() != yn) {
958 check->set_active (yn);
963 RouteUI::disconnect_input ()
965 _route->disconnect_inputs (this);
969 RouteUI::disconnect_output ()
971 _route->disconnect_outputs (this);
975 RouteUI::is_track () const
977 return boost::dynamic_pointer_cast<Track>(_route) != 0;
980 boost::shared_ptr<Track>
981 RouteUI::track() const
983 return boost::dynamic_pointer_cast<Track>(_route);
987 RouteUI::is_audio_track () const
989 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
992 boost::shared_ptr<AudioTrack>
993 RouteUI::audio_track() const
995 return boost::dynamic_pointer_cast<AudioTrack>(_route);
999 RouteUI::is_midi_track () const
1001 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1004 boost::shared_ptr<MidiTrack>
1005 RouteUI::midi_track() const
1007 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1010 boost::shared_ptr<Diskstream>
1011 RouteUI::get_diskstream () const
1013 boost::shared_ptr<Track> t;
1015 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1016 return t->diskstream();
1018 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1023 RouteUI::name() const
1025 return _route->name();
1029 RouteUI::map_frozen ()
1031 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1033 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1036 switch (at->freeze_state()) {
1037 case AudioTrack::Frozen:
1038 rec_enable_button->set_sensitive (false);
1041 rec_enable_button->set_sensitive (true);
1048 RouteUI::adjust_latency ()
1050 LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());