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 */
1526 RouteUI::property_changed (const PropertyChange& what_changed)
1528 if (what_changed.contains (ARDOUR::Properties::name)) {
1529 name_label.set_text (_route->name());
1534 RouteUI::set_route_active (bool a, bool apply_to_selection)
1536 if (apply_to_selection) {
1537 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1539 _route->set_active (a, this);
1544 RouteUI::toggle_denormal_protection ()
1546 if (denormal_menu_item) {
1550 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1552 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1553 _route->set_denormal_protection (x);
1559 RouteUI::denormal_protection_changed ()
1561 if (denormal_menu_item) {
1562 denormal_menu_item->set_active (_route->denormal_protection());
1567 RouteUI::disconnect_input ()
1569 _route->input()->disconnect (this);
1573 RouteUI::disconnect_output ()
1575 _route->output()->disconnect (this);
1579 RouteUI::is_track () const
1581 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1584 boost::shared_ptr<Track>
1585 RouteUI::track() const
1587 return boost::dynamic_pointer_cast<Track>(_route);
1591 RouteUI::is_audio_track () const
1593 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1596 boost::shared_ptr<AudioTrack>
1597 RouteUI::audio_track() const
1599 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1603 RouteUI::is_midi_track () const
1605 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1608 boost::shared_ptr<MidiTrack>
1609 RouteUI::midi_track() const
1611 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1615 RouteUI::has_audio_outputs () const
1617 return (_route->n_outputs().n_audio() > 0);
1621 RouteUI::name() const
1623 return _route->name();
1627 RouteUI::map_frozen ()
1629 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1631 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1634 switch (at->freeze_state()) {
1635 case AudioTrack::Frozen:
1636 rec_enable_button->set_sensitive (false);
1639 rec_enable_button->set_sensitive (true);
1646 RouteUI::adjust_latency ()
1648 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1652 RouteUI::save_as_template ()
1655 std::string safe_name;
1658 path = ARDOUR::user_route_template_directory ();
1660 if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1661 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1665 Prompter p (true); // modal
1667 p.set_title (_("Save As Template"));
1668 p.set_prompt (_("Template name:"));
1669 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1671 case RESPONSE_ACCEPT:
1678 p.get_result (name, true);
1680 safe_name = legalize_for_path (name);
1681 safe_name += template_suffix;
1685 _route->save_as_template (path.to_string(), name);
1689 RouteUI::check_rec_enable_sensitivity ()
1691 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1692 rec_enable_button->set_sensitive (false);
1694 rec_enable_button->set_sensitive (true);
1697 update_monitoring_display ();
1701 RouteUI::parameter_changed (string const & p)
1703 /* this handles RC and per-session parameter changes */
1705 if (p == "disable-disarm-during-roll") {
1706 check_rec_enable_sensitivity ();
1707 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1708 set_button_names ();
1709 } else if (p == "auto-input") {
1710 update_monitoring_display ();
1715 RouteUI::step_gain_up ()
1717 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1721 RouteUI::page_gain_up ()
1723 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1727 RouteUI::step_gain_down ()
1729 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1733 RouteUI::page_gain_down ()
1735 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1739 RouteUI::open_remote_control_id_dialog ()
1741 ArdourDialog dialog (_("Remote Control ID"));
1743 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1745 HBox* hbox = manage (new HBox);
1746 hbox->set_spacing (6);
1747 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1748 SpinButton* spin = manage (new SpinButton);
1749 spin->set_digits (0);
1750 spin->set_increments (1, 10);
1751 spin->set_range (0, limit);
1752 spin->set_value (_route->remote_control_id());
1753 hbox->pack_start (*spin);
1754 dialog.get_vbox()->pack_start (*hbox);
1756 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1757 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1760 int const r = dialog.run ();
1762 if (r == RESPONSE_ACCEPT) {
1763 _route->set_remote_control_id (spin->get_value_as_int ());
1768 RouteUI::setup_invert_buttons ()
1770 /* remove old invert buttons */
1771 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1772 _invert_button_box.remove (**i);
1775 _invert_buttons.clear ();
1777 if (!_route || !_route->input()) {
1781 uint32_t const N = _route->input()->n_ports().n_audio ();
1783 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1785 for (uint32_t i = 0; i < to_add; ++i) {
1786 ArdourButton* b = manage (new ArdourButton);
1787 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1788 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1790 b->set_name (X_("mixer strip button"));
1792 b->set_text (X_("Ø"));
1794 b->set_text (string_compose (X_("Ø%1"), i + 1));
1798 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));
1800 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));
1803 _invert_buttons.push_back (b);
1804 _invert_button_box.pack_start (*b);
1807 _invert_button_box.set_spacing (1);
1808 _invert_button_box.show_all ();
1812 RouteUI::set_invert_button_state ()
1814 ++_i_am_the_modifier;
1816 uint32_t const N = _route->input()->n_ports().n_audio();
1817 if (N > _max_invert_buttons) {
1818 _invert_buttons.front()->set_active (_route->phase_invert().any());
1819 --_i_am_the_modifier;
1824 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1825 (*i)->set_active (_route->phase_invert (j));
1828 --_i_am_the_modifier;
1832 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1834 if (ev->button == 1 && i < _invert_buttons.size()) {
1835 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1843 RouteUI::invert_press (GdkEventButton* ev)
1845 using namespace Menu_Helpers;
1847 if (ev->button != 3) {
1851 delete _invert_menu;
1852 _invert_menu = new Menu;
1853 _invert_menu->set_name ("ArdourContextMenu");
1854 MenuList& items = _invert_menu->items ();
1856 uint32_t const N = _route->input()->n_ports().n_audio();
1857 for (uint32_t i = 0; i < N; ++i) {
1858 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1859 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1860 ++_i_am_the_modifier;
1861 e->set_active (_route->phase_invert (i));
1862 --_i_am_the_modifier;
1865 _invert_menu->popup (0, ev->time);
1871 RouteUI::invert_menu_toggled (uint32_t c)
1873 if (_i_am_the_modifier) {
1877 _route->set_phase_invert (c, !_route->phase_invert (c));
1881 RouteUI::set_invert_sensitive (bool yn)
1883 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1884 (*b)->set_sensitive (yn);
1889 RouteUI::request_redraw ()
1892 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1896 /** The Route's gui_changed signal has been emitted */
1898 RouteUI::route_gui_changed (string what_changed)
1900 if (what_changed == "color") {
1901 if (set_color_from_route () == 0) {
1902 route_color_changed ();
1907 /** @return the color that this route should use; it maybe its own,
1908 or it maybe that of its route group.
1911 RouteUI::color () const
1913 RouteGroup* g = _route->route_group ();
1915 if (g && g->is_color()) {
1916 return GroupTabs::group_color (g);
1923 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
1925 _showing_sends_to = send_to;
1926 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
1930 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
1932 if (_route == send_to) {
1933 show_sends_button->set_active_state (Gtkmm2ext::Active);
1934 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
1936 show_sends_button->unset_active_state ();
1937 send_blink_connection.disconnect ();
1942 RouteUI::route_group() const
1944 return _route->route_group();