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"
51 #include "ardour/audio_track.h"
52 #include "ardour/audioengine.h"
53 #include "ardour/filename_extensions.h"
54 #include "ardour/midi_track.h"
55 #include "ardour/internal_send.h"
56 #include "ardour/send.h"
57 #include "ardour/route.h"
58 #include "ardour/session.h"
59 #include "ardour/template_utils.h"
63 using namespace Gtkmm2ext;
64 using namespace ARDOUR;
65 using namespace ARDOUR_UI_UTILS;
69 uint32_t RouteUI::_max_invert_buttons = 3;
70 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
71 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
73 RouteUI::RouteUI (ARDOUR::Session* sess)
91 gui_object_state().remove_node (route_state_id());
94 _route.reset (); /* drop reference to route, so that it can be cleaned up */
95 route_connections.drop_connections ();
101 delete comment_window;
102 delete input_selector;
103 delete output_selector;
106 send_blink_connection.disconnect ();
107 rec_blink_connection.disconnect ();
113 self_destruct = true;
119 pre_fader_mute_check = 0;
120 post_fader_mute_check = 0;
121 listen_mute_check = 0;
124 solo_isolated_check = 0;
125 solo_isolated_led = 0;
129 denormal_menu_item = 0;
131 multiple_mute_change = false;
132 multiple_solo_change = false;
133 _i_am_the_modifier = 0;
138 setup_invert_buttons ();
140 mute_button = manage (new ArdourButton);
141 mute_button->set_name ("mute button");
142 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
144 solo_button = manage (new ArdourButton);
145 solo_button->set_name ("solo button");
146 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
147 solo_button->set_no_show_all (true);
149 rec_enable_button = manage (new ArdourButton);
150 rec_enable_button->set_name ("record enable button");
151 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::VectorIcon));
152 rec_enable_button->set_icon (ArdourButton::RecButton);
153 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
155 if (ARDOUR_UI::config()->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 (!ARDOUR_UI::config()->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->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);
1538 /** @return true if this name should be used for the route, otherwise false */
1540 RouteUI::verify_new_route_name (const std::string& name)
1542 if (name.find (':') == string::npos) {
1546 MessageDialog colon_msg (
1547 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1548 false, MESSAGE_QUESTION, BUTTONS_NONE
1551 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1552 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1554 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1558 RouteUI::route_rename ()
1560 ArdourPrompter name_prompter (true);
1565 name_prompter.set_title (_("Rename Track"));
1567 name_prompter.set_title (_("Rename Bus"));
1569 name_prompter.set_prompt (_("New name:"));
1570 name_prompter.set_initial_text (_route->name());
1571 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1572 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1573 name_prompter.show_all ();
1576 switch (name_prompter.run ()) {
1577 case Gtk::RESPONSE_ACCEPT:
1578 name_prompter.get_result (result);
1579 name_prompter.hide ();
1580 if (result.length()) {
1581 if (verify_new_route_name (result)) {
1582 _route->set_name (result);
1585 /* back to name prompter */
1589 /* nothing entered, just get out of here */
1604 RouteUI::property_changed (const PropertyChange& what_changed)
1606 if (what_changed.contains (ARDOUR::Properties::name)) {
1607 name_label.set_text (_route->name());
1612 RouteUI::toggle_comment_editor ()
1614 // if (ignore_toggle) {
1618 if (comment_window && comment_window->is_visible ()) {
1619 comment_window->hide ();
1621 open_comment_editor ();
1627 RouteUI::open_comment_editor ()
1629 if (comment_window == 0) {
1630 setup_comment_editor ();
1634 title = _route->name();
1635 title += _(": comment editor");
1637 comment_window->set_title (title);
1638 comment_window->present();
1642 RouteUI::setup_comment_editor ()
1644 comment_window = new ArdourWindow (""); // title will be reset to show route
1645 comment_window->set_skip_taskbar_hint (true);
1646 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1647 comment_window->set_default_size (400, 200);
1649 comment_area = manage (new TextView());
1650 comment_area->set_name ("MixerTrackCommentArea");
1651 comment_area->set_wrap_mode (WRAP_WORD);
1652 comment_area->set_editable (true);
1653 comment_area->get_buffer()->set_text (_route->comment());
1654 comment_area->show ();
1656 comment_window->add (*comment_area);
1660 RouteUI::comment_changed (void *src)
1662 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1665 ignore_comment_edit = true;
1667 comment_area->get_buffer()->set_text (_route->comment());
1669 ignore_comment_edit = false;
1674 RouteUI::comment_editor_done_editing ()
1676 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1678 string const str = comment_area->get_buffer()->get_text();
1679 if (str == _route->comment ()) {
1683 _route->set_comment (str, this);
1687 RouteUI::set_route_active (bool a, bool apply_to_selection)
1689 if (apply_to_selection) {
1690 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1692 _route->set_active (a, this);
1697 RouteUI::toggle_denormal_protection ()
1699 if (denormal_menu_item) {
1703 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1705 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1706 _route->set_denormal_protection (x);
1712 RouteUI::denormal_protection_changed ()
1714 if (denormal_menu_item) {
1715 denormal_menu_item->set_active (_route->denormal_protection());
1720 RouteUI::disconnect_input ()
1722 _route->input()->disconnect (this);
1726 RouteUI::disconnect_output ()
1728 _route->output()->disconnect (this);
1732 RouteUI::is_track () const
1734 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1737 boost::shared_ptr<Track>
1738 RouteUI::track() const
1740 return boost::dynamic_pointer_cast<Track>(_route);
1744 RouteUI::is_audio_track () const
1746 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1749 boost::shared_ptr<AudioTrack>
1750 RouteUI::audio_track() const
1752 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1756 RouteUI::is_midi_track () const
1758 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1761 boost::shared_ptr<MidiTrack>
1762 RouteUI::midi_track() const
1764 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1768 RouteUI::has_audio_outputs () const
1770 return (_route->n_outputs().n_audio() > 0);
1774 RouteUI::name() const
1776 return _route->name();
1780 RouteUI::map_frozen ()
1782 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1784 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1787 switch (at->freeze_state()) {
1788 case AudioTrack::Frozen:
1789 rec_enable_button->set_sensitive (false);
1792 rec_enable_button->set_sensitive (true);
1799 RouteUI::adjust_latency ()
1801 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1805 RouteUI::save_as_template ()
1808 std::string safe_name;
1811 path = ARDOUR::user_route_template_directory ();
1813 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1814 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1818 Prompter p (true); // modal
1820 p.set_title (_("Save As Template"));
1821 p.set_prompt (_("Template name:"));
1822 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1824 case RESPONSE_ACCEPT:
1831 p.get_result (name, true);
1833 safe_name = legalize_for_path (name);
1834 safe_name += template_suffix;
1836 path = Glib::build_filename (path, safe_name);
1838 _route->save_as_template (path, name);
1842 RouteUI::check_rec_enable_sensitivity ()
1844 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1845 rec_enable_button->set_sensitive (false);
1847 rec_enable_button->set_sensitive (true);
1850 update_monitoring_display ();
1854 RouteUI::parameter_changed (string const & p)
1856 /* this handles RC and per-session parameter changes */
1858 if (p == "disable-disarm-during-roll") {
1859 check_rec_enable_sensitivity ();
1860 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1861 set_button_names ();
1862 } else if (p == "auto-input") {
1863 update_monitoring_display ();
1864 } else if (p == "blink-rec-arm") {
1865 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
1866 rec_blink_connection.disconnect ();
1867 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1869 rec_blink_connection.disconnect ();
1870 RouteUI::blink_rec_display(false);
1876 RouteUI::step_gain_up ()
1878 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1882 RouteUI::page_gain_up ()
1884 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1888 RouteUI::step_gain_down ()
1890 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1894 RouteUI::page_gain_down ()
1896 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1900 RouteUI::open_remote_control_id_dialog ()
1902 ArdourDialog dialog (_("Remote Control ID"));
1903 SpinButton* spin = 0;
1905 dialog.get_vbox()->set_border_width (18);
1907 if (Config->get_remote_model() == UserOrdered) {
1908 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1910 HBox* hbox = manage (new HBox);
1911 hbox->set_spacing (6);
1912 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1913 spin = manage (new SpinButton);
1914 spin->set_digits (0);
1915 spin->set_increments (1, 10);
1916 spin->set_range (0, limit);
1917 spin->set_value (_route->remote_control_id());
1918 hbox->pack_start (*spin);
1919 dialog.get_vbox()->pack_start (*hbox);
1921 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1922 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1924 Label* l = manage (new Label());
1925 if (_route->is_master() || _route->is_monitor()) {
1926 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1927 "The remote control ID of %3 cannot be changed."),
1928 Glib::Markup::escape_text (_route->name()),
1929 _route->remote_control_id(),
1930 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1932 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1933 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1934 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1935 (is_track() ? _("track") : _("bus")),
1936 _route->remote_control_id(),
1937 "<span size=\"small\" style=\"italic\">",
1939 Glib::Markup::escape_text (_route->name()),
1942 dialog.get_vbox()->pack_start (*l);
1943 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1947 int const r = dialog.run ();
1949 if (r == RESPONSE_ACCEPT && spin) {
1950 _route->set_remote_control_id (spin->get_value_as_int ());
1955 RouteUI::setup_invert_buttons ()
1957 /* remove old invert buttons */
1958 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1959 _invert_button_box.remove (**i);
1962 _invert_buttons.clear ();
1964 if (!_route || !_route->input()) {
1968 uint32_t const N = _route->input()->n_ports().n_audio ();
1970 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1972 for (uint32_t i = 0; i < to_add; ++i) {
1973 ArdourButton* b = manage (new ArdourButton);
1974 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
1975 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
1977 b->set_name (X_("invert button"));
1980 b->set_text (string_compose (X_("Ø (%1)"), N));
1982 b->set_text (X_("Ø"));
1985 b->set_text (string_compose (X_("Ø%1"), i + 1));
1988 if (N <= _max_invert_buttons) {
1989 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));
1991 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1994 _invert_buttons.push_back (b);
1995 _invert_button_box.pack_start (*b);
1998 _invert_button_box.set_spacing (1);
1999 _invert_button_box.show_all ();
2003 RouteUI::set_invert_button_state ()
2005 uint32_t const N = _route->input()->n_ports().n_audio();
2006 if (N > _max_invert_buttons) {
2008 /* One button for many channels; explicit active if all channels are inverted,
2009 implicit active if some are, off if none are.
2012 ArdourButton* b = _invert_buttons.front ();
2014 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2015 b->set_active_state (Gtkmm2ext::ExplicitActive);
2016 } else if (_route->phase_invert().any()) {
2017 b->set_active_state (Gtkmm2ext::ImplicitActive);
2019 b->set_active_state (Gtkmm2ext::Off);
2024 /* One button per channel; just set active */
2027 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2028 (*i)->set_active (_route->phase_invert (j));
2035 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2037 if (ev->button == 1 && i < _invert_buttons.size()) {
2038 uint32_t const N = _route->input()->n_ports().n_audio ();
2039 if (N <= _max_invert_buttons) {
2040 /* left-click inverts phase so long as we have a button per channel */
2041 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2050 RouteUI::invert_press (GdkEventButton* ev)
2052 using namespace Menu_Helpers;
2054 uint32_t const N = _route->input()->n_ports().n_audio();
2055 if (N <= _max_invert_buttons && ev->button != 3) {
2056 /* If we have an invert button per channel, we only pop
2057 up a menu on right-click; left click is handled
2063 delete _invert_menu;
2064 _invert_menu = new Menu;
2065 _invert_menu->set_name ("ArdourContextMenu");
2066 MenuList& items = _invert_menu->items ();
2068 for (uint32_t i = 0; i < N; ++i) {
2069 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2070 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2071 ++_i_am_the_modifier;
2072 e->set_active (_route->phase_invert (i));
2073 --_i_am_the_modifier;
2076 _invert_menu->popup (0, ev->time);
2082 RouteUI::invert_menu_toggled (uint32_t c)
2084 if (_i_am_the_modifier) {
2088 _route->set_phase_invert (c, !_route->phase_invert (c));
2092 RouteUI::set_invert_sensitive (bool yn)
2094 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2095 (*b)->set_sensitive (yn);
2100 RouteUI::request_redraw ()
2103 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2107 /** The Route's gui_changed signal has been emitted */
2109 RouteUI::route_gui_changed (string what_changed)
2111 if (what_changed == "color") {
2112 if (set_color_from_route () == 0) {
2113 route_color_changed ();
2119 RouteUI::track_mode_changed (void)
2122 switch (track()->mode()) {
2123 case ARDOUR::NonLayered:
2124 case ARDOUR::Normal:
2125 rec_enable_button->set_icon (ArdourButton::RecButton);
2127 case ARDOUR::Destructive:
2128 rec_enable_button->set_icon (ArdourButton::RecTapeMode);
2131 rec_enable_button->queue_draw();
2134 /** @return the color that this route should use; it maybe its own,
2135 or it maybe that of its route group.
2138 RouteUI::color () const
2140 RouteGroup* g = _route->route_group ();
2142 if (g && g->is_color()) {
2144 set_color_from_rgba (c, GroupTabs::group_color (g));
2152 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2154 _showing_sends_to = send_to;
2155 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2159 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2161 if (_route == send_to) {
2162 show_sends_button->set_active (true);
2163 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2165 show_sends_button->set_active (false);
2166 send_blink_connection.disconnect ();
2171 RouteUI::route_group() const
2173 return _route->route_group();