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>
26 #include <ardour/route_group.h>
27 #include <pbd/memento_command.h>
28 #include <pbd/stacktrace.h>
29 #include <pbd/shiva.h>
35 #include "gui_thread.h"
37 #include <ardour/route.h>
38 #include <ardour/session.h>
39 #include <ardour/audioengine.h>
40 #include <ardour/audio_track.h>
41 #include <ardour/audio_diskstream.h>
46 using namespace Gtkmm2ext;
47 using namespace ARDOUR;
50 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess, const char* m_name,
51 const char* s_name, const char* r_name)
61 remote_control_menu = 0;
62 ignore_toggle = false;
63 wait_for_release = false;
64 route_active_menu_item = 0;
65 was_solo_safe = false;
67 if (set_color_from_route()) {
68 set_color (unique_random_color());
71 new PairedShiva<Route,RouteUI> (*_route, *this);
73 _route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed));
75 mute_button = manage (new BindableToggleButton (_route->mute_control(), m_name ));
76 mute_button->set_self_managed (true);
78 solo_button = manage (new BindableToggleButton (_route->solo_control(), s_name ));
79 solo_button->set_self_managed (true);
81 mute_button->set_name ("MuteButton");
82 solo_button->set_name ("SoloButton");
84 _route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed));
85 _route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
86 _route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
88 /* when solo changes, update mute state too, in case the user wants us to display it */
90 _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
92 update_solo_display ();
93 update_mute_display ();
96 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
98 t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed));
100 _session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed));
102 rec_enable_button = manage (new BindableToggleButton (t->rec_enable_control(), r_name ));
103 rec_enable_button->set_name ("RecordEnableButton");
104 rec_enable_button->set_self_managed (true);
106 update_rec_display ();
109 _route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu));
111 /* map the current state */
118 GoingAway (); /* EMIT SIGNAL */
123 RouteUI::mute_press(GdkEventButton* ev)
125 if (!ignore_toggle) {
127 if (Keyboard::is_context_menu_event (ev)) {
133 mute_menu->popup(0,ev->time);
137 if (ev->button == 2) {
138 // ctrl-button2 click is the midi binding click
139 // button2-click is "momentary"
141 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
142 wait_for_release = true;
148 if (ev->button == 1 || ev->button == 2) {
150 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
152 /* ctrl-shift-click applies change to all routes */
154 _session.begin_reversible_command (_("mute change"));
155 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
156 _session.set_all_mute (!_route->muted());
158 _session.add_command(cmd);
159 _session.commit_reversible_command ();
161 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
163 /* ctrl-click applies change to the mix group.
164 ctrl-button2 is MIDI learn.
167 if (ev->button == 1) {
168 set_mix_group_mute (_route, !_route->muted());
173 /* plain click applies change to this route */
175 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
186 RouteUI::mute_release(GdkEventButton* ev)
188 if (!ignore_toggle) {
189 if (wait_for_release){
190 wait_for_release = false;
192 // because the press was the last undoable thing we did
200 RouteUI::solo_press(GdkEventButton* ev)
202 if (!ignore_toggle) {
204 if (Keyboard::is_context_menu_event (ev)) {
206 if (solo_menu == 0) {
210 solo_menu->popup (1, ev->time);
214 if (ev->button == 2) {
216 // ctrl-button2 click is the midi binding click
217 // button2-click is "momentary"
219 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control))) {
220 wait_for_release = true;
226 if (ev->button == 1 || ev->button == 2) {
228 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
230 /* ctrl-shift-click applies change to all routes */
232 _session.begin_reversible_command (_("solo change"));
233 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
234 _session.set_all_solo (!_route->soloed());
236 _session.add_command (cmd);
237 _session.commit_reversible_command ();
239 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Alt))) {
241 // ctrl-alt-click: exclusively solo this track, not a toggle */
243 _session.begin_reversible_command (_("solo change"));
244 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
245 _session.set_all_solo (false);
246 _route->set_solo (true, this);
248 _session.add_command(cmd);
249 _session.commit_reversible_command ();
251 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
253 // shift-click: set this route to solo safe
255 _route->set_solo_safe (!_route->solo_safe(), this);
256 wait_for_release = false;
258 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
260 /* ctrl-click: solo mix group.
261 ctrl-button2 is MIDI learn.
264 if (ev->button == 1) {
265 set_mix_group_solo (_route, !_route->soloed());
270 /* click: solo this route */
272 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
282 RouteUI::solo_release(GdkEventButton* ev)
284 if (!ignore_toggle) {
285 if (wait_for_release) {
286 wait_for_release = false;
288 // because the press was the last undoable thing we did
298 RouteUI::rec_enable_press(GdkEventButton* ev)
300 if (!_session.engine().connected()) {
301 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
306 if (!ignore_toggle && is_track() && rec_enable_button) {
308 if (ev->button == 2 && Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
310 // do nothing on midi bind event
312 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::Control|Keyboard::Shift))) {
314 _session.begin_reversible_command (_("rec-enable change"));
315 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
317 if (rec_enable_button->get_active()) {
318 _session.record_disenable_all ();
320 _session.record_enable_all ();
324 _session.add_command(cmd);
325 _session.commit_reversible_command ();
327 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
329 set_mix_group_rec_enable (_route, !_route->record_enabled());
333 reversibly_apply_audio_track_boolean ("rec-enable change", &AudioTrack::set_record_enable, !audio_track()->record_enabled(), this);
341 RouteUI::rec_enable_release (GdkEventButton* ev)
347 RouteUI::solo_changed(void* src)
349 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
353 RouteUI::update_solo_display ()
356 vector<Gdk::Color> fg_colors;
359 if (solo_button->get_active() != (x = _route->soloed())){
360 ignore_toggle = true;
361 solo_button->set_active(x);
362 ignore_toggle = false;
365 if (_route->solo_safe()) {
366 solo_button->set_visual_state (2);
367 } else if (_route->soloed()) {
368 solo_button->set_visual_state (1);
370 solo_button->set_visual_state (0);
375 RouteUI::solo_changed_so_update_mute ()
377 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
381 RouteUI::mute_changed(void* src)
383 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
387 RouteUI::update_mute_display ()
389 bool model = _route->muted();
390 bool view = mute_button->get_active();
392 /* first make sure the button's "depressed" visual
397 ignore_toggle = true;
398 mute_button->set_active (model);
399 ignore_toggle = false;
402 /* now attend to visual state */
404 if (Config->get_show_solo_mutes()) {
405 if (_route->muted()) {
406 mute_button->set_visual_state (2);
407 } else if (!_route->soloed() && _route->solo_muted()) {
409 mute_button->set_visual_state (1);
411 mute_button->set_visual_state (0);
414 if (_route->muted()) {
415 mute_button->set_visual_state (2);
417 mute_button->set_visual_state (0);
424 RouteUI::route_rec_enable_changed ()
426 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
430 RouteUI::session_rec_enable_changed ()
432 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
436 RouteUI::update_rec_display ()
438 bool model = _route->record_enabled();
439 bool view = rec_enable_button->get_active();
441 /* first make sure the button's "depressed" visual
446 ignore_toggle = true;
447 rec_enable_button->set_active (model);
448 ignore_toggle = false;
451 /* now make sure its color state is correct */
455 switch (_session.record_status ()) {
456 case Session::Recording:
457 rec_enable_button->set_visual_state (1);
460 case Session::Disabled:
461 case Session::Enabled:
462 rec_enable_button->set_visual_state (2);
468 rec_enable_button->set_visual_state (0);
473 RouteUI::build_remote_control_menu ()
475 remote_control_menu = manage (new Menu);
476 refresh_remote_control_menu ();
480 RouteUI::refresh_remote_control_menu ()
482 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
484 // only refresh the menu if it has been instantiated
486 if (remote_control_menu == 0) {
490 using namespace Menu_Helpers;
492 RadioMenuItem::Group rc_group;
493 CheckMenuItem* rc_active;
494 uint32_t limit = _session.ntracks() + _session.nbusses();
497 MenuList& rc_items = remote_control_menu->items();
500 /* note that this menu list starts at zero, not 1, because zero
501 is a valid, if useless, ID.
504 limit += 4; /* leave some breathing room */
506 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
507 if (_route->remote_control_id() == 0) {
508 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
509 rc_active->set_active ();
512 for (uint32_t i = 1; i < limit; ++i) {
513 snprintf (buf, sizeof (buf), "%u", i);
514 rc_items.push_back (RadioMenuElem (rc_group, buf));
515 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
516 if (_route->remote_control_id() == i) {
517 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
518 rc_active->set_active ();
520 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
525 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
527 /* this is called when the radio menu item is toggled, and so
528 is actually invoked twice per menu selection. we only
529 care about the invocation for the item that was being
533 if (item->get_active()) {
534 _route->set_remote_control_id (id);
539 RouteUI::build_solo_menu (void)
541 using namespace Menu_Helpers;
543 solo_menu = new Menu;
544 solo_menu->set_name ("ArdourContextMenu");
545 MenuList& items = solo_menu->items();
546 CheckMenuItem* check;
548 check = new CheckMenuItem(_("Solo-safe"));
549 check->set_active (_route->solo_safe());
550 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
551 _route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
552 items.push_back (CheckMenuElem(*check));
555 //items.push_back (SeparatorElem());
556 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
561 RouteUI::build_mute_menu(void)
563 using namespace Menu_Helpers;
565 mute_menu = new Menu;
566 mute_menu->set_name ("ArdourContextMenu");
567 MenuList& items = mute_menu->items();
568 CheckMenuItem* check;
570 check = new CheckMenuItem(_("Pre Fader"));
571 init_mute_menu(PRE_FADER, check);
572 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
573 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
574 items.push_back (CheckMenuElem(*check));
577 check = new CheckMenuItem(_("Post Fader"));
578 init_mute_menu(POST_FADER, check);
579 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
580 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
581 items.push_back (CheckMenuElem(*check));
584 check = new CheckMenuItem(_("Control Outs"));
585 init_mute_menu(CONTROL_OUTS, check);
586 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
587 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
588 items.push_back (CheckMenuElem(*check));
591 check = new CheckMenuItem(_("Main Outs"));
592 init_mute_menu(MAIN_OUTS, check);
593 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
594 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
595 items.push_back (CheckMenuElem(*check));
598 //items.push_back (SeparatorElem());
599 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
603 RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
605 if (_route->get_mute_config (type)) {
606 check->set_active (true);
611 RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
613 _route->set_mute_config(type, check->get_active(), this);
617 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
619 _route->set_solo_safe (check->get_active(), this);
623 RouteUI::set_mix_group_solo(boost::shared_ptr<Route> route, bool yn)
625 RouteGroup* mix_group;
627 if((mix_group = route->mix_group()) != 0){
628 _session.begin_reversible_command (_("mix group solo change"));
629 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
630 mix_group->apply(&Route::set_solo, yn, this);
632 _session.add_command (cmd);
633 _session.commit_reversible_command ();
635 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
640 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
642 _session.begin_reversible_command (name);
643 XMLNode &before = _route->get_state();
644 bind(mem_fun(*_route, func), yn, arg)();
645 XMLNode &after = _route->get_state();
646 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
647 _session.commit_reversible_command ();
651 RouteUI::reversibly_apply_audio_track_boolean (string name, void (AudioTrack::*func)(bool, void *), bool yn, void *arg)
653 _session.begin_reversible_command (name);
654 XMLNode &before = audio_track()->get_state();
655 bind (mem_fun (*audio_track(), func), yn, arg)();
656 XMLNode &after = audio_track()->get_state();
657 _session.add_command (new MementoCommand<AudioTrack>(*audio_track(), &before, &after));
658 _session.commit_reversible_command ();
662 RouteUI::set_mix_group_mute(boost::shared_ptr<Route> route, bool yn)
664 RouteGroup* mix_group;
666 if((mix_group = route->mix_group()) != 0){
667 _session.begin_reversible_command (_("mix group mute change"));
668 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
669 mix_group->apply(&Route::set_mute, yn, this);
671 _session.add_command(cmd);
672 _session.commit_reversible_command ();
674 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
679 RouteUI::set_mix_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
681 RouteGroup* mix_group;
683 if((mix_group = route->mix_group()) != 0){
684 _session.begin_reversible_command (_("mix group rec-enable change"));
685 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
686 mix_group->apply (&Route::set_record_enable, yn, this);
688 _session.add_command(cmd);
689 _session.commit_reversible_command ();
691 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
697 RouteUI::choose_color()
702 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
712 RouteUI::set_color (const Gdk::Color & c)
719 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
720 xml_node->add_property ("color", buf);
722 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
727 RouteUI::ensure_xml_node ()
730 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
731 xml_node = new XMLNode ("GUI");
732 _route->add_extra_xml (*xml_node);
738 RouteUI::get_child_xml_node (const string & childname)
745 if ((child = find_named_node (*xml_node, childname)) == 0) {
746 child = new XMLNode (childname);
747 xml_node->add_child_nocopy (*child);
754 RouteUI::set_color_from_route ()
758 RouteUI::ensure_xml_node ();
760 if ((prop = xml_node->property ("color")) != 0) {
762 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
772 RouteUI::remove_this_route ()
774 vector<string> choices;
778 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());
780 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
783 choices.push_back (_("No, do nothing."));
784 choices.push_back (_("Yes, remove it."));
786 Choice prompter (prompt, choices);
788 if (prompter.run () == 1) {
789 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
794 RouteUI::idle_remove_this_route (RouteUI *rui)
796 rui->_session.remove_route (rui->_route);
801 RouteUI::route_rename ()
803 ArdourPrompter name_prompter (true);
805 name_prompter.set_prompt (_("New Name: "));
806 name_prompter.set_initial_text (_route->name());
807 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
808 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
809 name_prompter.show_all ();
811 switch (name_prompter.run ()) {
813 case Gtk::RESPONSE_ACCEPT:
814 name_prompter.get_result (result);
815 if (result.length()) {
816 _route->set_name (result, this);
826 RouteUI::name_changed (void *src)
828 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::name_changed), src));
830 name_label.set_text (_route->name());
834 RouteUI::toggle_route_active ()
838 if (route_active_menu_item) {
839 if (route_active_menu_item->get_active() != (yn = _route->active())) {
840 _route->set_active (!yn);
846 RouteUI::route_active_changed ()
848 if (route_active_menu_item) {
849 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
854 RouteUI::toggle_polarity ()
856 if (polarity_menu_item) {
860 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
862 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
863 _route->set_phase_invert (x, this);
865 name_label.set_text (X_("Ø ") + name_label.get_text());
867 name_label.set_text (_route->name());
874 RouteUI::polarity_changed ()
876 /* no signal for this yet */
880 RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
882 bool yn = _route->solo_safe ();
884 if (check->get_active() != yn) {
885 check->set_active (yn);
889 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
891 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
893 bool yn = _route->get_mute_config(PRE_FADER);
894 if (check->get_active() != yn) {
895 check->set_active (yn);
900 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
902 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
904 bool yn = _route->get_mute_config(POST_FADER);
905 if (check->get_active() != yn) {
906 check->set_active (yn);
911 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
913 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
915 bool yn = _route->get_mute_config(CONTROL_OUTS);
916 if (check->get_active() != yn) {
917 check->set_active (yn);
922 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
924 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
926 bool yn = _route->get_mute_config(MAIN_OUTS);
927 if (check->get_active() != yn) {
928 check->set_active (yn);
933 RouteUI::disconnect_input ()
935 _route->disconnect_inputs (this);
939 RouteUI::disconnect_output ()
941 _route->disconnect_outputs (this);
945 RouteUI::is_track () const
947 return dynamic_cast<Track*>(_route.get()) != 0;
951 RouteUI::track() const
953 return dynamic_cast<Track*>(_route.get());
957 RouteUI::is_audio_track () const
959 return dynamic_cast<AudioTrack*>(_route.get()) != 0;
963 RouteUI::audio_track() const
965 return dynamic_cast<AudioTrack*>(_route.get());
968 boost::shared_ptr<Diskstream>
969 RouteUI::get_diskstream () const
971 boost::shared_ptr<Track> t;
973 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
974 return t->diskstream();
976 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
981 RouteUI::name() const
983 return _route->name();
987 RouteUI::map_frozen ()
989 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
991 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
994 switch (at->freeze_state()) {
995 case AudioTrack::Frozen:
996 rec_enable_button->set_sensitive (false);
999 rec_enable_button->set_sensitive (true);