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->button == 1) {
1456 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1462 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1464 bool view = check->get_active();
1465 bool model = _route->solo_isolated();
1467 /* called AFTER the view has changed */
1469 if (model != view) {
1470 _route->set_solo_isolated (view, this);
1475 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1477 _route->set_solo_safe (check->get_active(), this);
1480 /** Ask the user to choose a colour, and then apply that color to my route
1483 RouteUI::choose_color ()
1486 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1493 /** Set the route's own color. This may not be used for display if
1494 * the route is in a group which shares its color with its routes.
1497 RouteUI::set_color (const Gdk::Color & c)
1499 /* leave _color alone in the group case so that tracks can retain their
1500 * own pre-group colors.
1505 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1507 /* note: we use the route state ID here so that color is the same for both
1508 the time axis view and the mixer strip
1511 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1512 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1515 /** @return GUI state ID for things that are common to the route in all its representations */
1517 RouteUI::route_state_id () const
1519 return string_compose (X_("route %1"), _route->id().to_s());
1523 RouteUI::set_color_from_route ()
1525 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1533 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1536 _color.set_green (g);
1537 _color.set_blue (b);
1542 /** @return true if this name should be used for the route, otherwise false */
1544 RouteUI::verify_new_route_name (const std::string& name)
1546 if (name.find (':') == string::npos) {
1550 MessageDialog colon_msg (
1551 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1552 false, MESSAGE_QUESTION, BUTTONS_NONE
1555 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1556 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1558 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1562 RouteUI::route_rename ()
1564 ArdourPrompter name_prompter (true);
1569 name_prompter.set_title (_("Rename Track"));
1571 name_prompter.set_title (_("Rename Bus"));
1573 name_prompter.set_prompt (_("New name:"));
1574 name_prompter.set_initial_text (_route->name());
1575 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1576 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1577 name_prompter.show_all ();
1580 switch (name_prompter.run ()) {
1581 case Gtk::RESPONSE_ACCEPT:
1582 name_prompter.get_result (result);
1583 name_prompter.hide ();
1584 if (result.length()) {
1585 if (verify_new_route_name (result)) {
1586 _route->set_name (result);
1589 /* back to name prompter */
1593 /* nothing entered, just get out of here */
1608 RouteUI::property_changed (const PropertyChange& what_changed)
1610 if (what_changed.contains (ARDOUR::Properties::name)) {
1611 name_label.set_text (_route->name());
1616 RouteUI::toggle_comment_editor ()
1618 // if (ignore_toggle) {
1622 if (comment_window && comment_window->is_visible ()) {
1623 comment_window->hide ();
1625 open_comment_editor ();
1631 RouteUI::open_comment_editor ()
1633 if (comment_window == 0) {
1634 setup_comment_editor ();
1638 title = _route->name();
1639 title += _(": comment editor");
1641 comment_window->set_title (title);
1642 comment_window->present();
1646 RouteUI::setup_comment_editor ()
1648 comment_window = new ArdourWindow (""); // title will be reset to show route
1649 comment_window->set_skip_taskbar_hint (true);
1650 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1651 comment_window->set_default_size (400, 200);
1653 comment_area = manage (new TextView());
1654 comment_area->set_name ("MixerTrackCommentArea");
1655 comment_area->set_wrap_mode (WRAP_WORD);
1656 comment_area->set_editable (true);
1657 comment_area->get_buffer()->set_text (_route->comment());
1658 comment_area->show ();
1660 comment_window->add (*comment_area);
1664 RouteUI::comment_changed (void *src)
1666 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1669 ignore_comment_edit = true;
1671 comment_area->get_buffer()->set_text (_route->comment());
1673 ignore_comment_edit = false;
1678 RouteUI::comment_editor_done_editing ()
1680 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1682 string const str = comment_area->get_buffer()->get_text();
1683 if (str == _route->comment ()) {
1687 _route->set_comment (str, this);
1691 RouteUI::set_route_active (bool a, bool apply_to_selection)
1693 if (apply_to_selection) {
1694 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1696 _route->set_active (a, this);
1701 RouteUI::toggle_denormal_protection ()
1703 if (denormal_menu_item) {
1707 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1709 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1710 _route->set_denormal_protection (x);
1716 RouteUI::denormal_protection_changed ()
1718 if (denormal_menu_item) {
1719 denormal_menu_item->set_active (_route->denormal_protection());
1724 RouteUI::disconnect_input ()
1726 _route->input()->disconnect (this);
1730 RouteUI::disconnect_output ()
1732 _route->output()->disconnect (this);
1736 RouteUI::is_track () const
1738 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1741 boost::shared_ptr<Track>
1742 RouteUI::track() const
1744 return boost::dynamic_pointer_cast<Track>(_route);
1748 RouteUI::is_audio_track () const
1750 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1753 boost::shared_ptr<AudioTrack>
1754 RouteUI::audio_track() const
1756 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1760 RouteUI::is_midi_track () const
1762 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1765 boost::shared_ptr<MidiTrack>
1766 RouteUI::midi_track() const
1768 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1772 RouteUI::has_audio_outputs () const
1774 return (_route->n_outputs().n_audio() > 0);
1778 RouteUI::name() const
1780 return _route->name();
1784 RouteUI::map_frozen ()
1786 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1788 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1791 switch (at->freeze_state()) {
1792 case AudioTrack::Frozen:
1793 rec_enable_button->set_sensitive (false);
1796 rec_enable_button->set_sensitive (true);
1803 RouteUI::adjust_latency ()
1805 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1809 RouteUI::save_as_template ()
1812 std::string safe_name;
1815 path = ARDOUR::user_route_template_directory ();
1817 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1818 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1822 Prompter p (true); // modal
1824 p.set_title (_("Save As Template"));
1825 p.set_prompt (_("Template name:"));
1826 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1828 case RESPONSE_ACCEPT:
1835 p.get_result (name, true);
1837 safe_name = legalize_for_path (name);
1838 safe_name += template_suffix;
1840 path = Glib::build_filename (path, safe_name);
1842 _route->save_as_template (path, name);
1846 RouteUI::check_rec_enable_sensitivity ()
1848 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1849 rec_enable_button->set_sensitive (false);
1851 rec_enable_button->set_sensitive (true);
1854 update_monitoring_display ();
1858 RouteUI::parameter_changed (string const & p)
1860 /* this handles RC and per-session parameter changes */
1862 if (p == "disable-disarm-during-roll") {
1863 check_rec_enable_sensitivity ();
1864 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1865 set_button_names ();
1866 } else if (p == "auto-input") {
1867 update_monitoring_display ();
1868 } else if (p == "blink-rec-arm") {
1869 if (UIConfiguration::instance().get_blink_rec_arm()) {
1870 rec_blink_connection.disconnect ();
1871 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1873 rec_blink_connection.disconnect ();
1874 RouteUI::blink_rec_display(false);
1880 RouteUI::step_gain_up ()
1882 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1886 RouteUI::page_gain_up ()
1888 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1892 RouteUI::step_gain_down ()
1894 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1898 RouteUI::page_gain_down ()
1900 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1904 RouteUI::open_remote_control_id_dialog ()
1906 ArdourDialog dialog (_("Remote Control ID"));
1907 SpinButton* spin = 0;
1909 dialog.get_vbox()->set_border_width (18);
1911 if (Config->get_remote_model() == UserOrdered) {
1912 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1914 HBox* hbox = manage (new HBox);
1915 hbox->set_spacing (6);
1916 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1917 spin = manage (new SpinButton);
1918 spin->set_digits (0);
1919 spin->set_increments (1, 10);
1920 spin->set_range (0, limit);
1921 spin->set_value (_route->remote_control_id());
1922 hbox->pack_start (*spin);
1923 dialog.get_vbox()->pack_start (*hbox);
1925 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1926 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1928 Label* l = manage (new Label());
1929 if (_route->is_master() || _route->is_monitor()) {
1930 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1931 "The remote control ID of %3 cannot be changed."),
1932 Glib::Markup::escape_text (_route->name()),
1933 _route->remote_control_id(),
1934 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1936 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1937 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1938 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1939 (is_track() ? _("track") : _("bus")),
1940 _route->remote_control_id(),
1941 "<span size=\"small\" style=\"italic\">",
1943 Glib::Markup::escape_text (_route->name()),
1946 dialog.get_vbox()->pack_start (*l);
1947 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1951 int const r = dialog.run ();
1953 if (r == RESPONSE_ACCEPT && spin) {
1954 _route->set_remote_control_id (spin->get_value_as_int ());
1959 RouteUI::setup_invert_buttons ()
1961 /* remove old invert buttons */
1962 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1963 _invert_button_box.remove (**i);
1966 _invert_buttons.clear ();
1968 if (!_route || !_route->input()) {
1972 uint32_t const N = _route->input()->n_ports().n_audio ();
1974 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1976 for (uint32_t i = 0; i < to_add; ++i) {
1977 ArdourButton* b = manage (new ArdourButton);
1978 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
1979 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
1981 b->set_name (X_("invert button"));
1984 b->set_text (string_compose (X_("Ø (%1)"), N));
1986 b->set_text (X_("Ø"));
1989 b->set_text (string_compose (X_("Ø%1"), i + 1));
1992 if (N <= _max_invert_buttons) {
1993 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));
1995 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1998 _invert_buttons.push_back (b);
1999 _invert_button_box.pack_start (*b);
2002 _invert_button_box.set_spacing (1);
2003 _invert_button_box.show_all ();
2007 RouteUI::set_invert_button_state ()
2009 uint32_t const N = _route->input()->n_ports().n_audio();
2010 if (N > _max_invert_buttons) {
2012 /* One button for many channels; explicit active if all channels are inverted,
2013 implicit active if some are, off if none are.
2016 ArdourButton* b = _invert_buttons.front ();
2018 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2019 b->set_active_state (Gtkmm2ext::ExplicitActive);
2020 } else if (_route->phase_invert().any()) {
2021 b->set_active_state (Gtkmm2ext::ImplicitActive);
2023 b->set_active_state (Gtkmm2ext::Off);
2028 /* One button per channel; just set active */
2031 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2032 (*i)->set_active (_route->phase_invert (j));
2039 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2041 if (ev->button == 1 && i < _invert_buttons.size()) {
2042 uint32_t const N = _route->input()->n_ports().n_audio ();
2043 if (N <= _max_invert_buttons) {
2044 /* left-click inverts phase so long as we have a button per channel */
2045 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2054 RouteUI::invert_press (GdkEventButton* ev)
2056 using namespace Menu_Helpers;
2058 uint32_t const N = _route->input()->n_ports().n_audio();
2059 if (N <= _max_invert_buttons && ev->button != 3) {
2060 /* If we have an invert button per channel, we only pop
2061 up a menu on right-click; left click is handled
2067 delete _invert_menu;
2068 _invert_menu = new Menu;
2069 _invert_menu->set_name ("ArdourContextMenu");
2070 MenuList& items = _invert_menu->items ();
2072 for (uint32_t i = 0; i < N; ++i) {
2073 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2074 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2075 ++_i_am_the_modifier;
2076 e->set_active (_route->phase_invert (i));
2077 --_i_am_the_modifier;
2080 _invert_menu->popup (0, ev->time);
2086 RouteUI::invert_menu_toggled (uint32_t c)
2088 if (_i_am_the_modifier) {
2092 _route->set_phase_invert (c, !_route->phase_invert (c));
2096 RouteUI::set_invert_sensitive (bool yn)
2098 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2099 (*b)->set_sensitive (yn);
2104 RouteUI::request_redraw ()
2107 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2111 /** The Route's gui_changed signal has been emitted */
2113 RouteUI::route_gui_changed (string what_changed)
2115 if (what_changed == "color") {
2116 if (set_color_from_route () == 0) {
2117 route_color_changed ();
2123 RouteUI::track_mode_changed (void)
2126 switch (track()->mode()) {
2127 case ARDOUR::NonLayered:
2128 case ARDOUR::Normal:
2129 rec_enable_button->set_icon (ArdourIcon::RecButton);
2131 case ARDOUR::Destructive:
2132 rec_enable_button->set_icon (ArdourIcon::RecTapeMode);
2135 rec_enable_button->queue_draw();
2138 /** @return the color that this route should use; it maybe its own,
2139 or it maybe that of its route group.
2142 RouteUI::color () const
2144 RouteGroup* g = _route->route_group ();
2146 if (g && g->is_color()) {
2148 set_color_from_rgba (c, GroupTabs::group_color (g));
2156 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2158 _showing_sends_to = send_to;
2159 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2163 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2165 if (_route == send_to) {
2166 show_sends_button->set_active (true);
2167 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2169 show_sends_button->set_active (false);
2170 send_blink_connection.disconnect ();
2175 RouteUI::route_group() const
2177 return _route->route_group();