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 "ui_config.h"
52 #include "ardour/audio_track.h"
53 #include "ardour/audioengine.h"
54 #include "ardour/filename_extensions.h"
55 #include "ardour/midi_track.h"
56 #include "ardour/internal_send.h"
57 #include "ardour/send.h"
58 #include "ardour/route.h"
59 #include "ardour/session.h"
60 #include "ardour/template_utils.h"
64 using namespace Gtkmm2ext;
65 using namespace ARDOUR;
66 using namespace ARDOUR_UI_UTILS;
70 uint32_t RouteUI::_max_invert_buttons = 3;
71 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
72 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
74 RouteUI::RouteUI (ARDOUR::Session* sess)
92 gui_object_state().remove_node (route_state_id());
95 _route.reset (); /* drop reference to route, so that it can be cleaned up */
96 route_connections.drop_connections ();
102 delete comment_window;
103 delete input_selector;
104 delete output_selector;
107 send_blink_connection.disconnect ();
108 rec_blink_connection.disconnect ();
114 self_destruct = true;
120 pre_fader_mute_check = 0;
121 post_fader_mute_check = 0;
122 listen_mute_check = 0;
125 solo_isolated_check = 0;
126 solo_isolated_led = 0;
130 denormal_menu_item = 0;
132 multiple_mute_change = false;
133 multiple_solo_change = false;
134 _i_am_the_modifier = 0;
139 setup_invert_buttons ();
141 mute_button = manage (new ArdourButton);
142 mute_button->set_name ("mute button");
143 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
145 solo_button = manage (new ArdourButton);
146 solo_button->set_name ("solo button");
147 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
148 solo_button->set_no_show_all (true);
150 rec_enable_button = manage (new ArdourButton);
151 rec_enable_button->set_name ("record enable button");
152 rec_enable_button->set_icon (ArdourIcon::RecButton);
153 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
155 if (UIConfiguration::instance().get_blink_rec_arm()) {
156 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
159 show_sends_button = manage (new ArdourButton);
160 show_sends_button->set_name ("send alert button");
161 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
163 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
164 monitor_input_button->set_name ("monitor button");
165 monitor_input_button->set_text (_("In"));
166 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
167 monitor_input_button->set_no_show_all (true);
169 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
170 monitor_disk_button->set_name ("monitor button");
171 monitor_disk_button->set_text (_("Disk"));
172 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
173 monitor_disk_button->set_no_show_all (true);
175 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
176 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
177 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
179 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
180 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
182 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
183 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
185 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
186 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
188 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
189 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
190 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
191 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
193 monitor_input_button->set_distinct_led_click (false);
194 monitor_disk_button->set_distinct_led_click (false);
196 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
197 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
199 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
200 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
202 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
208 route_connections.drop_connections ();
216 denormal_menu_item = 0;
220 RouteUI::self_delete ()
226 RouteUI::set_route (boost::shared_ptr<Route> rp)
232 if (set_color_from_route()) {
233 set_color (unique_random_color());
237 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
240 delete input_selector;
243 delete output_selector;
246 mute_button->set_controllable (_route->mute_control());
247 solo_button->set_controllable (_route->solo_control());
249 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
250 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context());
252 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
254 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
255 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
256 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
257 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
259 track()->TrackModeChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::track_mode_changed, this), gui_context());
260 track_mode_changed();
263 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
264 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
266 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
267 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
269 if (_session->writable() && is_track()) {
270 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
272 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
274 rec_enable_button->show();
275 rec_enable_button->set_controllable (t->rec_enable_control());
277 if (is_midi_track()) {
278 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
279 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
284 /* this will work for busses and tracks, and needs to be called to
285 set up the name entry/name label display.
289 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
290 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
292 update_monitoring_display ();
295 mute_button->unset_flags (Gtk::CAN_FOCUS);
296 solo_button->unset_flags (Gtk::CAN_FOCUS);
300 if (_route->is_monitor() || _route->is_master()) {
301 solo_button->hide ();
308 setup_invert_buttons ();
309 set_invert_button_state ();
311 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
312 bus_send_display_changed (s);
314 update_mute_display ();
315 update_solo_display ();
317 if (!UIConfiguration::instance().get_blink_rec_arm()) {
318 blink_rec_display(true); // set initial rec-en button state
321 route_color_changed();
325 RouteUI::polarity_changed ()
331 set_invert_button_state ();
335 RouteUI::mute_press (GdkEventButton* ev)
337 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
341 //if this is a binding action, let the ArdourButton handle it
342 if ( BindingProxy::is_bind_action(ev) )
345 multiple_mute_change = false;
347 if (Keyboard::is_context_menu_event (ev)) {
353 mute_menu->popup(0,ev->time);
359 if (Keyboard::is_button2_event (ev)) {
360 // button2-click is "momentary"
362 _mute_release = new SoloMuteRelease (_route->muted ());
365 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
367 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
369 /* toggle mute on everything (but
370 * exclude the master and monitor)
372 * because we are going to erase
373 * elements of the list we need to work
377 boost::shared_ptr<RouteList> copy (new RouteList);
379 *copy = *_session->get_routes ();
381 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
382 if ((*i)->is_master() || (*i)->is_monitor()) {
390 _mute_release->routes = copy;
394 _session->set_mute (copy, !_route->muted());
396 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
398 /* Primary-button1 applies change to the mix group even if it is not active
399 NOTE: Primary-button2 is MIDI learn.
402 boost::shared_ptr<RouteList> rl;
404 if (ev->button == 1) {
406 if (_route->route_group()) {
408 rl = _route->route_group()->route_list();
411 _mute_release->routes = rl;
414 rl.reset (new RouteList);
415 rl->push_back (_route);
419 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
424 /* plain click applies change to this route */
426 boost::shared_ptr<RouteList> rl (new RouteList);
427 rl->push_back (_route);
430 _mute_release->routes = rl;
433 _session->set_mute (rl, !_route->muted());
443 RouteUI::mute_release (GdkEventButton* /*ev*/)
447 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
448 delete _mute_release;
456 RouteUI::edit_output_configuration ()
458 if (output_selector == 0) {
460 boost::shared_ptr<Send> send;
461 boost::shared_ptr<IO> output;
463 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
464 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
465 output = send->output();
467 output = _route->output ();
470 output = _route->output ();
473 output_selector = new IOSelectorWindow (_session, output);
476 if (output_selector->is_visible()) {
477 output_selector->get_toplevel()->get_window()->raise();
479 output_selector->present ();
482 //output_selector->set_keep_above (true);
486 RouteUI::edit_input_configuration ()
488 if (input_selector == 0) {
489 input_selector = new IOSelectorWindow (_session, _route->input());
492 if (input_selector->is_visible()) {
493 input_selector->get_toplevel()->get_window()->raise();
495 input_selector->present ();
498 //input_selector->set_keep_above (true);
502 RouteUI::solo_press(GdkEventButton* ev)
504 /* ignore double/triple clicks */
506 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
510 //if this is a binding action, let the ArdourButton handle it
511 if ( BindingProxy::is_bind_action(ev) )
514 multiple_solo_change = false;
516 if (Keyboard::is_context_menu_event (ev)) {
518 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
519 ! (solo_safe_led && solo_safe_led->is_visible())) {
521 if (solo_menu == 0) {
525 solo_menu->popup (1, ev->time);
530 if (Keyboard::is_button2_event (ev)) {
532 // button2-click is "momentary"
533 _solo_release = new SoloMuteRelease (_route->self_soloed());
536 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
538 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
540 /* Primary-Tertiary-click applies change to all routes */
543 _solo_release->routes = _session->get_routes ();
547 if (Config->get_solo_control_is_listen_control()) {
548 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
550 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
553 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
555 // Primary-Secondary-click: exclusively solo this track
558 _solo_release->exclusive = true;
560 boost::shared_ptr<RouteList> routes = _session->get_routes();
562 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
563 if ((*i)->soloed ()) {
564 _solo_release->routes_on->push_back (*i);
566 _solo_release->routes_off->push_back (*i);
571 if (Config->get_solo_control_is_listen_control()) {
572 /* ??? we need a just_one_listen() method */
575 _session->set_just_one_solo (_route, true);
578 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
580 // shift-click: toggle solo isolated status
582 _route->set_solo_isolated (!_route->solo_isolated(), this);
583 delete _solo_release;
586 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
588 /* Primary-button1: solo mix group.
589 NOTE: Primary-button2 is MIDI learn.
592 /* Primary-button1 applies change to the mix group even if it is not active
593 NOTE: Primary-button2 is MIDI learn.
596 boost::shared_ptr<RouteList> rl;
598 if (ev->button == 1) {
600 if (_route->route_group()) {
602 rl = _route->route_group()->route_list();
605 _solo_release->routes = rl;
608 rl.reset (new RouteList);
609 rl->push_back (_route);
613 if (Config->get_solo_control_is_listen_control()) {
614 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
616 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
622 /* click: solo this route */
624 boost::shared_ptr<RouteList> rl (new RouteList);
625 rl->push_back (route());
628 _solo_release->routes = rl;
632 if (Config->get_solo_control_is_listen_control()) {
633 _session->set_listen (rl, !_route->listening_via_monitor());
635 _session->set_solo (rl, !_route->self_soloed());
645 RouteUI::solo_release (GdkEventButton* /*ev*/)
649 if (_solo_release->exclusive) {
653 if (Config->get_solo_control_is_listen_control()) {
654 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
656 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
660 delete _solo_release;
668 RouteUI::rec_enable_press(GdkEventButton* ev)
670 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
674 //if this is a binding action, let the ArdourButton handle it
675 if ( BindingProxy::is_bind_action(ev) )
678 if (!_session->engine().connected()) {
679 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
684 if (is_midi_track()) {
686 /* rec-enable button exits from step editing */
688 if (midi_track()->step_editing()) {
689 midi_track()->set_step_editing (false);
694 if (is_track() && rec_enable_button) {
696 if (Keyboard::is_button2_event (ev)) {
698 //rec arm does not have a momentary mode
701 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
704 _session->set_record_enabled (_session->get_routes(), !_route->record_enabled());
706 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
708 /* Primary-button1 applies change to the route group (even if it is not active)
709 NOTE: Primary-button2 is MIDI learn.
712 if (ev->button == 1) {
714 boost::shared_ptr<RouteList> rl;
716 if (_route->route_group()) {
718 rl = _route->route_group()->route_list();
721 rl.reset (new RouteList);
722 rl->push_back (_route);
726 _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
729 } else if (Keyboard::is_context_menu_event (ev)) {
731 /* do this on release */
735 boost::shared_ptr<RouteList> rl (new RouteList);
736 rl->push_back (route());
738 _session->set_record_enabled (rl, !_route->record_enabled());
746 RouteUI::monitoring_changed ()
748 update_monitoring_display ();
752 RouteUI::update_monitoring_display ()
758 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
764 MonitorState ms = t->monitoring_state();
766 if (t->monitoring_choice() & MonitorInput) {
767 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
769 if (ms & MonitoringInput) {
770 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
772 monitor_input_button->unset_active_state ();
776 if (t->monitoring_choice() & MonitorDisk) {
777 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
779 if (ms & MonitoringDisk) {
780 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
782 monitor_disk_button->unset_active_state ();
788 RouteUI::monitor_input_press(GdkEventButton*)
794 RouteUI::monitor_input_release(GdkEventButton* ev)
796 return monitor_release (ev, MonitorInput);
800 RouteUI::monitor_disk_press (GdkEventButton*)
806 RouteUI::monitor_disk_release (GdkEventButton* ev)
808 return monitor_release (ev, MonitorDisk);
812 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
814 if (ev->button != 1) {
818 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
825 boost::shared_ptr<RouteList> rl;
827 /* XXX for now, monitoring choices are orthogonal. cue monitoring
828 will follow in 3.X but requires mixing the input and playback (disk)
829 signal together, which requires yet more buffers.
832 if (t->monitoring_choice() & monitor_choice) {
833 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
835 /* this line will change when the options are non-orthogonal */
836 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
840 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
841 rl = _session->get_routes ();
843 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
844 if (_route->route_group() && _route->route_group()->is_monitoring()) {
845 rl = _route->route_group()->route_list();
847 rl.reset (new RouteList);
848 rl->push_back (route());
851 rl.reset (new RouteList);
852 rl->push_back (route());
856 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
862 RouteUI::build_record_menu ()
868 /* no rec-button context menu for non-MIDI tracks
871 if (is_midi_track()) {
872 record_menu = new Menu;
873 record_menu->set_name ("ArdourContextMenu");
875 using namespace Menu_Helpers;
876 MenuList& items = record_menu->items();
878 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
879 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
881 if (_route->record_enabled()) {
882 step_edit_item->set_sensitive (false);
885 step_edit_item->set_active (midi_track()->step_editing());
890 RouteUI::toggle_step_edit ()
892 if (!is_midi_track() || _route->record_enabled()) {
896 midi_track()->set_step_editing (step_edit_item->get_active());
900 RouteUI::step_edit_changed (bool yn)
903 if (rec_enable_button) {
904 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
907 start_step_editing ();
909 if (step_edit_item) {
910 step_edit_item->set_active (true);
915 if (rec_enable_button) {
916 rec_enable_button->unset_active_state ();
919 stop_step_editing ();
921 if (step_edit_item) {
922 step_edit_item->set_active (false);
928 RouteUI::rec_enable_release (GdkEventButton* ev)
930 if (Keyboard::is_context_menu_event (ev)) {
931 build_record_menu ();
933 record_menu->popup (1, ev->time);
942 RouteUI::build_sends_menu ()
944 using namespace Menu_Helpers;
946 sends_menu = new Menu;
947 sends_menu->set_name ("ArdourContextMenu");
948 MenuList& items = sends_menu->items();
951 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
955 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
959 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
963 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
967 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
971 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
974 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
978 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
981 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
982 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
983 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
988 RouteUI::create_sends (Placement p, bool include_buses)
990 _session->globally_add_internal_sends (_route, p, include_buses);
994 RouteUI::create_selected_sends (Placement p, bool include_buses)
996 boost::shared_ptr<RouteList> rlist (new RouteList);
997 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
999 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
1000 RouteTimeAxisView* rtv;
1002 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1003 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1004 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1005 rlist->push_back (rui->route());
1011 _session->add_internal_sends (_route, p, rlist);
1015 RouteUI::set_sends_gain_from_track ()
1017 _session->globally_set_send_gains_from_track (_route);
1021 RouteUI::set_sends_gain_to_zero ()
1023 _session->globally_set_send_gains_to_zero (_route);
1027 RouteUI::set_sends_gain_to_unity ()
1029 _session->globally_set_send_gains_to_unity (_route);
1033 RouteUI::show_sends_press(GdkEventButton* ev)
1035 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1039 if (!is_track() && show_sends_button) {
1041 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1043 // do nothing on midi sigc::bind event
1046 } else if (Keyboard::is_context_menu_event (ev)) {
1048 if (sends_menu == 0) {
1049 build_sends_menu ();
1052 sends_menu->popup (0, ev->time);
1056 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1059 set_showing_sends_to (boost::shared_ptr<Route> ());
1061 set_showing_sends_to (_route);
1070 RouteUI::show_sends_release (GdkEventButton*)
1076 RouteUI::send_blink (bool onoff)
1078 if (!show_sends_button) {
1083 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1085 show_sends_button->unset_active_state ();
1089 Gtkmm2ext::ActiveState
1090 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1092 if (r->is_master() || r->is_monitor()) {
1093 return Gtkmm2ext::Off;
1096 if (Config->get_solo_control_is_listen_control()) {
1098 if (r->listening_via_monitor()) {
1099 return Gtkmm2ext::ExplicitActive;
1101 return Gtkmm2ext::Off;
1107 if (!r->self_soloed()) {
1108 return Gtkmm2ext::ImplicitActive;
1110 return Gtkmm2ext::ExplicitActive;
1113 return Gtkmm2ext::Off;
1117 Gtkmm2ext::ActiveState
1118 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1120 if (r->is_master() || r->is_monitor()) {
1121 return Gtkmm2ext::Off;
1124 if (r->solo_isolated()) {
1125 return Gtkmm2ext::ExplicitActive;
1127 return Gtkmm2ext::Off;
1131 Gtkmm2ext::ActiveState
1132 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1134 if (r->is_master() || r->is_monitor()) {
1135 return Gtkmm2ext::Off;
1138 if (r->solo_safe()) {
1139 return Gtkmm2ext::ExplicitActive;
1141 return Gtkmm2ext::Off;
1146 RouteUI::update_solo_display ()
1148 bool yn = _route->solo_safe ();
1150 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1151 solo_safe_check->set_active (yn);
1154 yn = _route->solo_isolated ();
1156 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1157 solo_isolated_check->set_active (yn);
1160 set_button_names ();
1162 if (solo_isolated_led) {
1163 if (_route->solo_isolated()) {
1164 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1166 solo_isolated_led->unset_active_state ();
1170 if (solo_safe_led) {
1171 if (_route->solo_safe()) {
1172 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1174 solo_safe_led->unset_active_state ();
1178 solo_button->set_active_state (solo_active_state (_route));
1180 /* some changes to solo status can affect mute display, so catch up
1183 update_mute_display ();
1187 RouteUI::solo_changed_so_update_mute ()
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->muted_by_others()) {
1206 return Gtkmm2ext::ImplicitActive;
1208 /* no mute at all */
1209 return Gtkmm2ext::Off;
1216 return Gtkmm2ext::ExplicitActive;
1218 /* no mute at all */
1219 return Gtkmm2ext::Off;
1223 return ActiveState(0);
1227 RouteUI::update_mute_display ()
1233 mute_button->set_active_state (mute_active_state (_session, _route));
1237 RouteUI::route_rec_enable_changed ()
1239 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1240 update_monitoring_display ();
1244 RouteUI::session_rec_enable_changed ()
1246 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1247 update_monitoring_display ();
1251 RouteUI::blink_rec_display (bool blinkOn)
1253 if (!rec_enable_button || !_route) {
1256 if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1260 if (_route->record_enabled()) {
1261 switch (_session->record_status ()) {
1262 case Session::Recording:
1263 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1266 case Session::Disabled:
1267 case Session::Enabled:
1268 if ( UIConfiguration::instance().get_blink_rec_arm() )
1269 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1271 rec_enable_button->set_active_state ( ImplicitActive );
1276 if (step_edit_item) {
1277 step_edit_item->set_sensitive (false);
1281 rec_enable_button->unset_active_state ();
1283 if (step_edit_item) {
1284 step_edit_item->set_sensitive (true);
1289 check_rec_enable_sensitivity ();
1293 RouteUI::build_solo_menu (void)
1295 using namespace Menu_Helpers;
1297 solo_menu = new Menu;
1298 solo_menu->set_name ("ArdourContextMenu");
1299 MenuList& items = solo_menu->items();
1300 Gtk::CheckMenuItem* check;
1302 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1303 check->set_active (_route->solo_isolated());
1304 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1305 items.push_back (CheckMenuElem(*check));
1306 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1309 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1310 check->set_active (_route->solo_safe());
1311 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1312 items.push_back (CheckMenuElem(*check));
1313 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1316 //items.push_back (SeparatorElem());
1317 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1322 RouteUI::build_mute_menu(void)
1324 using namespace Menu_Helpers;
1326 mute_menu = new Menu;
1327 mute_menu->set_name ("ArdourContextMenu");
1329 MenuList& items = mute_menu->items();
1331 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1332 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1333 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1334 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1335 pre_fader_mute_check->show_all();
1337 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1338 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1339 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1340 items.push_back (CheckMenuElem(*post_fader_mute_check));
1341 post_fader_mute_check->show_all();
1343 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1344 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1345 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1346 items.push_back (CheckMenuElem(*listen_mute_check));
1347 listen_mute_check->show_all();
1349 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1350 init_mute_menu(MuteMaster::Main, main_mute_check);
1351 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1352 items.push_back (CheckMenuElem(*main_mute_check));
1353 main_mute_check->show_all();
1355 //items.push_back (SeparatorElem());
1356 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1358 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1362 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1364 check->set_active (_route->mute_points() & mp);
1368 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1370 if (check->get_active()) {
1371 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1373 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1378 RouteUI::muting_change ()
1380 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1383 MuteMaster::MutePoint current = _route->mute_points ();
1385 yn = (current & MuteMaster::PreFader);
1387 if (pre_fader_mute_check->get_active() != yn) {
1388 pre_fader_mute_check->set_active (yn);
1391 yn = (current & MuteMaster::PostFader);
1393 if (post_fader_mute_check->get_active() != yn) {
1394 post_fader_mute_check->set_active (yn);
1397 yn = (current & MuteMaster::Listen);
1399 if (listen_mute_check->get_active() != yn) {
1400 listen_mute_check->set_active (yn);
1403 yn = (current & MuteMaster::Main);
1405 if (main_mute_check->get_active() != yn) {
1406 main_mute_check->set_active (yn);
1411 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1413 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1417 bool view = solo_isolated_led->active_state();
1418 bool model = _route->solo_isolated();
1420 /* called BEFORE the view has changed */
1422 if (ev->button == 1) {
1423 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1426 /* disable isolate for all routes */
1427 DisplaySuspender ds;
1428 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1430 /* enable isolate for all routes */
1431 DisplaySuspender ds;
1432 _session->set_solo_isolated (_session->get_routes(), true, Session::rt_cleanup, true);
1437 if (model == view) {
1439 /* flip just this route */
1441 boost::shared_ptr<RouteList> rl (new RouteList);
1442 rl->push_back (_route);
1443 DisplaySuspender ds;
1444 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1453 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1455 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1459 bool view = solo_safe_led->active_state();
1460 bool model = _route->solo_safe();
1462 if (ev->button == 1) {
1463 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1464 boost::shared_ptr<RouteList> rl (_session->get_routes());
1466 /* disable solo safe for all routes */
1467 DisplaySuspender ds;
1468 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1469 (*i)->set_solo_safe (false, this);
1472 /* enable solo safe for all routes */
1473 DisplaySuspender ds;
1474 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1475 (*i)->set_solo_safe (true, this);
1480 if (model == view) {
1481 /* flip just this route */
1482 _route->set_solo_safe (!view, this);
1491 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1493 bool view = check->get_active();
1494 bool model = _route->solo_isolated();
1496 /* called AFTER the view has changed */
1498 if (model != view) {
1499 _route->set_solo_isolated (view, this);
1504 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1506 _route->set_solo_safe (check->get_active(), this);
1509 /** Ask the user to choose a colour, and then apply that color to my route
1512 RouteUI::choose_color ()
1515 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1522 /** Set the route's own color. This may not be used for display if
1523 * the route is in a group which shares its color with its routes.
1526 RouteUI::set_color (const Gdk::Color & c)
1528 /* leave _color alone in the group case so that tracks can retain their
1529 * own pre-group colors.
1534 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1536 /* note: we use the route state ID here so that color is the same for both
1537 the time axis view and the mixer strip
1540 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1541 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1544 /** @return GUI state ID for things that are common to the route in all its representations */
1546 RouteUI::route_state_id () const
1548 return string_compose (X_("route %1"), _route->id().to_s());
1552 RouteUI::set_color_from_route ()
1554 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1562 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1565 _color.set_green (g);
1566 _color.set_blue (b);
1571 /** @return true if this name should be used for the route, otherwise false */
1573 RouteUI::verify_new_route_name (const std::string& name)
1575 if (name.find (':') == string::npos) {
1579 MessageDialog colon_msg (
1580 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1581 false, MESSAGE_QUESTION, BUTTONS_NONE
1584 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1585 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1587 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1591 RouteUI::route_rename ()
1593 ArdourPrompter name_prompter (true);
1598 name_prompter.set_title (_("Rename Track"));
1600 name_prompter.set_title (_("Rename Bus"));
1602 name_prompter.set_prompt (_("New name:"));
1603 name_prompter.set_initial_text (_route->name());
1604 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1605 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1606 name_prompter.show_all ();
1609 switch (name_prompter.run ()) {
1610 case Gtk::RESPONSE_ACCEPT:
1611 name_prompter.get_result (result);
1612 name_prompter.hide ();
1613 if (result.length()) {
1614 if (verify_new_route_name (result)) {
1615 _route->set_name (result);
1618 /* back to name prompter */
1622 /* nothing entered, just get out of here */
1637 RouteUI::property_changed (const PropertyChange& what_changed)
1639 if (what_changed.contains (ARDOUR::Properties::name)) {
1640 name_label.set_text (_route->name());
1645 RouteUI::toggle_comment_editor ()
1647 // if (ignore_toggle) {
1651 if (comment_window && comment_window->is_visible ()) {
1652 comment_window->hide ();
1654 open_comment_editor ();
1660 RouteUI::open_comment_editor ()
1662 if (comment_window == 0) {
1663 setup_comment_editor ();
1667 title = _route->name();
1668 title += _(": comment editor");
1670 comment_window->set_title (title);
1671 comment_window->present();
1675 RouteUI::setup_comment_editor ()
1677 comment_window = new ArdourWindow (""); // title will be reset to show route
1678 comment_window->set_skip_taskbar_hint (true);
1679 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1680 comment_window->set_default_size (400, 200);
1682 comment_area = manage (new TextView());
1683 comment_area->set_name ("MixerTrackCommentArea");
1684 comment_area->set_wrap_mode (WRAP_WORD);
1685 comment_area->set_editable (true);
1686 comment_area->get_buffer()->set_text (_route->comment());
1687 comment_area->show ();
1689 comment_window->add (*comment_area);
1693 RouteUI::comment_changed (void *src)
1695 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1698 ignore_comment_edit = true;
1700 comment_area->get_buffer()->set_text (_route->comment());
1702 ignore_comment_edit = false;
1707 RouteUI::comment_editor_done_editing ()
1709 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1711 string const str = comment_area->get_buffer()->get_text();
1712 if (str == _route->comment ()) {
1716 _route->set_comment (str, this);
1720 RouteUI::set_route_active (bool a, bool apply_to_selection)
1722 if (apply_to_selection) {
1723 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1725 _route->set_active (a, this);
1730 RouteUI::toggle_denormal_protection ()
1732 if (denormal_menu_item) {
1736 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1738 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1739 _route->set_denormal_protection (x);
1745 RouteUI::denormal_protection_changed ()
1747 if (denormal_menu_item) {
1748 denormal_menu_item->set_active (_route->denormal_protection());
1753 RouteUI::disconnect_input ()
1755 _route->input()->disconnect (this);
1759 RouteUI::disconnect_output ()
1761 _route->output()->disconnect (this);
1765 RouteUI::is_track () const
1767 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1770 boost::shared_ptr<Track>
1771 RouteUI::track() const
1773 return boost::dynamic_pointer_cast<Track>(_route);
1777 RouteUI::is_audio_track () const
1779 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1782 boost::shared_ptr<AudioTrack>
1783 RouteUI::audio_track() const
1785 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1789 RouteUI::is_midi_track () const
1791 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1794 boost::shared_ptr<MidiTrack>
1795 RouteUI::midi_track() const
1797 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1801 RouteUI::has_audio_outputs () const
1803 return (_route->n_outputs().n_audio() > 0);
1807 RouteUI::name() const
1809 return _route->name();
1813 RouteUI::map_frozen ()
1815 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1817 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1820 switch (at->freeze_state()) {
1821 case AudioTrack::Frozen:
1822 rec_enable_button->set_sensitive (false);
1825 rec_enable_button->set_sensitive (true);
1832 RouteUI::adjust_latency ()
1834 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1838 RouteUI::save_as_template ()
1841 std::string safe_name;
1844 path = ARDOUR::user_route_template_directory ();
1846 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1847 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1851 Prompter p (true); // modal
1853 p.set_title (_("Save As Template"));
1854 p.set_prompt (_("Template name:"));
1855 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1857 case RESPONSE_ACCEPT:
1864 p.get_result (name, true);
1866 safe_name = legalize_for_path (name);
1867 safe_name += template_suffix;
1869 path = Glib::build_filename (path, safe_name);
1871 _route->save_as_template (path, name);
1875 RouteUI::check_rec_enable_sensitivity ()
1877 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1878 rec_enable_button->set_sensitive (false);
1880 rec_enable_button->set_sensitive (true);
1883 update_monitoring_display ();
1887 RouteUI::parameter_changed (string const & p)
1889 /* this handles RC and per-session parameter changes */
1891 if (p == "disable-disarm-during-roll") {
1892 check_rec_enable_sensitivity ();
1893 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1894 set_button_names ();
1895 } else if (p == "auto-input") {
1896 update_monitoring_display ();
1897 } else if (p == "blink-rec-arm") {
1898 if (UIConfiguration::instance().get_blink_rec_arm()) {
1899 rec_blink_connection.disconnect ();
1900 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1902 rec_blink_connection.disconnect ();
1903 RouteUI::blink_rec_display(false);
1909 RouteUI::step_gain_up ()
1911 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1915 RouteUI::page_gain_up ()
1917 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1921 RouteUI::step_gain_down ()
1923 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1927 RouteUI::page_gain_down ()
1929 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1933 RouteUI::open_remote_control_id_dialog ()
1935 ArdourDialog dialog (_("Remote Control ID"));
1936 SpinButton* spin = 0;
1938 dialog.get_vbox()->set_border_width (18);
1940 if (Config->get_remote_model() == UserOrdered) {
1941 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1943 HBox* hbox = manage (new HBox);
1944 hbox->set_spacing (6);
1945 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1946 spin = manage (new SpinButton);
1947 spin->set_digits (0);
1948 spin->set_increments (1, 10);
1949 spin->set_range (0, limit);
1950 spin->set_value (_route->remote_control_id());
1951 hbox->pack_start (*spin);
1952 dialog.get_vbox()->pack_start (*hbox);
1954 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1955 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1957 Label* l = manage (new Label());
1958 if (_route->is_master() || _route->is_monitor()) {
1959 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1960 "The remote control ID of %3 cannot be changed."),
1961 Glib::Markup::escape_text (_route->name()),
1962 _route->remote_control_id(),
1963 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1965 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1966 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1967 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1968 (is_track() ? _("track") : _("bus")),
1969 _route->remote_control_id(),
1970 "<span size=\"small\" style=\"italic\">",
1972 Glib::Markup::escape_text (_route->name()),
1975 dialog.get_vbox()->pack_start (*l);
1976 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1980 int const r = dialog.run ();
1982 if (r == RESPONSE_ACCEPT && spin) {
1983 _route->set_remote_control_id (spin->get_value_as_int ());
1988 RouteUI::setup_invert_buttons ()
1990 /* remove old invert buttons */
1991 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1992 _invert_button_box.remove (**i);
1995 _invert_buttons.clear ();
1997 if (!_route || !_route->input()) {
2001 uint32_t const N = _route->input()->n_ports().n_audio ();
2003 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2005 for (uint32_t i = 0; i < to_add; ++i) {
2006 ArdourButton* b = manage (new ArdourButton);
2007 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2008 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2010 b->set_name (X_("invert button"));
2013 b->set_text (string_compose (X_("Ø (%1)"), N));
2015 b->set_text (X_("Ø"));
2018 b->set_text (string_compose (X_("Ø%1"), i + 1));
2021 if (N <= _max_invert_buttons) {
2022 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));
2024 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2027 _invert_buttons.push_back (b);
2028 _invert_button_box.pack_start (*b);
2031 _invert_button_box.set_spacing (1);
2032 _invert_button_box.show_all ();
2036 RouteUI::set_invert_button_state ()
2038 uint32_t const N = _route->input()->n_ports().n_audio();
2039 if (N > _max_invert_buttons) {
2041 /* One button for many channels; explicit active if all channels are inverted,
2042 implicit active if some are, off if none are.
2045 ArdourButton* b = _invert_buttons.front ();
2047 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2048 b->set_active_state (Gtkmm2ext::ExplicitActive);
2049 } else if (_route->phase_invert().any()) {
2050 b->set_active_state (Gtkmm2ext::ImplicitActive);
2052 b->set_active_state (Gtkmm2ext::Off);
2057 /* One button per channel; just set active */
2060 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2061 (*i)->set_active (_route->phase_invert (j));
2068 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2070 if (ev->button == 1 && i < _invert_buttons.size()) {
2071 uint32_t const N = _route->input()->n_ports().n_audio ();
2072 if (N <= _max_invert_buttons) {
2073 /* left-click inverts phase so long as we have a button per channel */
2074 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2083 RouteUI::invert_press (GdkEventButton* ev)
2085 using namespace Menu_Helpers;
2087 uint32_t const N = _route->input()->n_ports().n_audio();
2088 if (N <= _max_invert_buttons && ev->button != 3) {
2089 /* If we have an invert button per channel, we only pop
2090 up a menu on right-click; left click is handled
2096 delete _invert_menu;
2097 _invert_menu = new Menu;
2098 _invert_menu->set_name ("ArdourContextMenu");
2099 MenuList& items = _invert_menu->items ();
2101 for (uint32_t i = 0; i < N; ++i) {
2102 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2103 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2104 ++_i_am_the_modifier;
2105 e->set_active (_route->phase_invert (i));
2106 --_i_am_the_modifier;
2109 _invert_menu->popup (0, ev->time);
2115 RouteUI::invert_menu_toggled (uint32_t c)
2117 if (_i_am_the_modifier) {
2121 _route->set_phase_invert (c, !_route->phase_invert (c));
2125 RouteUI::set_invert_sensitive (bool yn)
2127 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2128 (*b)->set_sensitive (yn);
2133 RouteUI::request_redraw ()
2136 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2140 /** The Route's gui_changed signal has been emitted */
2142 RouteUI::route_gui_changed (string what_changed)
2144 if (what_changed == "color") {
2145 if (set_color_from_route () == 0) {
2146 route_color_changed ();
2152 RouteUI::track_mode_changed (void)
2155 switch (track()->mode()) {
2156 case ARDOUR::NonLayered:
2157 case ARDOUR::Normal:
2158 rec_enable_button->set_icon (ArdourIcon::RecButton);
2160 case ARDOUR::Destructive:
2161 rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2164 rec_enable_button->queue_draw();
2167 /** @return the color that this route should use; it maybe its own,
2168 or it maybe that of its route group.
2171 RouteUI::color () const
2173 RouteGroup* g = _route->route_group ();
2175 if (g && g->is_color()) {
2177 set_color_from_rgba (c, GroupTabs::group_color (g));
2185 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2187 _showing_sends_to = send_to;
2188 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2192 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2194 if (_route == send_to) {
2195 show_sends_button->set_active (true);
2196 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2198 show_sends_button->set_active (false);
2199 send_blink_connection.disconnect ();
2204 RouteUI::route_group() const
2206 return _route->route_group();