2 Copyright (C) 2002-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
26 #include <gtkmm2ext/utils.h>
28 #include "ardour/route_group.h"
29 #include "ardour/dB.h"
30 #include "pbd/memento_command.h"
31 #include "pbd/stacktrace.h"
32 #include "pbd/controllable.h"
33 #include "pbd/enumwriter.h"
35 #include "ardour_ui.h"
38 #include "ardour_button.h"
42 #include "gui_thread.h"
43 #include "ardour_dialog.h"
44 #include "latency_gui.h"
45 #include "mixer_strip.h"
46 #include "automation_time_axis.h"
47 #include "route_time_axis.h"
48 #include "group_tabs.h"
50 #include "ardour/audio_track.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/filename_extensions.h"
53 #include "ardour/midi_track.h"
54 #include "ardour/internal_send.h"
55 #include "ardour/send.h"
56 #include "ardour/route.h"
57 #include "ardour/session.h"
58 #include "ardour/template_utils.h"
62 using namespace Gtkmm2ext;
63 using namespace ARDOUR;
64 using namespace ARDOUR_UI_UTILS;
67 uint32_t RouteUI::_max_invert_buttons = 3;
68 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
69 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
71 static const int _button_vpad = 2;
73 RouteUI::RouteUI (ARDOUR::Session* sess)
90 _route.reset (); /* drop reference to route, so that it can be cleaned up */
91 route_connections.drop_connections ();
97 delete comment_window;
98 delete input_selector;
99 delete output_selector;
102 send_blink_connection.disconnect ();
103 rec_blink_connection.disconnect ();
109 self_destruct = true;
115 pre_fader_mute_check = 0;
116 post_fader_mute_check = 0;
117 listen_mute_check = 0;
120 solo_isolated_check = 0;
121 solo_isolated_led = 0;
125 denormal_menu_item = 0;
127 multiple_mute_change = false;
128 multiple_solo_change = false;
129 _i_am_the_modifier = 0;
134 setup_invert_buttons ();
136 mute_button = manage (new ArdourButton);
137 mute_button->set_name ("mute button");
138 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
140 solo_button = manage (new ArdourButton);
141 solo_button->set_name ("solo button");
142 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
143 solo_button->set_no_show_all (true);
145 rec_enable_button = manage (new ArdourButton);
146 rec_enable_button->set_name ("record enable button");
147 rec_enable_button->set_markup ("<span weight=\"bold\" color=\"#f46f6f\">\u2B24</span>");
148 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
150 rec_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
152 show_sends_button = manage (new ArdourButton);
153 show_sends_button->set_name ("send alert button");
154 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
156 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
157 monitor_input_button->set_name ("monitor button");
158 monitor_input_button->set_text (_("In"));
159 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
160 monitor_input_button->set_no_show_all (true);
162 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
163 monitor_disk_button->set_name ("monitor button");
164 monitor_disk_button->set_text (_("Disk"));
165 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
166 monitor_disk_button->set_no_show_all (true);
168 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
169 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
170 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
172 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
173 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
175 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
176 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
178 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
179 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
181 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
182 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
183 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
184 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
186 monitor_input_button->set_distinct_led_click (false);
187 monitor_disk_button->set_distinct_led_click (false);
189 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
190 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
192 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
193 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
195 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
201 route_connections.drop_connections ();
209 denormal_menu_item = 0;
213 RouteUI::self_delete ()
219 RouteUI::set_route (boost::shared_ptr<Route> rp)
225 if (set_color_from_route()) {
226 set_color (unique_random_color());
230 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
233 delete input_selector;
236 delete output_selector;
239 mute_button->set_controllable (_route->mute_control());
240 solo_button->set_controllable (_route->solo_control());
242 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
243 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
245 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
247 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
248 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
249 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
250 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
252 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
253 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
255 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
256 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
258 if (_session->writable() && is_track()) {
259 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
261 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
263 rec_enable_button->show();
264 rec_enable_button->set_controllable (t->rec_enable_control());
266 if (is_midi_track()) {
267 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
268 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
273 /* this will work for busses and tracks, and needs to be called to
274 set up the name entry/name label display.
278 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
279 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
281 update_monitoring_display ();
284 mute_button->unset_flags (Gtk::CAN_FOCUS);
285 solo_button->unset_flags (Gtk::CAN_FOCUS);
289 if (_route->is_monitor() || _route->is_master()) {
290 solo_button->hide ();
297 setup_invert_buttons ();
298 set_invert_button_state ();
300 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
301 bus_send_display_changed (s);
303 update_mute_display ();
304 update_solo_display ();
306 route_color_changed();
310 RouteUI::polarity_changed ()
316 set_invert_button_state ();
320 RouteUI::mute_press (GdkEventButton* ev)
322 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
326 //if this is a binding action, let the ArdourButton handle it
327 if ( BindingProxy::is_bind_action(ev) )
330 multiple_mute_change = false;
332 if (Keyboard::is_context_menu_event (ev)) {
338 mute_menu->popup(0,ev->time);
344 if (Keyboard::is_button2_event (ev)) {
345 // button2-click is "momentary"
347 _mute_release = new SoloMuteRelease (_route->muted ());
350 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
352 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
354 /* toggle mute on everything (but
355 * exclude the master and monitor)
357 * because we are going to erase
358 * elements of the list we need to work
362 boost::shared_ptr<RouteList> copy (new RouteList);
364 *copy = *_session->get_routes ();
366 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
367 if ((*i)->is_master() || (*i)->is_monitor()) {
375 _mute_release->routes = copy;
379 _session->set_mute (copy, !_route->muted());
381 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
383 /* Primary-button1 applies change to the mix group even if it is not active
384 NOTE: Primary-button2 is MIDI learn.
387 boost::shared_ptr<RouteList> rl;
389 if (ev->button == 1) {
391 if (_route->route_group()) {
393 rl = _route->route_group()->route_list();
396 _mute_release->routes = rl;
399 rl.reset (new RouteList);
400 rl->push_back (_route);
404 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
409 /* plain click applies change to this route */
411 boost::shared_ptr<RouteList> rl (new RouteList);
412 rl->push_back (_route);
415 _mute_release->routes = rl;
418 _session->set_mute (rl, !_route->muted());
428 RouteUI::mute_release (GdkEventButton *ev)
432 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
433 delete _mute_release;
441 RouteUI::edit_output_configuration ()
443 if (output_selector == 0) {
445 boost::shared_ptr<Send> send;
446 boost::shared_ptr<IO> output;
448 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
449 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
450 output = send->output();
452 output = _route->output ();
455 output = _route->output ();
458 output_selector = new IOSelectorWindow (_session, output);
461 if (output_selector->is_visible()) {
462 output_selector->get_toplevel()->get_window()->raise();
464 output_selector->present ();
467 output_selector->set_keep_above (true);
471 RouteUI::edit_input_configuration ()
473 if (input_selector == 0) {
474 input_selector = new IOSelectorWindow (_session, _route->input());
477 if (input_selector->is_visible()) {
478 input_selector->get_toplevel()->get_window()->raise();
480 input_selector->present ();
483 input_selector->set_keep_above (true);
487 RouteUI::solo_press(GdkEventButton* ev)
489 /* ignore double/triple clicks */
491 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
495 //if this is a binding action, let the ArdourButton handle it
496 if ( BindingProxy::is_bind_action(ev) )
499 multiple_solo_change = false;
501 if (Keyboard::is_context_menu_event (ev)) {
503 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
504 ! (solo_safe_led && solo_safe_led->is_visible())) {
506 if (solo_menu == 0) {
510 solo_menu->popup (1, ev->time);
515 if (Keyboard::is_button2_event (ev)) {
517 // button2-click is "momentary"
518 _solo_release = new SoloMuteRelease (_route->self_soloed());
521 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
523 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
525 /* Primary-Tertiary-click applies change to all routes */
528 _solo_release->routes = _session->get_routes ();
532 if (Config->get_solo_control_is_listen_control()) {
533 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
535 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
538 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
540 // Primary-Secondary-click: exclusively solo this track
543 _solo_release->exclusive = true;
545 boost::shared_ptr<RouteList> routes = _session->get_routes();
547 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
548 if ((*i)->soloed ()) {
549 _solo_release->routes_on->push_back (*i);
551 _solo_release->routes_off->push_back (*i);
556 if (Config->get_solo_control_is_listen_control()) {
557 /* ??? we need a just_one_listen() method */
560 _session->set_just_one_solo (_route, true);
563 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
565 // shift-click: toggle solo isolated status
567 _route->set_solo_isolated (!_route->solo_isolated(), this);
568 delete _solo_release;
571 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
573 /* Primary-button1: solo mix group.
574 NOTE: Primary-button2 is MIDI learn.
577 /* Primary-button1 applies change to the mix group even if it is not active
578 NOTE: Primary-button2 is MIDI learn.
581 boost::shared_ptr<RouteList> rl;
583 if (ev->button == 1) {
585 if (_route->route_group()) {
587 rl = _route->route_group()->route_list();
590 _solo_release->routes = rl;
593 rl.reset (new RouteList);
594 rl->push_back (_route);
598 if (Config->get_solo_control_is_listen_control()) {
599 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
601 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
607 /* click: solo this route */
609 boost::shared_ptr<RouteList> rl (new RouteList);
610 rl->push_back (route());
613 _solo_release->routes = rl;
617 if (Config->get_solo_control_is_listen_control()) {
618 _session->set_listen (rl, !_route->listening_via_monitor());
620 _session->set_solo (rl, !_route->self_soloed());
630 RouteUI::solo_release (GdkEventButton *ev)
634 if (_solo_release->exclusive) {
638 if (Config->get_solo_control_is_listen_control()) {
639 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
641 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
645 delete _solo_release;
653 RouteUI::rec_enable_press(GdkEventButton* ev)
655 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
659 //if this is a binding action, let the ArdourButton handle it
660 if ( BindingProxy::is_bind_action(ev) )
663 if (!_session->engine().connected()) {
664 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
669 if (is_midi_track()) {
671 /* rec-enable button exits from step editing */
673 if (midi_track()->step_editing()) {
674 midi_track()->set_step_editing (false);
679 if (is_track() && rec_enable_button) {
681 if (Keyboard::is_button2_event (ev)) {
683 //rec arm does not have a momentary mode
686 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
689 _session->set_record_enabled (_session->get_routes(), !_route->record_enabled());
691 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
693 /* Primary-button1 applies change to the route group (even if it is not active)
694 NOTE: Primary-button2 is MIDI learn.
697 if (ev->button == 1) {
699 boost::shared_ptr<RouteList> rl;
701 if (_route->route_group()) {
703 rl = _route->route_group()->route_list();
706 rl.reset (new RouteList);
707 rl->push_back (_route);
711 _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
714 } else if (Keyboard::is_context_menu_event (ev)) {
716 /* do this on release */
720 boost::shared_ptr<RouteList> rl (new RouteList);
721 rl->push_back (route());
723 _session->set_record_enabled (rl, !_route->record_enabled());
731 RouteUI::monitoring_changed ()
733 update_monitoring_display ();
737 RouteUI::update_monitoring_display ()
743 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
749 MonitorState ms = t->monitoring_state();
751 if (t->monitoring_choice() & MonitorInput) {
752 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
754 if (ms & MonitoringInput) {
755 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
757 monitor_input_button->unset_active_state ();
761 if (t->monitoring_choice() & MonitorDisk) {
762 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
764 if (ms & MonitoringDisk) {
765 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
767 monitor_disk_button->unset_active_state ();
773 RouteUI::monitor_input_press(GdkEventButton*)
779 RouteUI::monitor_input_release(GdkEventButton* ev)
781 return monitor_release (ev, MonitorInput);
785 RouteUI::monitor_disk_press (GdkEventButton*)
791 RouteUI::monitor_disk_release (GdkEventButton* ev)
793 return monitor_release (ev, MonitorDisk);
797 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
799 if (ev->button != 1) {
803 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
810 boost::shared_ptr<RouteList> rl;
812 /* XXX for now, monitoring choices are orthogonal. cue monitoring
813 will follow in 3.X but requires mixing the input and playback (disk)
814 signal together, which requires yet more buffers.
817 if (t->monitoring_choice() & monitor_choice) {
818 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
820 /* this line will change when the options are non-orthogonal */
821 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
825 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
826 rl = _session->get_routes ();
828 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
829 if (_route->route_group() && _route->route_group()->is_monitoring()) {
830 rl = _route->route_group()->route_list();
832 rl.reset (new RouteList);
833 rl->push_back (route());
836 rl.reset (new RouteList);
837 rl->push_back (route());
841 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
847 RouteUI::build_record_menu ()
853 /* no rec-button context menu for non-MIDI tracks
856 if (is_midi_track()) {
857 record_menu = new Menu;
858 record_menu->set_name ("ArdourContextMenu");
860 using namespace Menu_Helpers;
861 MenuList& items = record_menu->items();
863 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
864 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
866 if (_route->record_enabled()) {
867 step_edit_item->set_sensitive (false);
870 step_edit_item->set_active (midi_track()->step_editing());
875 RouteUI::toggle_step_edit ()
877 if (!is_midi_track() || _route->record_enabled()) {
881 midi_track()->set_step_editing (step_edit_item->get_active());
885 RouteUI::step_edit_changed (bool yn)
888 if (rec_enable_button) {
889 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
892 start_step_editing ();
894 if (step_edit_item) {
895 step_edit_item->set_active (true);
900 if (rec_enable_button) {
901 rec_enable_button->unset_active_state ();
904 stop_step_editing ();
906 if (step_edit_item) {
907 step_edit_item->set_active (false);
913 RouteUI::rec_enable_release (GdkEventButton* ev)
915 if (Keyboard::is_context_menu_event (ev)) {
916 build_record_menu ();
918 record_menu->popup (1, ev->time);
927 RouteUI::build_sends_menu ()
929 using namespace Menu_Helpers;
931 sends_menu = new Menu;
932 sends_menu->set_name ("ArdourContextMenu");
933 MenuList& items = sends_menu->items();
936 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
940 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
944 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
948 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
952 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
956 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
959 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
963 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
966 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
967 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
968 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
973 RouteUI::create_sends (Placement p, bool include_buses)
975 _session->globally_add_internal_sends (_route, p, include_buses);
979 RouteUI::create_selected_sends (Placement p, bool include_buses)
981 boost::shared_ptr<RouteList> rlist (new RouteList);
982 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
984 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
985 RouteTimeAxisView* rtv;
987 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
988 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
989 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
990 rlist->push_back (rui->route());
996 _session->add_internal_sends (_route, p, rlist);
1000 RouteUI::set_sends_gain_from_track ()
1002 _session->globally_set_send_gains_from_track (_route);
1006 RouteUI::set_sends_gain_to_zero ()
1008 _session->globally_set_send_gains_to_zero (_route);
1012 RouteUI::set_sends_gain_to_unity ()
1014 _session->globally_set_send_gains_to_unity (_route);
1018 RouteUI::show_sends_press(GdkEventButton* ev)
1020 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1024 if (!is_track() && show_sends_button) {
1026 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1028 // do nothing on midi sigc::bind event
1031 } else if (Keyboard::is_context_menu_event (ev)) {
1033 if (sends_menu == 0) {
1034 build_sends_menu ();
1037 sends_menu->popup (0, ev->time);
1041 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1044 set_showing_sends_to (boost::shared_ptr<Route> ());
1046 set_showing_sends_to (_route);
1055 RouteUI::show_sends_release (GdkEventButton*)
1061 RouteUI::send_blink (bool onoff)
1063 if (!show_sends_button) {
1068 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1070 show_sends_button->unset_active_state ();
1074 Gtkmm2ext::ActiveState
1075 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1077 if (r->is_master() || r->is_monitor()) {
1078 return Gtkmm2ext::Off;
1081 if (Config->get_solo_control_is_listen_control()) {
1083 if (r->listening_via_monitor()) {
1084 return Gtkmm2ext::ExplicitActive;
1086 return Gtkmm2ext::Off;
1092 if (!r->self_soloed()) {
1093 return Gtkmm2ext::ImplicitActive;
1095 return Gtkmm2ext::ExplicitActive;
1098 return Gtkmm2ext::Off;
1102 Gtkmm2ext::ActiveState
1103 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1105 if (r->is_master() || r->is_monitor()) {
1106 return Gtkmm2ext::Off;
1109 if (r->solo_isolated()) {
1110 return Gtkmm2ext::ExplicitActive;
1112 return Gtkmm2ext::Off;
1116 Gtkmm2ext::ActiveState
1117 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1119 if (r->is_master() || r->is_monitor()) {
1120 return Gtkmm2ext::Off;
1123 if (r->solo_safe()) {
1124 return Gtkmm2ext::ExplicitActive;
1126 return Gtkmm2ext::Off;
1131 RouteUI::update_solo_display ()
1133 bool yn = _route->solo_safe ();
1135 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1136 solo_safe_check->set_active (yn);
1139 yn = _route->solo_isolated ();
1141 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1142 solo_isolated_check->set_active (yn);
1145 set_button_names ();
1147 if (solo_isolated_led) {
1148 if (_route->solo_isolated()) {
1149 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1151 solo_isolated_led->unset_active_state ();
1155 if (solo_safe_led) {
1156 if (_route->solo_safe()) {
1157 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1159 solo_safe_led->unset_active_state ();
1163 solo_button->set_active_state (solo_active_state (_route));
1165 /* some changes to solo status can affect mute display, so catch up
1168 update_mute_display ();
1172 RouteUI::solo_changed_so_update_mute ()
1174 update_mute_display ();
1178 RouteUI::mute_changed(void* /*src*/)
1180 update_mute_display ();
1184 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1186 if (r->is_monitor()) {
1187 return ActiveState(0);
1191 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1195 return Gtkmm2ext::ExplicitActive;
1196 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1197 /* master is NEVER muted by others */
1198 return Gtkmm2ext::ImplicitActive;
1200 /* no mute at all */
1201 return Gtkmm2ext::Off;
1208 return Gtkmm2ext::ExplicitActive;
1210 /* no mute at all */
1211 return Gtkmm2ext::Off;
1215 return ActiveState(0);
1219 RouteUI::update_mute_display ()
1225 mute_button->set_active_state (mute_active_state (_session, _route));
1229 RouteUI::route_rec_enable_changed ()
1231 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1232 update_monitoring_display ();
1236 RouteUI::session_rec_enable_changed ()
1238 update_monitoring_display ();
1242 RouteUI::blink_rec_display (bool blinkOn)
1244 if (!rec_enable_button || !_route) {
1248 if (_route->record_enabled()) {
1249 switch (_session->record_status ()) {
1250 case Session::Recording:
1251 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1254 case Session::Disabled:
1255 case Session::Enabled:
1256 if ( ARDOUR_UI::config()->get_blink_rec_arm() )
1257 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1259 rec_enable_button->set_active_state ( ImplicitActive );
1264 if (step_edit_item) {
1265 step_edit_item->set_sensitive (false);
1269 rec_enable_button->unset_active_state ();
1271 if (step_edit_item) {
1272 step_edit_item->set_sensitive (true);
1277 check_rec_enable_sensitivity ();
1281 RouteUI::build_solo_menu (void)
1283 using namespace Menu_Helpers;
1285 solo_menu = new Menu;
1286 solo_menu->set_name ("ArdourContextMenu");
1287 MenuList& items = solo_menu->items();
1288 Gtk::CheckMenuItem* check;
1290 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1291 check->set_active (_route->solo_isolated());
1292 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1293 items.push_back (CheckMenuElem(*check));
1294 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1297 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1298 check->set_active (_route->solo_safe());
1299 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1300 items.push_back (CheckMenuElem(*check));
1301 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1304 //items.push_back (SeparatorElem());
1305 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1310 RouteUI::build_mute_menu(void)
1312 using namespace Menu_Helpers;
1314 mute_menu = new Menu;
1315 mute_menu->set_name ("ArdourContextMenu");
1317 MenuList& items = mute_menu->items();
1319 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1320 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1321 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1322 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1323 pre_fader_mute_check->show_all();
1325 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1326 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1327 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1328 items.push_back (CheckMenuElem(*post_fader_mute_check));
1329 post_fader_mute_check->show_all();
1331 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1332 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1333 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1334 items.push_back (CheckMenuElem(*listen_mute_check));
1335 listen_mute_check->show_all();
1337 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1338 init_mute_menu(MuteMaster::Main, main_mute_check);
1339 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1340 items.push_back (CheckMenuElem(*main_mute_check));
1341 main_mute_check->show_all();
1343 //items.push_back (SeparatorElem());
1344 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1346 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1350 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1352 check->set_active (_route->mute_points() & mp);
1356 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1358 if (check->get_active()) {
1359 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1361 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1366 RouteUI::muting_change ()
1368 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1371 MuteMaster::MutePoint current = _route->mute_points ();
1373 yn = (current & MuteMaster::PreFader);
1375 if (pre_fader_mute_check->get_active() != yn) {
1376 pre_fader_mute_check->set_active (yn);
1379 yn = (current & MuteMaster::PostFader);
1381 if (post_fader_mute_check->get_active() != yn) {
1382 post_fader_mute_check->set_active (yn);
1385 yn = (current & MuteMaster::Listen);
1387 if (listen_mute_check->get_active() != yn) {
1388 listen_mute_check->set_active (yn);
1391 yn = (current & MuteMaster::Main);
1393 if (main_mute_check->get_active() != yn) {
1394 main_mute_check->set_active (yn);
1399 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1401 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1405 bool view = solo_isolated_led->active_state();
1406 bool model = _route->solo_isolated();
1408 /* called BEFORE the view has changed */
1410 if (ev->button == 1) {
1411 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1414 /* disable isolate for all routes */
1415 DisplaySuspender ds;
1416 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1420 if (model == view) {
1422 /* flip just this route */
1424 boost::shared_ptr<RouteList> rl (new RouteList);
1425 rl->push_back (_route);
1426 DisplaySuspender ds;
1427 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1436 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1438 if (ev->button == 1) {
1439 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1445 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1447 bool view = check->get_active();
1448 bool model = _route->solo_isolated();
1450 /* called AFTER the view has changed */
1452 if (model != view) {
1453 _route->set_solo_isolated (view, this);
1458 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1460 _route->set_solo_safe (check->get_active(), this);
1463 /** Ask the user to choose a colour, and then apply that color to my route
1466 RouteUI::choose_color ()
1469 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1476 /** Set the route's own color. This may not be used for display if
1477 * the route is in a group which shares its color with its routes.
1480 RouteUI::set_color (const Gdk::Color & c)
1482 /* leave _color alone in the group case so that tracks can retain their
1483 * own pre-group colors.
1488 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1490 /* note: we use the route state ID here so that color is the same for both
1491 the time axis view and the mixer strip
1494 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1495 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1498 /** @return GUI state ID for things that are common to the route in all its representations */
1500 RouteUI::route_state_id () const
1502 return string_compose (X_("route %1"), _route->id().to_s());
1506 RouteUI::set_color_from_route ()
1508 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1516 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1519 _color.set_green (g);
1520 _color.set_blue (b);
1526 RouteUI::remove_this_route (bool apply_to_selection)
1528 if (apply_to_selection) {
1529 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1531 if ((route()->is_master() || route()->is_monitor()) &&
1532 !Config->get_allow_special_bus_removal()) {
1533 MessageDialog msg (_("That would be bad news ...."),
1537 msg.set_secondary_text (string_compose (_(
1538 "Removing the master or monitor bus is such a bad idea\n\
1539 that %1 is not going to allow it.\n\
1541 If you really want to do this sort of thing\n\
1542 edit your ardour.rc file to set the\n\
1543 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1550 vector<string> choices;
1554 prompt = string_compose (_("Do you really want to remove track \"%1\" ?\n\nYou may also lose the playlist used by this track.\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1556 prompt = string_compose (_("Do you really want to remove bus \"%1\" ?\n\n(This action cannot be undone, and the session file will be overwritten)"), _route->name());
1559 choices.push_back (_("No, do nothing."));
1560 choices.push_back (_("Yes, remove it."));
1564 title = _("Remove track");
1566 title = _("Remove bus");
1569 Choice prompter (title, prompt, choices);
1571 if (prompter.run () == 1) {
1572 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1578 RouteUI::idle_remove_this_route (RouteUI *rui)
1580 rui->_session->remove_route (rui->route());
1584 /** @return true if this name should be used for the route, otherwise false */
1586 RouteUI::verify_new_route_name (const std::string& name)
1588 if (name.find (':') == string::npos) {
1592 MessageDialog colon_msg (
1593 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1594 false, MESSAGE_QUESTION, BUTTONS_NONE
1597 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1598 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1600 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1604 RouteUI::route_rename ()
1606 ArdourPrompter name_prompter (true);
1611 name_prompter.set_title (_("Rename Track"));
1613 name_prompter.set_title (_("Rename Bus"));
1615 name_prompter.set_prompt (_("New name:"));
1616 name_prompter.set_initial_text (_route->name());
1617 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1618 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1619 name_prompter.show_all ();
1622 switch (name_prompter.run ()) {
1623 case Gtk::RESPONSE_ACCEPT:
1624 name_prompter.get_result (result);
1625 name_prompter.hide ();
1626 if (result.length()) {
1627 if (verify_new_route_name (result)) {
1628 _route->set_name (result);
1631 /* back to name prompter */
1635 /* nothing entered, just get out of here */
1650 RouteUI::property_changed (const PropertyChange& what_changed)
1652 if (what_changed.contains (ARDOUR::Properties::name)) {
1653 name_label.set_text (_route->name());
1658 RouteUI::toggle_comment_editor ()
1660 // if (ignore_toggle) {
1664 if (comment_window && comment_window->is_visible ()) {
1665 comment_window->hide ();
1667 open_comment_editor ();
1673 RouteUI::open_comment_editor ()
1675 if (comment_window == 0) {
1676 setup_comment_editor ();
1680 title = _route->name();
1681 title += _(": comment editor");
1683 comment_window->set_title (title);
1684 comment_window->present();
1688 RouteUI::setup_comment_editor ()
1690 comment_window = new ArdourWindow (""); // title will be reset to show route
1691 comment_window->set_skip_taskbar_hint (true);
1692 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1693 comment_window->set_default_size (400, 200);
1695 comment_area = manage (new TextView());
1696 comment_area->set_name ("MixerTrackCommentArea");
1697 comment_area->set_wrap_mode (WRAP_WORD);
1698 comment_area->set_editable (true);
1699 comment_area->get_buffer()->set_text (_route->comment());
1700 comment_area->show ();
1702 comment_window->add (*comment_area);
1706 RouteUI::comment_changed (void *src)
1708 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1711 ignore_comment_edit = true;
1713 comment_area->get_buffer()->set_text (_route->comment());
1715 ignore_comment_edit = false;
1720 RouteUI::comment_editor_done_editing ()
1722 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1724 string const str = comment_area->get_buffer()->get_text();
1725 if (str == _route->comment ()) {
1729 _route->set_comment (str, this);
1733 RouteUI::set_route_active (bool a, bool apply_to_selection)
1735 if (apply_to_selection) {
1736 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1738 _route->set_active (a, this);
1743 RouteUI::toggle_denormal_protection ()
1745 if (denormal_menu_item) {
1749 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1751 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1752 _route->set_denormal_protection (x);
1758 RouteUI::denormal_protection_changed ()
1760 if (denormal_menu_item) {
1761 denormal_menu_item->set_active (_route->denormal_protection());
1766 RouteUI::disconnect_input ()
1768 _route->input()->disconnect (this);
1772 RouteUI::disconnect_output ()
1774 _route->output()->disconnect (this);
1778 RouteUI::is_track () const
1780 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1783 boost::shared_ptr<Track>
1784 RouteUI::track() const
1786 return boost::dynamic_pointer_cast<Track>(_route);
1790 RouteUI::is_audio_track () const
1792 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1795 boost::shared_ptr<AudioTrack>
1796 RouteUI::audio_track() const
1798 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1802 RouteUI::is_midi_track () const
1804 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1807 boost::shared_ptr<MidiTrack>
1808 RouteUI::midi_track() const
1810 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1814 RouteUI::has_audio_outputs () const
1816 return (_route->n_outputs().n_audio() > 0);
1820 RouteUI::name() const
1822 return _route->name();
1826 RouteUI::map_frozen ()
1828 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1830 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1833 switch (at->freeze_state()) {
1834 case AudioTrack::Frozen:
1835 rec_enable_button->set_sensitive (false);
1838 rec_enable_button->set_sensitive (true);
1845 RouteUI::adjust_latency ()
1847 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1851 RouteUI::save_as_template ()
1854 std::string safe_name;
1857 path = ARDOUR::user_route_template_directory ();
1859 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1860 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1864 Prompter p (true); // modal
1866 p.set_title (_("Save As Template"));
1867 p.set_prompt (_("Template name:"));
1868 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1870 case RESPONSE_ACCEPT:
1877 p.get_result (name, true);
1879 safe_name = legalize_for_path (name);
1880 safe_name += template_suffix;
1882 path = Glib::build_filename (path, safe_name);
1884 _route->save_as_template (path, name);
1888 RouteUI::check_rec_enable_sensitivity ()
1890 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1891 rec_enable_button->set_sensitive (false);
1893 rec_enable_button->set_sensitive (true);
1896 update_monitoring_display ();
1900 RouteUI::parameter_changed (string const & p)
1902 /* this handles RC and per-session parameter changes */
1904 if (p == "disable-disarm-during-roll") {
1905 check_rec_enable_sensitivity ();
1906 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1907 set_button_names ();
1908 } else if (p == "auto-input") {
1909 update_monitoring_display ();
1914 RouteUI::step_gain_up ()
1916 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1920 RouteUI::page_gain_up ()
1922 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1926 RouteUI::step_gain_down ()
1928 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1932 RouteUI::page_gain_down ()
1934 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1938 RouteUI::open_remote_control_id_dialog ()
1940 ArdourDialog dialog (_("Remote Control ID"));
1941 SpinButton* spin = 0;
1943 dialog.get_vbox()->set_border_width (18);
1945 if (Config->get_remote_model() == UserOrdered) {
1946 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1948 HBox* hbox = manage (new HBox);
1949 hbox->set_spacing (6);
1950 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1951 spin = manage (new SpinButton);
1952 spin->set_digits (0);
1953 spin->set_increments (1, 10);
1954 spin->set_range (0, limit);
1955 spin->set_value (_route->remote_control_id());
1956 hbox->pack_start (*spin);
1957 dialog.get_vbox()->pack_start (*hbox);
1959 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1960 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1962 Label* l = manage (new Label());
1963 if (_route->is_master() || _route->is_monitor()) {
1964 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1965 "The remote control ID of %3 cannot be changed."),
1966 Glib::Markup::escape_text (_route->name()),
1967 _route->remote_control_id(),
1968 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1970 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1971 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1972 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1973 (is_track() ? _("track") : _("bus")),
1974 _route->remote_control_id(),
1975 "<span size=\"small\" style=\"italic\">",
1977 Glib::Markup::escape_text (_route->name()),
1980 dialog.get_vbox()->pack_start (*l);
1981 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1985 int const r = dialog.run ();
1987 if (r == RESPONSE_ACCEPT && spin) {
1988 _route->set_remote_control_id (spin->get_value_as_int ());
1993 RouteUI::setup_invert_buttons ()
1995 /* remove old invert buttons */
1996 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1997 _invert_button_box.remove (**i);
2000 _invert_buttons.clear ();
2002 if (!_route || !_route->input()) {
2006 uint32_t const N = _route->input()->n_ports().n_audio ();
2008 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2010 for (uint32_t i = 0; i < to_add; ++i) {
2011 ArdourButton* b = manage (new ArdourButton);
2012 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2013 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2015 b->set_name (X_("invert button"));
2018 b->set_text (string_compose (X_("Ø (%1)"), N));
2020 b->set_text (X_("Ø"));
2023 b->set_text (string_compose (X_("Ø%1"), i + 1));
2026 if (N <= _max_invert_buttons) {
2027 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));
2029 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2032 _invert_buttons.push_back (b);
2033 _invert_button_box.pack_start (*b);
2036 _invert_button_box.set_spacing (1);
2037 _invert_button_box.show_all ();
2041 RouteUI::set_invert_button_state ()
2043 uint32_t const N = _route->input()->n_ports().n_audio();
2044 if (N > _max_invert_buttons) {
2046 /* One button for many channels; explicit active if all channels are inverted,
2047 implicit active if some are, off if none are.
2050 ArdourButton* b = _invert_buttons.front ();
2052 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2053 b->set_active_state (Gtkmm2ext::ExplicitActive);
2054 } else if (_route->phase_invert().any()) {
2055 b->set_active_state (Gtkmm2ext::ImplicitActive);
2057 b->set_active_state (Gtkmm2ext::Off);
2062 /* One button per channel; just set active */
2065 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2066 (*i)->set_active (_route->phase_invert (j));
2073 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2075 if (ev->button == 1 && i < _invert_buttons.size()) {
2076 uint32_t const N = _route->input()->n_ports().n_audio ();
2077 if (N <= _max_invert_buttons) {
2078 /* left-click inverts phase so long as we have a button per channel */
2079 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2088 RouteUI::invert_press (GdkEventButton* ev)
2090 using namespace Menu_Helpers;
2092 uint32_t const N = _route->input()->n_ports().n_audio();
2093 if (N <= _max_invert_buttons && ev->button != 3) {
2094 /* If we have an invert button per channel, we only pop
2095 up a menu on right-click; left click is handled
2101 delete _invert_menu;
2102 _invert_menu = new Menu;
2103 _invert_menu->set_name ("ArdourContextMenu");
2104 MenuList& items = _invert_menu->items ();
2106 for (uint32_t i = 0; i < N; ++i) {
2107 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2108 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2109 ++_i_am_the_modifier;
2110 e->set_active (_route->phase_invert (i));
2111 --_i_am_the_modifier;
2114 _invert_menu->popup (0, ev->time);
2120 RouteUI::invert_menu_toggled (uint32_t c)
2122 if (_i_am_the_modifier) {
2126 _route->set_phase_invert (c, !_route->phase_invert (c));
2130 RouteUI::set_invert_sensitive (bool yn)
2132 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2133 (*b)->set_sensitive (yn);
2138 RouteUI::request_redraw ()
2141 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2145 /** The Route's gui_changed signal has been emitted */
2147 RouteUI::route_gui_changed (string what_changed)
2149 if (what_changed == "color") {
2150 if (set_color_from_route () == 0) {
2151 route_color_changed ();
2156 /** @return the color that this route should use; it maybe its own,
2157 or it maybe that of its route group.
2160 RouteUI::color () const
2162 RouteGroup* g = _route->route_group ();
2164 if (g && g->is_color()) {
2166 set_color_from_rgba (c, GroupTabs::group_color (g));
2174 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2176 _showing_sends_to = send_to;
2177 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2181 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2183 if (_route == send_to) {
2184 show_sends_button->set_active (true);
2185 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2187 show_sends_button->set_active (false);
2188 send_blink_connection.disconnect ();
2193 RouteUI::route_group() const
2195 return _route->route_group();