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;
61 using namespace ARDOUR_UI_UTILS;
64 uint32_t RouteUI::_max_invert_buttons = 3;
65 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
66 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
68 RouteUI::RouteUI (ARDOUR::Session* sess)
81 _route.reset (); /* drop reference to route, so that it can be cleaned up */
82 route_connections.drop_connections ();
100 pre_fader_mute_check = 0;
101 post_fader_mute_check = 0;
102 listen_mute_check = 0;
105 solo_isolated_check = 0;
106 solo_isolated_led = 0;
110 denormal_menu_item = 0;
112 multiple_mute_change = false;
113 multiple_solo_change = false;
114 _i_am_the_modifier = 0;
116 setup_invert_buttons ();
118 mute_button = manage (new ArdourButton);
119 mute_button->set_name ("mute button");
120 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
122 solo_button = manage (new ArdourButton);
123 solo_button->set_name ("solo button");
124 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
125 solo_button->set_no_show_all (true);
127 rec_enable_button = manage (new ArdourButton);
128 rec_enable_button->set_name ("record enable button");
129 // rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
130 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
132 show_sends_button = manage (new ArdourButton);
133 show_sends_button->set_name ("send alert button");
134 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
136 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
137 monitor_input_button->set_name ("monitor button");
138 monitor_input_button->set_text (_("In"));
139 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
140 monitor_input_button->set_no_show_all (true);
142 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
143 monitor_disk_button->set_name ("monitor button");
144 monitor_disk_button->set_text (_("Disk"));
145 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
146 monitor_disk_button->set_no_show_all (true);
148 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
149 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
150 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
152 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
153 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
155 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
156 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
158 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
159 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
161 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
162 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
163 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
164 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
166 monitor_input_button->set_distinct_led_click (false);
167 monitor_disk_button->set_distinct_led_click (false);
169 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
170 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
172 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
173 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
175 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
181 route_connections.drop_connections ();
189 denormal_menu_item = 0;
193 RouteUI::self_delete ()
199 RouteUI::set_route (boost::shared_ptr<Route> rp)
205 if (set_color_from_route()) {
206 set_color (unique_random_color());
210 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
213 mute_button->set_controllable (_route->mute_control());
214 solo_button->set_controllable (_route->solo_control());
216 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
217 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
219 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
220 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
221 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
222 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
224 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
225 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
227 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
228 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
230 if (_session->writable() && is_track()) {
231 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
233 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
235 rec_enable_button->show();
236 rec_enable_button->set_controllable (t->rec_enable_control());
238 if (is_midi_track()) {
239 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
240 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
245 /* this will work for busses and tracks, and needs to be called to
246 set up the name entry/name label display.
249 update_rec_display ();
252 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
253 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
255 update_monitoring_display ();
258 mute_button->unset_flags (Gtk::CAN_FOCUS);
259 solo_button->unset_flags (Gtk::CAN_FOCUS);
263 if (_route->is_monitor() || _route->is_master()) {
264 solo_button->hide ();
271 setup_invert_buttons ();
272 set_invert_button_state ();
274 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
275 bus_send_display_changed (s);
277 update_mute_display ();
278 update_solo_display ();
282 RouteUI::polarity_changed ()
288 set_invert_button_state ();
292 RouteUI::mute_press (GdkEventButton* ev)
294 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
298 multiple_mute_change = false;
300 if (!_i_am_the_modifier) {
302 if (Keyboard::is_context_menu_event (ev)) {
308 mute_menu->popup(0,ev->time);
312 if (Keyboard::is_button2_event (ev)) {
313 // Primary-button2 click is the midi binding click
314 // button2-click is "momentary"
317 if (mute_button->on_button_press_event (ev)) {
321 _mute_release = new SoloMuteRelease (_route->muted ());
324 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
326 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
328 /* toggle mute on everything (but
329 * exclude the master and monitor)
331 * because we are going to erase
332 * elements of the list we need to work
336 boost::shared_ptr<RouteList> copy (new RouteList);
338 *copy = *_session->get_routes ();
340 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
341 if ((*i)->is_master() || (*i)->is_monitor()) {
349 _mute_release->routes = copy;
353 _session->set_mute (copy, !_route->muted());
355 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
357 /* Primary-button1 applies change to the mix group even if it is not active
358 NOTE: Primary-button2 is MIDI learn.
361 boost::shared_ptr<RouteList> rl;
363 if (ev->button == 1) {
365 if (_route->route_group()) {
367 rl = _route->route_group()->route_list();
370 _mute_release->routes = rl;
373 rl.reset (new RouteList);
374 rl->push_back (_route);
378 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
383 /* plain click applies change to this route */
385 boost::shared_ptr<RouteList> rl (new RouteList);
386 rl->push_back (_route);
389 _mute_release->routes = rl;
392 _session->set_mute (rl, !_route->muted());
404 RouteUI::mute_release (GdkEventButton*)
406 if (!_i_am_the_modifier) {
409 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
410 delete _mute_release;
419 RouteUI::solo_press(GdkEventButton* ev)
421 /* ignore double/triple clicks */
423 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
427 multiple_solo_change = false;
429 if (!_i_am_the_modifier) {
431 if (Keyboard::is_context_menu_event (ev)) {
433 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
434 ! (solo_safe_led && solo_safe_led->is_visible())) {
436 if (solo_menu == 0) {
440 solo_menu->popup (1, ev->time);
445 if (Keyboard::is_button2_event (ev)) {
447 // Primary-button2 click is the midi binding click
448 // button2-click is "momentary"
450 if (solo_button->on_button_press_event (ev)) {
454 _solo_release = new SoloMuteRelease (_route->self_soloed());
457 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
459 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
461 /* Primary-Tertiary-click applies change to all routes */
464 _solo_release->routes = _session->get_routes ();
468 if (Config->get_solo_control_is_listen_control()) {
469 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
471 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
474 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
476 // Primary-Secondary-click: exclusively solo this track
479 _solo_release->exclusive = true;
481 boost::shared_ptr<RouteList> routes = _session->get_routes();
483 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
484 if ((*i)->soloed ()) {
485 _solo_release->routes_on->push_back (*i);
487 _solo_release->routes_off->push_back (*i);
492 if (Config->get_solo_control_is_listen_control()) {
493 /* ??? we need a just_one_listen() method */
496 _session->set_just_one_solo (_route, true);
499 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
501 // shift-click: toggle solo isolated status
503 _route->set_solo_isolated (!_route->solo_isolated(), this);
504 delete _solo_release;
507 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
509 /* Primary-button1: solo mix group.
510 NOTE: Primary-button2 is MIDI learn.
513 /* Primary-button1 applies change to the mix group even if it is not active
514 NOTE: Primary-button2 is MIDI learn.
517 boost::shared_ptr<RouteList> rl;
519 if (ev->button == 1) {
521 if (_route->route_group()) {
523 rl = _route->route_group()->route_list();
526 _solo_release->routes = rl;
529 rl.reset (new RouteList);
530 rl->push_back (_route);
534 if (Config->get_solo_control_is_listen_control()) {
535 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
537 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
543 /* click: solo this route */
545 boost::shared_ptr<RouteList> rl (new RouteList);
546 rl->push_back (route());
549 _solo_release->routes = rl;
553 if (Config->get_solo_control_is_listen_control()) {
554 _session->set_listen (rl, !_route->listening_via_monitor());
556 _session->set_solo (rl, !_route->self_soloed());
567 RouteUI::solo_release (GdkEventButton*)
569 if (!_i_am_the_modifier) {
573 if (_solo_release->exclusive) {
577 if (Config->get_solo_control_is_listen_control()) {
578 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
580 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
584 delete _solo_release;
593 RouteUI::rec_enable_press(GdkEventButton* ev)
595 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
599 if (!_session->engine().connected()) {
600 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
605 if (is_midi_track()) {
607 /* rec-enable button exits from step editing */
609 if (midi_track()->step_editing()) {
610 midi_track()->set_step_editing (false);
615 if (!_i_am_the_modifier && is_track() && rec_enable_button) {
617 if (Keyboard::is_button2_event (ev)) {
619 // do nothing on midi sigc::bind event
620 return rec_enable_button->on_button_press_event (ev);
622 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
625 _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
627 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
629 /* Primary-button1 applies change to the route group (even if it is not active)
630 NOTE: Primary-button2 is MIDI learn.
633 if (ev->button == 1) {
635 boost::shared_ptr<RouteList> rl;
637 if (_route->route_group()) {
639 rl = _route->route_group()->route_list();
642 rl.reset (new RouteList);
643 rl->push_back (_route);
647 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
650 } else if (Keyboard::is_context_menu_event (ev)) {
652 /* do this on release */
656 boost::shared_ptr<RouteList> rl (new RouteList);
657 rl->push_back (route());
659 _session->set_record_enabled (rl, !rec_enable_button->active_state());
667 RouteUI::monitoring_changed ()
669 update_monitoring_display ();
673 RouteUI::update_monitoring_display ()
679 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
685 MonitorState ms = t->monitoring_state();
687 if (t->monitoring_choice() & MonitorInput) {
688 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
690 if (ms & MonitoringInput) {
691 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
693 monitor_input_button->unset_active_state ();
697 if (t->monitoring_choice() & MonitorDisk) {
698 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
700 if (ms & MonitoringDisk) {
701 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
703 monitor_disk_button->unset_active_state ();
709 RouteUI::monitor_input_press(GdkEventButton*)
715 RouteUI::monitor_input_release(GdkEventButton* ev)
717 return monitor_release (ev, MonitorInput);
721 RouteUI::monitor_disk_press (GdkEventButton*)
727 RouteUI::monitor_disk_release (GdkEventButton* ev)
729 return monitor_release (ev, MonitorDisk);
733 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
735 if (ev->button != 1) {
739 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
746 boost::shared_ptr<RouteList> rl;
748 /* XXX for now, monitoring choices are orthogonal. cue monitoring
749 will follow in 3.X but requires mixing the input and playback (disk)
750 signal together, which requires yet more buffers.
753 if (t->monitoring_choice() & monitor_choice) {
754 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
756 /* this line will change when the options are non-orthogonal */
757 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
761 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
762 rl = _session->get_routes ();
764 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
765 if (_route->route_group() && _route->route_group()->is_monitoring()) {
766 rl = _route->route_group()->route_list();
768 rl.reset (new RouteList);
769 rl->push_back (route());
772 rl.reset (new RouteList);
773 rl->push_back (route());
777 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
783 RouteUI::build_record_menu ()
789 /* no rec-button context menu for non-MIDI tracks
792 if (is_midi_track()) {
793 record_menu = new Menu;
794 record_menu->set_name ("ArdourContextMenu");
796 using namespace Menu_Helpers;
797 MenuList& items = record_menu->items();
799 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
800 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
802 if (_route->record_enabled()) {
803 step_edit_item->set_sensitive (false);
806 step_edit_item->set_active (midi_track()->step_editing());
811 RouteUI::toggle_step_edit ()
813 if (!is_midi_track() || _route->record_enabled()) {
817 midi_track()->set_step_editing (step_edit_item->get_active());
821 RouteUI::step_edit_changed (bool yn)
824 if (rec_enable_button) {
825 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
828 start_step_editing ();
830 if (step_edit_item) {
831 step_edit_item->set_active (true);
836 if (rec_enable_button) {
837 rec_enable_button->unset_active_state ();
840 stop_step_editing ();
842 if (step_edit_item) {
843 step_edit_item->set_active (false);
849 RouteUI::rec_enable_release (GdkEventButton* ev)
851 if (Keyboard::is_context_menu_event (ev)) {
852 build_record_menu ();
854 record_menu->popup (1, ev->time);
863 RouteUI::build_sends_menu ()
865 using namespace Menu_Helpers;
867 sends_menu = new Menu;
868 sends_menu->set_name ("ArdourContextMenu");
869 MenuList& items = sends_menu->items();
872 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
876 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
880 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
884 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
888 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
892 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
895 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
899 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
902 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
903 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
904 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
909 RouteUI::create_sends (Placement p, bool include_buses)
911 _session->globally_add_internal_sends (_route, p, include_buses);
915 RouteUI::create_selected_sends (Placement p, bool include_buses)
917 boost::shared_ptr<RouteList> rlist (new RouteList);
918 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
920 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
921 RouteTimeAxisView* rtv;
923 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
924 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
925 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
926 rlist->push_back (rui->route());
932 _session->add_internal_sends (_route, p, rlist);
936 RouteUI::set_sends_gain_from_track ()
938 _session->globally_set_send_gains_from_track (_route);
942 RouteUI::set_sends_gain_to_zero ()
944 _session->globally_set_send_gains_to_zero (_route);
948 RouteUI::set_sends_gain_to_unity ()
950 _session->globally_set_send_gains_to_unity (_route);
954 RouteUI::show_sends_press(GdkEventButton* ev)
956 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
960 if (!_i_am_the_modifier && !is_track() && show_sends_button) {
962 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
964 // do nothing on midi sigc::bind event
967 } else if (Keyboard::is_context_menu_event (ev)) {
969 if (sends_menu == 0) {
973 sends_menu->popup (0, ev->time);
977 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
980 set_showing_sends_to (boost::shared_ptr<Route> ());
982 set_showing_sends_to (_route);
991 RouteUI::show_sends_release (GdkEventButton*)
997 RouteUI::send_blink (bool onoff)
999 if (!show_sends_button) {
1004 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1006 show_sends_button->unset_active_state ();
1010 Gtkmm2ext::ActiveState
1011 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1013 if (r->is_master() || r->is_monitor()) {
1014 return Gtkmm2ext::Off;
1017 if (Config->get_solo_control_is_listen_control()) {
1019 if (r->listening_via_monitor()) {
1020 return Gtkmm2ext::ExplicitActive;
1022 return Gtkmm2ext::Off;
1028 if (!r->self_soloed()) {
1029 return Gtkmm2ext::ImplicitActive;
1031 return Gtkmm2ext::ExplicitActive;
1034 return Gtkmm2ext::Off;
1038 Gtkmm2ext::ActiveState
1039 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1041 if (r->is_master() || r->is_monitor()) {
1042 return Gtkmm2ext::Off;
1045 if (r->solo_isolated()) {
1046 return Gtkmm2ext::ExplicitActive;
1048 return Gtkmm2ext::Off;
1052 Gtkmm2ext::ActiveState
1053 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1055 if (r->is_master() || r->is_monitor()) {
1056 return Gtkmm2ext::Off;
1059 if (r->solo_safe()) {
1060 return Gtkmm2ext::ExplicitActive;
1062 return Gtkmm2ext::Off;
1067 RouteUI::update_solo_display ()
1069 bool yn = _route->solo_safe ();
1071 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1072 solo_safe_check->set_active (yn);
1075 yn = _route->solo_isolated ();
1077 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1078 solo_isolated_check->set_active (yn);
1081 set_button_names ();
1083 if (solo_isolated_led) {
1084 if (_route->solo_isolated()) {
1085 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1087 solo_isolated_led->unset_active_state ();
1091 if (solo_safe_led) {
1092 if (_route->solo_safe()) {
1093 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1095 solo_safe_led->unset_active_state ();
1099 solo_button->set_active_state (solo_active_state (_route));
1101 /* some changes to solo status can affect mute display, so catch up
1104 update_mute_display ();
1108 RouteUI::solo_changed_so_update_mute ()
1110 update_mute_display ();
1114 RouteUI::mute_changed(void* /*src*/)
1116 update_mute_display ();
1120 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1122 if (r->is_monitor()) {
1123 return ActiveState(0);
1127 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1131 return Gtkmm2ext::ExplicitActive;
1132 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1133 /* master is NEVER muted by others */
1134 return Gtkmm2ext::ImplicitActive;
1136 /* no mute at all */
1137 return Gtkmm2ext::Off;
1144 return Gtkmm2ext::ExplicitActive;
1146 /* no mute at all */
1147 return Gtkmm2ext::Off;
1151 return ActiveState(0);
1155 RouteUI::update_mute_display ()
1161 mute_button->set_active_state (mute_active_state (_session, _route));
1165 RouteUI::route_rec_enable_changed ()
1167 update_rec_display ();
1168 update_monitoring_display ();
1172 RouteUI::session_rec_enable_changed ()
1174 update_rec_display ();
1175 update_monitoring_display ();
1179 RouteUI::update_rec_display ()
1181 if (!rec_enable_button || !_route) {
1185 if (_route->record_enabled()) {
1186 switch (_session->record_status ()) {
1187 case Session::Recording:
1188 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1191 case Session::Disabled:
1192 case Session::Enabled:
1193 rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1198 if (step_edit_item) {
1199 step_edit_item->set_sensitive (false);
1203 rec_enable_button->unset_active_state ();
1205 if (step_edit_item) {
1206 step_edit_item->set_sensitive (true);
1211 check_rec_enable_sensitivity ();
1215 RouteUI::build_solo_menu (void)
1217 using namespace Menu_Helpers;
1219 solo_menu = new Menu;
1220 solo_menu->set_name ("ArdourContextMenu");
1221 MenuList& items = solo_menu->items();
1222 Gtk::CheckMenuItem* check;
1224 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1225 check->set_active (_route->solo_isolated());
1226 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1227 items.push_back (CheckMenuElem(*check));
1228 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1231 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1232 check->set_active (_route->solo_safe());
1233 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1234 items.push_back (CheckMenuElem(*check));
1235 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1238 //items.push_back (SeparatorElem());
1239 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1244 RouteUI::build_mute_menu(void)
1246 using namespace Menu_Helpers;
1248 mute_menu = new Menu;
1249 mute_menu->set_name ("ArdourContextMenu");
1251 MenuList& items = mute_menu->items();
1253 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1254 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1255 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1256 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1257 pre_fader_mute_check->show_all();
1259 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1260 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1261 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1262 items.push_back (CheckMenuElem(*post_fader_mute_check));
1263 post_fader_mute_check->show_all();
1265 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1266 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1267 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1268 items.push_back (CheckMenuElem(*listen_mute_check));
1269 listen_mute_check->show_all();
1271 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1272 init_mute_menu(MuteMaster::Main, main_mute_check);
1273 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1274 items.push_back (CheckMenuElem(*main_mute_check));
1275 main_mute_check->show_all();
1277 //items.push_back (SeparatorElem());
1278 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1280 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1284 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1286 check->set_active (_route->mute_points() & mp);
1290 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1292 if (check->get_active()) {
1293 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1295 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1300 RouteUI::muting_change ()
1302 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1305 MuteMaster::MutePoint current = _route->mute_points ();
1307 yn = (current & MuteMaster::PreFader);
1309 if (pre_fader_mute_check->get_active() != yn) {
1310 pre_fader_mute_check->set_active (yn);
1313 yn = (current & MuteMaster::PostFader);
1315 if (post_fader_mute_check->get_active() != yn) {
1316 post_fader_mute_check->set_active (yn);
1319 yn = (current & MuteMaster::Listen);
1321 if (listen_mute_check->get_active() != yn) {
1322 listen_mute_check->set_active (yn);
1325 yn = (current & MuteMaster::Main);
1327 if (main_mute_check->get_active() != yn) {
1328 main_mute_check->set_active (yn);
1333 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1335 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1339 bool view = solo_isolated_led->active_state();
1340 bool model = _route->solo_isolated();
1342 /* called BEFORE the view has changed */
1344 if (ev->button == 1) {
1345 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1348 /* disable isolate for all routes */
1349 DisplaySuspender ds;
1350 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1354 if (model == view) {
1356 /* flip just this route */
1358 boost::shared_ptr<RouteList> rl (new RouteList);
1359 rl->push_back (_route);
1360 DisplaySuspender ds;
1361 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1370 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1372 if (ev->button == 1) {
1373 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1380 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1382 bool view = check->get_active();
1383 bool model = _route->solo_isolated();
1385 /* called AFTER the view has changed */
1387 if (model != view) {
1388 _route->set_solo_isolated (view, this);
1393 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1395 _route->set_solo_safe (check->get_active(), this);
1398 /** Ask the user to choose a colour, and then set all selected tracks
1402 RouteUI::choose_color ()
1405 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1408 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1409 boost::bind (&RouteUI::set_color, _1, color)
1414 /** Set the route's own color. This may not be used for display if
1415 * the route is in a group which shares its color with its routes.
1418 RouteUI::set_color (const Gdk::Color & c)
1420 /* leave _color alone in the group case so that tracks can retain their
1421 * own pre-group colors.
1426 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1428 /* note: we use the route state ID here so that color is the same for both
1429 the time axis view and the mixer strip
1432 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1433 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1436 /** @return GUI state ID for things that are common to the route in all its representations */
1438 RouteUI::route_state_id () const
1440 return string_compose (X_("route %1"), _route->id().to_s());
1444 RouteUI::set_color_from_route ()
1446 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1454 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1457 _color.set_green (g);
1458 _color.set_blue (b);
1464 RouteUI::remove_this_route (bool apply_to_selection)
1466 if (apply_to_selection) {
1467 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1469 if ((route()->is_master() || route()->is_monitor()) &&
1470 !Config->get_allow_special_bus_removal()) {
1471 MessageDialog msg (_("That would be bad news ...."),
1475 msg.set_secondary_text (string_compose (_(
1476 "Removing the master or monitor bus is such a bad idea\n\
1477 that %1 is not going to allow it.\n\
1479 If you really want to do this sort of thing\n\
1480 edit your ardour.rc file to set the\n\
1481 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1488 vector<string> choices;
1492 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());
1494 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());
1497 choices.push_back (_("No, do nothing."));
1498 choices.push_back (_("Yes, remove it."));
1502 title = _("Remove track");
1504 title = _("Remove bus");
1507 Choice prompter (title, prompt, choices);
1509 if (prompter.run () == 1) {
1510 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1516 RouteUI::idle_remove_this_route (RouteUI *rui)
1518 rui->_session->remove_route (rui->route());
1522 /** @return true if this name should be used for the route, otherwise false */
1524 RouteUI::verify_new_route_name (const std::string& name)
1526 if (name.find (':') == string::npos) {
1530 MessageDialog colon_msg (
1531 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1532 false, MESSAGE_QUESTION, BUTTONS_NONE
1535 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1536 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1538 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1542 RouteUI::route_rename ()
1544 ArdourPrompter name_prompter (true);
1549 name_prompter.set_title (_("Rename Track"));
1551 name_prompter.set_title (_("Rename Bus"));
1553 name_prompter.set_prompt (_("New name:"));
1554 name_prompter.set_initial_text (_route->name());
1555 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1556 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1557 name_prompter.show_all ();
1560 switch (name_prompter.run ()) {
1561 case Gtk::RESPONSE_ACCEPT:
1562 name_prompter.get_result (result);
1563 name_prompter.hide ();
1564 if (result.length()) {
1565 if (verify_new_route_name (result)) {
1566 _route->set_name (result);
1569 /* back to name prompter */
1573 /* nothing entered, just get out of here */
1588 RouteUI::property_changed (const PropertyChange& what_changed)
1590 if (what_changed.contains (ARDOUR::Properties::name)) {
1591 name_label.set_text (_route->name());
1596 RouteUI::set_route_active (bool a, bool apply_to_selection)
1598 if (apply_to_selection) {
1599 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1601 _route->set_active (a, this);
1606 RouteUI::toggle_denormal_protection ()
1608 if (denormal_menu_item) {
1612 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1614 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1615 _route->set_denormal_protection (x);
1621 RouteUI::denormal_protection_changed ()
1623 if (denormal_menu_item) {
1624 denormal_menu_item->set_active (_route->denormal_protection());
1629 RouteUI::disconnect_input ()
1631 _route->input()->disconnect (this);
1635 RouteUI::disconnect_output ()
1637 _route->output()->disconnect (this);
1641 RouteUI::is_track () const
1643 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1646 boost::shared_ptr<Track>
1647 RouteUI::track() const
1649 return boost::dynamic_pointer_cast<Track>(_route);
1653 RouteUI::is_audio_track () const
1655 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1658 boost::shared_ptr<AudioTrack>
1659 RouteUI::audio_track() const
1661 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1665 RouteUI::is_midi_track () const
1667 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1670 boost::shared_ptr<MidiTrack>
1671 RouteUI::midi_track() const
1673 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1677 RouteUI::has_audio_outputs () const
1679 return (_route->n_outputs().n_audio() > 0);
1683 RouteUI::name() const
1685 return _route->name();
1689 RouteUI::map_frozen ()
1691 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1693 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1696 switch (at->freeze_state()) {
1697 case AudioTrack::Frozen:
1698 rec_enable_button->set_sensitive (false);
1701 rec_enable_button->set_sensitive (true);
1708 RouteUI::adjust_latency ()
1710 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1714 RouteUI::save_as_template ()
1717 std::string safe_name;
1720 path = ARDOUR::user_route_template_directory ();
1722 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1723 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1727 Prompter p (true); // modal
1729 p.set_title (_("Save As Template"));
1730 p.set_prompt (_("Template name:"));
1731 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1733 case RESPONSE_ACCEPT:
1740 p.get_result (name, true);
1742 safe_name = legalize_for_path (name);
1743 safe_name += template_suffix;
1745 path = Glib::build_filename (path, safe_name);
1747 _route->save_as_template (path, name);
1751 RouteUI::check_rec_enable_sensitivity ()
1753 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1754 rec_enable_button->set_sensitive (false);
1756 rec_enable_button->set_sensitive (true);
1759 update_monitoring_display ();
1763 RouteUI::parameter_changed (string const & p)
1765 /* this handles RC and per-session parameter changes */
1767 if (p == "disable-disarm-during-roll") {
1768 check_rec_enable_sensitivity ();
1769 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1770 set_button_names ();
1771 } else if (p == "auto-input") {
1772 update_monitoring_display ();
1777 RouteUI::step_gain_up ()
1779 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1783 RouteUI::page_gain_up ()
1785 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1789 RouteUI::step_gain_down ()
1791 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1795 RouteUI::page_gain_down ()
1797 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1801 RouteUI::open_remote_control_id_dialog ()
1803 ArdourDialog dialog (_("Remote Control ID"));
1804 SpinButton* spin = 0;
1806 dialog.get_vbox()->set_border_width (18);
1808 if (Config->get_remote_model() == UserOrdered) {
1809 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1811 HBox* hbox = manage (new HBox);
1812 hbox->set_spacing (6);
1813 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1814 spin = manage (new SpinButton);
1815 spin->set_digits (0);
1816 spin->set_increments (1, 10);
1817 spin->set_range (0, limit);
1818 spin->set_value (_route->remote_control_id());
1819 hbox->pack_start (*spin);
1820 dialog.get_vbox()->pack_start (*hbox);
1822 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1823 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1825 Label* l = manage (new Label());
1826 if (_route->is_master() || _route->is_monitor()) {
1827 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1828 "The remote control ID of %3 cannot be changed."),
1829 Glib::Markup::escape_text (_route->name()),
1830 _route->remote_control_id(),
1831 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1833 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1834 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1835 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1836 (is_track() ? _("track") : _("bus")),
1837 _route->remote_control_id(),
1838 "<span size=\"small\" style=\"italic\">",
1840 Glib::Markup::escape_text (_route->name()),
1843 dialog.get_vbox()->pack_start (*l);
1844 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1848 int const r = dialog.run ();
1850 if (r == RESPONSE_ACCEPT && spin) {
1851 _route->set_remote_control_id (spin->get_value_as_int ());
1856 RouteUI::setup_invert_buttons ()
1858 /* remove old invert buttons */
1859 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1860 _invert_button_box.remove (**i);
1863 _invert_buttons.clear ();
1865 if (!_route || !_route->input()) {
1869 uint32_t const N = _route->input()->n_ports().n_audio ();
1871 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1873 for (uint32_t i = 0; i < to_add; ++i) {
1874 ArdourButton* b = manage (new ArdourButton);
1875 b->set_size_request(20,20);
1876 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1877 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1879 b->set_name (X_("invert button"));
1882 b->set_text (string_compose (X_("Ø (%1)"), N));
1884 b->set_text (X_("Ø"));
1887 b->set_text (string_compose (X_("Ø%1"), i + 1));
1890 if (N <= _max_invert_buttons) {
1891 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));
1893 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1896 _invert_buttons.push_back (b);
1897 _invert_button_box.pack_start (*b);
1900 _invert_button_box.set_spacing (1);
1901 _invert_button_box.show_all ();
1905 RouteUI::set_invert_button_state ()
1907 ++_i_am_the_modifier;
1909 uint32_t const N = _route->input()->n_ports().n_audio();
1910 if (N > _max_invert_buttons) {
1912 /* One button for many channels; explicit active if all channels are inverted,
1913 implicit active if some are, off if none are.
1916 ArdourButton* b = _invert_buttons.front ();
1918 if (_route->phase_invert().count() == _route->phase_invert().size()) {
1919 b->set_active_state (Gtkmm2ext::ExplicitActive);
1920 } else if (_route->phase_invert().any()) {
1921 b->set_active_state (Gtkmm2ext::ImplicitActive);
1923 b->set_active_state (Gtkmm2ext::Off);
1928 /* One button per channel; just set active */
1931 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1932 (*i)->set_active (_route->phase_invert (j));
1937 --_i_am_the_modifier;
1941 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1943 if (ev->button == 1 && i < _invert_buttons.size()) {
1944 uint32_t const N = _route->input()->n_ports().n_audio ();
1945 if (N <= _max_invert_buttons) {
1946 /* left-click inverts phase so long as we have a button per channel */
1947 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1956 RouteUI::invert_press (GdkEventButton* ev)
1958 using namespace Menu_Helpers;
1960 uint32_t const N = _route->input()->n_ports().n_audio();
1961 if (N <= _max_invert_buttons && ev->button != 3) {
1962 /* If we have an invert button per channel, we only pop
1963 up a menu on right-click; left click is handled
1969 delete _invert_menu;
1970 _invert_menu = new Menu;
1971 _invert_menu->set_name ("ArdourContextMenu");
1972 MenuList& items = _invert_menu->items ();
1974 for (uint32_t i = 0; i < N; ++i) {
1975 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1976 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
1977 ++_i_am_the_modifier;
1978 e->set_active (_route->phase_invert (i));
1979 --_i_am_the_modifier;
1982 _invert_menu->popup (0, ev->time);
1988 RouteUI::invert_menu_toggled (uint32_t c)
1990 if (_i_am_the_modifier) {
1994 _route->set_phase_invert (c, !_route->phase_invert (c));
1998 RouteUI::set_invert_sensitive (bool yn)
2000 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2001 (*b)->set_sensitive (yn);
2006 RouteUI::request_redraw ()
2009 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2013 /** The Route's gui_changed signal has been emitted */
2015 RouteUI::route_gui_changed (string what_changed)
2017 if (what_changed == "color") {
2018 if (set_color_from_route () == 0) {
2019 route_color_changed ();
2024 /** @return the color that this route should use; it maybe its own,
2025 or it maybe that of its route group.
2028 RouteUI::color () const
2030 RouteGroup* g = _route->route_group ();
2032 if (g && g->is_color()) {
2034 set_color_from_rgba (c, GroupTabs::group_color (g));
2042 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2044 _showing_sends_to = send_to;
2045 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2049 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2051 if (_route == send_to) {
2052 show_sends_button->set_active (true);
2053 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2055 show_sends_button->set_active (false);
2056 send_blink_connection.disconnect ();
2061 RouteUI::route_group() const
2063 return _route->route_group();