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>
27 #include "ardour/route_group.h"
28 #include "ardour/dB.h"
29 #include "pbd/memento_command.h"
30 #include "pbd/stacktrace.h"
31 #include "pbd/controllable.h"
32 #include "pbd/enumwriter.h"
34 #include "ardour_ui.h"
37 #include "ardour_button.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
46 #include "route_time_axis.h"
47 #include "group_tabs.h"
49 #include "ardour/audio_track.h"
50 #include "ardour/audioengine.h"
51 #include "ardour/filename_extensions.h"
52 #include "ardour/midi_track.h"
53 #include "ardour/route.h"
54 #include "ardour/session.h"
55 #include "ardour/template_utils.h"
59 using namespace Gtkmm2ext;
60 using namespace ARDOUR;
63 uint32_t RouteUI::_max_invert_buttons = 3;
64 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
65 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
67 RouteUI::RouteUI (ARDOUR::Session* sess)
80 _route.reset (); /* drop reference to route, so that it can be cleaned up */
81 route_connections.drop_connections ();
99 pre_fader_mute_check = 0;
100 post_fader_mute_check = 0;
101 listen_mute_check = 0;
104 solo_isolated_check = 0;
105 solo_isolated_led = 0;
109 denormal_menu_item = 0;
111 multiple_mute_change = false;
112 multiple_solo_change = false;
113 _i_am_the_modifier = 0;
115 setup_invert_buttons ();
117 mute_button = manage (new ArdourButton);
118 mute_button->set_name ("mute button");
119 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
121 solo_button = manage (new ArdourButton);
122 solo_button->set_name ("solo button");
123 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
124 solo_button->set_no_show_all (true);
126 rec_enable_button = manage (new ArdourButton);
127 rec_enable_button->set_name ("record enable button");
128 rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
129 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
131 show_sends_button = manage (new ArdourButton);
132 show_sends_button->set_name ("send alert button");
133 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
135 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
136 monitor_input_button->set_name ("monitor button");
137 monitor_input_button->set_text (_("In"));
138 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
139 monitor_input_button->set_no_show_all (true);
141 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
142 monitor_disk_button->set_name ("monitor button");
143 monitor_disk_button->set_text (_("Disk"));
144 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
145 monitor_disk_button->set_no_show_all (true);
147 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
148 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
149 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
151 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
152 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
154 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
155 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
157 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
158 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
160 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
161 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
162 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
163 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
165 monitor_input_button->set_distinct_led_click (false);
166 monitor_disk_button->set_distinct_led_click (false);
168 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
169 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
171 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
172 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
174 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
180 route_connections.drop_connections ();
188 denormal_menu_item = 0;
192 RouteUI::self_delete ()
198 RouteUI::set_route (boost::shared_ptr<Route> rp)
204 if (set_color_from_route()) {
205 set_color (unique_random_color());
209 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
212 mute_button->set_controllable (_route->mute_control());
213 solo_button->set_controllable (_route->solo_control());
215 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
216 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
218 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
219 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
220 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
221 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
223 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
224 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
226 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
227 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
229 if (_session->writable() && is_track()) {
230 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
232 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
234 rec_enable_button->show();
235 rec_enable_button->set_controllable (t->rec_enable_control());
237 if (is_midi_track()) {
238 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
239 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
244 /* this will work for busses and tracks, and needs to be called to
245 set up the name entry/name label display.
248 update_rec_display ();
251 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
252 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
254 update_monitoring_display ();
257 mute_button->unset_flags (Gtk::CAN_FOCUS);
258 solo_button->unset_flags (Gtk::CAN_FOCUS);
262 if (_route->is_monitor() || _route->is_master()) {
263 solo_button->hide ();
270 setup_invert_buttons ();
271 set_invert_button_state ();
273 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
274 bus_send_display_changed (s);
276 update_mute_display ();
277 update_solo_display ();
281 RouteUI::polarity_changed ()
287 set_invert_button_state ();
291 RouteUI::mute_press (GdkEventButton* ev)
293 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
297 multiple_mute_change = false;
299 if (!_i_am_the_modifier) {
301 if (Keyboard::is_context_menu_event (ev)) {
307 mute_menu->popup(0,ev->time);
311 if (Keyboard::is_button2_event (ev)) {
312 // Primary-button2 click is the midi binding click
313 // button2-click is "momentary"
316 if (mute_button->on_button_press_event (ev)) {
320 _mute_release = new SoloMuteRelease (_route->muted ());
323 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
325 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
327 /* toggle mute on everything (but
328 * exclude the master and monitor)
330 * because we are going to erase
331 * elements of the list we need to work
335 boost::shared_ptr<RouteList> copy (new RouteList);
337 *copy = *_session->get_routes ();
339 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
340 if ((*i)->is_master() || (*i)->is_monitor()) {
348 _mute_release->routes = copy;
351 _session->set_mute (copy, !_route->muted());
353 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
355 /* Primary-button1 applies change to the mix group even if it is not active
356 NOTE: Primary-button2 is MIDI learn.
359 boost::shared_ptr<RouteList> rl;
361 if (ev->button == 1) {
363 if (_route->route_group()) {
365 rl = _route->route_group()->route_list();
368 _mute_release->routes = rl;
371 rl.reset (new RouteList);
372 rl->push_back (_route);
375 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
380 /* plain click applies change to this route */
382 boost::shared_ptr<RouteList> rl (new RouteList);
383 rl->push_back (_route);
386 _mute_release->routes = rl;
389 _session->set_mute (rl, !_route->muted());
401 RouteUI::mute_release (GdkEventButton*)
403 if (!_i_am_the_modifier) {
405 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
406 delete _mute_release;
415 RouteUI::solo_press(GdkEventButton* ev)
417 /* ignore double/triple clicks */
419 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
423 multiple_solo_change = false;
425 if (!_i_am_the_modifier) {
427 if (Keyboard::is_context_menu_event (ev)) {
429 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
430 ! (solo_safe_led && solo_safe_led->is_visible())) {
432 if (solo_menu == 0) {
436 solo_menu->popup (1, ev->time);
441 if (Keyboard::is_button2_event (ev)) {
443 // Primary-button2 click is the midi binding click
444 // button2-click is "momentary"
446 if (solo_button->on_button_press_event (ev)) {
450 _solo_release = new SoloMuteRelease (_route->self_soloed());
453 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
455 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
457 /* Primary-Tertiary-click applies change to all routes */
460 _solo_release->routes = _session->get_routes ();
463 if (Config->get_solo_control_is_listen_control()) {
464 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
466 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
469 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
471 // Primary-Secondary-click: exclusively solo this track
474 _solo_release->exclusive = true;
476 boost::shared_ptr<RouteList> routes = _session->get_routes();
478 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
479 if ((*i)->soloed ()) {
480 _solo_release->routes_on->push_back (*i);
482 _solo_release->routes_off->push_back (*i);
487 if (Config->get_solo_control_is_listen_control()) {
488 /* ??? we need a just_one_listen() method */
490 _session->set_just_one_solo (_route, true);
493 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
495 // shift-click: toggle solo isolated status
497 _route->set_solo_isolated (!_route->solo_isolated(), this);
498 delete _solo_release;
501 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
503 /* Primary-button1: solo mix group.
504 NOTE: Primary-button2 is MIDI learn.
507 /* Primary-button1 applies change to the mix group even if it is not active
508 NOTE: Primary-button2 is MIDI learn.
511 boost::shared_ptr<RouteList> rl;
513 if (ev->button == 1) {
515 if (_route->route_group()) {
517 rl = _route->route_group()->route_list();
520 _solo_release->routes = rl;
523 rl.reset (new RouteList);
524 rl->push_back (_route);
527 if (Config->get_solo_control_is_listen_control()) {
528 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
530 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
536 /* click: solo this route */
538 boost::shared_ptr<RouteList> rl (new RouteList);
539 rl->push_back (route());
542 _solo_release->routes = rl;
545 if (Config->get_solo_control_is_listen_control()) {
546 _session->set_listen (rl, !_route->listening_via_monitor());
548 _session->set_solo (rl, !_route->self_soloed());
559 RouteUI::solo_release (GdkEventButton*)
561 if (!_i_am_the_modifier) {
565 if (_solo_release->exclusive) {
568 if (Config->get_solo_control_is_listen_control()) {
569 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
571 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
575 delete _solo_release;
584 RouteUI::rec_enable_press(GdkEventButton* ev)
586 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
590 if (!_session->engine().connected()) {
591 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
596 if (is_midi_track()) {
598 /* rec-enable button exits from step editing */
600 if (midi_track()->step_editing()) {
601 midi_track()->set_step_editing (false);
606 if (!_i_am_the_modifier && is_track() && rec_enable_button) {
608 if (Keyboard::is_button2_event (ev)) {
610 // do nothing on midi sigc::bind event
611 return rec_enable_button->on_button_press_event (ev);
613 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
615 _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
617 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
619 /* Primary-button1 applies change to the route group (even if it is not active)
620 NOTE: Primary-button2 is MIDI learn.
623 if (ev->button == 1) {
625 boost::shared_ptr<RouteList> rl;
627 if (_route->route_group()) {
629 rl = _route->route_group()->route_list();
632 rl.reset (new RouteList);
633 rl->push_back (_route);
636 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
639 } else if (Keyboard::is_context_menu_event (ev)) {
641 /* do this on release */
645 boost::shared_ptr<RouteList> rl (new RouteList);
646 rl->push_back (route());
647 _session->set_record_enabled (rl, !rec_enable_button->active_state());
655 RouteUI::monitoring_changed ()
657 update_monitoring_display ();
661 RouteUI::update_monitoring_display ()
667 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
673 MonitorState ms = t->monitoring_state();
675 if (t->monitoring_choice() & MonitorInput) {
676 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
678 if (ms & MonitoringInput) {
679 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
681 monitor_input_button->unset_active_state ();
685 if (t->monitoring_choice() & MonitorDisk) {
686 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
688 if (ms & MonitoringDisk) {
689 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
691 monitor_disk_button->unset_active_state ();
697 RouteUI::monitor_input_press(GdkEventButton*)
703 RouteUI::monitor_input_release(GdkEventButton* ev)
705 return monitor_release (ev, MonitorInput);
709 RouteUI::monitor_disk_press (GdkEventButton*)
715 RouteUI::monitor_disk_release (GdkEventButton* ev)
717 return monitor_release (ev, MonitorDisk);
721 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
723 if (ev->button != 1) {
727 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
734 boost::shared_ptr<RouteList> rl;
736 /* XXX for now, monitoring choices are orthogonal. cue monitoring
737 will follow in 3.X but requires mixing the input and playback (disk)
738 signal together, which requires yet more buffers.
741 if (t->monitoring_choice() & monitor_choice) {
742 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
744 /* this line will change when the options are non-orthogonal */
745 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
749 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
750 rl = _session->get_routes ();
752 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
753 if (_route->route_group() && _route->route_group()->is_monitoring()) {
754 rl = _route->route_group()->route_list();
756 rl.reset (new RouteList);
757 rl->push_back (route());
760 rl.reset (new RouteList);
761 rl->push_back (route());
764 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
770 RouteUI::build_record_menu ()
776 /* no rec-button context menu for non-MIDI tracks
779 if (is_midi_track()) {
780 record_menu = new Menu;
781 record_menu->set_name ("ArdourContextMenu");
783 using namespace Menu_Helpers;
784 MenuList& items = record_menu->items();
786 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
787 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
789 if (_route->record_enabled()) {
790 step_edit_item->set_sensitive (false);
793 step_edit_item->set_active (midi_track()->step_editing());
798 RouteUI::toggle_step_edit ()
800 if (!is_midi_track() || _route->record_enabled()) {
804 midi_track()->set_step_editing (step_edit_item->get_active());
808 RouteUI::step_edit_changed (bool yn)
811 if (rec_enable_button) {
812 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
815 start_step_editing ();
817 if (step_edit_item) {
818 step_edit_item->set_active (true);
823 if (rec_enable_button) {
824 rec_enable_button->unset_active_state ();
827 stop_step_editing ();
829 if (step_edit_item) {
830 step_edit_item->set_active (false);
836 RouteUI::rec_enable_release (GdkEventButton* ev)
838 if (Keyboard::is_context_menu_event (ev)) {
839 build_record_menu ();
841 record_menu->popup (1, ev->time);
850 RouteUI::build_sends_menu ()
852 using namespace Menu_Helpers;
854 sends_menu = new Menu;
855 sends_menu->set_name ("ArdourContextMenu");
856 MenuList& items = sends_menu->items();
859 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
863 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
867 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
871 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
875 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
879 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
882 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
886 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
889 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
890 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
891 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
896 RouteUI::create_sends (Placement p, bool include_buses)
898 _session->globally_add_internal_sends (_route, p, include_buses);
902 RouteUI::create_selected_sends (Placement p, bool include_buses)
904 boost::shared_ptr<RouteList> rlist (new RouteList);
905 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
907 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
908 RouteTimeAxisView* rtv;
910 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
911 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
912 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
913 rlist->push_back (rui->route());
919 _session->add_internal_sends (_route, p, rlist);
923 RouteUI::set_sends_gain_from_track ()
925 _session->globally_set_send_gains_from_track (_route);
929 RouteUI::set_sends_gain_to_zero ()
931 _session->globally_set_send_gains_to_zero (_route);
935 RouteUI::set_sends_gain_to_unity ()
937 _session->globally_set_send_gains_to_unity (_route);
941 RouteUI::show_sends_press(GdkEventButton* ev)
943 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
947 if (!_i_am_the_modifier && !is_track() && show_sends_button) {
949 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
951 // do nothing on midi sigc::bind event
954 } else if (Keyboard::is_context_menu_event (ev)) {
956 if (sends_menu == 0) {
960 sends_menu->popup (0, ev->time);
964 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
967 set_showing_sends_to (boost::shared_ptr<Route> ());
969 set_showing_sends_to (_route);
978 RouteUI::show_sends_release (GdkEventButton*)
984 RouteUI::send_blink (bool onoff)
986 if (!show_sends_button) {
991 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
993 show_sends_button->unset_active_state ();
997 Gtkmm2ext::ActiveState
998 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1000 if (r->is_master() || r->is_monitor()) {
1001 return Gtkmm2ext::Off;
1004 if (Config->get_solo_control_is_listen_control()) {
1006 if (r->listening_via_monitor()) {
1007 return Gtkmm2ext::ExplicitActive;
1009 return Gtkmm2ext::Off;
1015 if (!r->self_soloed()) {
1016 return Gtkmm2ext::ImplicitActive;
1018 return Gtkmm2ext::ExplicitActive;
1021 return Gtkmm2ext::Off;
1025 Gtkmm2ext::ActiveState
1026 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1028 if (r->is_master() || r->is_monitor()) {
1029 return Gtkmm2ext::Off;
1032 if (r->solo_isolated()) {
1033 return Gtkmm2ext::ExplicitActive;
1035 return Gtkmm2ext::Off;
1039 Gtkmm2ext::ActiveState
1040 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1042 if (r->is_master() || r->is_monitor()) {
1043 return Gtkmm2ext::Off;
1046 if (r->solo_safe()) {
1047 return Gtkmm2ext::ExplicitActive;
1049 return Gtkmm2ext::Off;
1054 RouteUI::update_solo_display ()
1056 bool yn = _route->solo_safe ();
1058 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1059 solo_safe_check->set_active (yn);
1062 yn = _route->solo_isolated ();
1064 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1065 solo_isolated_check->set_active (yn);
1068 set_button_names ();
1070 if (solo_isolated_led) {
1071 if (_route->solo_isolated()) {
1072 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1074 solo_isolated_led->unset_active_state ();
1078 if (solo_safe_led) {
1079 if (_route->solo_safe()) {
1080 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1082 solo_safe_led->unset_active_state ();
1086 solo_button->set_active_state (solo_active_state (_route));
1088 /* some changes to solo status can affect mute display, so catch up
1091 update_mute_display ();
1095 RouteUI::solo_changed_so_update_mute ()
1097 update_mute_display ();
1101 RouteUI::mute_changed(void* /*src*/)
1103 update_mute_display ();
1107 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1109 if (r->is_monitor()) {
1110 return ActiveState(0);
1114 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1118 return Gtkmm2ext::ExplicitActive;
1119 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1120 /* master is NEVER muted by others */
1121 return Gtkmm2ext::ImplicitActive;
1123 /* no mute at all */
1124 return Gtkmm2ext::Off;
1131 return Gtkmm2ext::ExplicitActive;
1133 /* no mute at all */
1134 return Gtkmm2ext::Off;
1138 return ActiveState(0);
1142 RouteUI::update_mute_display ()
1148 mute_button->set_active_state (mute_active_state (_session, _route));
1152 RouteUI::route_rec_enable_changed ()
1154 update_rec_display ();
1155 update_monitoring_display ();
1159 RouteUI::session_rec_enable_changed ()
1161 update_rec_display ();
1162 update_monitoring_display ();
1166 RouteUI::update_rec_display ()
1168 if (!rec_enable_button || !_route) {
1172 if (_route->record_enabled()) {
1173 switch (_session->record_status ()) {
1174 case Session::Recording:
1175 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1178 case Session::Disabled:
1179 case Session::Enabled:
1180 rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1185 if (step_edit_item) {
1186 step_edit_item->set_sensitive (false);
1190 rec_enable_button->unset_active_state ();
1192 if (step_edit_item) {
1193 step_edit_item->set_sensitive (true);
1198 check_rec_enable_sensitivity ();
1202 RouteUI::build_solo_menu (void)
1204 using namespace Menu_Helpers;
1206 solo_menu = new Menu;
1207 solo_menu->set_name ("ArdourContextMenu");
1208 MenuList& items = solo_menu->items();
1209 Gtk::CheckMenuItem* check;
1211 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1212 check->set_active (_route->solo_isolated());
1213 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1214 items.push_back (CheckMenuElem(*check));
1215 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1218 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1219 check->set_active (_route->solo_safe());
1220 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1221 items.push_back (CheckMenuElem(*check));
1222 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1225 //items.push_back (SeparatorElem());
1226 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1231 RouteUI::build_mute_menu(void)
1233 using namespace Menu_Helpers;
1235 mute_menu = new Menu;
1236 mute_menu->set_name ("ArdourContextMenu");
1238 MenuList& items = mute_menu->items();
1240 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader")));
1241 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1242 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1243 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1244 pre_fader_mute_check->show_all();
1246 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader")));
1247 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1248 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1249 items.push_back (CheckMenuElem(*post_fader_mute_check));
1250 post_fader_mute_check->show_all();
1252 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1253 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1254 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1255 items.push_back (CheckMenuElem(*listen_mute_check));
1256 listen_mute_check->show_all();
1258 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1259 init_mute_menu(MuteMaster::Main, main_mute_check);
1260 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1261 items.push_back (CheckMenuElem(*main_mute_check));
1262 main_mute_check->show_all();
1264 //items.push_back (SeparatorElem());
1265 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1267 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1271 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1273 check->set_active (_route->mute_points() & mp);
1277 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1279 if (check->get_active()) {
1280 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1282 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1287 RouteUI::muting_change ()
1289 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1292 MuteMaster::MutePoint current = _route->mute_points ();
1294 yn = (current & MuteMaster::PreFader);
1296 if (pre_fader_mute_check->get_active() != yn) {
1297 pre_fader_mute_check->set_active (yn);
1300 yn = (current & MuteMaster::PostFader);
1302 if (post_fader_mute_check->get_active() != yn) {
1303 post_fader_mute_check->set_active (yn);
1306 yn = (current & MuteMaster::Listen);
1308 if (listen_mute_check->get_active() != yn) {
1309 listen_mute_check->set_active (yn);
1312 yn = (current & MuteMaster::Main);
1314 if (main_mute_check->get_active() != yn) {
1315 main_mute_check->set_active (yn);
1320 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1322 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1326 bool view = solo_isolated_led->active_state();
1327 bool model = _route->solo_isolated();
1329 /* called BEFORE the view has changed */
1331 if (ev->button == 1) {
1332 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1335 /* disable isolate for all routes */
1336 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1340 if (model == view) {
1342 /* flip just this route */
1344 boost::shared_ptr<RouteList> rl (new RouteList);
1345 rl->push_back (_route);
1346 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1355 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1357 if (ev->button == 1) {
1358 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1365 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1367 bool view = check->get_active();
1368 bool model = _route->solo_isolated();
1370 /* called AFTER the view has changed */
1372 if (model != view) {
1373 _route->set_solo_isolated (view, this);
1378 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1380 _route->set_solo_safe (check->get_active(), this);
1383 /** Ask the user to choose a colour, and then set all selected tracks
1387 RouteUI::choose_color ()
1390 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1393 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1394 boost::bind (&RouteUI::set_color, _1, color)
1399 /** Set the route's own color. This may not be used for display if
1400 * the route is in a group which shares its color with its routes.
1403 RouteUI::set_color (const Gdk::Color & c)
1405 /* leave _color alone in the group case so that tracks can retain their
1406 * own pre-group colors.
1411 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1413 /* note: we use the route state ID here so that color is the same for both
1414 the time axis view and the mixer strip
1417 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1418 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1421 /** @return GUI state ID for things that are common to the route in all its representations */
1423 RouteUI::route_state_id () const
1425 return string_compose (X_("route %1"), _route->id().to_s());
1429 RouteUI::set_color_from_route ()
1431 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1439 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1442 _color.set_green (g);
1443 _color.set_blue (b);
1449 RouteUI::remove_this_route (bool apply_to_selection)
1451 if (apply_to_selection) {
1452 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1454 if ((route()->is_master() || route()->is_monitor()) &&
1455 !Config->get_allow_special_bus_removal()) {
1456 MessageDialog msg (_("That would be bad news ...."),
1460 msg.set_secondary_text (string_compose (_(
1461 "Removing the master or monitor bus is such a bad idea\n\
1462 that %1 is not going to allow it.\n\
1464 If you really want to do this sort of thing\n\
1465 edit your ardour.rc file to set the\n\
1466 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1473 vector<string> choices;
1477 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());
1479 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());
1482 choices.push_back (_("No, do nothing."));
1483 choices.push_back (_("Yes, remove it."));
1487 title = _("Remove track");
1489 title = _("Remove bus");
1492 Choice prompter (title, prompt, choices);
1494 if (prompter.run () == 1) {
1495 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1501 RouteUI::idle_remove_this_route (RouteUI *rui)
1503 rui->_session->remove_route (rui->route());
1507 /** @return true if this name should be used for the route, otherwise false */
1509 RouteUI::verify_new_route_name (const std::string& name)
1511 if (name.find (':') == string::npos) {
1515 MessageDialog colon_msg (
1516 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1517 false, MESSAGE_QUESTION, BUTTONS_NONE
1520 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1521 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1523 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1527 RouteUI::route_rename ()
1529 ArdourPrompter name_prompter (true);
1534 name_prompter.set_title (_("Rename Track"));
1536 name_prompter.set_title (_("Rename Bus"));
1538 name_prompter.set_prompt (_("New name:"));
1539 name_prompter.set_initial_text (_route->name());
1540 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1541 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1542 name_prompter.show_all ();
1545 switch (name_prompter.run ()) {
1546 case Gtk::RESPONSE_ACCEPT:
1547 name_prompter.get_result (result);
1548 name_prompter.hide ();
1549 if (result.length()) {
1550 if (verify_new_route_name (result)) {
1551 _route->set_name (result);
1554 /* back to name prompter */
1558 /* nothing entered, just get out of here */
1573 RouteUI::property_changed (const PropertyChange& what_changed)
1575 if (what_changed.contains (ARDOUR::Properties::name)) {
1576 name_label.set_text (_route->name());
1581 RouteUI::set_route_active (bool a, bool apply_to_selection)
1583 if (apply_to_selection) {
1584 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1586 _route->set_active (a, this);
1591 RouteUI::toggle_denormal_protection ()
1593 if (denormal_menu_item) {
1597 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1599 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1600 _route->set_denormal_protection (x);
1606 RouteUI::denormal_protection_changed ()
1608 if (denormal_menu_item) {
1609 denormal_menu_item->set_active (_route->denormal_protection());
1614 RouteUI::disconnect_input ()
1616 _route->input()->disconnect (this);
1620 RouteUI::disconnect_output ()
1622 _route->output()->disconnect (this);
1626 RouteUI::is_track () const
1628 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1631 boost::shared_ptr<Track>
1632 RouteUI::track() const
1634 return boost::dynamic_pointer_cast<Track>(_route);
1638 RouteUI::is_audio_track () const
1640 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1643 boost::shared_ptr<AudioTrack>
1644 RouteUI::audio_track() const
1646 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1650 RouteUI::is_midi_track () const
1652 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1655 boost::shared_ptr<MidiTrack>
1656 RouteUI::midi_track() const
1658 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1662 RouteUI::has_audio_outputs () const
1664 return (_route->n_outputs().n_audio() > 0);
1668 RouteUI::name() const
1670 return _route->name();
1674 RouteUI::map_frozen ()
1676 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1678 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1681 switch (at->freeze_state()) {
1682 case AudioTrack::Frozen:
1683 rec_enable_button->set_sensitive (false);
1686 rec_enable_button->set_sensitive (true);
1693 RouteUI::adjust_latency ()
1695 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1699 RouteUI::save_as_template ()
1702 std::string safe_name;
1705 path = ARDOUR::user_route_template_directory ();
1707 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1708 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1712 Prompter p (true); // modal
1714 p.set_title (_("Save As Template"));
1715 p.set_prompt (_("Template name:"));
1716 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1718 case RESPONSE_ACCEPT:
1725 p.get_result (name, true);
1727 safe_name = legalize_for_path (name);
1728 safe_name += template_suffix;
1730 path = Glib::build_filename (path, safe_name);
1732 _route->save_as_template (path, name);
1736 RouteUI::check_rec_enable_sensitivity ()
1738 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1739 rec_enable_button->set_sensitive (false);
1741 rec_enable_button->set_sensitive (true);
1744 update_monitoring_display ();
1748 RouteUI::parameter_changed (string const & p)
1750 /* this handles RC and per-session parameter changes */
1752 if (p == "disable-disarm-during-roll") {
1753 check_rec_enable_sensitivity ();
1754 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1755 set_button_names ();
1756 } else if (p == "auto-input") {
1757 update_monitoring_display ();
1762 RouteUI::step_gain_up ()
1764 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1768 RouteUI::page_gain_up ()
1770 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1774 RouteUI::step_gain_down ()
1776 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1780 RouteUI::page_gain_down ()
1782 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1786 RouteUI::open_remote_control_id_dialog ()
1788 ArdourDialog dialog (_("Remote Control ID"));
1789 SpinButton* spin = 0;
1791 dialog.get_vbox()->set_border_width (18);
1793 if (Config->get_remote_model() == UserOrdered) {
1794 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1796 HBox* hbox = manage (new HBox);
1797 hbox->set_spacing (6);
1798 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1799 spin = manage (new SpinButton);
1800 spin->set_digits (0);
1801 spin->set_increments (1, 10);
1802 spin->set_range (0, limit);
1803 spin->set_value (_route->remote_control_id());
1804 hbox->pack_start (*spin);
1805 dialog.get_vbox()->pack_start (*hbox);
1807 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1808 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1810 Label* l = manage (new Label());
1811 if (_route->is_master() || _route->is_monitor()) {
1812 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1813 "The remote control ID of %3 cannot be changed."),
1814 Glib::Markup::escape_text (_route->name()),
1815 _route->remote_control_id(),
1816 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1818 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1819 "Remote Control IDs are currently determined by track/bus ordering in Ardour.\n\n"
1820 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1821 (is_track() ? _("track") : _("bus")),
1822 _route->remote_control_id(),
1823 "<span size=\"small\" style=\"italic\">",
1825 Glib::Markup::escape_text (_route->name())));
1827 dialog.get_vbox()->pack_start (*l);
1828 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1832 int const r = dialog.run ();
1834 if (r == RESPONSE_ACCEPT && spin) {
1835 _route->set_remote_control_id (spin->get_value_as_int ());
1840 RouteUI::setup_invert_buttons ()
1842 /* remove old invert buttons */
1843 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1844 _invert_button_box.remove (**i);
1847 _invert_buttons.clear ();
1849 if (!_route || !_route->input()) {
1853 uint32_t const N = _route->input()->n_ports().n_audio ();
1855 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1857 for (uint32_t i = 0; i < to_add; ++i) {
1858 ArdourButton* b = manage (new ArdourButton);
1859 b->set_size_request(20,20);
1860 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1861 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1863 b->set_name (X_("invert button"));
1866 b->set_text (string_compose (X_("Ø (%1)"), N));
1868 b->set_text (X_("Ø"));
1871 b->set_text (string_compose (X_("Ø%1"), i + 1));
1874 if (N <= _max_invert_buttons) {
1875 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));
1877 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1880 _invert_buttons.push_back (b);
1881 _invert_button_box.pack_start (*b);
1884 _invert_button_box.set_spacing (1);
1885 _invert_button_box.show_all ();
1889 RouteUI::set_invert_button_state ()
1891 ++_i_am_the_modifier;
1893 uint32_t const N = _route->input()->n_ports().n_audio();
1894 if (N > _max_invert_buttons) {
1896 /* One button for many channels; explicit active if all channels are inverted,
1897 implicit active if some are, off if none are.
1900 ArdourButton* b = _invert_buttons.front ();
1902 if (_route->phase_invert().count() == _route->phase_invert().size()) {
1903 b->set_active_state (Gtkmm2ext::ExplicitActive);
1904 } else if (_route->phase_invert().any()) {
1905 b->set_active_state (Gtkmm2ext::ImplicitActive);
1907 b->set_active_state (Gtkmm2ext::Off);
1912 /* One button per channel; just set active */
1915 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1916 (*i)->set_active (_route->phase_invert (j));
1921 --_i_am_the_modifier;
1925 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1927 if (ev->button == 1 && i < _invert_buttons.size()) {
1928 uint32_t const N = _route->input()->n_ports().n_audio ();
1929 if (N <= _max_invert_buttons) {
1930 /* left-click inverts phase so long as we have a button per channel */
1931 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1940 RouteUI::invert_press (GdkEventButton* ev)
1942 using namespace Menu_Helpers;
1944 uint32_t const N = _route->input()->n_ports().n_audio();
1945 if (N <= _max_invert_buttons && ev->button != 3) {
1946 /* If we have an invert button per channel, we only pop
1947 up a menu on right-click; left click is handled
1953 delete _invert_menu;
1954 _invert_menu = new Menu;
1955 _invert_menu->set_name ("ArdourContextMenu");
1956 MenuList& items = _invert_menu->items ();
1958 for (uint32_t i = 0; i < N; ++i) {
1959 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1960 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
1961 ++_i_am_the_modifier;
1962 e->set_active (_route->phase_invert (i));
1963 --_i_am_the_modifier;
1966 _invert_menu->popup (0, ev->time);
1972 RouteUI::invert_menu_toggled (uint32_t c)
1974 if (_i_am_the_modifier) {
1978 _route->set_phase_invert (c, !_route->phase_invert (c));
1982 RouteUI::set_invert_sensitive (bool yn)
1984 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1985 (*b)->set_sensitive (yn);
1990 RouteUI::request_redraw ()
1993 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1997 /** The Route's gui_changed signal has been emitted */
1999 RouteUI::route_gui_changed (string what_changed)
2001 if (what_changed == "color") {
2002 if (set_color_from_route () == 0) {
2003 route_color_changed ();
2008 /** @return the color that this route should use; it maybe its own,
2009 or it maybe that of its route group.
2012 RouteUI::color () const
2014 RouteGroup* g = _route->route_group ();
2016 if (g && g->is_color()) {
2017 return GroupTabs::group_color (g);
2024 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2026 _showing_sends_to = send_to;
2027 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2031 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2033 if (_route == send_to) {
2034 show_sends_button->set_active (true);
2035 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2037 show_sends_button->set_active (false);
2038 send_blink_connection.disconnect ();
2043 RouteUI::route_group() const
2045 return _route->route_group();