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/route.h"
50 #include "ardour/event_type_map.h"
51 #include "ardour/session.h"
52 #include "ardour/audioengine.h"
53 #include "ardour/audio_track.h"
54 #include "ardour/midi_track.h"
55 #include "ardour/template_utils.h"
56 #include "ardour/filename_extensions.h"
57 #include "ardour/directory_names.h"
58 #include "ardour/profile.h"
62 using namespace Gtkmm2ext;
63 using namespace ARDOUR;
66 uint32_t RouteUI::_max_invert_buttons = 3;
67 sigc::signal<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
68 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
70 RouteUI::RouteUI (ARDOUR::Session* sess)
78 _route.reset (); /* drop reference to route, so that it can be cleaned up */
79 route_connections.drop_connections ();
97 pre_fader_mute_check = 0;
98 post_fader_mute_check = 0;
99 listen_mute_check = 0;
102 solo_isolated_check = 0;
103 solo_isolated_led = 0;
107 denormal_menu_item = 0;
109 multiple_mute_change = false;
110 multiple_solo_change = false;
111 _i_am_the_modifier = 0;
113 setup_invert_buttons ();
115 mute_button = manage (new ArdourButton);
116 mute_button->set_name ("mute button");
117 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
119 solo_button = manage (new ArdourButton);
120 solo_button->set_name ("solo button");
121 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
122 solo_button->set_no_show_all (true);
124 rec_enable_button = manage (new ArdourButton);
125 rec_enable_button->set_name ("record enable button");
126 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
128 show_sends_button = manage (new ArdourButton);
129 show_sends_button->set_name ("send alert button");
130 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
132 monitor_input_button = manage (new ArdourButton (ArdourButton::led_default_elements));
133 monitor_input_button->set_name ("monitor");
134 monitor_input_button->set_text (_("In"));
135 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
136 monitor_input_button->set_no_show_all (true);
138 monitor_disk_button = manage (new ArdourButton (ArdourButton::led_default_elements));
139 monitor_disk_button->set_name ("monitor");
140 monitor_disk_button->set_text (_("Disk"));
141 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
142 monitor_disk_button->set_no_show_all (true);
144 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
145 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
146 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
148 _session->config.ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
149 Config->ParameterChanged.connect (*this, invalidator (*this), ui_bind (&RouteUI::parameter_changed, this, _1), gui_context());
151 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
152 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
154 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
155 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
157 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
158 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
159 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
160 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
162 monitor_input_button->set_distinct_led_click (false);
163 monitor_disk_button->set_distinct_led_click (false);
165 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
166 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
168 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
169 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
171 BusSendDisplayChanged.connect (sigc::mem_fun (*this, &RouteUI::bus_send_display_changed));
177 route_connections.drop_connections ();
185 denormal_menu_item = 0;
189 RouteUI::self_delete ()
195 RouteUI::set_route (boost::shared_ptr<Route> rp)
201 if (set_color_from_route()) {
202 set_color (unique_random_color());
206 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
209 mute_button->set_controllable (_route->mute_control());
210 solo_button->set_controllable (_route->solo_control());
212 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
213 _route->mute_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::mute_changed, this, _1), gui_context());
215 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
216 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
217 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
218 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
220 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
221 _route->PropertyChanged.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::property_changed, this, _1), gui_context());
223 _route->io_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::setup_invert_buttons, this), gui_context ());
224 _route->gui_changed.connect (route_connections, invalidator (*this), ui_bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
226 if (_session->writable() && is_track()) {
227 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
229 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
231 rec_enable_button->show();
232 rec_enable_button->set_controllable (t->rec_enable_control());
234 update_rec_display ();
236 if (is_midi_track()) {
237 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
238 ui_bind (&RouteUI::step_edit_changed, this, _1), gui_context());
244 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
245 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
247 update_monitoring_display ();
250 mute_button->unset_flags (Gtk::CAN_FOCUS);
251 solo_button->unset_flags (Gtk::CAN_FOCUS);
255 if (_route->is_monitor()) {
256 solo_button->hide ();
263 setup_invert_buttons ();
264 set_invert_button_state ();
266 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
267 bus_send_display_changed (s);
269 update_mute_display ();
270 update_solo_display ();
274 RouteUI::polarity_changed ()
280 set_invert_button_state ();
284 RouteUI::mute_press (GdkEventButton* ev)
286 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
290 multiple_mute_change = false;
292 if (!_i_am_the_modifier) {
294 if (Keyboard::is_context_menu_event (ev)) {
300 mute_menu->popup(0,ev->time);
304 if (Keyboard::is_button2_event (ev)) {
305 // Primary-button2 click is the midi binding click
306 // button2-click is "momentary"
309 if (mute_button->on_button_press_event (ev)) {
313 _mute_release = new SoloMuteRelease (_route->muted ());
316 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
318 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
321 _mute_release->routes = _session->get_routes ();
324 _session->set_mute (_session->get_routes(), !_route->muted());
326 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
328 /* Primary-button1 applies change to the mix group even if it is not active
329 NOTE: Primary-button2 is MIDI learn.
332 if (ev->button == 1 && _route->route_group()) {
334 _mute_release->routes = _session->get_routes ();
337 _session->set_mute (_session->get_routes(), !_route->muted(), Session::rt_cleanup, true);
342 /* plain click applies change to this route */
344 boost::shared_ptr<RouteList> rl (new RouteList);
345 rl->push_back (_route);
348 _mute_release->routes = rl;
351 _session->set_mute (rl, !_route->muted());
363 RouteUI::mute_release (GdkEventButton*)
365 if (!_i_am_the_modifier) {
367 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
368 delete _mute_release;
377 RouteUI::solo_press(GdkEventButton* ev)
379 /* ignore double/triple clicks */
381 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
385 multiple_solo_change = false;
387 if (!_i_am_the_modifier) {
389 if (Keyboard::is_context_menu_event (ev)) {
391 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
392 ! (solo_safe_led && solo_safe_led->is_visible())) {
394 if (solo_menu == 0) {
398 solo_menu->popup (1, ev->time);
403 if (Keyboard::is_button2_event (ev)) {
405 // Primary-button2 click is the midi binding click
406 // button2-click is "momentary"
408 if (solo_button->on_button_press_event (ev)) {
412 _solo_release = new SoloMuteRelease (_route->self_soloed());
415 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
417 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
419 /* Primary-Tertiary-click applies change to all routes */
422 _solo_release->routes = _session->get_routes ();
425 if (Config->get_solo_control_is_listen_control()) {
426 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
428 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
431 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
433 // Primary-Secondary-click: exclusively solo this track
436 _solo_release->exclusive = true;
438 boost::shared_ptr<RouteList> routes = _session->get_routes();
440 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
441 if ((*i)->soloed ()) {
442 _solo_release->routes_on->push_back (*i);
444 _solo_release->routes_off->push_back (*i);
449 if (Config->get_solo_control_is_listen_control()) {
450 /* ??? we need a just_one_listen() method */
452 _session->set_just_one_solo (_route, true);
455 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
457 // shift-click: toggle solo isolated status
459 _route->set_solo_isolated (!_route->solo_isolated(), this);
460 delete _solo_release;
463 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
465 /* Primary-button1: solo mix group.
466 NOTE: Primary-button2 is MIDI learn.
469 if (ev->button == 1 && _route->route_group()) {
472 _solo_release->routes = _route->route_group()->route_list();
475 if (Config->get_solo_control_is_listen_control()) {
476 _session->set_listen (_route->route_group()->route_list(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
478 _session->set_solo (_route->route_group()->route_list(), !_route->self_soloed(), Session::rt_cleanup, true);
484 /* click: solo this route */
486 boost::shared_ptr<RouteList> rl (new RouteList);
487 rl->push_back (route());
490 _solo_release->routes = rl;
493 if (Config->get_solo_control_is_listen_control()) {
494 _session->set_listen (rl, !_route->listening_via_monitor());
496 _session->set_solo (rl, !_route->self_soloed());
507 RouteUI::solo_release (GdkEventButton*)
509 if (!_i_am_the_modifier) {
513 if (_solo_release->exclusive) {
516 if (Config->get_solo_control_is_listen_control()) {
517 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
519 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
523 delete _solo_release;
532 RouteUI::rec_enable_press(GdkEventButton* ev)
534 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
538 if (!_session->engine().connected()) {
539 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
544 if (is_midi_track()) {
546 /* cannot rec-enable while step-editing */
548 if (midi_track()->step_editing()) {
553 if (!_i_am_the_modifier && is_track() && rec_enable_button) {
555 if (Keyboard::is_button2_event (ev)) {
557 // do nothing on midi sigc::bind event
558 return rec_enable_button->on_button_press_event (ev);
560 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
562 _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
564 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
566 /* Primary-button1 applies change to the route group (even if it is not active)
567 NOTE: Primary-button2 is MIDI learn.
569 if (ev->button == 1 && _route->route_group()) {
570 _session->set_record_enabled (_route->route_group()->route_list(), !rec_enable_button->active_state(), Session::rt_cleanup, true);
573 } else if (Keyboard::is_context_menu_event (ev)) {
575 /* do this on release */
579 boost::shared_ptr<RouteList> rl (new RouteList);
580 rl->push_back (route());
581 _session->set_record_enabled (rl, !rec_enable_button->active_state());
589 RouteUI::monitoring_changed ()
591 update_monitoring_display ();
595 RouteUI::update_monitoring_display ()
601 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
607 MonitorState ms = t->monitoring_state();
609 if (t->monitoring_choice() & MonitorInput) {
610 monitor_input_button->set_active_state (Gtkmm2ext::Active);
612 if (ms & MonitoringInput) {
613 monitor_input_button->set_active_state (Gtkmm2ext::Mid);
615 monitor_input_button->unset_active_state ();
619 if (t->monitoring_choice() & MonitorDisk) {
620 monitor_disk_button->set_active_state (Gtkmm2ext::Active);
622 if (ms & MonitoringDisk) {
623 monitor_disk_button->set_active_state (Gtkmm2ext::Mid);
625 monitor_disk_button->unset_active_state ();
631 RouteUI::monitor_input_press(GdkEventButton* ev)
637 RouteUI::monitor_input_release(GdkEventButton* ev)
639 return monitor_release (ev, MonitorInput);
643 RouteUI::monitor_disk_press (GdkEventButton* ev)
649 RouteUI::monitor_disk_release (GdkEventButton* ev)
651 return monitor_release (ev, MonitorDisk);
655 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
657 if (ev->button != 1) {
661 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
668 boost::shared_ptr<RouteList> rl;
670 /* XXX for now, monitoring choices are orthogonal. cue monitoring
671 will follow in 3.X but requires mixing the input and playback (disk)
672 signal together, which requires yet more buffers.
675 if (t->monitoring_choice() & monitor_choice) {
676 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
678 /* this line will change when the options are non-orthogonal */
679 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
683 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
684 rl = _session->get_routes ();
686 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
687 if (_route->route_group() && _route->route_group()->is_monitoring()) {
688 rl = _route->route_group()->route_list();
690 rl.reset (new RouteList);
691 rl->push_back (route());
694 rl.reset (new RouteList);
695 rl->push_back (route());
698 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
704 RouteUI::build_record_menu ()
710 /* no rec-button context menu for non-MIDI tracks
713 if (is_midi_track()) {
714 record_menu = new Menu;
715 record_menu->set_name ("ArdourContextMenu");
717 using namespace Menu_Helpers;
718 MenuList& items = record_menu->items();
720 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
721 step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
723 if (_route->record_enabled()) {
724 step_edit_item->set_sensitive (false);
727 step_edit_item->set_active (midi_track()->step_editing());
732 RouteUI::toggle_step_edit ()
734 if (!is_midi_track() || _route->record_enabled()) {
738 midi_track()->set_step_editing (step_edit_item->get_active());
742 RouteUI::step_edit_changed (bool yn)
745 if (rec_enable_button) {
746 rec_enable_button->set_active_state (Active);
749 start_step_editing ();
751 if (step_edit_item) {
752 step_edit_item->set_active (true);
757 if (rec_enable_button) {
758 rec_enable_button->unset_active_state ();
761 stop_step_editing ();
763 if (step_edit_item) {
764 step_edit_item->set_active (false);
770 RouteUI::rec_enable_release (GdkEventButton* ev)
772 if (Keyboard::is_context_menu_event (ev)) {
773 build_record_menu ();
775 record_menu->popup (1, ev->time);
784 RouteUI::build_sends_menu ()
786 using namespace Menu_Helpers;
788 sends_menu = new Menu;
789 sends_menu->set_name ("ArdourContextMenu");
790 MenuList& items = sends_menu->items();
793 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
797 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
801 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
805 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
809 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
813 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
816 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
820 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
823 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
824 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
825 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
830 RouteUI::create_sends (Placement p, bool include_buses)
832 _session->globally_add_internal_sends (_route, p, include_buses);
836 RouteUI::create_selected_sends (Placement p, bool include_buses)
838 boost::shared_ptr<RouteList> rlist (new RouteList);
839 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
841 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
842 RouteTimeAxisView* rtv;
844 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
845 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
846 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
847 rlist->push_back (rui->route());
853 _session->add_internal_sends (_route, p, rlist);
857 RouteUI::set_sends_gain_from_track ()
859 _session->globally_set_send_gains_from_track (_route);
863 RouteUI::set_sends_gain_to_zero ()
865 _session->globally_set_send_gains_to_zero (_route);
869 RouteUI::set_sends_gain_to_unity ()
871 _session->globally_set_send_gains_to_unity (_route);
875 RouteUI::show_sends_press(GdkEventButton* ev)
877 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
881 if (!_i_am_the_modifier && !is_track() && show_sends_button) {
883 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
885 // do nothing on midi sigc::bind event
888 } else if (Keyboard::is_context_menu_event (ev)) {
890 if (sends_menu == 0) {
894 sends_menu->popup (0, ev->time);
898 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
901 set_showing_sends_to (boost::shared_ptr<Route> ());
903 set_showing_sends_to (_route);
912 RouteUI::show_sends_release (GdkEventButton*)
918 RouteUI::send_blink (bool onoff)
920 if (!show_sends_button) {
925 show_sends_button->set_active_state (Gtkmm2ext::Active);
927 show_sends_button->unset_active_state ();
931 Gtkmm2ext::ActiveState
932 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
934 if (r->is_master() || r->is_monitor()) {
935 return ActiveState (0);
938 if (Config->get_solo_control_is_listen_control()) {
940 if (r->listening_via_monitor()) {
943 return ActiveState (0);
949 if (!r->self_soloed()) {
955 return ActiveState(0);
959 Gtkmm2ext::ActiveState
960 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
962 if (r->is_master() || r->is_monitor()) {
963 return ActiveState (0);
966 if (r->solo_isolated()) {
969 return ActiveState(0);
973 Gtkmm2ext::ActiveState
974 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
976 if (r->is_master() || r->is_monitor()) {
977 return ActiveState (0);
980 if (r->solo_safe()) {
983 return ActiveState (0);
988 RouteUI::update_solo_display ()
992 if (Config->get_solo_control_is_listen_control()) {
994 if ((bool) solo_button->active_state() != (x = _route->listening_via_monitor())) {
995 ++_i_am_the_modifier;
996 solo_button->set_active_state (Active);
997 --_i_am_the_modifier;
1002 if ((bool) solo_button->active_state() != (x = _route->soloed())) {
1003 ++_i_am_the_modifier;
1005 solo_button->set_active_state (Active);
1007 solo_button->unset_active_state();
1009 --_i_am_the_modifier;
1014 bool yn = _route->solo_safe ();
1016 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1017 solo_safe_check->set_active (yn);
1020 yn = _route->solo_isolated ();
1022 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1023 solo_isolated_check->set_active (yn);
1026 set_button_names ();
1028 if (solo_isolated_led) {
1029 if (_route->solo_isolated()) {
1030 solo_isolated_led->set_active_state (Gtkmm2ext::Active);
1032 solo_isolated_led->unset_active_state ();
1036 if (solo_safe_led) {
1037 if (_route->solo_safe()) {
1038 solo_safe_led->set_active_state (Gtkmm2ext::Active);
1040 solo_safe_led->unset_active_state ();
1044 solo_button->set_active_state (solo_active_state (_route));
1046 /* some changes to solo status can affect mute display, so catch up
1049 update_mute_display ();
1053 RouteUI::solo_changed_so_update_mute ()
1055 update_mute_display ();
1059 RouteUI::mute_changed(void* /*src*/)
1061 update_mute_display ();
1065 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1067 if (r->is_monitor()) {
1068 return ActiveState(0);
1072 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1077 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1078 /* master is NEVER muted by others */
1081 /* no mute at all */
1082 return ActiveState(0);
1091 /* no mute at all */
1092 return ActiveState(0);
1096 return ActiveState(0);
1100 RouteUI::update_mute_display ()
1106 mute_button->set_active_state (mute_active_state (_session, _route));
1110 RouteUI::route_rec_enable_changed ()
1112 update_rec_display ();
1113 update_monitoring_display ();
1117 RouteUI::session_rec_enable_changed ()
1119 update_rec_display ();
1120 update_monitoring_display ();
1124 RouteUI::update_rec_display ()
1126 if (!rec_enable_button || !_route) {
1130 if (_route->record_enabled()) {
1131 switch (_session->record_status ()) {
1132 case Session::Recording:
1133 rec_enable_button->set_active_state (Active);
1136 case Session::Disabled:
1137 case Session::Enabled:
1138 rec_enable_button->set_active_state (Mid);
1143 if (step_edit_item) {
1144 step_edit_item->set_sensitive (false);
1148 rec_enable_button->unset_active_state ();
1150 if (step_edit_item) {
1151 step_edit_item->set_sensitive (true);
1156 check_rec_enable_sensitivity ();
1160 RouteUI::build_solo_menu (void)
1162 using namespace Menu_Helpers;
1164 solo_menu = new Menu;
1165 solo_menu->set_name ("ArdourContextMenu");
1166 MenuList& items = solo_menu->items();
1167 CheckMenuItem* check;
1169 check = new CheckMenuItem(_("Solo Isolate"));
1170 check->set_active (_route->solo_isolated());
1171 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1172 items.push_back (CheckMenuElem(*check));
1173 solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1176 check = new CheckMenuItem(_("Solo Safe"));
1177 check->set_active (_route->solo_safe());
1178 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1179 items.push_back (CheckMenuElem(*check));
1180 solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1183 //items.push_back (SeparatorElem());
1184 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1189 RouteUI::build_mute_menu(void)
1191 using namespace Menu_Helpers;
1193 mute_menu = new Menu;
1194 mute_menu->set_name ("ArdourContextMenu");
1196 MenuList& items = mute_menu->items();
1198 pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1199 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1200 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1201 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1202 pre_fader_mute_check->show_all();
1204 post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1205 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1206 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1207 items.push_back (CheckMenuElem(*post_fader_mute_check));
1208 post_fader_mute_check->show_all();
1210 listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1211 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1212 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1213 items.push_back (CheckMenuElem(*listen_mute_check));
1214 listen_mute_check->show_all();
1216 main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1217 init_mute_menu(MuteMaster::Main, main_mute_check);
1218 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1219 items.push_back (CheckMenuElem(*main_mute_check));
1220 main_mute_check->show_all();
1222 //items.push_back (SeparatorElem());
1223 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1225 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1229 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1231 check->set_active (_route->mute_points() & mp);
1235 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1237 if (check->get_active()) {
1238 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1240 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1245 RouteUI::muting_change ()
1247 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1250 MuteMaster::MutePoint current = _route->mute_points ();
1252 yn = (current & MuteMaster::PreFader);
1254 if (pre_fader_mute_check->get_active() != yn) {
1255 pre_fader_mute_check->set_active (yn);
1258 yn = (current & MuteMaster::PostFader);
1260 if (post_fader_mute_check->get_active() != yn) {
1261 post_fader_mute_check->set_active (yn);
1264 yn = (current & MuteMaster::Listen);
1266 if (listen_mute_check->get_active() != yn) {
1267 listen_mute_check->set_active (yn);
1270 yn = (current & MuteMaster::Main);
1272 if (main_mute_check->get_active() != yn) {
1273 main_mute_check->set_active (yn);
1278 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1280 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1284 bool view = solo_isolated_led->active_state();
1285 bool model = _route->solo_isolated();
1287 /* called BEFORE the view has changed */
1289 if (ev->button == 1) {
1290 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1293 /* disable isolate for all routes */
1294 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1298 if (model == view) {
1300 /* flip just this route */
1302 boost::shared_ptr<RouteList> rl (new RouteList);
1303 rl->push_back (_route);
1304 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1313 RouteUI::solo_safe_button_release (GdkEventButton*)
1315 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1320 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1322 bool view = check->get_active();
1323 bool model = _route->solo_isolated();
1325 /* called AFTER the view has changed */
1327 if (model != view) {
1328 _route->set_solo_isolated (view, this);
1333 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1335 _route->set_solo_safe (check->get_active(), this);
1338 /** Ask the user to choose a colour, and then set all selected tracks
1342 RouteUI::choose_color ()
1345 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1348 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1349 boost::bind (&RouteUI::set_color, _1, color)
1354 /** Set the route's own color. This may not be used for display if
1355 * the route is in a group which shares its color with its routes.
1358 RouteUI::set_color (const Gdk::Color & c)
1364 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1366 /* note: we use the route state ID here so that color is the same for both
1367 the time axis view and the mixer strip
1370 gui_object_state().set<string> (route_state_id(), X_("color"), buf);
1371 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1374 /** @return GUI state ID for things that are common to the route in all its representations */
1376 RouteUI::route_state_id () const
1378 return string_compose (X_("route %1"), _route->id().to_s());
1382 RouteUI::set_color_from_route ()
1384 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1392 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1395 _color.set_green (g);
1396 _color.set_blue (b);
1402 RouteUI::remove_this_route (bool apply_to_selection)
1404 if (apply_to_selection) {
1405 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1407 if ((route()->is_master() || route()->is_monitor()) &&
1408 !Config->get_allow_special_bus_removal()) {
1409 MessageDialog msg (_("That would be bad news ...."),
1413 msg.set_secondary_text (string_compose (_(
1414 "Removing the master or monitor bus is such a bad idea\n\
1415 that %1 is not going to allow it.\n\
1417 If you really want to do this sort of thing\n\
1418 edit your ardour.rc file to set the\n\
1419 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1426 vector<string> choices;
1430 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());
1432 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());
1435 choices.push_back (_("No, do nothing."));
1436 choices.push_back (_("Yes, remove it."));
1440 title = _("Remove track");
1442 title = _("Remove bus");
1445 Choice prompter (title, prompt, choices);
1447 if (prompter.run () == 1) {
1448 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1454 RouteUI::idle_remove_this_route (RouteUI *rui)
1456 rui->_session->remove_route (rui->route());
1460 /** @return true if this name should be used for the route, otherwise false */
1462 RouteUI::verify_new_route_name (const std::string& name)
1464 if (name.find (':') == string::npos) {
1468 MessageDialog colon_msg (
1469 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1470 false, MESSAGE_QUESTION, BUTTONS_NONE
1473 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1474 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1476 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1480 RouteUI::route_rename ()
1482 ArdourPrompter name_prompter (true);
1487 name_prompter.set_title (_("Rename Track"));
1489 name_prompter.set_title (_("Rename Bus"));
1491 name_prompter.set_prompt (_("New name:"));
1492 name_prompter.set_initial_text (_route->name());
1493 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1494 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1495 name_prompter.show_all ();
1498 switch (name_prompter.run ()) {
1499 case Gtk::RESPONSE_ACCEPT:
1500 name_prompter.get_result (result);
1501 name_prompter.hide ();
1502 if (result.length()) {
1503 if (verify_new_route_name (result)) {
1504 _route->set_name (result);
1507 /* back to name prompter */
1511 /* nothing entered, just get out of here */
1523 RouteUI::property_changed (const PropertyChange& what_changed)
1525 if (what_changed.contains (ARDOUR::Properties::name)) {
1526 name_label.set_text (_route->name());
1531 RouteUI::set_route_active (bool a, bool apply_to_selection)
1533 if (apply_to_selection) {
1534 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1536 _route->set_active (a, this);
1541 RouteUI::toggle_denormal_protection ()
1543 if (denormal_menu_item) {
1547 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1549 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1550 _route->set_denormal_protection (x);
1556 RouteUI::denormal_protection_changed ()
1558 if (denormal_menu_item) {
1559 denormal_menu_item->set_active (_route->denormal_protection());
1564 RouteUI::disconnect_input ()
1566 _route->input()->disconnect (this);
1570 RouteUI::disconnect_output ()
1572 _route->output()->disconnect (this);
1576 RouteUI::is_track () const
1578 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1581 boost::shared_ptr<Track>
1582 RouteUI::track() const
1584 return boost::dynamic_pointer_cast<Track>(_route);
1588 RouteUI::is_audio_track () const
1590 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1593 boost::shared_ptr<AudioTrack>
1594 RouteUI::audio_track() const
1596 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1600 RouteUI::is_midi_track () const
1602 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1605 boost::shared_ptr<MidiTrack>
1606 RouteUI::midi_track() const
1608 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1612 RouteUI::has_audio_outputs () const
1614 return (_route->n_outputs().n_audio() > 0);
1618 RouteUI::name() const
1620 return _route->name();
1624 RouteUI::map_frozen ()
1626 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1628 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1631 switch (at->freeze_state()) {
1632 case AudioTrack::Frozen:
1633 rec_enable_button->set_sensitive (false);
1636 rec_enable_button->set_sensitive (true);
1643 RouteUI::adjust_latency ()
1645 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1649 RouteUI::save_as_template ()
1652 std::string safe_name;
1655 path = ARDOUR::user_route_template_directory ();
1657 if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1658 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1662 Prompter p (true); // modal
1664 p.set_title (_("Save As Template"));
1665 p.set_prompt (_("Template name:"));
1666 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1668 case RESPONSE_ACCEPT:
1675 p.get_result (name, true);
1677 safe_name = legalize_for_path (name);
1678 safe_name += template_suffix;
1682 _route->save_as_template (path.to_string(), name);
1686 RouteUI::check_rec_enable_sensitivity ()
1688 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1689 rec_enable_button->set_sensitive (false);
1691 rec_enable_button->set_sensitive (true);
1694 update_monitoring_display ();
1698 RouteUI::parameter_changed (string const & p)
1700 /* this handles RC and per-session parameter changes */
1702 if (p == "disable-disarm-during-roll") {
1703 check_rec_enable_sensitivity ();
1704 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1705 set_button_names ();
1706 } else if (p == "auto-input") {
1707 update_monitoring_display ();
1712 RouteUI::step_gain_up ()
1714 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1718 RouteUI::page_gain_up ()
1720 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1724 RouteUI::step_gain_down ()
1726 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1730 RouteUI::page_gain_down ()
1732 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1736 RouteUI::open_remote_control_id_dialog ()
1738 ArdourDialog dialog (_("Remote Control ID"));
1740 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1742 HBox* hbox = manage (new HBox);
1743 hbox->set_spacing (6);
1744 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1745 SpinButton* spin = manage (new SpinButton);
1746 spin->set_digits (0);
1747 spin->set_increments (1, 10);
1748 spin->set_range (0, limit);
1749 spin->set_value (_route->remote_control_id());
1750 hbox->pack_start (*spin);
1751 dialog.get_vbox()->pack_start (*hbox);
1753 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1754 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1757 int const r = dialog.run ();
1759 if (r == RESPONSE_ACCEPT) {
1760 _route->set_remote_control_id (spin->get_value_as_int ());
1765 RouteUI::setup_invert_buttons ()
1767 /* remove old invert buttons */
1768 for (list<BindableToggleButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1769 _invert_button_box.remove (**i);
1772 _invert_buttons.clear ();
1774 if (!_route || !_route->input()) {
1778 uint32_t const N = _route->input()->n_ports().n_audio ();
1780 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1782 for (uint32_t i = 0; i < to_add; ++i) {
1783 BindableToggleButton* b = manage (new BindableToggleButton);
1784 b->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_toggled), i, b));
1785 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1787 b->set_name (X_("MixerInvertButton"));
1789 b->add (*manage (new Label (X_("Ø"))));
1791 b->add (*manage (new Label (string_compose (X_("Ø%1"), i + 1))));
1795 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));
1797 UI::instance()->set_tip (*b, string_compose (_("Left-click to invert (phase reverse) all channels of this track. Right-click to show menu."), i + 1));
1800 _invert_buttons.push_back (b);
1801 _invert_button_box.pack_start (*b);
1804 _invert_button_box.show_all ();
1808 RouteUI::set_invert_button_state ()
1810 ++_i_am_the_modifier;
1812 uint32_t const N = _route->input()->n_ports().n_audio();
1813 if (N > _max_invert_buttons) {
1814 _invert_buttons.front()->set_active (_route->phase_invert().any());
1815 --_i_am_the_modifier;
1820 for (list<BindableToggleButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1821 (*i)->set_active (_route->phase_invert (j));
1824 --_i_am_the_modifier;
1828 RouteUI::invert_toggled (uint32_t i, BindableToggleButton* b)
1830 if (_i_am_the_modifier) {
1834 uint32_t const N = _route->input()->n_ports().n_audio();
1835 if (N <= _max_invert_buttons) {
1836 _route->set_phase_invert (i, b->get_active ());
1838 boost::dynamic_bitset<> p (N);
1839 if (b->get_active ()) {
1842 _route->set_phase_invert (p);
1847 RouteUI::invert_press (GdkEventButton* ev)
1849 using namespace Menu_Helpers;
1851 if (ev->button != 3) {
1855 delete _invert_menu;
1856 _invert_menu = new Menu;
1857 _invert_menu->set_name ("ArdourContextMenu");
1858 MenuList& items = _invert_menu->items ();
1860 uint32_t const N = _route->input()->n_ports().n_audio();
1861 for (uint32_t i = 0; i < N; ++i) {
1862 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1863 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1864 ++_i_am_the_modifier;
1865 e->set_active (_route->phase_invert (i));
1866 --_i_am_the_modifier;
1869 _invert_menu->popup (0, ev->time);
1875 RouteUI::invert_menu_toggled (uint32_t c)
1877 if (_i_am_the_modifier) {
1881 _route->set_phase_invert (c, !_route->phase_invert (c));
1885 RouteUI::set_invert_sensitive (bool yn)
1887 for (list<BindableToggleButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1888 (*b)->set_sensitive (yn);
1893 RouteUI::request_redraw ()
1896 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1900 /** The Route's gui_changed signal has been emitted */
1902 RouteUI::route_gui_changed (string what_changed)
1904 if (what_changed == "color") {
1905 if (set_color_from_route () == 0) {
1906 route_color_changed ();
1911 /** @return the color that this route should use; it maybe its own,
1912 or it maybe that of its route group.
1915 RouteUI::color () const
1917 RouteGroup* g = _route->route_group ();
1919 if (g && g->is_color()) {
1920 return GroupTabs::group_color (g);
1927 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
1929 _showing_sends_to = send_to;
1930 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
1934 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
1936 if (_route == send_to) {
1937 show_sends_button->set_active_state (Gtkmm2ext::Active);
1938 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
1940 show_sends_button->unset_active_state ();
1941 send_blink_connection.disconnect ();
1946 RouteUI::route_group() const
1948 return _route->route_group();