2 Copyright (C) 2002-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
27 #include "ardour/route_group.h"
28 #include "ardour/dB.h"
29 #include "pbd/memento_command.h"
30 #include "pbd/stacktrace.h"
31 #include "pbd/controllable.h"
32 #include "pbd/enumwriter.h"
34 #include "ardour_ui.h"
37 #include "ardour_button.h"
41 #include "gui_thread.h"
42 #include "ardour_dialog.h"
43 #include "latency_gui.h"
44 #include "mixer_strip.h"
45 #include "automation_time_axis.h"
46 #include "route_time_axis.h"
47 #include "group_tabs.h"
49 #include "ardour/audio_track.h"
50 #include "ardour/audioengine.h"
51 #include "ardour/filename_extensions.h"
52 #include "ardour/midi_track.h"
53 #include "ardour/route.h"
54 #include "ardour/session.h"
55 #include "ardour/template_utils.h"
59 using namespace Gtkmm2ext;
60 using namespace ARDOUR;
61 using namespace ARDOUR_UI_UTILS;
64 uint32_t RouteUI::_max_invert_buttons = 3;
65 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
66 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
68 RouteUI::RouteUI (ARDOUR::Session* sess)
81 _route.reset (); /* drop reference to route, so that it can be cleaned up */
82 route_connections.drop_connections ();
100 pre_fader_mute_check = 0;
101 post_fader_mute_check = 0;
102 listen_mute_check = 0;
105 solo_isolated_check = 0;
106 solo_isolated_led = 0;
110 denormal_menu_item = 0;
112 multiple_mute_change = false;
113 multiple_solo_change = false;
114 _i_am_the_modifier = 0;
116 setup_invert_buttons ();
118 mute_button = manage (new ArdourButton);
119 mute_button->set_name ("mute button");
120 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
122 solo_button = manage (new ArdourButton);
123 solo_button->set_name ("solo button");
124 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
125 solo_button->set_no_show_all (true);
127 rec_enable_button = manage (new ArdourButton);
128 rec_enable_button->set_name ("record enable button");
129 // rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
130 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
132 show_sends_button = manage (new ArdourButton);
133 show_sends_button->set_name ("send alert button");
134 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
136 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
137 monitor_input_button->set_name ("monitor button");
138 monitor_input_button->set_text (_("In"));
139 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
140 monitor_input_button->set_no_show_all (true);
142 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
143 monitor_disk_button->set_name ("monitor button");
144 monitor_disk_button->set_text (_("Disk"));
145 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
146 monitor_disk_button->set_no_show_all (true);
148 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
149 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
150 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
152 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
153 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
155 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
156 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
158 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
159 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
161 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
162 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
163 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
164 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
166 monitor_input_button->set_distinct_led_click (false);
167 monitor_disk_button->set_distinct_led_click (false);
169 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
170 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
172 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
173 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
175 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
181 route_connections.drop_connections ();
189 denormal_menu_item = 0;
193 RouteUI::self_delete ()
199 RouteUI::set_route (boost::shared_ptr<Route> rp)
205 if (set_color_from_route()) {
206 set_color (unique_random_color());
210 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
213 mute_button->set_controllable (_route->mute_control());
214 solo_button->set_controllable (_route->solo_control());
216 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
217 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
219 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
220 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
221 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
222 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
224 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
225 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
227 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
228 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
230 if (_session->writable() && is_track()) {
231 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
233 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
235 rec_enable_button->show();
236 rec_enable_button->set_controllable (t->rec_enable_control());
238 if (is_midi_track()) {
239 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
240 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
245 /* this will work for busses and tracks, and needs to be called to
246 set up the name entry/name label display.
249 update_rec_display ();
252 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
253 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
255 update_monitoring_display ();
258 mute_button->unset_flags (Gtk::CAN_FOCUS);
259 solo_button->unset_flags (Gtk::CAN_FOCUS);
263 if (_route->is_monitor() || _route->is_master()) {
264 solo_button->hide ();
271 setup_invert_buttons ();
272 set_invert_button_state ();
274 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
275 bus_send_display_changed (s);
277 update_mute_display ();
278 update_solo_display ();
282 RouteUI::polarity_changed ()
288 set_invert_button_state ();
292 RouteUI::mute_press (GdkEventButton* ev)
294 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
298 multiple_mute_change = false;
300 if (!_i_am_the_modifier) {
302 if (Keyboard::is_context_menu_event (ev)) {
308 mute_menu->popup(0,ev->time);
312 if (Keyboard::is_button2_event (ev)) {
313 // Primary-button2 click is the midi binding click
314 // button2-click is "momentary"
317 if (mute_button->on_button_press_event (ev)) {
321 _mute_release = new SoloMuteRelease (_route->muted ());
324 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
326 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
328 /* toggle mute on everything (but
329 * exclude the master and monitor)
331 * because we are going to erase
332 * elements of the list we need to work
336 boost::shared_ptr<RouteList> copy (new RouteList);
338 *copy = *_session->get_routes ();
340 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
341 if ((*i)->is_master() || (*i)->is_monitor()) {
349 _mute_release->routes = copy;
352 _session->set_mute (copy, !_route->muted());
354 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
356 /* Primary-button1 applies change to the mix group even if it is not active
357 NOTE: Primary-button2 is MIDI learn.
360 boost::shared_ptr<RouteList> rl;
362 if (ev->button == 1) {
364 if (_route->route_group()) {
366 rl = _route->route_group()->route_list();
369 _mute_release->routes = rl;
372 rl.reset (new RouteList);
373 rl->push_back (_route);
376 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
381 /* plain click applies change to this route */
383 boost::shared_ptr<RouteList> rl (new RouteList);
384 rl->push_back (_route);
387 _mute_release->routes = rl;
390 _session->set_mute (rl, !_route->muted());
402 RouteUI::mute_release (GdkEventButton*)
404 if (!_i_am_the_modifier) {
406 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
407 delete _mute_release;
416 RouteUI::solo_press(GdkEventButton* ev)
418 /* ignore double/triple clicks */
420 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
424 multiple_solo_change = false;
426 if (!_i_am_the_modifier) {
428 if (Keyboard::is_context_menu_event (ev)) {
430 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
431 ! (solo_safe_led && solo_safe_led->is_visible())) {
433 if (solo_menu == 0) {
437 solo_menu->popup (1, ev->time);
442 if (Keyboard::is_button2_event (ev)) {
444 // Primary-button2 click is the midi binding click
445 // button2-click is "momentary"
447 if (solo_button->on_button_press_event (ev)) {
451 _solo_release = new SoloMuteRelease (_route->self_soloed());
454 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
456 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
458 /* Primary-Tertiary-click applies change to all routes */
461 _solo_release->routes = _session->get_routes ();
464 if (Config->get_solo_control_is_listen_control()) {
465 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
467 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
470 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
472 // Primary-Secondary-click: exclusively solo this track
475 _solo_release->exclusive = true;
477 boost::shared_ptr<RouteList> routes = _session->get_routes();
479 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
480 if ((*i)->soloed ()) {
481 _solo_release->routes_on->push_back (*i);
483 _solo_release->routes_off->push_back (*i);
488 if (Config->get_solo_control_is_listen_control()) {
489 /* ??? we need a just_one_listen() method */
491 _session->set_just_one_solo (_route, true);
494 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
496 // shift-click: toggle solo isolated status
498 _route->set_solo_isolated (!_route->solo_isolated(), this);
499 delete _solo_release;
502 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
504 /* Primary-button1: solo mix group.
505 NOTE: Primary-button2 is MIDI learn.
508 /* Primary-button1 applies change to the mix group even if it is not active
509 NOTE: Primary-button2 is MIDI learn.
512 boost::shared_ptr<RouteList> rl;
514 if (ev->button == 1) {
516 if (_route->route_group()) {
518 rl = _route->route_group()->route_list();
521 _solo_release->routes = rl;
524 rl.reset (new RouteList);
525 rl->push_back (_route);
528 if (Config->get_solo_control_is_listen_control()) {
529 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
531 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
537 /* click: solo this route */
539 boost::shared_ptr<RouteList> rl (new RouteList);
540 rl->push_back (route());
543 _solo_release->routes = rl;
546 if (Config->get_solo_control_is_listen_control()) {
547 _session->set_listen (rl, !_route->listening_via_monitor());
549 _session->set_solo (rl, !_route->self_soloed());
560 RouteUI::solo_release (GdkEventButton*)
562 if (!_i_am_the_modifier) {
566 if (_solo_release->exclusive) {
569 if (Config->get_solo_control_is_listen_control()) {
570 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
572 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
576 delete _solo_release;
585 RouteUI::rec_enable_press(GdkEventButton* ev)
587 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
591 if (!_session->engine().connected()) {
592 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
597 if (is_midi_track()) {
599 /* rec-enable button exits from step editing */
601 if (midi_track()->step_editing()) {
602 midi_track()->set_step_editing (false);
607 if (!_i_am_the_modifier && is_track() && rec_enable_button) {
609 if (Keyboard::is_button2_event (ev)) {
611 // do nothing on midi sigc::bind event
612 return rec_enable_button->on_button_press_event (ev);
614 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
616 _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
618 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
620 /* Primary-button1 applies change to the route group (even if it is not active)
621 NOTE: Primary-button2 is MIDI learn.
624 if (ev->button == 1) {
626 boost::shared_ptr<RouteList> rl;
628 if (_route->route_group()) {
630 rl = _route->route_group()->route_list();
633 rl.reset (new RouteList);
634 rl->push_back (_route);
637 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
640 } else if (Keyboard::is_context_menu_event (ev)) {
642 /* do this on release */
646 boost::shared_ptr<RouteList> rl (new RouteList);
647 rl->push_back (route());
648 _session->set_record_enabled (rl, !rec_enable_button->active_state());
656 RouteUI::monitoring_changed ()
658 update_monitoring_display ();
662 RouteUI::update_monitoring_display ()
668 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
674 MonitorState ms = t->monitoring_state();
676 if (t->monitoring_choice() & MonitorInput) {
677 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
679 if (ms & MonitoringInput) {
680 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
682 monitor_input_button->unset_active_state ();
686 if (t->monitoring_choice() & MonitorDisk) {
687 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
689 if (ms & MonitoringDisk) {
690 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
692 monitor_disk_button->unset_active_state ();
698 RouteUI::monitor_input_press(GdkEventButton*)
704 RouteUI::monitor_input_release(GdkEventButton* ev)
706 return monitor_release (ev, MonitorInput);
710 RouteUI::monitor_disk_press (GdkEventButton*)
716 RouteUI::monitor_disk_release (GdkEventButton* ev)
718 return monitor_release (ev, MonitorDisk);
722 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
724 if (ev->button != 1) {
728 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
735 boost::shared_ptr<RouteList> rl;
737 /* XXX for now, monitoring choices are orthogonal. cue monitoring
738 will follow in 3.X but requires mixing the input and playback (disk)
739 signal together, which requires yet more buffers.
742 if (t->monitoring_choice() & monitor_choice) {
743 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
745 /* this line will change when the options are non-orthogonal */
746 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
750 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
751 rl = _session->get_routes ();
753 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
754 if (_route->route_group() && _route->route_group()->is_monitoring()) {
755 rl = _route->route_group()->route_list();
757 rl.reset (new RouteList);
758 rl->push_back (route());
761 rl.reset (new RouteList);
762 rl->push_back (route());
765 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
771 RouteUI::build_record_menu ()
777 /* no rec-button context menu for non-MIDI tracks
780 if (is_midi_track()) {
781 record_menu = new Menu;
782 record_menu->set_name ("ArdourContextMenu");
784 using namespace Menu_Helpers;
785 MenuList& items = record_menu->items();
787 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
788 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
790 if (_route->record_enabled()) {
791 step_edit_item->set_sensitive (false);
794 step_edit_item->set_active (midi_track()->step_editing());
799 RouteUI::toggle_step_edit ()
801 if (!is_midi_track() || _route->record_enabled()) {
805 midi_track()->set_step_editing (step_edit_item->get_active());
809 RouteUI::step_edit_changed (bool yn)
812 if (rec_enable_button) {
813 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
816 start_step_editing ();
818 if (step_edit_item) {
819 step_edit_item->set_active (true);
824 if (rec_enable_button) {
825 rec_enable_button->unset_active_state ();
828 stop_step_editing ();
830 if (step_edit_item) {
831 step_edit_item->set_active (false);
837 RouteUI::rec_enable_release (GdkEventButton* ev)
839 if (Keyboard::is_context_menu_event (ev)) {
840 build_record_menu ();
842 record_menu->popup (1, ev->time);
851 RouteUI::build_sends_menu ()
853 using namespace Menu_Helpers;
855 sends_menu = new Menu;
856 sends_menu->set_name ("ArdourContextMenu");
857 MenuList& items = sends_menu->items();
860 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
864 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
868 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
872 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
876 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
880 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
883 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
887 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
890 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
891 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
892 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
897 RouteUI::create_sends (Placement p, bool include_buses)
899 _session->globally_add_internal_sends (_route, p, include_buses);
903 RouteUI::create_selected_sends (Placement p, bool include_buses)
905 boost::shared_ptr<RouteList> rlist (new RouteList);
906 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
908 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
909 RouteTimeAxisView* rtv;
911 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
912 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
913 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
914 rlist->push_back (rui->route());
920 _session->add_internal_sends (_route, p, rlist);
924 RouteUI::set_sends_gain_from_track ()
926 _session->globally_set_send_gains_from_track (_route);
930 RouteUI::set_sends_gain_to_zero ()
932 _session->globally_set_send_gains_to_zero (_route);
936 RouteUI::set_sends_gain_to_unity ()
938 _session->globally_set_send_gains_to_unity (_route);
942 RouteUI::show_sends_press(GdkEventButton* ev)
944 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
948 if (!_i_am_the_modifier && !is_track() && show_sends_button) {
950 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
952 // do nothing on midi sigc::bind event
955 } else if (Keyboard::is_context_menu_event (ev)) {
957 if (sends_menu == 0) {
961 sends_menu->popup (0, ev->time);
965 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
968 set_showing_sends_to (boost::shared_ptr<Route> ());
970 set_showing_sends_to (_route);
979 RouteUI::show_sends_release (GdkEventButton*)
985 RouteUI::send_blink (bool onoff)
987 if (!show_sends_button) {
992 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
994 show_sends_button->unset_active_state ();
998 Gtkmm2ext::ActiveState
999 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1001 if (r->is_master() || r->is_monitor()) {
1002 return Gtkmm2ext::Off;
1005 if (Config->get_solo_control_is_listen_control()) {
1007 if (r->listening_via_monitor()) {
1008 return Gtkmm2ext::ExplicitActive;
1010 return Gtkmm2ext::Off;
1016 if (!r->self_soloed()) {
1017 return Gtkmm2ext::ImplicitActive;
1019 return Gtkmm2ext::ExplicitActive;
1022 return Gtkmm2ext::Off;
1026 Gtkmm2ext::ActiveState
1027 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1029 if (r->is_master() || r->is_monitor()) {
1030 return Gtkmm2ext::Off;
1033 if (r->solo_isolated()) {
1034 return Gtkmm2ext::ExplicitActive;
1036 return Gtkmm2ext::Off;
1040 Gtkmm2ext::ActiveState
1041 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1043 if (r->is_master() || r->is_monitor()) {
1044 return Gtkmm2ext::Off;
1047 if (r->solo_safe()) {
1048 return Gtkmm2ext::ExplicitActive;
1050 return Gtkmm2ext::Off;
1055 RouteUI::update_solo_display ()
1057 bool yn = _route->solo_safe ();
1059 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1060 solo_safe_check->set_active (yn);
1063 yn = _route->solo_isolated ();
1065 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1066 solo_isolated_check->set_active (yn);
1069 set_button_names ();
1071 if (solo_isolated_led) {
1072 if (_route->solo_isolated()) {
1073 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1075 solo_isolated_led->unset_active_state ();
1079 if (solo_safe_led) {
1080 if (_route->solo_safe()) {
1081 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1083 solo_safe_led->unset_active_state ();
1087 solo_button->set_active_state (solo_active_state (_route));
1089 /* some changes to solo status can affect mute display, so catch up
1092 update_mute_display ();
1096 RouteUI::solo_changed_so_update_mute ()
1098 update_mute_display ();
1102 RouteUI::mute_changed(void* /*src*/)
1104 update_mute_display ();
1108 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1110 if (r->is_monitor()) {
1111 return ActiveState(0);
1115 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1119 return Gtkmm2ext::ExplicitActive;
1120 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1121 /* master is NEVER muted by others */
1122 return Gtkmm2ext::ImplicitActive;
1124 /* no mute at all */
1125 return Gtkmm2ext::Off;
1132 return Gtkmm2ext::ExplicitActive;
1134 /* no mute at all */
1135 return Gtkmm2ext::Off;
1139 return ActiveState(0);
1143 RouteUI::update_mute_display ()
1149 mute_button->set_active_state (mute_active_state (_session, _route));
1153 RouteUI::route_rec_enable_changed ()
1155 update_rec_display ();
1156 update_monitoring_display ();
1160 RouteUI::session_rec_enable_changed ()
1162 update_rec_display ();
1163 update_monitoring_display ();
1167 RouteUI::update_rec_display ()
1169 if (!rec_enable_button || !_route) {
1173 if (_route->record_enabled()) {
1174 switch (_session->record_status ()) {
1175 case Session::Recording:
1176 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1179 case Session::Disabled:
1180 case Session::Enabled:
1181 rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1186 if (step_edit_item) {
1187 step_edit_item->set_sensitive (false);
1191 rec_enable_button->unset_active_state ();
1193 if (step_edit_item) {
1194 step_edit_item->set_sensitive (true);
1199 check_rec_enable_sensitivity ();
1203 RouteUI::build_solo_menu (void)
1205 using namespace Menu_Helpers;
1207 solo_menu = new Menu;
1208 solo_menu->set_name ("ArdourContextMenu");
1209 MenuList& items = solo_menu->items();
1210 Gtk::CheckMenuItem* check;
1212 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1213 check->set_active (_route->solo_isolated());
1214 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1215 items.push_back (CheckMenuElem(*check));
1216 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1219 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1220 check->set_active (_route->solo_safe());
1221 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1222 items.push_back (CheckMenuElem(*check));
1223 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1226 //items.push_back (SeparatorElem());
1227 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1232 RouteUI::build_mute_menu(void)
1234 using namespace Menu_Helpers;
1236 mute_menu = new Menu;
1237 mute_menu->set_name ("ArdourContextMenu");
1239 MenuList& items = mute_menu->items();
1241 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1242 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1243 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1244 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1245 pre_fader_mute_check->show_all();
1247 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1248 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1249 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1250 items.push_back (CheckMenuElem(*post_fader_mute_check));
1251 post_fader_mute_check->show_all();
1253 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1254 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1255 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1256 items.push_back (CheckMenuElem(*listen_mute_check));
1257 listen_mute_check->show_all();
1259 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1260 init_mute_menu(MuteMaster::Main, main_mute_check);
1261 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1262 items.push_back (CheckMenuElem(*main_mute_check));
1263 main_mute_check->show_all();
1265 //items.push_back (SeparatorElem());
1266 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1268 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1272 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1274 check->set_active (_route->mute_points() & mp);
1278 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1280 if (check->get_active()) {
1281 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1283 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1288 RouteUI::muting_change ()
1290 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1293 MuteMaster::MutePoint current = _route->mute_points ();
1295 yn = (current & MuteMaster::PreFader);
1297 if (pre_fader_mute_check->get_active() != yn) {
1298 pre_fader_mute_check->set_active (yn);
1301 yn = (current & MuteMaster::PostFader);
1303 if (post_fader_mute_check->get_active() != yn) {
1304 post_fader_mute_check->set_active (yn);
1307 yn = (current & MuteMaster::Listen);
1309 if (listen_mute_check->get_active() != yn) {
1310 listen_mute_check->set_active (yn);
1313 yn = (current & MuteMaster::Main);
1315 if (main_mute_check->get_active() != yn) {
1316 main_mute_check->set_active (yn);
1321 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1323 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1327 bool view = solo_isolated_led->active_state();
1328 bool model = _route->solo_isolated();
1330 /* called BEFORE the view has changed */
1332 if (ev->button == 1) {
1333 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1336 /* disable isolate for all routes */
1337 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1341 if (model == view) {
1343 /* flip just this route */
1345 boost::shared_ptr<RouteList> rl (new RouteList);
1346 rl->push_back (_route);
1347 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1356 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1358 if (ev->button == 1) {
1359 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1366 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1368 bool view = check->get_active();
1369 bool model = _route->solo_isolated();
1371 /* called AFTER the view has changed */
1373 if (model != view) {
1374 _route->set_solo_isolated (view, this);
1379 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1381 _route->set_solo_safe (check->get_active(), this);
1384 /** Ask the user to choose a colour, and then set all selected tracks
1388 RouteUI::choose_color ()
1391 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1394 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1395 boost::bind (&RouteUI::set_color, _1, color)
1400 /** Set the route's own color. This may not be used for display if
1401 * the route is in a group which shares its color with its routes.
1404 RouteUI::set_color (const Gdk::Color & c)
1406 /* leave _color alone in the group case so that tracks can retain their
1407 * own pre-group colors.
1412 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1414 /* note: we use the route state ID here so that color is the same for both
1415 the time axis view and the mixer strip
1418 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1419 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1422 /** @return GUI state ID for things that are common to the route in all its representations */
1424 RouteUI::route_state_id () const
1426 return string_compose (X_("route %1"), _route->id().to_s());
1430 RouteUI::set_color_from_route ()
1432 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1440 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1443 _color.set_green (g);
1444 _color.set_blue (b);
1450 RouteUI::remove_this_route (bool apply_to_selection)
1452 if (apply_to_selection) {
1453 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1455 if ((route()->is_master() || route()->is_monitor()) &&
1456 !Config->get_allow_special_bus_removal()) {
1457 MessageDialog msg (_("That would be bad news ...."),
1461 msg.set_secondary_text (string_compose (_(
1462 "Removing the master or monitor bus is such a bad idea\n\
1463 that %1 is not going to allow it.\n\
1465 If you really want to do this sort of thing\n\
1466 edit your ardour.rc file to set the\n\
1467 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1474 vector<string> choices;
1478 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());
1480 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());
1483 choices.push_back (_("No, do nothing."));
1484 choices.push_back (_("Yes, remove it."));
1488 title = _("Remove track");
1490 title = _("Remove bus");
1493 Choice prompter (title, prompt, choices);
1495 if (prompter.run () == 1) {
1496 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1502 RouteUI::idle_remove_this_route (RouteUI *rui)
1504 rui->_session->remove_route (rui->route());
1508 /** @return true if this name should be used for the route, otherwise false */
1510 RouteUI::verify_new_route_name (const std::string& name)
1512 if (name.find (':') == string::npos) {
1516 MessageDialog colon_msg (
1517 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1518 false, MESSAGE_QUESTION, BUTTONS_NONE
1521 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1522 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1524 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1528 RouteUI::route_rename ()
1530 ArdourPrompter name_prompter (true);
1535 name_prompter.set_title (_("Rename Track"));
1537 name_prompter.set_title (_("Rename Bus"));
1539 name_prompter.set_prompt (_("New name:"));
1540 name_prompter.set_initial_text (_route->name());
1541 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1542 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1543 name_prompter.show_all ();
1546 switch (name_prompter.run ()) {
1547 case Gtk::RESPONSE_ACCEPT:
1548 name_prompter.get_result (result);
1549 name_prompter.hide ();
1550 if (result.length()) {
1551 if (verify_new_route_name (result)) {
1552 _route->set_name (result);
1555 /* back to name prompter */
1559 /* nothing entered, just get out of here */
1574 RouteUI::property_changed (const PropertyChange& what_changed)
1576 if (what_changed.contains (ARDOUR::Properties::name)) {
1577 name_label.set_text (_route->name());
1582 RouteUI::set_route_active (bool a, bool apply_to_selection)
1584 if (apply_to_selection) {
1585 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1587 _route->set_active (a, this);
1592 RouteUI::toggle_denormal_protection ()
1594 if (denormal_menu_item) {
1598 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1600 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1601 _route->set_denormal_protection (x);
1607 RouteUI::denormal_protection_changed ()
1609 if (denormal_menu_item) {
1610 denormal_menu_item->set_active (_route->denormal_protection());
1615 RouteUI::disconnect_input ()
1617 _route->input()->disconnect (this);
1621 RouteUI::disconnect_output ()
1623 _route->output()->disconnect (this);
1627 RouteUI::is_track () const
1629 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1632 boost::shared_ptr<Track>
1633 RouteUI::track() const
1635 return boost::dynamic_pointer_cast<Track>(_route);
1639 RouteUI::is_audio_track () const
1641 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1644 boost::shared_ptr<AudioTrack>
1645 RouteUI::audio_track() const
1647 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1651 RouteUI::is_midi_track () const
1653 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1656 boost::shared_ptr<MidiTrack>
1657 RouteUI::midi_track() const
1659 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1663 RouteUI::has_audio_outputs () const
1665 return (_route->n_outputs().n_audio() > 0);
1669 RouteUI::name() const
1671 return _route->name();
1675 RouteUI::map_frozen ()
1677 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1679 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1682 switch (at->freeze_state()) {
1683 case AudioTrack::Frozen:
1684 rec_enable_button->set_sensitive (false);
1687 rec_enable_button->set_sensitive (true);
1694 RouteUI::adjust_latency ()
1696 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1700 RouteUI::save_as_template ()
1703 std::string safe_name;
1706 path = ARDOUR::user_route_template_directory ();
1708 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1709 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1713 Prompter p (true); // modal
1715 p.set_title (_("Save As Template"));
1716 p.set_prompt (_("Template name:"));
1717 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1719 case RESPONSE_ACCEPT:
1726 p.get_result (name, true);
1728 safe_name = legalize_for_path (name);
1729 safe_name += template_suffix;
1731 path = Glib::build_filename (path, safe_name);
1733 _route->save_as_template (path, name);
1737 RouteUI::check_rec_enable_sensitivity ()
1739 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1740 rec_enable_button->set_sensitive (false);
1742 rec_enable_button->set_sensitive (true);
1745 update_monitoring_display ();
1749 RouteUI::parameter_changed (string const & p)
1751 /* this handles RC and per-session parameter changes */
1753 if (p == "disable-disarm-during-roll") {
1754 check_rec_enable_sensitivity ();
1755 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1756 set_button_names ();
1757 } else if (p == "auto-input") {
1758 update_monitoring_display ();
1763 RouteUI::step_gain_up ()
1765 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1769 RouteUI::page_gain_up ()
1771 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1775 RouteUI::step_gain_down ()
1777 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1781 RouteUI::page_gain_down ()
1783 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1787 RouteUI::open_remote_control_id_dialog ()
1789 ArdourDialog dialog (_("Remote Control ID"));
1790 SpinButton* spin = 0;
1792 dialog.get_vbox()->set_border_width (18);
1794 if (Config->get_remote_model() == UserOrdered) {
1795 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1797 HBox* hbox = manage (new HBox);
1798 hbox->set_spacing (6);
1799 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1800 spin = manage (new SpinButton);
1801 spin->set_digits (0);
1802 spin->set_increments (1, 10);
1803 spin->set_range (0, limit);
1804 spin->set_value (_route->remote_control_id());
1805 hbox->pack_start (*spin);
1806 dialog.get_vbox()->pack_start (*hbox);
1808 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1809 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1811 Label* l = manage (new Label());
1812 if (_route->is_master() || _route->is_monitor()) {
1813 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1814 "The remote control ID of %3 cannot be changed."),
1815 Glib::Markup::escape_text (_route->name()),
1816 _route->remote_control_id(),
1817 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1819 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1820 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1821 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1822 (is_track() ? _("track") : _("bus")),
1823 _route->remote_control_id(),
1824 "<span size=\"small\" style=\"italic\">",
1826 Glib::Markup::escape_text (_route->name()),
1829 dialog.get_vbox()->pack_start (*l);
1830 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1834 int const r = dialog.run ();
1836 if (r == RESPONSE_ACCEPT && spin) {
1837 _route->set_remote_control_id (spin->get_value_as_int ());
1842 RouteUI::setup_invert_buttons ()
1844 /* remove old invert buttons */
1845 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1846 _invert_button_box.remove (**i);
1849 _invert_buttons.clear ();
1851 if (!_route || !_route->input()) {
1855 uint32_t const N = _route->input()->n_ports().n_audio ();
1857 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1859 for (uint32_t i = 0; i < to_add; ++i) {
1860 ArdourButton* b = manage (new ArdourButton);
1861 b->set_size_request(20,20);
1862 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1863 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1865 b->set_name (X_("invert button"));
1868 b->set_text (string_compose (X_("Ø (%1)"), N));
1870 b->set_text (X_("Ø"));
1873 b->set_text (string_compose (X_("Ø%1"), i + 1));
1876 if (N <= _max_invert_buttons) {
1877 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));
1879 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1882 _invert_buttons.push_back (b);
1883 _invert_button_box.pack_start (*b);
1886 _invert_button_box.set_spacing (1);
1887 _invert_button_box.show_all ();
1891 RouteUI::set_invert_button_state ()
1893 ++_i_am_the_modifier;
1895 uint32_t const N = _route->input()->n_ports().n_audio();
1896 if (N > _max_invert_buttons) {
1898 /* One button for many channels; explicit active if all channels are inverted,
1899 implicit active if some are, off if none are.
1902 ArdourButton* b = _invert_buttons.front ();
1904 if (_route->phase_invert().count() == _route->phase_invert().size()) {
1905 b->set_active_state (Gtkmm2ext::ExplicitActive);
1906 } else if (_route->phase_invert().any()) {
1907 b->set_active_state (Gtkmm2ext::ImplicitActive);
1909 b->set_active_state (Gtkmm2ext::Off);
1914 /* One button per channel; just set active */
1917 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1918 (*i)->set_active (_route->phase_invert (j));
1923 --_i_am_the_modifier;
1927 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1929 if (ev->button == 1 && i < _invert_buttons.size()) {
1930 uint32_t const N = _route->input()->n_ports().n_audio ();
1931 if (N <= _max_invert_buttons) {
1932 /* left-click inverts phase so long as we have a button per channel */
1933 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1942 RouteUI::invert_press (GdkEventButton* ev)
1944 using namespace Menu_Helpers;
1946 uint32_t const N = _route->input()->n_ports().n_audio();
1947 if (N <= _max_invert_buttons && ev->button != 3) {
1948 /* If we have an invert button per channel, we only pop
1949 up a menu on right-click; left click is handled
1955 delete _invert_menu;
1956 _invert_menu = new Menu;
1957 _invert_menu->set_name ("ArdourContextMenu");
1958 MenuList& items = _invert_menu->items ();
1960 for (uint32_t i = 0; i < N; ++i) {
1961 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1962 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
1963 ++_i_am_the_modifier;
1964 e->set_active (_route->phase_invert (i));
1965 --_i_am_the_modifier;
1968 _invert_menu->popup (0, ev->time);
1974 RouteUI::invert_menu_toggled (uint32_t c)
1976 if (_i_am_the_modifier) {
1980 _route->set_phase_invert (c, !_route->phase_invert (c));
1984 RouteUI::set_invert_sensitive (bool yn)
1986 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1987 (*b)->set_sensitive (yn);
1992 RouteUI::request_redraw ()
1995 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1999 /** The Route's gui_changed signal has been emitted */
2001 RouteUI::route_gui_changed (string what_changed)
2003 if (what_changed == "color") {
2004 if (set_color_from_route () == 0) {
2005 route_color_changed ();
2010 /** @return the color that this route should use; it maybe its own,
2011 or it maybe that of its route group.
2014 RouteUI::color () const
2016 RouteGroup* g = _route->route_group ();
2018 if (g && g->is_color()) {
2020 set_color_from_rgba (c, GroupTabs::group_color (g));
2028 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2030 _showing_sends_to = send_to;
2031 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2035 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2037 if (_route == send_to) {
2038 show_sends_button->set_active (true);
2039 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2041 show_sends_button->set_active (false);
2042 send_blink_connection.disconnect ();
2047 RouteUI::route_group() const
2049 return _route->route_group();