2 Copyright (C) 2002-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
27 #include "ardour/route_group.h"
28 #include "ardour/dB.h"
29 #include "pbd/memento_command.h"
30 #include "pbd/stacktrace.h"
31 #include "pbd/controllable.h"
32 #include "pbd/enumwriter.h"
34 #include "ardour_ui.h"
37 #include "ardour_button.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
46 #include "route_time_axis.h"
47 #include "group_tabs.h"
49 #include "ardour/audio_track.h"
50 #include "ardour/audioengine.h"
51 #include "ardour/filename_extensions.h"
52 #include "ardour/midi_track.h"
53 #include "ardour/route.h"
54 #include "ardour/session.h"
55 #include "ardour/template_utils.h"
59 using namespace Gtkmm2ext;
60 using namespace ARDOUR;
63 uint32_t RouteUI::_max_invert_buttons = 3;
64 sigc::signal<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
65 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
67 RouteUI::RouteUI (ARDOUR::Session* sess)
75 _route.reset (); /* drop reference to route, so that it can be cleaned up */
76 route_connections.drop_connections ();
94 pre_fader_mute_check = 0;
95 post_fader_mute_check = 0;
96 listen_mute_check = 0;
99 solo_isolated_check = 0;
100 solo_isolated_led = 0;
104 denormal_menu_item = 0;
106 multiple_mute_change = false;
107 multiple_solo_change = false;
108 _i_am_the_modifier = 0;
110 setup_invert_buttons ();
112 mute_button = manage (new ArdourButton);
113 mute_button->set_name ("mute button");
114 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
116 solo_button = manage (new ArdourButton);
117 solo_button->set_name ("solo button");
118 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
119 solo_button->set_no_show_all (true);
121 rec_enable_button = manage (new ArdourButton);
122 rec_enable_button->set_name ("record enable button");
123 rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
124 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
126 show_sends_button = manage (new ArdourButton);
127 show_sends_button->set_name ("send alert button");
128 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
130 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
131 monitor_input_button->set_name ("monitor button");
132 monitor_input_button->set_text (_("In"));
133 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
134 monitor_input_button->set_no_show_all (true);
136 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
137 monitor_disk_button->set_name ("monitor button");
138 monitor_disk_button->set_text (_("Disk"));
139 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
140 monitor_disk_button->set_no_show_all (true);
142 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
143 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
144 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
146 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
147 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
149 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
150 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
152 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
153 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
155 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
156 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
157 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
158 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
160 monitor_input_button->set_distinct_led_click (false);
161 monitor_disk_button->set_distinct_led_click (false);
163 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
164 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
166 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
167 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
169 BusSendDisplayChanged.connect (sigc::mem_fun (*this, &RouteUI::bus_send_display_changed));
175 route_connections.drop_connections ();
183 denormal_menu_item = 0;
187 RouteUI::self_delete ()
193 RouteUI::set_route (boost::shared_ptr<Route> rp)
199 if (set_color_from_route()) {
200 set_color (unique_random_color());
204 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
207 mute_button->set_controllable (_route->mute_control());
208 solo_button->set_controllable (_route->solo_control());
210 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
211 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
213 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
214 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
215 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
216 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
218 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
219 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
221 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
222 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
224 if (_session->writable() && is_track()) {
225 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
227 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
229 rec_enable_button->show();
230 rec_enable_button->set_controllable (t->rec_enable_control());
232 if (is_midi_track()) {
233 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
234 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
239 /* this will work for busses and tracks, and needs to be called to
240 set up the name entry/name label display.
243 update_rec_display ();
246 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
247 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
249 update_monitoring_display ();
252 mute_button->unset_flags (Gtk::CAN_FOCUS);
253 solo_button->unset_flags (Gtk::CAN_FOCUS);
257 if (_route->is_monitor() || _route->is_master()) {
258 solo_button->hide ();
265 setup_invert_buttons ();
266 set_invert_button_state ();
268 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
269 bus_send_display_changed (s);
271 update_mute_display ();
272 update_solo_display ();
276 RouteUI::polarity_changed ()
282 set_invert_button_state ();
286 RouteUI::mute_press (GdkEventButton* ev)
288 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
292 multiple_mute_change = false;
294 if (!_i_am_the_modifier) {
296 if (Keyboard::is_context_menu_event (ev)) {
302 mute_menu->popup(0,ev->time);
306 if (Keyboard::is_button2_event (ev)) {
307 // Primary-button2 click is the midi binding click
308 // button2-click is "momentary"
311 if (mute_button->on_button_press_event (ev)) {
315 _mute_release = new SoloMuteRelease (_route->muted ());
318 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
320 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
322 /* toggle mute on everything (but
323 * exclude the master and monitor)
325 * because we are going to erase
326 * elements of the list we need to work
330 boost::shared_ptr<RouteList> copy (new RouteList);
332 *copy = *_session->get_routes ();
334 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
335 if ((*i)->is_master() || (*i)->is_monitor()) {
343 _mute_release->routes = copy;
346 _session->set_mute (copy, !_route->muted());
348 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
350 /* Primary-button1 applies change to the mix group even if it is not active
351 NOTE: Primary-button2 is MIDI learn.
354 boost::shared_ptr<RouteList> rl;
356 if (ev->button == 1) {
358 if (_route->route_group()) {
360 rl = _route->route_group()->route_list();
363 _mute_release->routes = rl;
366 rl.reset (new RouteList);
367 rl->push_back (_route);
370 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
375 /* plain click applies change to this route */
377 boost::shared_ptr<RouteList> rl (new RouteList);
378 rl->push_back (_route);
381 _mute_release->routes = rl;
384 _session->set_mute (rl, !_route->muted());
396 RouteUI::mute_release (GdkEventButton*)
398 if (!_i_am_the_modifier) {
400 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
401 delete _mute_release;
410 RouteUI::solo_press(GdkEventButton* ev)
412 /* ignore double/triple clicks */
414 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
418 multiple_solo_change = false;
420 if (!_i_am_the_modifier) {
422 if (Keyboard::is_context_menu_event (ev)) {
424 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
425 ! (solo_safe_led && solo_safe_led->is_visible())) {
427 if (solo_menu == 0) {
431 solo_menu->popup (1, ev->time);
436 if (Keyboard::is_button2_event (ev)) {
438 // Primary-button2 click is the midi binding click
439 // button2-click is "momentary"
441 if (solo_button->on_button_press_event (ev)) {
445 _solo_release = new SoloMuteRelease (_route->self_soloed());
448 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
450 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
452 /* Primary-Tertiary-click applies change to all routes */
455 _solo_release->routes = _session->get_routes ();
458 if (Config->get_solo_control_is_listen_control()) {
459 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
461 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
464 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
466 // Primary-Secondary-click: exclusively solo this track
469 _solo_release->exclusive = true;
471 boost::shared_ptr<RouteList> routes = _session->get_routes();
473 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
474 if ((*i)->soloed ()) {
475 _solo_release->routes_on->push_back (*i);
477 _solo_release->routes_off->push_back (*i);
482 if (Config->get_solo_control_is_listen_control()) {
483 /* ??? we need a just_one_listen() method */
485 _session->set_just_one_solo (_route, true);
488 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
490 // shift-click: toggle solo isolated status
492 _route->set_solo_isolated (!_route->solo_isolated(), this);
493 delete _solo_release;
496 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
498 /* Primary-button1: solo mix group.
499 NOTE: Primary-button2 is MIDI learn.
502 /* Primary-button1 applies change to the mix group even if it is not active
503 NOTE: Primary-button2 is MIDI learn.
506 boost::shared_ptr<RouteList> rl;
508 if (ev->button == 1) {
510 if (_route->route_group()) {
512 rl = _route->route_group()->route_list();
515 _solo_release->routes = rl;
518 rl.reset (new RouteList);
519 rl->push_back (_route);
522 if (Config->get_solo_control_is_listen_control()) {
523 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
525 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
531 /* click: solo this route */
533 boost::shared_ptr<RouteList> rl (new RouteList);
534 rl->push_back (route());
537 _solo_release->routes = rl;
540 if (Config->get_solo_control_is_listen_control()) {
541 _session->set_listen (rl, !_route->listening_via_monitor());
543 _session->set_solo (rl, !_route->self_soloed());
554 RouteUI::solo_release (GdkEventButton*)
556 if (!_i_am_the_modifier) {
560 if (_solo_release->exclusive) {
563 if (Config->get_solo_control_is_listen_control()) {
564 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
566 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
570 delete _solo_release;
579 RouteUI::rec_enable_press(GdkEventButton* ev)
581 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
585 if (!_session->engine().connected()) {
586 MessageDialog msg (_("Not connected to JACK - cannot engage record"));
591 if (is_midi_track()) {
593 /* rec-enable button exits from step editing */
595 if (midi_track()->step_editing()) {
596 midi_track()->set_step_editing (false);
601 if (!_i_am_the_modifier && is_track() && rec_enable_button) {
603 if (Keyboard::is_button2_event (ev)) {
605 // do nothing on midi sigc::bind event
606 return rec_enable_button->on_button_press_event (ev);
608 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
610 _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
612 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
614 /* Primary-button1 applies change to the route group (even if it is not active)
615 NOTE: Primary-button2 is MIDI learn.
618 if (ev->button == 1) {
620 boost::shared_ptr<RouteList> rl;
622 if (_route->route_group()) {
624 rl = _route->route_group()->route_list();
627 rl.reset (new RouteList);
628 rl->push_back (_route);
631 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
634 } else if (Keyboard::is_context_menu_event (ev)) {
636 /* do this on release */
640 boost::shared_ptr<RouteList> rl (new RouteList);
641 rl->push_back (route());
642 _session->set_record_enabled (rl, !rec_enable_button->active_state());
650 RouteUI::monitoring_changed ()
652 update_monitoring_display ();
656 RouteUI::update_monitoring_display ()
662 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
668 MonitorState ms = t->monitoring_state();
670 if (t->monitoring_choice() & MonitorInput) {
671 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
673 if (ms & MonitoringInput) {
674 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
676 monitor_input_button->unset_active_state ();
680 if (t->monitoring_choice() & MonitorDisk) {
681 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
683 if (ms & MonitoringDisk) {
684 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
686 monitor_disk_button->unset_active_state ();
692 RouteUI::monitor_input_press(GdkEventButton*)
698 RouteUI::monitor_input_release(GdkEventButton* ev)
700 return monitor_release (ev, MonitorInput);
704 RouteUI::monitor_disk_press (GdkEventButton*)
710 RouteUI::monitor_disk_release (GdkEventButton* ev)
712 return monitor_release (ev, MonitorDisk);
716 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
718 if (ev->button != 1) {
722 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
729 boost::shared_ptr<RouteList> rl;
731 /* XXX for now, monitoring choices are orthogonal. cue monitoring
732 will follow in 3.X but requires mixing the input and playback (disk)
733 signal together, which requires yet more buffers.
736 if (t->monitoring_choice() & monitor_choice) {
737 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
739 /* this line will change when the options are non-orthogonal */
740 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
744 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
745 rl = _session->get_routes ();
747 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
748 if (_route->route_group() && _route->route_group()->is_monitoring()) {
749 rl = _route->route_group()->route_list();
751 rl.reset (new RouteList);
752 rl->push_back (route());
755 rl.reset (new RouteList);
756 rl->push_back (route());
759 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
765 RouteUI::build_record_menu ()
771 /* no rec-button context menu for non-MIDI tracks
774 if (is_midi_track()) {
775 record_menu = new Menu;
776 record_menu->set_name ("ArdourContextMenu");
778 using namespace Menu_Helpers;
779 MenuList& items = record_menu->items();
781 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
782 step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
784 if (_route->record_enabled()) {
785 step_edit_item->set_sensitive (false);
788 step_edit_item->set_active (midi_track()->step_editing());
793 RouteUI::toggle_step_edit ()
795 if (!is_midi_track() || _route->record_enabled()) {
799 midi_track()->set_step_editing (step_edit_item->get_active());
803 RouteUI::step_edit_changed (bool yn)
806 if (rec_enable_button) {
807 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
810 start_step_editing ();
812 if (step_edit_item) {
813 step_edit_item->set_active (true);
818 if (rec_enable_button) {
819 rec_enable_button->unset_active_state ();
822 stop_step_editing ();
824 if (step_edit_item) {
825 step_edit_item->set_active (false);
831 RouteUI::rec_enable_release (GdkEventButton* ev)
833 if (Keyboard::is_context_menu_event (ev)) {
834 build_record_menu ();
836 record_menu->popup (1, ev->time);
845 RouteUI::build_sends_menu ()
847 using namespace Menu_Helpers;
849 sends_menu = new Menu;
850 sends_menu->set_name ("ArdourContextMenu");
851 MenuList& items = sends_menu->items();
854 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
858 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
862 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
866 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
870 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
874 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
877 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
881 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
884 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
885 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
886 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
891 RouteUI::create_sends (Placement p, bool include_buses)
893 _session->globally_add_internal_sends (_route, p, include_buses);
897 RouteUI::create_selected_sends (Placement p, bool include_buses)
899 boost::shared_ptr<RouteList> rlist (new RouteList);
900 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
902 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
903 RouteTimeAxisView* rtv;
905 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
906 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
907 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
908 rlist->push_back (rui->route());
914 _session->add_internal_sends (_route, p, rlist);
918 RouteUI::set_sends_gain_from_track ()
920 _session->globally_set_send_gains_from_track (_route);
924 RouteUI::set_sends_gain_to_zero ()
926 _session->globally_set_send_gains_to_zero (_route);
930 RouteUI::set_sends_gain_to_unity ()
932 _session->globally_set_send_gains_to_unity (_route);
936 RouteUI::show_sends_press(GdkEventButton* ev)
938 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
942 if (!_i_am_the_modifier && !is_track() && show_sends_button) {
944 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
946 // do nothing on midi sigc::bind event
949 } else if (Keyboard::is_context_menu_event (ev)) {
951 if (sends_menu == 0) {
955 sends_menu->popup (0, ev->time);
959 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
962 set_showing_sends_to (boost::shared_ptr<Route> ());
964 set_showing_sends_to (_route);
973 RouteUI::show_sends_release (GdkEventButton*)
979 RouteUI::send_blink (bool onoff)
981 if (!show_sends_button) {
986 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
988 show_sends_button->unset_active_state ();
992 Gtkmm2ext::ActiveState
993 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
995 if (r->is_master() || r->is_monitor()) {
996 return Gtkmm2ext::Off;
999 if (Config->get_solo_control_is_listen_control()) {
1001 if (r->listening_via_monitor()) {
1002 return Gtkmm2ext::ExplicitActive;
1004 return Gtkmm2ext::Off;
1010 if (!r->self_soloed()) {
1011 return Gtkmm2ext::ImplicitActive;
1013 return Gtkmm2ext::ExplicitActive;
1016 return Gtkmm2ext::Off;
1020 Gtkmm2ext::ActiveState
1021 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1023 if (r->is_master() || r->is_monitor()) {
1024 return Gtkmm2ext::Off;
1027 if (r->solo_isolated()) {
1028 return Gtkmm2ext::ExplicitActive;
1030 return Gtkmm2ext::Off;
1034 Gtkmm2ext::ActiveState
1035 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1037 if (r->is_master() || r->is_monitor()) {
1038 return Gtkmm2ext::Off;
1041 if (r->solo_safe()) {
1042 return Gtkmm2ext::ExplicitActive;
1044 return Gtkmm2ext::Off;
1049 RouteUI::update_solo_display ()
1051 bool yn = _route->solo_safe ();
1053 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1054 solo_safe_check->set_active (yn);
1057 yn = _route->solo_isolated ();
1059 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1060 solo_isolated_check->set_active (yn);
1063 set_button_names ();
1065 if (solo_isolated_led) {
1066 if (_route->solo_isolated()) {
1067 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1069 solo_isolated_led->unset_active_state ();
1073 if (solo_safe_led) {
1074 if (_route->solo_safe()) {
1075 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1077 solo_safe_led->unset_active_state ();
1081 solo_button->set_active_state (solo_active_state (_route));
1083 /* some changes to solo status can affect mute display, so catch up
1086 update_mute_display ();
1090 RouteUI::solo_changed_so_update_mute ()
1092 update_mute_display ();
1096 RouteUI::mute_changed(void* /*src*/)
1098 update_mute_display ();
1102 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1104 if (r->is_monitor()) {
1105 return ActiveState(0);
1109 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1113 return Gtkmm2ext::ExplicitActive;
1114 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1115 /* master is NEVER muted by others */
1116 return Gtkmm2ext::ImplicitActive;
1118 /* no mute at all */
1119 return Gtkmm2ext::Off;
1126 return Gtkmm2ext::ExplicitActive;
1128 /* no mute at all */
1129 return Gtkmm2ext::Off;
1133 return ActiveState(0);
1137 RouteUI::update_mute_display ()
1143 mute_button->set_active_state (mute_active_state (_session, _route));
1147 RouteUI::route_rec_enable_changed ()
1149 update_rec_display ();
1150 update_monitoring_display ();
1154 RouteUI::session_rec_enable_changed ()
1156 update_rec_display ();
1157 update_monitoring_display ();
1161 RouteUI::update_rec_display ()
1163 if (!rec_enable_button || !_route) {
1167 if (_route->record_enabled()) {
1168 switch (_session->record_status ()) {
1169 case Session::Recording:
1170 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1173 case Session::Disabled:
1174 case Session::Enabled:
1175 rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1180 if (step_edit_item) {
1181 step_edit_item->set_sensitive (false);
1185 rec_enable_button->unset_active_state ();
1187 if (step_edit_item) {
1188 step_edit_item->set_sensitive (true);
1193 check_rec_enable_sensitivity ();
1197 RouteUI::build_solo_menu (void)
1199 using namespace Menu_Helpers;
1201 solo_menu = new Menu;
1202 solo_menu->set_name ("ArdourContextMenu");
1203 MenuList& items = solo_menu->items();
1204 CheckMenuItem* check;
1206 check = new CheckMenuItem(_("Solo Isolate"));
1207 check->set_active (_route->solo_isolated());
1208 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1209 items.push_back (CheckMenuElem(*check));
1210 solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1213 check = new CheckMenuItem(_("Solo Safe"));
1214 check->set_active (_route->solo_safe());
1215 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1216 items.push_back (CheckMenuElem(*check));
1217 solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1220 //items.push_back (SeparatorElem());
1221 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1226 RouteUI::build_mute_menu(void)
1228 using namespace Menu_Helpers;
1230 mute_menu = new Menu;
1231 mute_menu->set_name ("ArdourContextMenu");
1233 MenuList& items = mute_menu->items();
1235 pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1236 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1237 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1238 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1239 pre_fader_mute_check->show_all();
1241 post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1242 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1243 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1244 items.push_back (CheckMenuElem(*post_fader_mute_check));
1245 post_fader_mute_check->show_all();
1247 listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1248 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1249 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1250 items.push_back (CheckMenuElem(*listen_mute_check));
1251 listen_mute_check->show_all();
1253 main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1254 init_mute_menu(MuteMaster::Main, main_mute_check);
1255 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1256 items.push_back (CheckMenuElem(*main_mute_check));
1257 main_mute_check->show_all();
1259 //items.push_back (SeparatorElem());
1260 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1262 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1266 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1268 check->set_active (_route->mute_points() & mp);
1272 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1274 if (check->get_active()) {
1275 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1277 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1282 RouteUI::muting_change ()
1284 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1287 MuteMaster::MutePoint current = _route->mute_points ();
1289 yn = (current & MuteMaster::PreFader);
1291 if (pre_fader_mute_check->get_active() != yn) {
1292 pre_fader_mute_check->set_active (yn);
1295 yn = (current & MuteMaster::PostFader);
1297 if (post_fader_mute_check->get_active() != yn) {
1298 post_fader_mute_check->set_active (yn);
1301 yn = (current & MuteMaster::Listen);
1303 if (listen_mute_check->get_active() != yn) {
1304 listen_mute_check->set_active (yn);
1307 yn = (current & MuteMaster::Main);
1309 if (main_mute_check->get_active() != yn) {
1310 main_mute_check->set_active (yn);
1315 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1317 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1321 bool view = solo_isolated_led->active_state();
1322 bool model = _route->solo_isolated();
1324 /* called BEFORE the view has changed */
1326 if (ev->button == 1) {
1327 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1330 /* disable isolate for all routes */
1331 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1335 if (model == view) {
1337 /* flip just this route */
1339 boost::shared_ptr<RouteList> rl (new RouteList);
1340 rl->push_back (_route);
1341 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1350 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1352 if (ev->button == 1) {
1353 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1360 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1362 bool view = check->get_active();
1363 bool model = _route->solo_isolated();
1365 /* called AFTER the view has changed */
1367 if (model != view) {
1368 _route->set_solo_isolated (view, this);
1373 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1375 _route->set_solo_safe (check->get_active(), this);
1378 /** Ask the user to choose a colour, and then set all selected tracks
1382 RouteUI::choose_color ()
1385 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1388 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1389 boost::bind (&RouteUI::set_color, _1, color)
1394 /** Set the route's own color. This may not be used for display if
1395 * the route is in a group which shares its color with its routes.
1398 RouteUI::set_color (const Gdk::Color & c)
1400 /* leave _color alone in the group case so that tracks can retain their
1401 * own pre-group colors.
1406 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1408 /* note: we use the route state ID here so that color is the same for both
1409 the time axis view and the mixer strip
1412 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1413 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1416 /** @return GUI state ID for things that are common to the route in all its representations */
1418 RouteUI::route_state_id () const
1420 return string_compose (X_("route %1"), _route->id().to_s());
1424 RouteUI::set_color_from_route ()
1426 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1434 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1437 _color.set_green (g);
1438 _color.set_blue (b);
1444 RouteUI::remove_this_route (bool apply_to_selection)
1446 if (apply_to_selection) {
1447 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1449 if ((route()->is_master() || route()->is_monitor()) &&
1450 !Config->get_allow_special_bus_removal()) {
1451 MessageDialog msg (_("That would be bad news ...."),
1455 msg.set_secondary_text (string_compose (_(
1456 "Removing the master or monitor bus is such a bad idea\n\
1457 that %1 is not going to allow it.\n\
1459 If you really want to do this sort of thing\n\
1460 edit your ardour.rc file to set the\n\
1461 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1468 vector<string> choices;
1472 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());
1474 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());
1477 choices.push_back (_("No, do nothing."));
1478 choices.push_back (_("Yes, remove it."));
1482 title = _("Remove track");
1484 title = _("Remove bus");
1487 Choice prompter (title, prompt, choices);
1489 if (prompter.run () == 1) {
1490 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1496 RouteUI::idle_remove_this_route (RouteUI *rui)
1498 rui->_session->remove_route (rui->route());
1502 /** @return true if this name should be used for the route, otherwise false */
1504 RouteUI::verify_new_route_name (const std::string& name)
1506 if (name.find (':') == string::npos) {
1510 MessageDialog colon_msg (
1511 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1512 false, MESSAGE_QUESTION, BUTTONS_NONE
1515 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1516 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1518 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1522 RouteUI::route_rename ()
1524 ArdourPrompter name_prompter (true);
1529 name_prompter.set_title (_("Rename Track"));
1531 name_prompter.set_title (_("Rename Bus"));
1533 name_prompter.set_prompt (_("New name:"));
1534 name_prompter.set_initial_text (_route->name());
1535 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1536 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1537 name_prompter.show_all ();
1540 switch (name_prompter.run ()) {
1541 case Gtk::RESPONSE_ACCEPT:
1542 name_prompter.get_result (result);
1543 name_prompter.hide ();
1544 if (result.length()) {
1545 if (verify_new_route_name (result)) {
1546 _route->set_name (result);
1549 /* back to name prompter */
1553 /* nothing entered, just get out of here */
1568 RouteUI::property_changed (const PropertyChange& what_changed)
1570 if (what_changed.contains (ARDOUR::Properties::name)) {
1571 name_label.set_text (_route->name());
1576 RouteUI::set_route_active (bool a, bool apply_to_selection)
1578 if (apply_to_selection) {
1579 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1581 _route->set_active (a, this);
1586 RouteUI::toggle_denormal_protection ()
1588 if (denormal_menu_item) {
1592 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1594 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1595 _route->set_denormal_protection (x);
1601 RouteUI::denormal_protection_changed ()
1603 if (denormal_menu_item) {
1604 denormal_menu_item->set_active (_route->denormal_protection());
1609 RouteUI::disconnect_input ()
1611 _route->input()->disconnect (this);
1615 RouteUI::disconnect_output ()
1617 _route->output()->disconnect (this);
1621 RouteUI::is_track () const
1623 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1626 boost::shared_ptr<Track>
1627 RouteUI::track() const
1629 return boost::dynamic_pointer_cast<Track>(_route);
1633 RouteUI::is_audio_track () const
1635 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1638 boost::shared_ptr<AudioTrack>
1639 RouteUI::audio_track() const
1641 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1645 RouteUI::is_midi_track () const
1647 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1650 boost::shared_ptr<MidiTrack>
1651 RouteUI::midi_track() const
1653 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1657 RouteUI::has_audio_outputs () const
1659 return (_route->n_outputs().n_audio() > 0);
1663 RouteUI::name() const
1665 return _route->name();
1669 RouteUI::map_frozen ()
1671 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1673 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1676 switch (at->freeze_state()) {
1677 case AudioTrack::Frozen:
1678 rec_enable_button->set_sensitive (false);
1681 rec_enable_button->set_sensitive (true);
1688 RouteUI::adjust_latency ()
1690 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1694 RouteUI::save_as_template ()
1697 std::string safe_name;
1700 path = ARDOUR::user_route_template_directory ();
1702 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1703 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1707 Prompter p (true); // modal
1709 p.set_title (_("Save As Template"));
1710 p.set_prompt (_("Template name:"));
1711 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1713 case RESPONSE_ACCEPT:
1720 p.get_result (name, true);
1722 safe_name = legalize_for_path (name);
1723 safe_name += template_suffix;
1725 path = Glib::build_filename (path, safe_name);
1727 _route->save_as_template (path, name);
1731 RouteUI::check_rec_enable_sensitivity ()
1733 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1734 rec_enable_button->set_sensitive (false);
1736 rec_enable_button->set_sensitive (true);
1739 update_monitoring_display ();
1743 RouteUI::parameter_changed (string const & p)
1745 /* this handles RC and per-session parameter changes */
1747 if (p == "disable-disarm-during-roll") {
1748 check_rec_enable_sensitivity ();
1749 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1750 set_button_names ();
1751 } else if (p == "auto-input") {
1752 update_monitoring_display ();
1757 RouteUI::step_gain_up ()
1759 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1763 RouteUI::page_gain_up ()
1765 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1769 RouteUI::step_gain_down ()
1771 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1775 RouteUI::page_gain_down ()
1777 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1781 RouteUI::open_remote_control_id_dialog ()
1783 ArdourDialog dialog (_("Remote Control ID"));
1784 SpinButton* spin = 0;
1786 dialog.get_vbox()->set_border_width (18);
1788 if (Config->get_remote_model() == UserOrdered) {
1789 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1791 HBox* hbox = manage (new HBox);
1792 hbox->set_spacing (6);
1793 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1794 spin = manage (new SpinButton);
1795 spin->set_digits (0);
1796 spin->set_increments (1, 10);
1797 spin->set_range (0, limit);
1798 spin->set_value (_route->remote_control_id());
1799 hbox->pack_start (*spin);
1800 dialog.get_vbox()->pack_start (*hbox);
1802 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1803 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1805 Label* l = manage (new Label());
1806 if (_route->is_master() || _route->is_monitor()) {
1807 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1808 "The remote control ID of %3 cannot be changed."),
1809 Glib::Markup::escape_text (_route->name()),
1810 _route->remote_control_id(),
1811 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1813 l->set_markup (string_compose (_("The remote control ID of %6 is: %3\n\n\n"
1814 "Remote Control IDs are currently determined by track/bus ordering in %1\n\n"
1815 "%4Use the User Interaction tab of the Preferences window if you want to change this%5"),
1816 (Config->get_remote_model() == MixerOrdered ? _("the mixer") : _("the editor")),
1817 (is_track() ? _("track") : _("bus")),
1818 _route->remote_control_id(),
1819 "<span size=\"small\" style=\"italic\">",
1821 Glib::Markup::escape_text (_route->name())));
1823 dialog.get_vbox()->pack_start (*l);
1824 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1828 int const r = dialog.run ();
1830 if (r == RESPONSE_ACCEPT && spin) {
1831 _route->set_remote_control_id (spin->get_value_as_int ());
1836 RouteUI::setup_invert_buttons ()
1838 /* remove old invert buttons */
1839 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1840 _invert_button_box.remove (**i);
1843 _invert_buttons.clear ();
1845 if (!_route || !_route->input()) {
1849 uint32_t const N = _route->input()->n_ports().n_audio ();
1851 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1853 for (uint32_t i = 0; i < to_add; ++i) {
1854 ArdourButton* b = manage (new ArdourButton);
1855 b->set_size_request(20,20);
1856 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1857 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1859 b->set_name (X_("invert button"));
1862 b->set_text (string_compose (X_("Ø (%1)"), N));
1864 b->set_text (X_("Ø"));
1867 b->set_text (string_compose (X_("Ø%1"), i + 1));
1870 if (N <= _max_invert_buttons) {
1871 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));
1873 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1876 _invert_buttons.push_back (b);
1877 _invert_button_box.pack_start (*b);
1880 _invert_button_box.set_spacing (1);
1881 _invert_button_box.show_all ();
1885 RouteUI::set_invert_button_state ()
1887 ++_i_am_the_modifier;
1889 uint32_t const N = _route->input()->n_ports().n_audio();
1890 if (N > _max_invert_buttons) {
1892 /* One button for many channels; explicit active if all channels are inverted,
1893 implicit active if some are, off if none are.
1896 ArdourButton* b = _invert_buttons.front ();
1898 if (_route->phase_invert().count() == _route->phase_invert().size()) {
1899 b->set_active_state (Gtkmm2ext::ExplicitActive);
1900 } else if (_route->phase_invert().any()) {
1901 b->set_active_state (Gtkmm2ext::ImplicitActive);
1903 b->set_active_state (Gtkmm2ext::Off);
1908 /* One button per channel; just set active */
1911 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1912 (*i)->set_active (_route->phase_invert (j));
1917 --_i_am_the_modifier;
1921 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1923 if (ev->button == 1 && i < _invert_buttons.size()) {
1924 uint32_t const N = _route->input()->n_ports().n_audio ();
1925 if (N <= _max_invert_buttons) {
1926 /* left-click inverts phase so long as we have a button per channel */
1927 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1936 RouteUI::invert_press (GdkEventButton* ev)
1938 using namespace Menu_Helpers;
1940 uint32_t const N = _route->input()->n_ports().n_audio();
1941 if (N <= _max_invert_buttons && ev->button != 3) {
1942 /* If we have an invert button per channel, we only pop
1943 up a menu on right-click; left click is handled
1949 delete _invert_menu;
1950 _invert_menu = new Menu;
1951 _invert_menu->set_name ("ArdourContextMenu");
1952 MenuList& items = _invert_menu->items ();
1954 for (uint32_t i = 0; i < N; ++i) {
1955 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1956 CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1957 ++_i_am_the_modifier;
1958 e->set_active (_route->phase_invert (i));
1959 --_i_am_the_modifier;
1962 _invert_menu->popup (0, ev->time);
1968 RouteUI::invert_menu_toggled (uint32_t c)
1970 if (_i_am_the_modifier) {
1974 _route->set_phase_invert (c, !_route->phase_invert (c));
1978 RouteUI::set_invert_sensitive (bool yn)
1980 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1981 (*b)->set_sensitive (yn);
1986 RouteUI::request_redraw ()
1989 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1993 /** The Route's gui_changed signal has been emitted */
1995 RouteUI::route_gui_changed (string what_changed)
1997 if (what_changed == "color") {
1998 if (set_color_from_route () == 0) {
1999 route_color_changed ();
2004 /** @return the color that this route should use; it maybe its own,
2005 or it maybe that of its route group.
2008 RouteUI::color () const
2010 RouteGroup* g = _route->route_group ();
2012 if (g && g->is_color()) {
2013 return GroupTabs::group_color (g);
2020 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2022 _showing_sends_to = send_to;
2023 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2027 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2029 if (_route == send_to) {
2030 show_sends_button->set_active (true);
2031 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2033 show_sends_button->set_active (false);
2034 send_blink_connection.disconnect ();
2039 RouteUI::route_group() const
2041 return _route->route_group();