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>
26 #include <gtkmm2ext/gtk_ui.h>
28 #include "ardour/route_group.h"
29 #include "ardour/dB.h"
30 #include "pbd/memento_command.h"
31 #include "pbd/stacktrace.h"
32 #include "pbd/shiva.h"
33 #include "pbd/controllable.h"
35 #include "ardour_ui.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
47 #include "ardour/route.h"
48 #include "ardour/session.h"
49 #include "ardour/audioengine.h"
50 #include "ardour/audio_track.h"
51 #include "ardour/audio_diskstream.h"
52 #include "ardour/midi_track.h"
53 #include "ardour/midi_diskstream.h"
54 #include "ardour/template_utils.h"
55 #include "ardour/filename_extensions.h"
56 #include "ardour/directory_names.h"
57 #include "ardour/profile.h"
62 using namespace Gtkmm2ext;
63 using namespace ARDOUR;
66 RouteUI::RouteUI (ARDOUR::Session& sess)
72 RouteUI::RouteUI (boost::shared_ptr<ARDOUR::Route> rt, ARDOUR::Session& sess)
81 /* derived classes should emit GoingAway so that they receive the signal
82 when the object is still a legal derived instance.
87 delete remote_control_menu;
98 remote_control_menu = 0;
100 ignore_toggle = false;
101 wait_for_release = false;
102 route_active_menu_item = 0;
103 polarity_menu_item = 0;
104 denormal_menu_item = 0;
105 multiple_mute_change = false;
106 multiple_solo_change = false;
108 mute_button = manage (new BindableToggleButton ());
109 mute_button->set_self_managed (true);
110 mute_button->set_name ("MuteButton");
111 mute_button->add (mute_button_label);
112 mute_button_label.show ();
113 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
115 solo_button = manage (new BindableToggleButton ());
116 solo_button->set_self_managed (true);
117 solo_button->set_name ("SoloButton");
118 solo_button->add (solo_button_label);
119 solo_button_label.show ();
120 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
121 solo_button->set_no_show_all (true);
123 rec_enable_button = manage (new BindableToggleButton ());
124 rec_enable_button->set_name ("RecordEnableButton");
125 rec_enable_button->set_self_managed (true);
126 rec_enable_button->add (rec_enable_button_label);
127 rec_enable_button_label.show ();
128 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
130 show_sends_button = manage (new BindableToggleButton (""));
131 show_sends_button->set_name ("SendAlert");
132 show_sends_button->set_self_managed (true);
133 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
135 _session.SoloChanged.connect (mem_fun(*this, &RouteUI::solo_changed_so_update_mute));
136 _session.TransportStateChange.connect (mem_fun (*this, &RouteUI::check_rec_enable_sensitivity));
138 Config->ParameterChanged.connect (mem_fun (*this, &RouteUI::parameter_changed));
144 //Remove route connections associated with us.
145 for (vector<sigc::connection>::iterator it = connections.begin(); it!=connections.end(); ++it) {
149 connections.clear ();
158 /* do not delete the node - its owned by the route */
162 route_active_menu_item = 0;
163 polarity_menu_item = 0;
164 denormal_menu_item = 0;
168 RouteUI::set_route (boost::shared_ptr<Route> rp)
174 if (set_color_from_route()) {
175 set_color (unique_random_color());
178 /* no, there is no memory leak here. This object cleans itself (and other stuff)
179 up when the route is destroyed.
183 new PairedShiva<Route,RouteUI> (*_route, *this);
186 mute_button->set_controllable (_route->mute_control());
187 solo_button->set_controllable (_route->solo_control());
189 connections.push_back (_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)));
190 connections.push_back (_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)));
191 connections.push_back (_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
192 connections.push_back (_route->listen_changed.connect (mem_fun(*this, &RouteUI::listen_changed)));
193 connections.push_back (_route->solo_isolated_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
196 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
198 connections.push_back (t->diskstream()->RecordEnableChanged.connect (mem_fun (*this, &RouteUI::route_rec_enable_changed)));
199 connections.push_back (_session.RecordStateChanged.connect (mem_fun (*this, &RouteUI::session_rec_enable_changed)));
201 rec_enable_button->show();
202 rec_enable_button->set_controllable (t->rec_enable_control());
204 update_rec_display ();
207 mute_button->unset_flags (Gtk::CAN_FOCUS);
208 solo_button->unset_flags (Gtk::CAN_FOCUS);
212 if (_route->is_control()) {
213 solo_button->hide ();
218 connections.push_back (_route->RemoteControlIDChanged.connect (mem_fun(*this, &RouteUI::refresh_remote_control_menu)));
220 /* map the current state */
229 RouteUI::mute_press(GdkEventButton* ev)
231 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
234 multiple_mute_change = false;
235 if (!ignore_toggle) {
237 if (Keyboard::is_context_menu_event (ev)) {
243 mute_menu->popup(0,ev->time);
247 if (Keyboard::is_button2_event (ev)) {
248 // Primary-button2 click is the midi binding click
249 // button2-click is "momentary"
251 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
252 wait_for_release = true;
258 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
260 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
262 /* Primary-Tertiary-click applies change to all routes */
264 _session.begin_reversible_command (_("mute change"));
265 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand(_session, this);
266 _session.set_all_mute (!_route->muted());
268 _session.add_command(cmd);
269 _session.commit_reversible_command ();
270 multiple_mute_change = true;
272 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
274 /* Primary-button1 applies change to the mix group.
275 NOTE: Primary-button2 is MIDI learn.
278 if (ev->button == 1) {
279 set_route_group_mute (_route, !_route->muted());
284 /* plain click applies change to this route */
285 if (wait_for_release) {
286 _route->set_mute (!_route->muted(), this);
288 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !_route->muted(), this);
300 RouteUI::mute_release(GdkEventButton*)
302 if (!ignore_toggle) {
303 if (wait_for_release){
304 wait_for_release = false;
305 if (multiple_mute_change) {
306 multiple_mute_change = false;
308 // because the press was the last undoable thing we did
311 _route->set_mute (!_route->muted(), this);
319 RouteUI::solo_press(GdkEventButton* ev)
321 /* ignore double/triple clicks */
323 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
327 if (Config->get_solo_control_is_listen_control()) {
329 _route->set_listen (!_route->listening(), this);
333 multiple_solo_change = false;
334 if (!ignore_toggle) {
336 if (Keyboard::is_context_menu_event (ev)) {
338 if (solo_menu == 0) {
342 solo_menu->popup (1, ev->time);
346 if (Keyboard::is_button2_event (ev)) {
348 // Primary-button2 click is the midi binding click
349 // button2-click is "momentary"
351 if (!Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier))) {
352 wait_for_release = true;
358 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
360 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
362 /* Primary-Tertiary-click applies change to all routes */
363 bool was_not_latched = false;
364 if (!Config->get_solo_latched ()) {
365 was_not_latched = true;
367 XXX it makes no sense to solo all tracks if we're
368 not in latched mode, but doing nothing feels like a bug,
371 Config->set_solo_latched (true);
373 _session.begin_reversible_command (_("solo change"));
374 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
375 _session.set_all_solo (!_route->soloed());
377 _session.add_command (cmd);
378 _session.commit_reversible_command ();
379 multiple_solo_change = true;
380 if (was_not_latched) {
381 Config->set_solo_latched (false);
384 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
386 // Primary-Secondary-click: exclusively solo this track, not a toggle */
388 _session.begin_reversible_command (_("solo change"));
389 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand (_session, this);
390 _session.set_all_solo (false);
391 _route->set_solo (true, this);
393 _session.add_command(cmd);
394 _session.commit_reversible_command ();
396 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
398 // shift-click: set this route to solo safe
400 if (Profile->get_sae() && ev->button == 1) {
401 // button 1 and shift-click: disables solo_latched for this click
402 if (!Config->get_solo_latched ()) {
403 Config->set_solo_latched (true);
404 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
405 Config->set_solo_latched (false);
408 _route->set_solo_isolated (!_route->solo_isolated(), this);
409 wait_for_release = false;
412 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
414 /* Primary-button1: solo mix group.
415 NOTE: Primary-button2 is MIDI learn.
418 if (ev->button == 1) {
419 set_route_group_solo (_route, !_route->soloed());
424 /* click: solo this route */
425 if (wait_for_release) {
426 _route->set_solo (!_route->soloed(), this);
428 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !_route->soloed(), this);
440 RouteUI::solo_release(GdkEventButton*)
442 if (!ignore_toggle) {
443 if (wait_for_release) {
444 wait_for_release = false;
445 if (multiple_solo_change) {
446 multiple_solo_change = false;
448 // because the press was the last undoable thing we did
451 // we don't use "undo the last op"
452 // here because its expensive for the GUI
453 _route->set_solo (!_route->soloed(), this);
462 RouteUI::rec_enable_press(GdkEventButton* ev)
464 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
468 if (!_session.engine().connected()) {
469 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
474 if (!ignore_toggle && is_track() && rec_enable_button) {
476 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
478 // do nothing on midi bind event
481 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
483 _session.begin_reversible_command (_("rec-enable change"));
484 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
486 if (rec_enable_button->get_active()) {
487 _session.record_disenable_all ();
489 _session.record_enable_all ();
490 check_rec_enable_sensitivity ();
494 _session.add_command(cmd);
495 _session.commit_reversible_command ();
497 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
499 /* Primary-button1 applies change to the mix group.
500 NOTE: Primary-button2 is MIDI learn.
503 set_route_group_rec_enable (_route, !_route->record_enabled());
506 reversibly_apply_track_boolean ("rec-enable change", &Track::set_record_enable, !track()->record_enabled(), this);
507 check_rec_enable_sensitivity ();
515 RouteUI::rec_enable_release (GdkEventButton*)
521 RouteUI::build_sends_menu ()
523 using namespace Menu_Helpers;
525 sends_menu = new Menu;
526 sends_menu->set_name ("ArdourContextMenu");
527 MenuList& items = sends_menu->items();
529 items.push_back (MenuElem(_("Assign all tracks (prefader)"), bind (mem_fun (*this, &RouteUI::create_sends), PreFader)));
530 items.push_back (MenuElem(_("Assign all tracks (postfader)"), bind (mem_fun (*this, &RouteUI::create_sends), PostFader)));
531 items.push_back (MenuElem(_("Copy track gains to sends"), mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
532 items.push_back (MenuElem(_("Set sends gain to -inf"), mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
533 items.push_back (MenuElem(_("Set sends gain to 0dB"), mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
538 RouteUI::create_sends (Placement p)
540 _session.globally_add_internal_sends (_route, p);
544 RouteUI::set_sends_gain_from_track ()
546 _session.globally_set_send_gains_from_track (_route);
550 RouteUI::set_sends_gain_to_zero ()
552 _session.globally_set_send_gains_to_zero (_route);
556 RouteUI::set_sends_gain_to_unity ()
558 _session.globally_set_send_gains_to_unity (_route);
562 RouteUI::show_sends_press(GdkEventButton* ev)
564 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
568 if (!ignore_toggle && !is_track() && show_sends_button) {
570 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
572 // do nothing on midi bind event
575 } else if (Keyboard::is_context_menu_event (ev)) {
577 if (sends_menu == 0) {
581 sends_menu->popup (0, ev->time);
585 /* change button state */
587 show_sends_button->set_active (!show_sends_button->get_active());
591 if (show_sends_button->get_active()) {
592 /* show sends to this bus */
593 MixerStrip::SwitchIO (_route);
594 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (mem_fun(*this, &RouteUI::send_blink));
596 /* everybody back to normal */
597 send_blink_connection.disconnect ();
598 MixerStrip::SwitchIO (boost::shared_ptr<Route>());
608 RouteUI::show_sends_release (GdkEventButton*)
614 RouteUI::send_blink (bool onoff)
616 if (!show_sends_button) {
621 show_sends_button->set_state (STATE_ACTIVE);
623 show_sends_button->set_state (STATE_NORMAL);
628 RouteUI::solo_changed(void* /*src*/)
630 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
635 RouteUI::listen_changed(void* /*src*/)
637 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_solo_display));
641 RouteUI::update_solo_display ()
645 if (Config->get_solo_control_is_listen_control()) {
647 if (solo_button->get_active() != (x = _route->listening())) {
648 ignore_toggle = true;
649 solo_button->set_active(x);
650 ignore_toggle = false;
654 solo_button->set_visual_state (1);
656 solo_button->set_visual_state (0);
662 if (solo_button->get_active() != (x = _route->soloed())){
663 ignore_toggle = true;
664 solo_button->set_active (x);
665 ignore_toggle = false;
668 if (_route->solo_isolated()) {
669 solo_button->set_visual_state (2);
671 solo_button->set_visual_state (1);
673 solo_button->set_visual_state (0);
679 RouteUI::solo_changed_so_update_mute ()
681 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
685 RouteUI::mute_changed(void* /*src*/)
687 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_mute_display));
691 RouteUI::update_mute_display ()
693 bool model = _route->muted();
694 bool view = mute_button->get_active();
696 /* first make sure the button's "depressed" visual
701 ignore_toggle = true;
702 mute_button->set_active (model);
703 ignore_toggle = false;
706 /* now attend to visual state */
708 if (Config->get_show_solo_mutes()) {
709 if (_route->muted()) {
710 mute_button->set_visual_state (2);
711 } else if (!_route->soloed() && _session.soloing()) {
712 mute_button->set_visual_state (1);
714 mute_button->set_visual_state (0);
717 if (_route->muted()) {
718 mute_button->set_visual_state (2);
720 mute_button->set_visual_state (0);
727 RouteUI::route_rec_enable_changed ()
729 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
733 RouteUI::session_rec_enable_changed ()
735 Gtkmm2ext::UI::instance()->call_slot (mem_fun (*this, &RouteUI::update_rec_display));
739 RouteUI::update_rec_display ()
741 bool model = _route->record_enabled();
742 bool view = rec_enable_button->get_active();
744 /* first make sure the button's "depressed" visual
749 ignore_toggle = true;
750 rec_enable_button->set_active (model);
751 ignore_toggle = false;
757 /* now make sure its color state is correct */
761 switch (_session.record_status ()) {
762 case Session::Recording:
763 rec_enable_button->set_visual_state (1);
766 case Session::Disabled:
767 case Session::Enabled:
768 rec_enable_button->set_visual_state (2);
774 rec_enable_button->set_visual_state (0);
779 RouteUI::build_remote_control_menu ()
781 remote_control_menu = new Menu;
782 refresh_remote_control_menu ();
786 RouteUI::refresh_remote_control_menu ()
788 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::refresh_remote_control_menu));
790 // only refresh the menu if it has been instantiated
792 if (remote_control_menu == 0) {
796 using namespace Menu_Helpers;
798 RadioMenuItem::Group rc_group;
799 CheckMenuItem* rc_active;
800 uint32_t limit = _session.ntracks() + _session.nbusses();
803 MenuList& rc_items = remote_control_menu->items();
806 /* note that this menu list starts at zero, not 1, because zero
807 is a valid, if useless, ID.
810 limit += 4; /* leave some breathing room */
812 rc_items.push_back (RadioMenuElem (rc_group, _("None")));
813 if (_route->remote_control_id() == 0) {
814 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
815 rc_active->set_active ();
818 for (uint32_t i = 1; i < limit; ++i) {
819 snprintf (buf, sizeof (buf), "%u", i);
820 rc_items.push_back (RadioMenuElem (rc_group, buf));
821 rc_active = dynamic_cast<RadioMenuItem*>(&rc_items.back());
822 if (_route->remote_control_id() == i) {
823 rc_active = dynamic_cast<CheckMenuItem*> (&rc_items.back());
824 rc_active->set_active ();
826 rc_active->signal_activate().connect (bind (mem_fun (*this, &RouteUI::set_remote_control_id), i, rc_active));
831 RouteUI::set_remote_control_id (uint32_t id, CheckMenuItem* item)
833 /* this is called when the radio menu item is toggled, and so
834 is actually invoked twice per menu selection. we only
835 care about the invocation for the item that was being
839 if (item->get_active()) {
840 _route->set_remote_control_id (id);
845 RouteUI::build_solo_menu (void)
847 using namespace Menu_Helpers;
849 solo_menu = new Menu;
850 solo_menu->set_name ("ArdourContextMenu");
851 MenuList& items = solo_menu->items();
852 CheckMenuItem* check;
854 check = new CheckMenuItem(_("Solo Isolate"));
855 check->set_active (_route->solo_isolated());
856 check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
857 _route->solo_isolated_changed.connect(bind (mem_fun (*this, &RouteUI::solo_isolated_toggle), check));
858 items.push_back (CheckMenuElem(*check));
861 //items.push_back (SeparatorElem());
862 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
867 RouteUI::build_mute_menu(void)
869 using namespace Menu_Helpers;
871 mute_menu = new Menu;
872 mute_menu->set_name ("ArdourContextMenu");
875 MenuList& items = mute_menu->items();
876 CheckMenuItem* check;
878 check = new CheckMenuItem(_("Pre Fader"));
879 init_mute_menu(PRE_FADER, check);
880 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
881 _route->pre_fader_changed.connect(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), check));
882 items.push_back (CheckMenuElem(*check));
885 check = new CheckMenuItem(_("Post Fader"));
886 init_mute_menu(POST_FADER, check);
887 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), POST_FADER, check));
888 _route->post_fader_changed.connect(bind (mem_fun (*this, &RouteUI::post_fader_toggle), check));
889 items.push_back (CheckMenuElem(*check));
892 check = new CheckMenuItem(_("Control Outs"));
893 init_mute_menu(CONTROL_OUTS, check);
894 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), CONTROL_OUTS, check));
895 _route->control_outs_changed.connect(bind (mem_fun (*this, &RouteUI::control_outs_toggle), check));
896 items.push_back (CheckMenuElem(*check));
899 check = new CheckMenuItem(_("Main Outs"));
900 init_mute_menu(MAIN_OUTS, check);
901 check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), MAIN_OUTS, check));
902 _route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
903 items.push_back (CheckMenuElem(*check));
906 //items.push_back (SeparatorElem());
907 // items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
911 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
913 check->set_active (_route->mute_master()->muted_at (mp));
917 RouteUI::toggle_mute_menu(MuteMaster::MutePoint /*mp*/, Gtk::CheckMenuItem* /*check*/)
919 // _route->set_mute_config(type, check->get_active(), this);
923 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
925 _route->set_solo_isolated (check->get_active(), this);
929 RouteUI::set_route_group_solo(boost::shared_ptr<Route> route, bool yn)
931 RouteGroup* route_group;
933 if((route_group = route->route_group()) != 0){
934 _session.begin_reversible_command (_("mix group solo change"));
935 Session::GlobalSoloStateCommand *cmd = new Session::GlobalSoloStateCommand(_session, this);
936 route_group->apply(&Route::set_solo, yn, this);
938 _session.add_command (cmd);
939 _session.commit_reversible_command ();
941 reversibly_apply_route_boolean ("solo change", &Route::set_solo, !route->soloed(), this);
946 RouteUI::reversibly_apply_route_boolean (string name, void (Route::*func)(bool, void *), bool yn, void *arg)
948 _session.begin_reversible_command (name);
949 XMLNode &before = _route->get_state();
950 bind(mem_fun(*_route, func), yn, arg)();
951 XMLNode &after = _route->get_state();
952 _session.add_command (new MementoCommand<Route>(*_route, &before, &after));
953 _session.commit_reversible_command ();
957 RouteUI::reversibly_apply_track_boolean (string name, void (Track::*func)(bool, void *), bool yn, void *arg)
959 _session.begin_reversible_command (name);
960 XMLNode &before = track()->get_state();
961 bind (mem_fun (*track(), func), yn, arg)();
962 XMLNode &after = track()->get_state();
963 _session.add_command (new MementoCommand<Track>(*track(), &before, &after));
964 _session.commit_reversible_command ();
968 RouteUI::set_route_group_mute(boost::shared_ptr<Route> route, bool yn)
970 RouteGroup* route_group;
972 if((route_group = route->route_group()) != 0){
973 _session.begin_reversible_command (_("mix group mute change"));
974 Session::GlobalMuteStateCommand *cmd = new Session::GlobalMuteStateCommand (_session, this);
975 route_group->apply(&Route::set_mute, yn, this);
977 _session.add_command(cmd);
978 _session.commit_reversible_command ();
980 reversibly_apply_route_boolean ("mute change", &Route::set_mute, !route->muted(), this);
985 RouteUI::set_route_group_rec_enable(boost::shared_ptr<Route> route, bool yn)
987 RouteGroup* route_group;
989 if((route_group = route->route_group()) != 0){
990 _session.begin_reversible_command (_("mix group rec-enable change"));
991 Session::GlobalRecordEnableStateCommand *cmd = new Session::GlobalRecordEnableStateCommand(_session, this);
992 route_group->apply (&Route::set_record_enable, yn, this);
994 _session.add_command(cmd);
995 _session.commit_reversible_command ();
997 reversibly_apply_route_boolean ("rec-enable change", &Route::set_record_enable, !_route->record_enabled(), this);
1003 RouteUI::choose_color()
1008 color = Gtkmm2ext::UI::instance()->get_color (_("ardour: color selection"), picked, &_color);
1018 RouteUI::set_color (const Gdk::Color & c)
1025 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1026 xml_node->add_property ("color", buf);
1028 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1033 RouteUI::ensure_xml_node ()
1035 if (xml_node == 0) {
1036 if ((xml_node = _route->extra_xml ("GUI")) == 0) {
1037 xml_node = new XMLNode ("GUI");
1038 _route->add_extra_xml (*xml_node);
1044 RouteUI::get_automation_child_xml_node (Evoral::Parameter param)
1048 XMLNodeList kids = xml_node->children();
1049 XMLNodeConstIterator iter;
1051 const string sym = ARDOUR::EventTypeMap::instance().to_symbol(param);
1053 for (iter = kids.begin(); iter != kids.end(); ++iter) {
1054 if ((*iter)->name() == AutomationTimeAxisView::state_node_name) {
1055 XMLProperty* type = (*iter)->property("automation-id");
1056 if (type && type->value() == sym)
1061 // Didn't find it, make a new one
1062 XMLNode* child = new XMLNode (AutomationTimeAxisView::state_node_name);
1063 child->add_property("automation-id", sym);
1064 xml_node->add_child_nocopy (*child);
1070 RouteUI::set_color_from_route ()
1074 RouteUI::ensure_xml_node ();
1076 if ((prop = xml_node->property ("color")) != 0) {
1078 sscanf (prop->value().c_str(), "%d:%d:%d", &r, &g, &b);
1080 _color.set_green(g);
1088 RouteUI::remove_this_route ()
1090 vector<string> choices;
1094 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());
1096 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n(cannot be undone)"), _route->name());
1099 choices.push_back (_("No, do nothing."));
1100 choices.push_back (_("Yes, remove it."));
1102 Choice prompter (prompt, choices);
1104 if (prompter.run () == 1) {
1105 Glib::signal_idle().connect (bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1110 RouteUI::idle_remove_this_route (RouteUI *rui)
1112 rui->_session.remove_route (rui->_route);
1117 RouteUI::route_rename ()
1119 ArdourPrompter name_prompter (true);
1121 name_prompter.set_prompt (_("New Name: "));
1122 name_prompter.set_initial_text (_route->name());
1123 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1124 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1125 name_prompter.show_all ();
1127 switch (name_prompter.run ()) {
1129 case Gtk::RESPONSE_ACCEPT:
1130 name_prompter.get_result (result);
1131 if (result.length()) {
1132 _route->set_name (result);
1142 RouteUI::name_changed ()
1144 ENSURE_GUI_THREAD(sigc::mem_fun(*this, &RouteUI::name_changed));
1146 name_label.set_text (_route->name());
1150 RouteUI::toggle_route_active ()
1154 if (route_active_menu_item) {
1155 if (route_active_menu_item->get_active() != (yn = _route->active())) {
1156 _route->set_active (!yn);
1162 RouteUI::route_active_changed ()
1164 if (route_active_menu_item) {
1165 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun (*route_active_menu_item, &CheckMenuItem::set_active), _route->active()));
1170 RouteUI::toggle_polarity ()
1172 if (polarity_menu_item) {
1176 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_polarity));
1178 if ((x = polarity_menu_item->get_active()) != _route->phase_invert()) {
1179 _route->set_phase_invert (x);
1181 name_label.set_text (X_("Ø ") + name_label.get_text());
1183 name_label.set_text (_route->name());
1190 RouteUI::polarity_changed ()
1192 if (_route->phase_invert()) {
1193 name_label.set_text (X_("Ø ") + name_label.get_text());
1195 name_label.set_text (_route->name());
1200 RouteUI::toggle_denormal_protection ()
1202 if (denormal_menu_item) {
1206 ENSURE_GUI_THREAD(mem_fun (*this, &RouteUI::toggle_denormal_protection));
1208 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1209 _route->set_denormal_protection (x);
1215 RouteUI::denormal_protection_changed ()
1217 if (denormal_menu_item) {
1218 denormal_menu_item->set_active (_route->denormal_protection());
1223 RouteUI::solo_isolated_toggle(void* /*src*/, Gtk::CheckMenuItem* check)
1225 bool yn = _route->solo_isolated ();
1227 if (check->get_active() != yn) {
1228 check->set_active (yn);
1232 #ifdef FIX_THIS_FOR_3_0
1234 RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
1236 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::pre_fader_toggle), src, check));
1238 bool yn = _route->get_mute_config(PRE_FADER);
1239 if (check->get_active() != yn) {
1240 check->set_active (yn);
1245 RouteUI::post_fader_toggle(void* src, Gtk::CheckMenuItem* check)
1247 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::post_fader_toggle), src, check));
1249 bool yn = _route->get_mute_config(POST_FADER);
1250 if (check->get_active() != yn) {
1251 check->set_active (yn);
1256 RouteUI::control_outs_toggle(void* src, Gtk::CheckMenuItem* check)
1258 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::control_outs_toggle), src, check));
1260 bool yn = _route->get_mute_config(CONTROL_OUTS);
1261 if (check->get_active() != yn) {
1262 check->set_active (yn);
1267 RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
1269 ENSURE_GUI_THREAD(bind (mem_fun (*this, &RouteUI::main_outs_toggle), src, check));
1271 bool yn = _route->get_mute_config(MAIN_OUTS);
1272 if (check->get_active() != yn) {
1273 check->set_active (yn);
1279 RouteUI::disconnect_input ()
1281 _route->input()->disconnect (this);
1285 RouteUI::disconnect_output ()
1287 _route->output()->disconnect (this);
1291 RouteUI::is_track () const
1293 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1296 boost::shared_ptr<Track>
1297 RouteUI::track() const
1299 return boost::dynamic_pointer_cast<Track>(_route);
1303 RouteUI::is_audio_track () const
1305 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1308 boost::shared_ptr<AudioTrack>
1309 RouteUI::audio_track() const
1311 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1315 RouteUI::is_midi_track () const
1317 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1320 boost::shared_ptr<MidiTrack>
1321 RouteUI::midi_track() const
1323 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1326 boost::shared_ptr<Diskstream>
1327 RouteUI::get_diskstream () const
1329 boost::shared_ptr<Track> t;
1331 if ((t = boost::dynamic_pointer_cast<Track>(_route)) != 0) {
1332 return t->diskstream();
1334 return boost::shared_ptr<Diskstream> ((Diskstream*) 0);
1339 RouteUI::name() const
1341 return _route->name();
1345 RouteUI::map_frozen ()
1347 ENSURE_GUI_THREAD (mem_fun (*this, &RouteUI::map_frozen));
1349 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1352 switch (at->freeze_state()) {
1353 case AudioTrack::Frozen:
1354 rec_enable_button->set_sensitive (false);
1357 rec_enable_button->set_sensitive (true);
1364 RouteUI::adjust_latency ()
1366 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session.frame_rate(), _session.engine().frames_per_cycle());
1370 RouteUI::save_as_template ()
1373 Glib::ustring safe_name;
1376 path = ARDOUR::user_route_template_directory ();
1378 if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1379 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1383 Prompter p (true); // modal
1385 p.set_prompt (_("Template name:"));
1387 case RESPONSE_ACCEPT:
1394 p.get_result (name, true);
1396 safe_name = legalize_for_path (name);
1397 safe_name += template_suffix;
1401 _route->save_as_template (path.to_string(), name);
1405 RouteUI::check_rec_enable_sensitivity ()
1407 if (_session.transport_rolling() && rec_enable_button->get_active() && Config->get_disable_disarm_during_roll()) {
1408 rec_enable_button->set_sensitive (false);
1410 rec_enable_button->set_sensitive (true);
1415 RouteUI::parameter_changed (string const & p)
1417 ENSURE_GUI_THREAD (bind (mem_fun (*this, &RouteUI::parameter_changed), p));
1419 if (p == "disable-disarm-during-roll") {
1420 check_rec_enable_sensitivity ();
1421 } else if (p == "solo-control-is-listen-control") {
1422 set_button_names ();
1423 } else if (p == "listen-position") {
1424 set_button_names ();
1429 RouteUI::step_gain_up ()
1431 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1435 RouteUI::page_gain_up ()
1437 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1441 RouteUI::step_gain_down ()
1443 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1447 RouteUI::page_gain_down ()
1449 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);