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/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
26 #include <gtkmm2ext/utils.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/controllable.h"
33 #include "pbd/enumwriter.h"
35 #include "ardour_ui.h"
38 #include "ardour_button.h"
42 #include "gui_thread.h"
43 #include "ardour_dialog.h"
44 #include "latency_gui.h"
45 #include "mixer_strip.h"
46 #include "automation_time_axis.h"
47 #include "route_time_axis.h"
48 #include "group_tabs.h"
50 #include "ardour/audio_track.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/filename_extensions.h"
53 #include "ardour/midi_track.h"
54 #include "ardour/internal_send.h"
55 #include "ardour/send.h"
56 #include "ardour/route.h"
57 #include "ardour/session.h"
58 #include "ardour/template_utils.h"
62 using namespace Gtkmm2ext;
63 using namespace ARDOUR;
64 using namespace ARDOUR_UI_UTILS;
68 uint32_t RouteUI::_max_invert_buttons = 3;
69 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
70 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
72 RouteUI::RouteUI (ARDOUR::Session* sess)
89 _route.reset (); /* drop reference to route, so that it can be cleaned up */
90 route_connections.drop_connections ();
96 delete comment_window;
97 delete input_selector;
98 delete output_selector;
101 send_blink_connection.disconnect ();
102 rec_blink_connection.disconnect ();
108 self_destruct = true;
114 pre_fader_mute_check = 0;
115 post_fader_mute_check = 0;
116 listen_mute_check = 0;
119 solo_isolated_check = 0;
120 solo_isolated_led = 0;
124 denormal_menu_item = 0;
126 multiple_mute_change = false;
127 multiple_solo_change = false;
128 _i_am_the_modifier = 0;
133 setup_invert_buttons ();
135 mute_button = manage (new ArdourButton);
136 mute_button->set_name ("mute button");
137 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
139 solo_button = manage (new ArdourButton);
140 solo_button->set_name ("solo button");
141 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
142 solo_button->set_no_show_all (true);
144 rec_enable_button = manage (new ArdourButton);
145 rec_enable_button->set_name ("record enable button");
146 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton));
147 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
149 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
150 rec_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
153 show_sends_button = manage (new ArdourButton);
154 show_sends_button->set_name ("send alert button");
155 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
157 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
158 monitor_input_button->set_name ("monitor button");
159 monitor_input_button->set_text (_("In"));
160 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
161 monitor_input_button->set_no_show_all (true);
163 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
164 monitor_disk_button->set_name ("monitor button");
165 monitor_disk_button->set_text (_("Disk"));
166 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
167 monitor_disk_button->set_no_show_all (true);
169 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
170 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
171 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
173 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
174 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
176 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
177 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
179 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
180 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
182 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
183 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
184 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
185 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
187 monitor_input_button->set_distinct_led_click (false);
188 monitor_disk_button->set_distinct_led_click (false);
190 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
191 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
193 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
194 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
196 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
202 route_connections.drop_connections ();
210 denormal_menu_item = 0;
214 RouteUI::self_delete ()
220 RouteUI::set_route (boost::shared_ptr<Route> rp)
226 if (set_color_from_route()) {
227 set_color (unique_random_color());
231 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
234 delete input_selector;
237 delete output_selector;
240 mute_button->set_controllable (_route->mute_control());
241 solo_button->set_controllable (_route->solo_control());
243 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
244 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
246 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
248 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
249 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
250 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
251 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
253 track()->TrackModeChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::track_mode_changed, this), gui_context());
254 track_mode_changed();
257 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
258 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
260 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
261 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
263 if (_session->writable() && is_track()) {
264 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
266 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
268 rec_enable_button->show();
269 rec_enable_button->set_controllable (t->rec_enable_control());
271 if (is_midi_track()) {
272 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
273 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
278 /* this will work for busses and tracks, and needs to be called to
279 set up the name entry/name label display.
283 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
284 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
286 update_monitoring_display ();
289 mute_button->unset_flags (Gtk::CAN_FOCUS);
290 solo_button->unset_flags (Gtk::CAN_FOCUS);
294 if (_route->is_monitor() || _route->is_master()) {
295 solo_button->hide ();
302 setup_invert_buttons ();
303 set_invert_button_state ();
305 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
306 bus_send_display_changed (s);
308 update_mute_display ();
309 update_solo_display ();
311 if (!ARDOUR_UI::config()->get_blink_rec_arm()) {
312 blink_rec_display(true); // set initial rec-en button state
315 route_color_changed();
319 RouteUI::polarity_changed ()
325 set_invert_button_state ();
329 RouteUI::mute_press (GdkEventButton* ev)
331 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
335 //if this is a binding action, let the ArdourButton handle it
336 if ( BindingProxy::is_bind_action(ev) )
339 multiple_mute_change = false;
341 if (Keyboard::is_context_menu_event (ev)) {
347 mute_menu->popup(0,ev->time);
353 if (Keyboard::is_button2_event (ev)) {
354 // button2-click is "momentary"
356 _mute_release = new SoloMuteRelease (_route->muted ());
359 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
361 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
363 /* toggle mute on everything (but
364 * exclude the master and monitor)
366 * because we are going to erase
367 * elements of the list we need to work
371 boost::shared_ptr<RouteList> copy (new RouteList);
373 *copy = *_session->get_routes ();
375 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
376 if ((*i)->is_master() || (*i)->is_monitor()) {
384 _mute_release->routes = copy;
388 _session->set_mute (copy, !_route->muted());
390 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
392 /* Primary-button1 applies change to the mix group even if it is not active
393 NOTE: Primary-button2 is MIDI learn.
396 boost::shared_ptr<RouteList> rl;
398 if (ev->button == 1) {
400 if (_route->route_group()) {
402 rl = _route->route_group()->route_list();
405 _mute_release->routes = rl;
408 rl.reset (new RouteList);
409 rl->push_back (_route);
413 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
418 /* plain click applies change to this route */
420 boost::shared_ptr<RouteList> rl (new RouteList);
421 rl->push_back (_route);
424 _mute_release->routes = rl;
427 _session->set_mute (rl, !_route->muted());
437 RouteUI::mute_release (GdkEventButton* /*ev*/)
441 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
442 delete _mute_release;
450 RouteUI::edit_output_configuration ()
452 if (output_selector == 0) {
454 boost::shared_ptr<Send> send;
455 boost::shared_ptr<IO> output;
457 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
458 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
459 output = send->output();
461 output = _route->output ();
464 output = _route->output ();
467 output_selector = new IOSelectorWindow (_session, output);
470 if (output_selector->is_visible()) {
471 output_selector->get_toplevel()->get_window()->raise();
473 output_selector->present ();
476 output_selector->set_keep_above (true);
480 RouteUI::edit_input_configuration ()
482 if (input_selector == 0) {
483 input_selector = new IOSelectorWindow (_session, _route->input());
486 if (input_selector->is_visible()) {
487 input_selector->get_toplevel()->get_window()->raise();
489 input_selector->present ();
492 input_selector->set_keep_above (true);
496 RouteUI::solo_press(GdkEventButton* ev)
498 /* ignore double/triple clicks */
500 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
504 //if this is a binding action, let the ArdourButton handle it
505 if ( BindingProxy::is_bind_action(ev) )
508 multiple_solo_change = false;
510 if (Keyboard::is_context_menu_event (ev)) {
512 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
513 ! (solo_safe_led && solo_safe_led->is_visible())) {
515 if (solo_menu == 0) {
519 solo_menu->popup (1, ev->time);
524 if (Keyboard::is_button2_event (ev)) {
526 // button2-click is "momentary"
527 _solo_release = new SoloMuteRelease (_route->self_soloed());
530 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
532 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
534 /* Primary-Tertiary-click applies change to all routes */
537 _solo_release->routes = _session->get_routes ();
541 if (Config->get_solo_control_is_listen_control()) {
542 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
544 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
547 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
549 // Primary-Secondary-click: exclusively solo this track
552 _solo_release->exclusive = true;
554 boost::shared_ptr<RouteList> routes = _session->get_routes();
556 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
557 if ((*i)->soloed ()) {
558 _solo_release->routes_on->push_back (*i);
560 _solo_release->routes_off->push_back (*i);
565 if (Config->get_solo_control_is_listen_control()) {
566 /* ??? we need a just_one_listen() method */
569 _session->set_just_one_solo (_route, true);
572 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
574 // shift-click: toggle solo isolated status
576 _route->set_solo_isolated (!_route->solo_isolated(), this);
577 delete _solo_release;
580 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
582 /* Primary-button1: solo mix group.
583 NOTE: Primary-button2 is MIDI learn.
586 /* Primary-button1 applies change to the mix group even if it is not active
587 NOTE: Primary-button2 is MIDI learn.
590 boost::shared_ptr<RouteList> rl;
592 if (ev->button == 1) {
594 if (_route->route_group()) {
596 rl = _route->route_group()->route_list();
599 _solo_release->routes = rl;
602 rl.reset (new RouteList);
603 rl->push_back (_route);
607 if (Config->get_solo_control_is_listen_control()) {
608 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
610 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
616 /* click: solo this route */
618 boost::shared_ptr<RouteList> rl (new RouteList);
619 rl->push_back (route());
622 _solo_release->routes = rl;
626 if (Config->get_solo_control_is_listen_control()) {
627 _session->set_listen (rl, !_route->listening_via_monitor());
629 _session->set_solo (rl, !_route->self_soloed());
639 RouteUI::solo_release (GdkEventButton* /*ev*/)
643 if (_solo_release->exclusive) {
647 if (Config->get_solo_control_is_listen_control()) {
648 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
650 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
654 delete _solo_release;
662 RouteUI::rec_enable_press(GdkEventButton* ev)
664 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
668 //if this is a binding action, let the ArdourButton handle it
669 if ( BindingProxy::is_bind_action(ev) )
672 if (!_session->engine().connected()) {
673 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
678 if (is_midi_track()) {
680 /* rec-enable button exits from step editing */
682 if (midi_track()->step_editing()) {
683 midi_track()->set_step_editing (false);
688 if (is_track() && rec_enable_button) {
690 if (Keyboard::is_button2_event (ev)) {
692 //rec arm does not have a momentary mode
695 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
698 _session->set_record_enabled (_session->get_routes(), !_route->record_enabled());
700 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
702 /* Primary-button1 applies change to the route group (even if it is not active)
703 NOTE: Primary-button2 is MIDI learn.
706 if (ev->button == 1) {
708 boost::shared_ptr<RouteList> rl;
710 if (_route->route_group()) {
712 rl = _route->route_group()->route_list();
715 rl.reset (new RouteList);
716 rl->push_back (_route);
720 _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
723 } else if (Keyboard::is_context_menu_event (ev)) {
725 /* do this on release */
729 boost::shared_ptr<RouteList> rl (new RouteList);
730 rl->push_back (route());
732 _session->set_record_enabled (rl, !_route->record_enabled());
740 RouteUI::monitoring_changed ()
742 update_monitoring_display ();
746 RouteUI::update_monitoring_display ()
752 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
758 MonitorState ms = t->monitoring_state();
760 if (t->monitoring_choice() & MonitorInput) {
761 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
763 if (ms & MonitoringInput) {
764 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
766 monitor_input_button->unset_active_state ();
770 if (t->monitoring_choice() & MonitorDisk) {
771 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
773 if (ms & MonitoringDisk) {
774 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
776 monitor_disk_button->unset_active_state ();
782 RouteUI::monitor_input_press(GdkEventButton*)
788 RouteUI::monitor_input_release(GdkEventButton* ev)
790 return monitor_release (ev, MonitorInput);
794 RouteUI::monitor_disk_press (GdkEventButton*)
800 RouteUI::monitor_disk_release (GdkEventButton* ev)
802 return monitor_release (ev, MonitorDisk);
806 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
808 if (ev->button != 1) {
812 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
819 boost::shared_ptr<RouteList> rl;
821 /* XXX for now, monitoring choices are orthogonal. cue monitoring
822 will follow in 3.X but requires mixing the input and playback (disk)
823 signal together, which requires yet more buffers.
826 if (t->monitoring_choice() & monitor_choice) {
827 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
829 /* this line will change when the options are non-orthogonal */
830 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
834 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
835 rl = _session->get_routes ();
837 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
838 if (_route->route_group() && _route->route_group()->is_monitoring()) {
839 rl = _route->route_group()->route_list();
841 rl.reset (new RouteList);
842 rl->push_back (route());
845 rl.reset (new RouteList);
846 rl->push_back (route());
850 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
856 RouteUI::build_record_menu ()
862 /* no rec-button context menu for non-MIDI tracks
865 if (is_midi_track()) {
866 record_menu = new Menu;
867 record_menu->set_name ("ArdourContextMenu");
869 using namespace Menu_Helpers;
870 MenuList& items = record_menu->items();
872 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
873 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
875 if (_route->record_enabled()) {
876 step_edit_item->set_sensitive (false);
879 step_edit_item->set_active (midi_track()->step_editing());
884 RouteUI::toggle_step_edit ()
886 if (!is_midi_track() || _route->record_enabled()) {
890 midi_track()->set_step_editing (step_edit_item->get_active());
894 RouteUI::step_edit_changed (bool yn)
897 if (rec_enable_button) {
898 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
901 start_step_editing ();
903 if (step_edit_item) {
904 step_edit_item->set_active (true);
909 if (rec_enable_button) {
910 rec_enable_button->unset_active_state ();
913 stop_step_editing ();
915 if (step_edit_item) {
916 step_edit_item->set_active (false);
922 RouteUI::rec_enable_release (GdkEventButton* ev)
924 if (Keyboard::is_context_menu_event (ev)) {
925 build_record_menu ();
927 record_menu->popup (1, ev->time);
936 RouteUI::build_sends_menu ()
938 using namespace Menu_Helpers;
940 sends_menu = new Menu;
941 sends_menu->set_name ("ArdourContextMenu");
942 MenuList& items = sends_menu->items();
945 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
949 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
953 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
957 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
961 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
965 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
968 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
972 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
975 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
976 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
977 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
982 RouteUI::create_sends (Placement p, bool include_buses)
984 _session->globally_add_internal_sends (_route, p, include_buses);
988 RouteUI::create_selected_sends (Placement p, bool include_buses)
990 boost::shared_ptr<RouteList> rlist (new RouteList);
991 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
993 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
994 RouteTimeAxisView* rtv;
996 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
997 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
998 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
999 rlist->push_back (rui->route());
1005 _session->add_internal_sends (_route, p, rlist);
1009 RouteUI::set_sends_gain_from_track ()
1011 _session->globally_set_send_gains_from_track (_route);
1015 RouteUI::set_sends_gain_to_zero ()
1017 _session->globally_set_send_gains_to_zero (_route);
1021 RouteUI::set_sends_gain_to_unity ()
1023 _session->globally_set_send_gains_to_unity (_route);
1027 RouteUI::show_sends_press(GdkEventButton* ev)
1029 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1033 if (!is_track() && show_sends_button) {
1035 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1037 // do nothing on midi sigc::bind event
1040 } else if (Keyboard::is_context_menu_event (ev)) {
1042 if (sends_menu == 0) {
1043 build_sends_menu ();
1046 sends_menu->popup (0, ev->time);
1050 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1053 set_showing_sends_to (boost::shared_ptr<Route> ());
1055 set_showing_sends_to (_route);
1064 RouteUI::show_sends_release (GdkEventButton*)
1070 RouteUI::send_blink (bool onoff)
1072 if (!show_sends_button) {
1077 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1079 show_sends_button->unset_active_state ();
1083 Gtkmm2ext::ActiveState
1084 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1086 if (r->is_master() || r->is_monitor()) {
1087 return Gtkmm2ext::Off;
1090 if (Config->get_solo_control_is_listen_control()) {
1092 if (r->listening_via_monitor()) {
1093 return Gtkmm2ext::ExplicitActive;
1095 return Gtkmm2ext::Off;
1101 if (!r->self_soloed()) {
1102 return Gtkmm2ext::ImplicitActive;
1104 return Gtkmm2ext::ExplicitActive;
1107 return Gtkmm2ext::Off;
1111 Gtkmm2ext::ActiveState
1112 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1114 if (r->is_master() || r->is_monitor()) {
1115 return Gtkmm2ext::Off;
1118 if (r->solo_isolated()) {
1119 return Gtkmm2ext::ExplicitActive;
1121 return Gtkmm2ext::Off;
1125 Gtkmm2ext::ActiveState
1126 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1128 if (r->is_master() || r->is_monitor()) {
1129 return Gtkmm2ext::Off;
1132 if (r->solo_safe()) {
1133 return Gtkmm2ext::ExplicitActive;
1135 return Gtkmm2ext::Off;
1140 RouteUI::update_solo_display ()
1142 bool yn = _route->solo_safe ();
1144 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1145 solo_safe_check->set_active (yn);
1148 yn = _route->solo_isolated ();
1150 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1151 solo_isolated_check->set_active (yn);
1154 set_button_names ();
1156 if (solo_isolated_led) {
1157 if (_route->solo_isolated()) {
1158 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1160 solo_isolated_led->unset_active_state ();
1164 if (solo_safe_led) {
1165 if (_route->solo_safe()) {
1166 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1168 solo_safe_led->unset_active_state ();
1172 solo_button->set_active_state (solo_active_state (_route));
1174 /* some changes to solo status can affect mute display, so catch up
1177 update_mute_display ();
1181 RouteUI::solo_changed_so_update_mute ()
1183 update_mute_display ();
1187 RouteUI::mute_changed(void* /*src*/)
1189 update_mute_display ();
1193 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1195 if (r->is_monitor()) {
1196 return ActiveState(0);
1200 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1204 return Gtkmm2ext::ExplicitActive;
1205 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1206 /* master is NEVER muted by others */
1207 return Gtkmm2ext::ImplicitActive;
1209 /* no mute at all */
1210 return Gtkmm2ext::Off;
1217 return Gtkmm2ext::ExplicitActive;
1219 /* no mute at all */
1220 return Gtkmm2ext::Off;
1224 return ActiveState(0);
1228 RouteUI::update_mute_display ()
1234 mute_button->set_active_state (mute_active_state (_session, _route));
1238 RouteUI::route_rec_enable_changed ()
1240 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1241 update_monitoring_display ();
1245 RouteUI::session_rec_enable_changed ()
1247 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1248 update_monitoring_display ();
1252 RouteUI::blink_rec_display (bool blinkOn)
1254 if (!rec_enable_button || !_route) {
1257 if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1261 if (_route->record_enabled()) {
1262 switch (_session->record_status ()) {
1263 case Session::Recording:
1264 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1267 case Session::Disabled:
1268 case Session::Enabled:
1269 if ( ARDOUR_UI::config()->get_blink_rec_arm() )
1270 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1272 rec_enable_button->set_active_state ( ImplicitActive );
1277 if (step_edit_item) {
1278 step_edit_item->set_sensitive (false);
1282 rec_enable_button->unset_active_state ();
1284 if (step_edit_item) {
1285 step_edit_item->set_sensitive (true);
1290 check_rec_enable_sensitivity ();
1294 RouteUI::build_solo_menu (void)
1296 using namespace Menu_Helpers;
1298 solo_menu = new Menu;
1299 solo_menu->set_name ("ArdourContextMenu");
1300 MenuList& items = solo_menu->items();
1301 Gtk::CheckMenuItem* check;
1303 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1304 check->set_active (_route->solo_isolated());
1305 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1306 items.push_back (CheckMenuElem(*check));
1307 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1310 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1311 check->set_active (_route->solo_safe());
1312 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1313 items.push_back (CheckMenuElem(*check));
1314 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1317 //items.push_back (SeparatorElem());
1318 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1323 RouteUI::build_mute_menu(void)
1325 using namespace Menu_Helpers;
1327 mute_menu = new Menu;
1328 mute_menu->set_name ("ArdourContextMenu");
1330 MenuList& items = mute_menu->items();
1332 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1333 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1334 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1335 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1336 pre_fader_mute_check->show_all();
1338 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1339 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1340 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1341 items.push_back (CheckMenuElem(*post_fader_mute_check));
1342 post_fader_mute_check->show_all();
1344 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1345 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1346 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1347 items.push_back (CheckMenuElem(*listen_mute_check));
1348 listen_mute_check->show_all();
1350 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1351 init_mute_menu(MuteMaster::Main, main_mute_check);
1352 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1353 items.push_back (CheckMenuElem(*main_mute_check));
1354 main_mute_check->show_all();
1356 //items.push_back (SeparatorElem());
1357 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1359 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1363 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1365 check->set_active (_route->mute_points() & mp);
1369 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1371 if (check->get_active()) {
1372 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1374 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1379 RouteUI::muting_change ()
1381 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1384 MuteMaster::MutePoint current = _route->mute_points ();
1386 yn = (current & MuteMaster::PreFader);
1388 if (pre_fader_mute_check->get_active() != yn) {
1389 pre_fader_mute_check->set_active (yn);
1392 yn = (current & MuteMaster::PostFader);
1394 if (post_fader_mute_check->get_active() != yn) {
1395 post_fader_mute_check->set_active (yn);
1398 yn = (current & MuteMaster::Listen);
1400 if (listen_mute_check->get_active() != yn) {
1401 listen_mute_check->set_active (yn);
1404 yn = (current & MuteMaster::Main);
1406 if (main_mute_check->get_active() != yn) {
1407 main_mute_check->set_active (yn);
1412 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1414 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1418 bool view = solo_isolated_led->active_state();
1419 bool model = _route->solo_isolated();
1421 /* called BEFORE the view has changed */
1423 if (ev->button == 1) {
1424 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1427 /* disable isolate for all routes */
1428 DisplaySuspender ds;
1429 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1433 if (model == view) {
1435 /* flip just this route */
1437 boost::shared_ptr<RouteList> rl (new RouteList);
1438 rl->push_back (_route);
1439 DisplaySuspender ds;
1440 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1449 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1451 if (ev->button == 1) {
1452 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1458 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1460 bool view = check->get_active();
1461 bool model = _route->solo_isolated();
1463 /* called AFTER the view has changed */
1465 if (model != view) {
1466 _route->set_solo_isolated (view, this);
1471 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1473 _route->set_solo_safe (check->get_active(), this);
1476 /** Ask the user to choose a colour, and then apply that color to my route
1479 RouteUI::choose_color ()
1482 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1489 /** Set the route's own color. This may not be used for display if
1490 * the route is in a group which shares its color with its routes.
1493 RouteUI::set_color (const Gdk::Color & c)
1495 /* leave _color alone in the group case so that tracks can retain their
1496 * own pre-group colors.
1501 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1503 /* note: we use the route state ID here so that color is the same for both
1504 the time axis view and the mixer strip
1507 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1508 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1511 /** @return GUI state ID for things that are common to the route in all its representations */
1513 RouteUI::route_state_id () const
1515 return string_compose (X_("route %1"), _route->id().to_s());
1519 RouteUI::set_color_from_route ()
1521 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1529 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1532 _color.set_green (g);
1533 _color.set_blue (b);
1539 RouteUI::remove_this_route (bool apply_to_selection)
1541 if (apply_to_selection) {
1542 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1544 if ((route()->is_master() || route()->is_monitor()) &&
1545 !Config->get_allow_special_bus_removal()) {
1546 MessageDialog msg (_("That would be bad news ...."),
1550 msg.set_secondary_text (string_compose (_(
1551 "Removing the master or monitor bus is such a bad idea\n\
1552 that %1 is not going to allow it.\n\
1554 If you really want to do this sort of thing\n\
1555 edit your ardour.rc file to set the\n\
1556 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1563 vector<string> choices;
1567 prompt = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1569 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1572 choices.push_back (_("No, do nothing."));
1573 choices.push_back (_("Yes, remove it."));
1577 title = _("Remove track");
1579 title = _("Remove bus");
1582 Choice prompter (title, prompt, choices);
1584 if (prompter.run () == 1) {
1585 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1591 RouteUI::idle_remove_this_route (RouteUI *rui)
1593 DisplaySuspender ds;
1594 rui->_session->remove_route (rui->route());
1598 /** @return true if this name should be used for the route, otherwise false */
1600 RouteUI::verify_new_route_name (const std::string& name)
1602 if (name.find (':') == string::npos) {
1606 MessageDialog colon_msg (
1607 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1608 false, MESSAGE_QUESTION, BUTTONS_NONE
1611 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1612 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1614 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1618 RouteUI::route_rename ()
1620 ArdourPrompter name_prompter (true);
1625 name_prompter.set_title (_("Rename Track"));
1627 name_prompter.set_title (_("Rename Bus"));
1629 name_prompter.set_prompt (_("New name:"));
1630 name_prompter.set_initial_text (_route->name());
1631 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1632 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1633 name_prompter.show_all ();
1636 switch (name_prompter.run ()) {
1637 case Gtk::RESPONSE_ACCEPT:
1638 name_prompter.get_result (result);
1639 name_prompter.hide ();
1640 if (result.length()) {
1641 if (verify_new_route_name (result)) {
1642 _route->set_name (result);
1645 /* back to name prompter */
1649 /* nothing entered, just get out of here */
1664 RouteUI::property_changed (const PropertyChange& what_changed)
1666 if (what_changed.contains (ARDOUR::Properties::name)) {
1667 name_label.set_text (_route->name());
1672 RouteUI::toggle_comment_editor ()
1674 // if (ignore_toggle) {
1678 if (comment_window && comment_window->is_visible ()) {
1679 comment_window->hide ();
1681 open_comment_editor ();
1687 RouteUI::open_comment_editor ()
1689 if (comment_window == 0) {
1690 setup_comment_editor ();
1694 title = _route->name();
1695 title += _(": comment editor");
1697 comment_window->set_title (title);
1698 comment_window->present();
1702 RouteUI::setup_comment_editor ()
1704 comment_window = new ArdourWindow (""); // title will be reset to show route
1705 comment_window->set_skip_taskbar_hint (true);
1706 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1707 comment_window->set_default_size (400, 200);
1709 comment_area = manage (new TextView());
1710 comment_area->set_name ("MixerTrackCommentArea");
1711 comment_area->set_wrap_mode (WRAP_WORD);
1712 comment_area->set_editable (true);
1713 comment_area->get_buffer()->set_text (_route->comment());
1714 comment_area->show ();
1716 comment_window->add (*comment_area);
1720 RouteUI::comment_changed (void *src)
1722 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1725 ignore_comment_edit = true;
1727 comment_area->get_buffer()->set_text (_route->comment());
1729 ignore_comment_edit = false;
1734 RouteUI::comment_editor_done_editing ()
1736 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1738 string const str = comment_area->get_buffer()->get_text();
1739 if (str == _route->comment ()) {
1743 _route->set_comment (str, this);
1747 RouteUI::set_route_active (bool a, bool apply_to_selection)
1749 if (apply_to_selection) {
1750 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1752 _route->set_active (a, this);
1757 RouteUI::toggle_denormal_protection ()
1759 if (denormal_menu_item) {
1763 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1765 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1766 _route->set_denormal_protection (x);
1772 RouteUI::denormal_protection_changed ()
1774 if (denormal_menu_item) {
1775 denormal_menu_item->set_active (_route->denormal_protection());
1780 RouteUI::disconnect_input ()
1782 _route->input()->disconnect (this);
1786 RouteUI::disconnect_output ()
1788 _route->output()->disconnect (this);
1792 RouteUI::is_track () const
1794 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1797 boost::shared_ptr<Track>
1798 RouteUI::track() const
1800 return boost::dynamic_pointer_cast<Track>(_route);
1804 RouteUI::is_audio_track () const
1806 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1809 boost::shared_ptr<AudioTrack>
1810 RouteUI::audio_track() const
1812 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1816 RouteUI::is_midi_track () const
1818 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1821 boost::shared_ptr<MidiTrack>
1822 RouteUI::midi_track() const
1824 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1828 RouteUI::has_audio_outputs () const
1830 return (_route->n_outputs().n_audio() > 0);
1834 RouteUI::name() const
1836 return _route->name();
1840 RouteUI::map_frozen ()
1842 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1844 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1847 switch (at->freeze_state()) {
1848 case AudioTrack::Frozen:
1849 rec_enable_button->set_sensitive (false);
1852 rec_enable_button->set_sensitive (true);
1859 RouteUI::adjust_latency ()
1861 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1865 RouteUI::save_as_template ()
1868 std::string safe_name;
1871 path = ARDOUR::user_route_template_directory ();
1873 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1874 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1878 Prompter p (true); // modal
1880 p.set_title (_("Save As Template"));
1881 p.set_prompt (_("Template name:"));
1882 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1884 case RESPONSE_ACCEPT:
1891 p.get_result (name, true);
1893 safe_name = legalize_for_path (name);
1894 safe_name += template_suffix;
1896 path = Glib::build_filename (path, safe_name);
1898 _route->save_as_template (path, name);
1902 RouteUI::check_rec_enable_sensitivity ()
1904 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1905 rec_enable_button->set_sensitive (false);
1907 rec_enable_button->set_sensitive (true);
1910 update_monitoring_display ();
1914 RouteUI::parameter_changed (string const & p)
1916 /* this handles RC and per-session parameter changes */
1918 if (p == "disable-disarm-during-roll") {
1919 check_rec_enable_sensitivity ();
1920 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1921 set_button_names ();
1922 } else if (p == "auto-input") {
1923 update_monitoring_display ();
1924 } else if (p == "blink-rec-arm") {
1925 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
1926 rec_blink_connection.disconnect ();
1927 rec_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1929 rec_blink_connection.disconnect ();
1930 RouteUI::blink_rec_display(false);
1936 RouteUI::step_gain_up ()
1938 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1942 RouteUI::page_gain_up ()
1944 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1948 RouteUI::step_gain_down ()
1950 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1954 RouteUI::page_gain_down ()
1956 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1960 RouteUI::open_remote_control_id_dialog ()
1962 ArdourDialog dialog (_("Remote Control ID"));
1963 SpinButton* spin = 0;
1965 dialog.get_vbox()->set_border_width (18);
1967 if (Config->get_remote_model() == UserOrdered) {
1968 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1970 HBox* hbox = manage (new HBox);
1971 hbox->set_spacing (6);
1972 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1973 spin = manage (new SpinButton);
1974 spin->set_digits (0);
1975 spin->set_increments (1, 10);
1976 spin->set_range (0, limit);
1977 spin->set_value (_route->remote_control_id());
1978 hbox->pack_start (*spin);
1979 dialog.get_vbox()->pack_start (*hbox);
1981 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1982 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1984 Label* l = manage (new Label());
1985 if (_route->is_master() || _route->is_monitor()) {
1986 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1987 "The remote control ID of %3 cannot be changed."),
1988 Glib::Markup::escape_text (_route->name()),
1989 _route->remote_control_id(),
1990 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1992 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1993 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1994 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1995 (is_track() ? _("track") : _("bus")),
1996 _route->remote_control_id(),
1997 "<span size=\"small\" style=\"italic\">",
1999 Glib::Markup::escape_text (_route->name()),
2002 dialog.get_vbox()->pack_start (*l);
2003 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
2007 int const r = dialog.run ();
2009 if (r == RESPONSE_ACCEPT && spin) {
2010 _route->set_remote_control_id (spin->get_value_as_int ());
2015 RouteUI::setup_invert_buttons ()
2017 /* remove old invert buttons */
2018 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
2019 _invert_button_box.remove (**i);
2022 _invert_buttons.clear ();
2024 if (!_route || !_route->input()) {
2028 uint32_t const N = _route->input()->n_ports().n_audio ();
2030 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2032 for (uint32_t i = 0; i < to_add; ++i) {
2033 ArdourButton* b = manage (new ArdourButton);
2034 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2035 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2037 b->set_name (X_("invert button"));
2040 b->set_text (string_compose (X_("Ø (%1)"), N));
2042 b->set_text (X_("Ø"));
2045 b->set_text (string_compose (X_("Ø%1"), i + 1));
2048 if (N <= _max_invert_buttons) {
2049 UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) channel %1 of this track. Right-click to show menu."), i + 1));
2051 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2054 _invert_buttons.push_back (b);
2055 _invert_button_box.pack_start (*b);
2058 _invert_button_box.set_spacing (1);
2059 _invert_button_box.show_all ();
2063 RouteUI::set_invert_button_state ()
2065 uint32_t const N = _route->input()->n_ports().n_audio();
2066 if (N > _max_invert_buttons) {
2068 /* One button for many channels; explicit active if all channels are inverted,
2069 implicit active if some are, off if none are.
2072 ArdourButton* b = _invert_buttons.front ();
2074 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2075 b->set_active_state (Gtkmm2ext::ExplicitActive);
2076 } else if (_route->phase_invert().any()) {
2077 b->set_active_state (Gtkmm2ext::ImplicitActive);
2079 b->set_active_state (Gtkmm2ext::Off);
2084 /* One button per channel; just set active */
2087 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2088 (*i)->set_active (_route->phase_invert (j));
2095 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2097 if (ev->button == 1 && i < _invert_buttons.size()) {
2098 uint32_t const N = _route->input()->n_ports().n_audio ();
2099 if (N <= _max_invert_buttons) {
2100 /* left-click inverts phase so long as we have a button per channel */
2101 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2110 RouteUI::invert_press (GdkEventButton* ev)
2112 using namespace Menu_Helpers;
2114 uint32_t const N = _route->input()->n_ports().n_audio();
2115 if (N <= _max_invert_buttons && ev->button != 3) {
2116 /* If we have an invert button per channel, we only pop
2117 up a menu on right-click; left click is handled
2123 delete _invert_menu;
2124 _invert_menu = new Menu;
2125 _invert_menu->set_name ("ArdourContextMenu");
2126 MenuList& items = _invert_menu->items ();
2128 for (uint32_t i = 0; i < N; ++i) {
2129 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2130 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2131 ++_i_am_the_modifier;
2132 e->set_active (_route->phase_invert (i));
2133 --_i_am_the_modifier;
2136 _invert_menu->popup (0, ev->time);
2142 RouteUI::invert_menu_toggled (uint32_t c)
2144 if (_i_am_the_modifier) {
2148 _route->set_phase_invert (c, !_route->phase_invert (c));
2152 RouteUI::set_invert_sensitive (bool yn)
2154 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2155 (*b)->set_sensitive (yn);
2160 RouteUI::request_redraw ()
2163 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2167 /** The Route's gui_changed signal has been emitted */
2169 RouteUI::route_gui_changed (string what_changed)
2171 if (what_changed == "color") {
2172 if (set_color_from_route () == 0) {
2173 route_color_changed ();
2179 RouteUI::track_mode_changed (void)
2182 switch (track()->mode()) {
2183 case ARDOUR::NonLayered:
2184 case ARDOUR::Normal:
2185 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton));
2187 case ARDOUR::Destructive:
2188 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton|ArdourButton::RecTapeMode));
2191 rec_enable_button->queue_draw();
2194 /** @return the color that this route should use; it maybe its own,
2195 or it maybe that of its route group.
2198 RouteUI::color () const
2200 RouteGroup* g = _route->route_group ();
2202 if (g && g->is_color()) {
2204 set_color_from_rgba (c, GroupTabs::group_color (g));
2212 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2214 _showing_sends_to = send_to;
2215 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2219 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2221 if (_route == send_to) {
2222 show_sends_button->set_active (true);
2223 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2225 show_sends_button->set_active (false);
2226 send_blink_connection.disconnect ();
2231 RouteUI::route_group() const
2233 return _route->route_group();