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 ()
990 bool yn = _route->solo_safe ();
992 if (solo_safe_check && solo_safe_check->get_active() != yn) {
993 solo_safe_check->set_active (yn);
996 yn = _route->solo_isolated ();
998 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
999 solo_isolated_check->set_active (yn);
1002 set_button_names ();
1004 if (solo_isolated_led) {
1005 if (_route->solo_isolated()) {
1006 solo_isolated_led->set_active_state (Gtkmm2ext::Active);
1008 solo_isolated_led->unset_active_state ();
1012 if (solo_safe_led) {
1013 if (_route->solo_safe()) {
1014 solo_safe_led->set_active_state (Gtkmm2ext::Active);
1016 solo_safe_led->unset_active_state ();
1020 solo_button->set_active_state (solo_active_state (_route));
1022 /* some changes to solo status can affect mute display, so catch up
1025 update_mute_display ();
1029 RouteUI::solo_changed_so_update_mute ()
1031 update_mute_display ();
1035 RouteUI::mute_changed(void* /*src*/)
1037 update_mute_display ();
1041 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1043 if (r->is_monitor()) {
1044 return ActiveState(0);
1048 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1053 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1054 /* master is NEVER muted by others */
1057 /* no mute at all */
1058 return ActiveState(0);
1067 /* no mute at all */
1068 return ActiveState(0);
1072 return ActiveState(0);
1076 RouteUI::update_mute_display ()
1082 mute_button->set_active_state (mute_active_state (_session, _route));
1086 RouteUI::route_rec_enable_changed ()
1088 update_rec_display ();
1089 update_monitoring_display ();
1093 RouteUI::session_rec_enable_changed ()
1095 update_rec_display ();
1096 update_monitoring_display ();
1100 RouteUI::update_rec_display ()
1102 if (!rec_enable_button || !_route) {
1106 if (_route->record_enabled()) {
1107 switch (_session->record_status ()) {
1108 case Session::Recording:
1109 rec_enable_button->set_active_state (Active);
1112 case Session::Disabled:
1113 case Session::Enabled:
1114 rec_enable_button->set_active_state (Mid);
1119 if (step_edit_item) {
1120 step_edit_item->set_sensitive (false);
1124 rec_enable_button->unset_active_state ();
1126 if (step_edit_item) {
1127 step_edit_item->set_sensitive (true);
1132 check_rec_enable_sensitivity ();
1136 RouteUI::build_solo_menu (void)
1138 using namespace Menu_Helpers;
1140 solo_menu = new Menu;
1141 solo_menu->set_name ("ArdourContextMenu");
1142 MenuList& items = solo_menu->items();
1143 CheckMenuItem* check;
1145 check = new CheckMenuItem(_("Solo Isolate"));
1146 check->set_active (_route->solo_isolated());
1147 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1148 items.push_back (CheckMenuElem(*check));
1149 solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1152 check = new CheckMenuItem(_("Solo Safe"));
1153 check->set_active (_route->solo_safe());
1154 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1155 items.push_back (CheckMenuElem(*check));
1156 solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1159 //items.push_back (SeparatorElem());
1160 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1165 RouteUI::build_mute_menu(void)
1167 using namespace Menu_Helpers;
1169 mute_menu = new Menu;
1170 mute_menu->set_name ("ArdourContextMenu");
1172 MenuList& items = mute_menu->items();
1174 pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1175 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1176 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1177 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1178 pre_fader_mute_check->show_all();
1180 post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1181 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1182 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1183 items.push_back (CheckMenuElem(*post_fader_mute_check));
1184 post_fader_mute_check->show_all();
1186 listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1187 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1188 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1189 items.push_back (CheckMenuElem(*listen_mute_check));
1190 listen_mute_check->show_all();
1192 main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1193 init_mute_menu(MuteMaster::Main, main_mute_check);
1194 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1195 items.push_back (CheckMenuElem(*main_mute_check));
1196 main_mute_check->show_all();
1198 //items.push_back (SeparatorElem());
1199 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1201 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1205 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1207 check->set_active (_route->mute_points() & mp);
1211 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1213 if (check->get_active()) {
1214 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1216 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1221 RouteUI::muting_change ()
1223 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1226 MuteMaster::MutePoint current = _route->mute_points ();
1228 yn = (current & MuteMaster::PreFader);
1230 if (pre_fader_mute_check->get_active() != yn) {
1231 pre_fader_mute_check->set_active (yn);
1234 yn = (current & MuteMaster::PostFader);
1236 if (post_fader_mute_check->get_active() != yn) {
1237 post_fader_mute_check->set_active (yn);
1240 yn = (current & MuteMaster::Listen);
1242 if (listen_mute_check->get_active() != yn) {
1243 listen_mute_check->set_active (yn);
1246 yn = (current & MuteMaster::Main);
1248 if (main_mute_check->get_active() != yn) {
1249 main_mute_check->set_active (yn);
1254 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1256 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1260 bool view = solo_isolated_led->active_state();
1261 bool model = _route->solo_isolated();
1263 /* called BEFORE the view has changed */
1265 if (ev->button == 1) {
1266 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1269 /* disable isolate for all routes */
1270 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1274 if (model == view) {
1276 /* flip just this route */
1278 boost::shared_ptr<RouteList> rl (new RouteList);
1279 rl->push_back (_route);
1280 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1289 RouteUI::solo_safe_button_release (GdkEventButton*)
1291 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1296 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1298 bool view = check->get_active();
1299 bool model = _route->solo_isolated();
1301 /* called AFTER the view has changed */
1303 if (model != view) {
1304 _route->set_solo_isolated (view, this);
1309 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1311 _route->set_solo_safe (check->get_active(), this);
1314 /** Ask the user to choose a colour, and then set all selected tracks
1318 RouteUI::choose_color ()
1321 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1324 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1325 boost::bind (&RouteUI::set_color, _1, color)
1330 /** Set the route's own color. This may not be used for display if
1331 * the route is in a group which shares its color with its routes.
1334 RouteUI::set_color (const Gdk::Color & c)
1340 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1342 /* note: we use the route state ID here so that color is the same for both
1343 the time axis view and the mixer strip
1346 gui_object_state().set<string> (route_state_id(), X_("color"), buf);
1347 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1350 /** @return GUI state ID for things that are common to the route in all its representations */
1352 RouteUI::route_state_id () const
1354 return string_compose (X_("route %1"), _route->id().to_s());
1358 RouteUI::set_color_from_route ()
1360 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1368 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1371 _color.set_green (g);
1372 _color.set_blue (b);
1378 RouteUI::remove_this_route (bool apply_to_selection)
1380 if (apply_to_selection) {
1381 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1383 if ((route()->is_master() || route()->is_monitor()) &&
1384 !Config->get_allow_special_bus_removal()) {
1385 MessageDialog msg (_("That would be bad news ...."),
1389 msg.set_secondary_text (string_compose (_(
1390 "Removing the master or monitor bus is such a bad idea\n\
1391 that %1 is not going to allow it.\n\
1393 If you really want to do this sort of thing\n\
1394 edit your ardour.rc file to set the\n\
1395 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1402 vector<string> choices;
1406 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());
1408 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());
1411 choices.push_back (_("No, do nothing."));
1412 choices.push_back (_("Yes, remove it."));
1416 title = _("Remove track");
1418 title = _("Remove bus");
1421 Choice prompter (title, prompt, choices);
1423 if (prompter.run () == 1) {
1424 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1430 RouteUI::idle_remove_this_route (RouteUI *rui)
1432 rui->_session->remove_route (rui->route());
1436 /** @return true if this name should be used for the route, otherwise false */
1438 RouteUI::verify_new_route_name (const std::string& name)
1440 if (name.find (':') == string::npos) {
1444 MessageDialog colon_msg (
1445 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1446 false, MESSAGE_QUESTION, BUTTONS_NONE
1449 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1450 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1452 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1456 RouteUI::route_rename ()
1458 ArdourPrompter name_prompter (true);
1463 name_prompter.set_title (_("Rename Track"));
1465 name_prompter.set_title (_("Rename Bus"));
1467 name_prompter.set_prompt (_("New name:"));
1468 name_prompter.set_initial_text (_route->name());
1469 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1470 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1471 name_prompter.show_all ();
1474 switch (name_prompter.run ()) {
1475 case Gtk::RESPONSE_ACCEPT:
1476 name_prompter.get_result (result);
1477 name_prompter.hide ();
1478 if (result.length()) {
1479 if (verify_new_route_name (result)) {
1480 _route->set_name (result);
1483 /* back to name prompter */
1487 /* nothing entered, just get out of here */
1502 RouteUI::property_changed (const PropertyChange& what_changed)
1504 if (what_changed.contains (ARDOUR::Properties::name)) {
1505 name_label.set_text (_route->name());
1510 RouteUI::set_route_active (bool a, bool apply_to_selection)
1512 if (apply_to_selection) {
1513 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1515 _route->set_active (a, this);
1520 RouteUI::toggle_denormal_protection ()
1522 if (denormal_menu_item) {
1526 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1528 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1529 _route->set_denormal_protection (x);
1535 RouteUI::denormal_protection_changed ()
1537 if (denormal_menu_item) {
1538 denormal_menu_item->set_active (_route->denormal_protection());
1543 RouteUI::disconnect_input ()
1545 _route->input()->disconnect (this);
1549 RouteUI::disconnect_output ()
1551 _route->output()->disconnect (this);
1555 RouteUI::is_track () const
1557 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1560 boost::shared_ptr<Track>
1561 RouteUI::track() const
1563 return boost::dynamic_pointer_cast<Track>(_route);
1567 RouteUI::is_audio_track () const
1569 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1572 boost::shared_ptr<AudioTrack>
1573 RouteUI::audio_track() const
1575 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1579 RouteUI::is_midi_track () const
1581 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1584 boost::shared_ptr<MidiTrack>
1585 RouteUI::midi_track() const
1587 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1591 RouteUI::has_audio_outputs () const
1593 return (_route->n_outputs().n_audio() > 0);
1597 RouteUI::name() const
1599 return _route->name();
1603 RouteUI::map_frozen ()
1605 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1607 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1610 switch (at->freeze_state()) {
1611 case AudioTrack::Frozen:
1612 rec_enable_button->set_sensitive (false);
1615 rec_enable_button->set_sensitive (true);
1622 RouteUI::adjust_latency ()
1624 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1628 RouteUI::save_as_template ()
1631 std::string safe_name;
1634 path = ARDOUR::user_route_template_directory ();
1636 if (g_mkdir_with_parents (path.to_string().c_str(), 0755)) {
1637 error << string_compose (_("Cannot create route template directory %1"), path.to_string()) << endmsg;
1641 Prompter p (true); // modal
1643 p.set_title (_("Save As Template"));
1644 p.set_prompt (_("Template name:"));
1645 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1647 case RESPONSE_ACCEPT:
1654 p.get_result (name, true);
1656 safe_name = legalize_for_path (name);
1657 safe_name += template_suffix;
1661 _route->save_as_template (path.to_string(), name);
1665 RouteUI::check_rec_enable_sensitivity ()
1667 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1668 rec_enable_button->set_sensitive (false);
1670 rec_enable_button->set_sensitive (true);
1673 update_monitoring_display ();
1677 RouteUI::parameter_changed (string const & p)
1679 /* this handles RC and per-session parameter changes */
1681 if (p == "disable-disarm-during-roll") {
1682 check_rec_enable_sensitivity ();
1683 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1684 set_button_names ();
1685 } else if (p == "auto-input") {
1686 update_monitoring_display ();
1691 RouteUI::step_gain_up ()
1693 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1697 RouteUI::page_gain_up ()
1699 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1703 RouteUI::step_gain_down ()
1705 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1709 RouteUI::page_gain_down ()
1711 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1715 RouteUI::open_remote_control_id_dialog ()
1717 ArdourDialog dialog (_("Remote Control ID"));
1719 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1721 HBox* hbox = manage (new HBox);
1722 hbox->set_spacing (6);
1723 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1724 SpinButton* spin = manage (new SpinButton);
1725 spin->set_digits (0);
1726 spin->set_increments (1, 10);
1727 spin->set_range (0, limit);
1728 spin->set_value (_route->remote_control_id());
1729 hbox->pack_start (*spin);
1730 dialog.get_vbox()->pack_start (*hbox);
1732 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1733 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1736 int const r = dialog.run ();
1738 if (r == RESPONSE_ACCEPT) {
1739 _route->set_remote_control_id (spin->get_value_as_int ());
1744 RouteUI::setup_invert_buttons ()
1746 /* remove old invert buttons */
1747 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1748 _invert_button_box.remove (**i);
1751 _invert_buttons.clear ();
1753 if (!_route || !_route->input()) {
1757 uint32_t const N = _route->input()->n_ports().n_audio ();
1759 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1761 for (uint32_t i = 0; i < to_add; ++i) {
1762 ArdourButton* b = manage (new ArdourButton);
1763 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1764 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1766 b->set_name (X_("mixer strip button"));
1768 b->set_text (X_("Ø"));
1770 b->set_text (string_compose (X_("Ø%1"), i + 1));
1774 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));
1776 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));
1779 _invert_buttons.push_back (b);
1780 _invert_button_box.pack_start (*b);
1783 _invert_button_box.set_spacing (1);
1784 _invert_button_box.show_all ();
1788 RouteUI::set_invert_button_state ()
1790 ++_i_am_the_modifier;
1792 uint32_t const N = _route->input()->n_ports().n_audio();
1793 if (N > _max_invert_buttons) {
1794 _invert_buttons.front()->set_active (_route->phase_invert().any());
1795 --_i_am_the_modifier;
1800 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1801 (*i)->set_active (_route->phase_invert (j));
1804 --_i_am_the_modifier;
1808 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1810 if (ev->button == 1 && i < _invert_buttons.size()) {
1811 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1819 RouteUI::invert_press (GdkEventButton* ev)
1821 using namespace Menu_Helpers;
1823 if (ev->button != 3) {
1827 delete _invert_menu;
1828 _invert_menu = new Menu;
1829 _invert_menu->set_name ("ArdourContextMenu");
1830 MenuList& items = _invert_menu->items ();
1832 uint32_t const N = _route->input()->n_ports().n_audio();
1833 for (uint32_t i = 0; i < N; ++i) {
1834 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1835 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1836 ++_i_am_the_modifier;
1837 e->set_active (_route->phase_invert (i));
1838 --_i_am_the_modifier;
1841 _invert_menu->popup (0, ev->time);
1847 RouteUI::invert_menu_toggled (uint32_t c)
1849 if (_i_am_the_modifier) {
1853 _route->set_phase_invert (c, !_route->phase_invert (c));
1857 RouteUI::set_invert_sensitive (bool yn)
1859 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1860 (*b)->set_sensitive (yn);
1865 RouteUI::request_redraw ()
1868 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1872 /** The Route's gui_changed signal has been emitted */
1874 RouteUI::route_gui_changed (string what_changed)
1876 if (what_changed == "color") {
1877 if (set_color_from_route () == 0) {
1878 route_color_changed ();
1883 /** @return the color that this route should use; it maybe its own,
1884 or it maybe that of its route group.
1887 RouteUI::color () const
1889 RouteGroup* g = _route->route_group ();
1891 if (g && g->is_color()) {
1892 return GroupTabs::group_color (g);
1899 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
1901 _showing_sends_to = send_to;
1902 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
1906 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
1908 if (_route == send_to) {
1909 show_sends_button->set_active_state (Gtkmm2ext::Active);
1910 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
1912 show_sends_button->unset_active_state ();
1913 send_blink_connection.disconnect ();
1918 RouteUI::route_group() const
1920 return _route->route_group();