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>
26 #include <gtkmm2ext/utils.h>
28 #include "ardour/route_group.h"
29 #include "ardour/dB.h"
30 #include "pbd/memento_command.h"
31 #include "pbd/stacktrace.h"
32 #include "pbd/controllable.h"
33 #include "pbd/enumwriter.h"
35 #include "ardour_ui.h"
38 #include "ardour_button.h"
42 #include "gui_thread.h"
43 #include "ardour_dialog.h"
44 #include "latency_gui.h"
45 #include "mixer_strip.h"
46 #include "automation_time_axis.h"
47 #include "route_time_axis.h"
48 #include "group_tabs.h"
50 #include "ardour/audio_track.h"
51 #include "ardour/audioengine.h"
52 #include "ardour/filename_extensions.h"
53 #include "ardour/midi_track.h"
54 #include "ardour/internal_send.h"
55 #include "ardour/send.h"
56 #include "ardour/route.h"
57 #include "ardour/session.h"
58 #include "ardour/template_utils.h"
62 using namespace Gtkmm2ext;
63 using namespace ARDOUR;
64 using namespace ARDOUR_UI_UTILS;
67 uint32_t RouteUI::_max_invert_buttons = 3;
68 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
69 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
71 static const int _button_vpad = 2;
73 RouteUI::RouteUI (ARDOUR::Session* sess)
89 _route.reset (); /* drop reference to route, so that it can be cleaned up */
90 route_connections.drop_connections ();
96 delete comment_window;
97 delete input_selector;
98 delete output_selector;
105 self_destruct = true;
111 pre_fader_mute_check = 0;
112 post_fader_mute_check = 0;
113 listen_mute_check = 0;
116 solo_isolated_check = 0;
117 solo_isolated_led = 0;
121 denormal_menu_item = 0;
123 multiple_mute_change = false;
124 multiple_solo_change = false;
125 _i_am_the_modifier = 0;
130 setup_invert_buttons ();
132 mute_button = manage (new ArdourButton);
133 mute_button->set_name ("mute button");
134 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
136 solo_button = manage (new ArdourButton);
137 solo_button->set_name ("solo button");
138 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
139 solo_button->set_no_show_all (true);
141 rec_enable_button = manage (new ArdourButton);
142 rec_enable_button->set_name ("record enable button");
143 // rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
144 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
146 show_sends_button = manage (new ArdourButton);
147 show_sends_button->set_name ("send alert button");
148 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
150 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
151 monitor_input_button->set_name ("monitor button");
152 monitor_input_button->set_text (_("In"));
153 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
154 monitor_input_button->set_no_show_all (true);
156 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
157 monitor_disk_button->set_name ("monitor button");
158 monitor_disk_button->set_text (_("Disk"));
159 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
160 monitor_disk_button->set_no_show_all (true);
162 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
163 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
164 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
166 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
167 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
169 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
170 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
172 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
173 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
175 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
176 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
177 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
178 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
180 monitor_input_button->set_distinct_led_click (false);
181 monitor_disk_button->set_distinct_led_click (false);
183 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
184 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
186 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
187 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
189 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
195 route_connections.drop_connections ();
203 denormal_menu_item = 0;
207 RouteUI::self_delete ()
213 RouteUI::set_route (boost::shared_ptr<Route> rp)
219 if (set_color_from_route()) {
220 set_color (unique_random_color());
224 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
227 delete input_selector;
230 delete output_selector;
233 mute_button->set_controllable (_route->mute_control());
234 solo_button->set_controllable (_route->solo_control());
236 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
237 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
239 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
241 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
242 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
243 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
244 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
246 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
247 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
249 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
250 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
252 if (_session->writable() && is_track()) {
253 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
255 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
257 rec_enable_button->show();
258 rec_enable_button->set_controllable (t->rec_enable_control());
260 if (is_midi_track()) {
261 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
262 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
267 /* this will work for busses and tracks, and needs to be called to
268 set up the name entry/name label display.
271 update_rec_display ();
274 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
275 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
277 update_monitoring_display ();
280 mute_button->unset_flags (Gtk::CAN_FOCUS);
281 solo_button->unset_flags (Gtk::CAN_FOCUS);
285 if (_route->is_monitor() || _route->is_master()) {
286 solo_button->hide ();
293 setup_invert_buttons ();
294 set_invert_button_state ();
296 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
297 bus_send_display_changed (s);
299 update_mute_display ();
300 update_solo_display ();
304 RouteUI::polarity_changed ()
310 set_invert_button_state ();
314 RouteUI::mute_press (GdkEventButton* ev)
316 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
320 multiple_mute_change = false;
322 if (Keyboard::is_context_menu_event (ev)) {
328 mute_menu->popup(0,ev->time);
332 if (Keyboard::is_button2_event (ev)) {
333 // Primary-button2 click is the midi binding click
334 // button2-click is "momentary"
337 if (mute_button->on_button_press_event (ev)) {
341 _mute_release = new SoloMuteRelease (_route->muted ());
344 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
346 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
348 /* toggle mute on everything (but
349 * exclude the master and monitor)
351 * because we are going to erase
352 * elements of the list we need to work
356 boost::shared_ptr<RouteList> copy (new RouteList);
358 *copy = *_session->get_routes ();
360 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
361 if ((*i)->is_master() || (*i)->is_monitor()) {
369 _mute_release->routes = copy;
373 _session->set_mute (copy, !_route->muted());
375 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
377 /* Primary-button1 applies change to the mix group even if it is not active
378 NOTE: Primary-button2 is MIDI learn.
381 boost::shared_ptr<RouteList> rl;
383 if (ev->button == 1) {
385 if (_route->route_group()) {
387 rl = _route->route_group()->route_list();
390 _mute_release->routes = rl;
393 rl.reset (new RouteList);
394 rl->push_back (_route);
398 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
403 /* plain click applies change to this route */
405 boost::shared_ptr<RouteList> rl (new RouteList);
406 rl->push_back (_route);
409 _mute_release->routes = rl;
412 _session->set_mute (rl, !_route->muted());
422 RouteUI::mute_release (GdkEventButton*)
426 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
427 delete _mute_release;
435 RouteUI::edit_output_configuration ()
437 if (output_selector == 0) {
439 boost::shared_ptr<Send> send;
440 boost::shared_ptr<IO> output;
442 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
443 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
444 output = send->output();
446 output = _route->output ();
449 output = _route->output ();
452 output_selector = new IOSelectorWindow (_session, output);
455 if (output_selector->is_visible()) {
456 output_selector->get_toplevel()->get_window()->raise();
458 output_selector->present ();
461 output_selector->set_keep_above (true);
465 RouteUI::edit_input_configuration ()
467 if (input_selector == 0) {
468 input_selector = new IOSelectorWindow (_session, _route->input());
471 if (input_selector->is_visible()) {
472 input_selector->get_toplevel()->get_window()->raise();
474 input_selector->present ();
477 input_selector->set_keep_above (true);
481 RouteUI::solo_press(GdkEventButton* ev)
483 /* ignore double/triple clicks */
485 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
489 multiple_solo_change = false;
491 if (Keyboard::is_context_menu_event (ev)) {
493 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
494 ! (solo_safe_led && solo_safe_led->is_visible())) {
496 if (solo_menu == 0) {
500 solo_menu->popup (1, ev->time);
505 if (Keyboard::is_button2_event (ev)) {
507 // Primary-button2 click is the midi binding click
508 // button2-click is "momentary"
510 if (solo_button->on_button_press_event (ev)) {
514 _solo_release = new SoloMuteRelease (_route->self_soloed());
517 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
519 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
521 /* Primary-Tertiary-click applies change to all routes */
524 _solo_release->routes = _session->get_routes ();
528 if (Config->get_solo_control_is_listen_control()) {
529 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
531 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
534 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
536 // Primary-Secondary-click: exclusively solo this track
539 _solo_release->exclusive = true;
541 boost::shared_ptr<RouteList> routes = _session->get_routes();
543 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
544 if ((*i)->soloed ()) {
545 _solo_release->routes_on->push_back (*i);
547 _solo_release->routes_off->push_back (*i);
552 if (Config->get_solo_control_is_listen_control()) {
553 /* ??? we need a just_one_listen() method */
556 _session->set_just_one_solo (_route, true);
559 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
561 // shift-click: toggle solo isolated status
563 _route->set_solo_isolated (!_route->solo_isolated(), this);
564 delete _solo_release;
567 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
569 /* Primary-button1: solo mix group.
570 NOTE: Primary-button2 is MIDI learn.
573 /* Primary-button1 applies change to the mix group even if it is not active
574 NOTE: Primary-button2 is MIDI learn.
577 boost::shared_ptr<RouteList> rl;
579 if (ev->button == 1) {
581 if (_route->route_group()) {
583 rl = _route->route_group()->route_list();
586 _solo_release->routes = rl;
589 rl.reset (new RouteList);
590 rl->push_back (_route);
594 if (Config->get_solo_control_is_listen_control()) {
595 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
597 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
603 /* click: solo this route */
605 boost::shared_ptr<RouteList> rl (new RouteList);
606 rl->push_back (route());
609 _solo_release->routes = rl;
613 if (Config->get_solo_control_is_listen_control()) {
614 _session->set_listen (rl, !_route->listening_via_monitor());
616 _session->set_solo (rl, !_route->self_soloed());
626 RouteUI::solo_release (GdkEventButton*)
630 if (_solo_release->exclusive) {
634 if (Config->get_solo_control_is_listen_control()) {
635 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
637 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
641 delete _solo_release;
649 RouteUI::rec_enable_press(GdkEventButton* ev)
651 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
655 if (!_session->engine().connected()) {
656 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
661 if (is_midi_track()) {
663 /* rec-enable button exits from step editing */
665 if (midi_track()->step_editing()) {
666 midi_track()->set_step_editing (false);
671 if (is_track() && rec_enable_button) {
673 if (Keyboard::is_button2_event (ev)) {
675 // do nothing on midi sigc::bind event
676 return rec_enable_button->on_button_press_event (ev);
678 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
681 _session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
683 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
685 /* Primary-button1 applies change to the route group (even if it is not active)
686 NOTE: Primary-button2 is MIDI learn.
689 if (ev->button == 1) {
691 boost::shared_ptr<RouteList> rl;
693 if (_route->route_group()) {
695 rl = _route->route_group()->route_list();
698 rl.reset (new RouteList);
699 rl->push_back (_route);
703 _session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
706 } else if (Keyboard::is_context_menu_event (ev)) {
708 /* do this on release */
712 boost::shared_ptr<RouteList> rl (new RouteList);
713 rl->push_back (route());
715 _session->set_record_enabled (rl, !rec_enable_button->active_state());
723 RouteUI::monitoring_changed ()
725 update_monitoring_display ();
729 RouteUI::update_monitoring_display ()
735 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
741 MonitorState ms = t->monitoring_state();
743 if (t->monitoring_choice() & MonitorInput) {
744 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
746 if (ms & MonitoringInput) {
747 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
749 monitor_input_button->unset_active_state ();
753 if (t->monitoring_choice() & MonitorDisk) {
754 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
756 if (ms & MonitoringDisk) {
757 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
759 monitor_disk_button->unset_active_state ();
765 RouteUI::monitor_input_press(GdkEventButton*)
771 RouteUI::monitor_input_release(GdkEventButton* ev)
773 return monitor_release (ev, MonitorInput);
777 RouteUI::monitor_disk_press (GdkEventButton*)
783 RouteUI::monitor_disk_release (GdkEventButton* ev)
785 return monitor_release (ev, MonitorDisk);
789 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
791 if (ev->button != 1) {
795 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
802 boost::shared_ptr<RouteList> rl;
804 /* XXX for now, monitoring choices are orthogonal. cue monitoring
805 will follow in 3.X but requires mixing the input and playback (disk)
806 signal together, which requires yet more buffers.
809 if (t->monitoring_choice() & monitor_choice) {
810 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
812 /* this line will change when the options are non-orthogonal */
813 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
817 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
818 rl = _session->get_routes ();
820 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
821 if (_route->route_group() && _route->route_group()->is_monitoring()) {
822 rl = _route->route_group()->route_list();
824 rl.reset (new RouteList);
825 rl->push_back (route());
828 rl.reset (new RouteList);
829 rl->push_back (route());
833 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
839 RouteUI::build_record_menu ()
845 /* no rec-button context menu for non-MIDI tracks
848 if (is_midi_track()) {
849 record_menu = new Menu;
850 record_menu->set_name ("ArdourContextMenu");
852 using namespace Menu_Helpers;
853 MenuList& items = record_menu->items();
855 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
856 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
858 if (_route->record_enabled()) {
859 step_edit_item->set_sensitive (false);
862 step_edit_item->set_active (midi_track()->step_editing());
867 RouteUI::toggle_step_edit ()
869 if (!is_midi_track() || _route->record_enabled()) {
873 midi_track()->set_step_editing (step_edit_item->get_active());
877 RouteUI::step_edit_changed (bool yn)
880 if (rec_enable_button) {
881 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
884 start_step_editing ();
886 if (step_edit_item) {
887 step_edit_item->set_active (true);
892 if (rec_enable_button) {
893 rec_enable_button->unset_active_state ();
896 stop_step_editing ();
898 if (step_edit_item) {
899 step_edit_item->set_active (false);
905 RouteUI::rec_enable_release (GdkEventButton* ev)
907 if (Keyboard::is_context_menu_event (ev)) {
908 build_record_menu ();
910 record_menu->popup (1, ev->time);
919 RouteUI::build_sends_menu ()
921 using namespace Menu_Helpers;
923 sends_menu = new Menu;
924 sends_menu->set_name ("ArdourContextMenu");
925 MenuList& items = sends_menu->items();
928 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
932 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
936 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
940 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
944 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
948 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
951 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
955 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
958 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
959 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
960 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
965 RouteUI::create_sends (Placement p, bool include_buses)
967 _session->globally_add_internal_sends (_route, p, include_buses);
971 RouteUI::create_selected_sends (Placement p, bool include_buses)
973 boost::shared_ptr<RouteList> rlist (new RouteList);
974 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
976 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
977 RouteTimeAxisView* rtv;
979 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
980 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
981 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
982 rlist->push_back (rui->route());
988 _session->add_internal_sends (_route, p, rlist);
992 RouteUI::set_sends_gain_from_track ()
994 _session->globally_set_send_gains_from_track (_route);
998 RouteUI::set_sends_gain_to_zero ()
1000 _session->globally_set_send_gains_to_zero (_route);
1004 RouteUI::set_sends_gain_to_unity ()
1006 _session->globally_set_send_gains_to_unity (_route);
1010 RouteUI::show_sends_press(GdkEventButton* ev)
1012 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1016 if (!is_track() && show_sends_button) {
1018 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1020 // do nothing on midi sigc::bind event
1023 } else if (Keyboard::is_context_menu_event (ev)) {
1025 if (sends_menu == 0) {
1026 build_sends_menu ();
1029 sends_menu->popup (0, ev->time);
1033 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1036 set_showing_sends_to (boost::shared_ptr<Route> ());
1038 set_showing_sends_to (_route);
1047 RouteUI::show_sends_release (GdkEventButton*)
1053 RouteUI::send_blink (bool onoff)
1055 if (!show_sends_button) {
1060 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1062 show_sends_button->unset_active_state ();
1066 Gtkmm2ext::ActiveState
1067 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1069 if (r->is_master() || r->is_monitor()) {
1070 return Gtkmm2ext::Off;
1073 if (Config->get_solo_control_is_listen_control()) {
1075 if (r->listening_via_monitor()) {
1076 return Gtkmm2ext::ExplicitActive;
1078 return Gtkmm2ext::Off;
1084 if (!r->self_soloed()) {
1085 return Gtkmm2ext::ImplicitActive;
1087 return Gtkmm2ext::ExplicitActive;
1090 return Gtkmm2ext::Off;
1094 Gtkmm2ext::ActiveState
1095 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1097 if (r->is_master() || r->is_monitor()) {
1098 return Gtkmm2ext::Off;
1101 if (r->solo_isolated()) {
1102 return Gtkmm2ext::ExplicitActive;
1104 return Gtkmm2ext::Off;
1108 Gtkmm2ext::ActiveState
1109 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1111 if (r->is_master() || r->is_monitor()) {
1112 return Gtkmm2ext::Off;
1115 if (r->solo_safe()) {
1116 return Gtkmm2ext::ExplicitActive;
1118 return Gtkmm2ext::Off;
1123 RouteUI::update_solo_display ()
1125 bool yn = _route->solo_safe ();
1127 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1128 solo_safe_check->set_active (yn);
1131 yn = _route->solo_isolated ();
1133 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1134 solo_isolated_check->set_active (yn);
1137 set_button_names ();
1139 if (solo_isolated_led) {
1140 if (_route->solo_isolated()) {
1141 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1143 solo_isolated_led->unset_active_state ();
1147 if (solo_safe_led) {
1148 if (_route->solo_safe()) {
1149 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1151 solo_safe_led->unset_active_state ();
1155 solo_button->set_active_state (solo_active_state (_route));
1157 /* some changes to solo status can affect mute display, so catch up
1160 update_mute_display ();
1164 RouteUI::solo_changed_so_update_mute ()
1166 update_mute_display ();
1170 RouteUI::mute_changed(void* /*src*/)
1172 update_mute_display ();
1176 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1178 if (r->is_monitor()) {
1179 return ActiveState(0);
1183 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1187 return Gtkmm2ext::ExplicitActive;
1188 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1189 /* master is NEVER muted by others */
1190 return Gtkmm2ext::ImplicitActive;
1192 /* no mute at all */
1193 return Gtkmm2ext::Off;
1200 return Gtkmm2ext::ExplicitActive;
1202 /* no mute at all */
1203 return Gtkmm2ext::Off;
1207 return ActiveState(0);
1211 RouteUI::update_mute_display ()
1217 mute_button->set_active_state (mute_active_state (_session, _route));
1221 RouteUI::route_rec_enable_changed ()
1223 update_rec_display ();
1224 update_monitoring_display ();
1228 RouteUI::session_rec_enable_changed ()
1230 update_rec_display ();
1231 update_monitoring_display ();
1235 RouteUI::update_rec_display ()
1237 if (!rec_enable_button || !_route) {
1241 if (_route->record_enabled()) {
1242 switch (_session->record_status ()) {
1243 case Session::Recording:
1244 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1247 case Session::Disabled:
1248 case Session::Enabled:
1249 rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1254 if (step_edit_item) {
1255 step_edit_item->set_sensitive (false);
1259 rec_enable_button->unset_active_state ();
1261 if (step_edit_item) {
1262 step_edit_item->set_sensitive (true);
1267 check_rec_enable_sensitivity ();
1271 RouteUI::build_solo_menu (void)
1273 using namespace Menu_Helpers;
1275 solo_menu = new Menu;
1276 solo_menu->set_name ("ArdourContextMenu");
1277 MenuList& items = solo_menu->items();
1278 Gtk::CheckMenuItem* check;
1280 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1281 check->set_active (_route->solo_isolated());
1282 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1283 items.push_back (CheckMenuElem(*check));
1284 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1287 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1288 check->set_active (_route->solo_safe());
1289 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1290 items.push_back (CheckMenuElem(*check));
1291 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1294 //items.push_back (SeparatorElem());
1295 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1300 RouteUI::build_mute_menu(void)
1302 using namespace Menu_Helpers;
1304 mute_menu = new Menu;
1305 mute_menu->set_name ("ArdourContextMenu");
1307 MenuList& items = mute_menu->items();
1309 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1310 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1311 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1312 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1313 pre_fader_mute_check->show_all();
1315 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1316 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1317 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1318 items.push_back (CheckMenuElem(*post_fader_mute_check));
1319 post_fader_mute_check->show_all();
1321 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1322 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1323 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1324 items.push_back (CheckMenuElem(*listen_mute_check));
1325 listen_mute_check->show_all();
1327 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1328 init_mute_menu(MuteMaster::Main, main_mute_check);
1329 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1330 items.push_back (CheckMenuElem(*main_mute_check));
1331 main_mute_check->show_all();
1333 //items.push_back (SeparatorElem());
1334 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1336 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1340 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1342 check->set_active (_route->mute_points() & mp);
1346 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1348 if (check->get_active()) {
1349 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1351 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1356 RouteUI::muting_change ()
1358 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1361 MuteMaster::MutePoint current = _route->mute_points ();
1363 yn = (current & MuteMaster::PreFader);
1365 if (pre_fader_mute_check->get_active() != yn) {
1366 pre_fader_mute_check->set_active (yn);
1369 yn = (current & MuteMaster::PostFader);
1371 if (post_fader_mute_check->get_active() != yn) {
1372 post_fader_mute_check->set_active (yn);
1375 yn = (current & MuteMaster::Listen);
1377 if (listen_mute_check->get_active() != yn) {
1378 listen_mute_check->set_active (yn);
1381 yn = (current & MuteMaster::Main);
1383 if (main_mute_check->get_active() != yn) {
1384 main_mute_check->set_active (yn);
1389 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1391 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1395 bool view = solo_isolated_led->active_state();
1396 bool model = _route->solo_isolated();
1398 /* called BEFORE the view has changed */
1400 if (ev->button == 1) {
1401 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1404 /* disable isolate for all routes */
1405 DisplaySuspender ds;
1406 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1410 if (model == view) {
1412 /* flip just this route */
1414 boost::shared_ptr<RouteList> rl (new RouteList);
1415 rl->push_back (_route);
1416 DisplaySuspender ds;
1417 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1426 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1428 if (ev->button == 1) {
1429 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1436 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1438 bool view = check->get_active();
1439 bool model = _route->solo_isolated();
1441 /* called AFTER the view has changed */
1443 if (model != view) {
1444 _route->set_solo_isolated (view, this);
1449 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1451 _route->set_solo_safe (check->get_active(), this);
1454 /** Ask the user to choose a colour, and then apply that color to my route
1457 RouteUI::choose_color ()
1460 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1467 /** Set the route's own color. This may not be used for display if
1468 * the route is in a group which shares its color with its routes.
1471 RouteUI::set_color (const Gdk::Color & c)
1473 /* leave _color alone in the group case so that tracks can retain their
1474 * own pre-group colors.
1479 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1481 /* note: we use the route state ID here so that color is the same for both
1482 the time axis view and the mixer strip
1485 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1486 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1489 /** @return GUI state ID for things that are common to the route in all its representations */
1491 RouteUI::route_state_id () const
1493 return string_compose (X_("route %1"), _route->id().to_s());
1497 RouteUI::set_color_from_route ()
1499 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1507 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1510 _color.set_green (g);
1511 _color.set_blue (b);
1517 RouteUI::remove_this_route (bool apply_to_selection)
1519 if (apply_to_selection) {
1520 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1522 if ((route()->is_master() || route()->is_monitor()) &&
1523 !Config->get_allow_special_bus_removal()) {
1524 MessageDialog msg (_("That would be bad news ...."),
1528 msg.set_secondary_text (string_compose (_(
1529 "Removing the master or monitor bus is such a bad idea\n\
1530 that %1 is not going to allow it.\n\
1532 If you really want to do this sort of thing\n\
1533 edit your ardour.rc file to set the\n\
1534 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1541 vector<string> choices;
1545 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());
1547 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());
1550 choices.push_back (_("No, do nothing."));
1551 choices.push_back (_("Yes, remove it."));
1555 title = _("Remove track");
1557 title = _("Remove bus");
1560 Choice prompter (title, prompt, choices);
1562 if (prompter.run () == 1) {
1563 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1569 RouteUI::idle_remove_this_route (RouteUI *rui)
1571 rui->_session->remove_route (rui->route());
1575 /** @return true if this name should be used for the route, otherwise false */
1577 RouteUI::verify_new_route_name (const std::string& name)
1579 if (name.find (':') == string::npos) {
1583 MessageDialog colon_msg (
1584 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1585 false, MESSAGE_QUESTION, BUTTONS_NONE
1588 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1589 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1591 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1595 RouteUI::route_rename ()
1597 ArdourPrompter name_prompter (true);
1602 name_prompter.set_title (_("Rename Track"));
1604 name_prompter.set_title (_("Rename Bus"));
1606 name_prompter.set_prompt (_("New name:"));
1607 name_prompter.set_initial_text (_route->name());
1608 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1609 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1610 name_prompter.show_all ();
1613 switch (name_prompter.run ()) {
1614 case Gtk::RESPONSE_ACCEPT:
1615 name_prompter.get_result (result);
1616 name_prompter.hide ();
1617 if (result.length()) {
1618 if (verify_new_route_name (result)) {
1619 _route->set_name (result);
1622 /* back to name prompter */
1626 /* nothing entered, just get out of here */
1641 RouteUI::property_changed (const PropertyChange& what_changed)
1643 if (what_changed.contains (ARDOUR::Properties::name)) {
1644 name_label.set_text (_route->name());
1649 RouteUI::toggle_comment_editor ()
1651 // if (ignore_toggle) {
1655 if (comment_window && comment_window->is_visible ()) {
1656 comment_window->hide ();
1658 open_comment_editor ();
1664 RouteUI::open_comment_editor ()
1666 if (comment_window == 0) {
1667 setup_comment_editor ();
1671 title = _route->name();
1672 title += _(": comment editor");
1674 comment_window->set_title (title);
1675 comment_window->present();
1679 RouteUI::setup_comment_editor ()
1681 comment_window = new ArdourWindow (""); // title will be reset to show route
1682 comment_window->set_skip_taskbar_hint (true);
1683 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1684 comment_window->set_default_size (400, 200);
1686 comment_area = manage (new TextView());
1687 comment_area->set_name ("MixerTrackCommentArea");
1688 comment_area->set_wrap_mode (WRAP_WORD);
1689 comment_area->set_editable (true);
1690 comment_area->get_buffer()->set_text (_route->comment());
1691 comment_area->show ();
1693 comment_window->add (*comment_area);
1697 RouteUI::comment_changed (void *src)
1699 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1702 ignore_comment_edit = true;
1704 comment_area->get_buffer()->set_text (_route->comment());
1706 ignore_comment_edit = false;
1711 RouteUI::comment_editor_done_editing ()
1713 string const str = comment_area->get_buffer()->get_text();
1714 if (str == _route->comment ()) {
1718 _route->set_comment (str, this);
1722 RouteUI::set_route_active (bool a, bool apply_to_selection)
1724 if (apply_to_selection) {
1725 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1727 _route->set_active (a, this);
1732 RouteUI::toggle_denormal_protection ()
1734 if (denormal_menu_item) {
1738 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1740 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1741 _route->set_denormal_protection (x);
1747 RouteUI::denormal_protection_changed ()
1749 if (denormal_menu_item) {
1750 denormal_menu_item->set_active (_route->denormal_protection());
1755 RouteUI::disconnect_input ()
1757 _route->input()->disconnect (this);
1761 RouteUI::disconnect_output ()
1763 _route->output()->disconnect (this);
1767 RouteUI::is_track () const
1769 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1772 boost::shared_ptr<Track>
1773 RouteUI::track() const
1775 return boost::dynamic_pointer_cast<Track>(_route);
1779 RouteUI::is_audio_track () const
1781 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1784 boost::shared_ptr<AudioTrack>
1785 RouteUI::audio_track() const
1787 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1791 RouteUI::is_midi_track () const
1793 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1796 boost::shared_ptr<MidiTrack>
1797 RouteUI::midi_track() const
1799 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1803 RouteUI::has_audio_outputs () const
1805 return (_route->n_outputs().n_audio() > 0);
1809 RouteUI::name() const
1811 return _route->name();
1815 RouteUI::map_frozen ()
1817 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1819 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1822 switch (at->freeze_state()) {
1823 case AudioTrack::Frozen:
1824 rec_enable_button->set_sensitive (false);
1827 rec_enable_button->set_sensitive (true);
1834 RouteUI::adjust_latency ()
1836 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1840 RouteUI::save_as_template ()
1843 std::string safe_name;
1846 path = ARDOUR::user_route_template_directory ();
1848 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1849 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1853 Prompter p (true); // modal
1855 p.set_title (_("Save As Template"));
1856 p.set_prompt (_("Template name:"));
1857 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1859 case RESPONSE_ACCEPT:
1866 p.get_result (name, true);
1868 safe_name = legalize_for_path (name);
1869 safe_name += template_suffix;
1871 path = Glib::build_filename (path, safe_name);
1873 _route->save_as_template (path, name);
1877 RouteUI::check_rec_enable_sensitivity ()
1879 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1880 rec_enable_button->set_sensitive (false);
1882 rec_enable_button->set_sensitive (true);
1885 update_monitoring_display ();
1889 RouteUI::parameter_changed (string const & p)
1891 /* this handles RC and per-session parameter changes */
1893 if (p == "disable-disarm-during-roll") {
1894 check_rec_enable_sensitivity ();
1895 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1896 set_button_names ();
1897 } else if (p == "auto-input") {
1898 update_monitoring_display ();
1903 RouteUI::step_gain_up ()
1905 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1909 RouteUI::page_gain_up ()
1911 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1915 RouteUI::step_gain_down ()
1917 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1921 RouteUI::page_gain_down ()
1923 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1927 RouteUI::open_remote_control_id_dialog ()
1929 ArdourDialog dialog (_("Remote Control ID"));
1930 SpinButton* spin = 0;
1932 dialog.get_vbox()->set_border_width (18);
1934 if (Config->get_remote_model() == UserOrdered) {
1935 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1937 HBox* hbox = manage (new HBox);
1938 hbox->set_spacing (6);
1939 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1940 spin = manage (new SpinButton);
1941 spin->set_digits (0);
1942 spin->set_increments (1, 10);
1943 spin->set_range (0, limit);
1944 spin->set_value (_route->remote_control_id());
1945 hbox->pack_start (*spin);
1946 dialog.get_vbox()->pack_start (*hbox);
1948 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1949 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1951 Label* l = manage (new Label());
1952 if (_route->is_master() || _route->is_monitor()) {
1953 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1954 "The remote control ID of %3 cannot be changed."),
1955 Glib::Markup::escape_text (_route->name()),
1956 _route->remote_control_id(),
1957 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1959 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1960 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1961 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1962 (is_track() ? _("track") : _("bus")),
1963 _route->remote_control_id(),
1964 "<span size=\"small\" style=\"italic\">",
1966 Glib::Markup::escape_text (_route->name()),
1969 dialog.get_vbox()->pack_start (*l);
1970 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1974 int const r = dialog.run ();
1976 if (r == RESPONSE_ACCEPT && spin) {
1977 _route->set_remote_control_id (spin->get_value_as_int ());
1982 RouteUI::setup_invert_buttons ()
1984 /* remove old invert buttons */
1985 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1986 _invert_button_box.remove (**i);
1989 _invert_buttons.clear ();
1991 if (!_route || !_route->input()) {
1995 uint32_t const N = _route->input()->n_ports().n_audio ();
1997 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1999 for (uint32_t i = 0; i < to_add; ++i) {
2000 ArdourButton* b = manage (new ArdourButton);
2001 b->set_size_request(20,20);
2002 Gtkmm2ext::set_height_request_to_display_any_text (*b, _button_vpad);
2003 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
2004 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
2006 b->set_name (X_("invert button"));
2009 b->set_text (string_compose (X_("Ø (%1)"), N));
2011 b->set_text (X_("Ø"));
2014 b->set_text (string_compose (X_("Ø%1"), i + 1));
2017 if (N <= _max_invert_buttons) {
2018 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));
2020 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2023 _invert_buttons.push_back (b);
2024 _invert_button_box.pack_start (*b);
2027 _invert_button_box.set_spacing (1);
2028 _invert_button_box.show_all ();
2032 RouteUI::set_invert_button_state ()
2034 uint32_t const N = _route->input()->n_ports().n_audio();
2035 if (N > _max_invert_buttons) {
2037 /* One button for many channels; explicit active if all channels are inverted,
2038 implicit active if some are, off if none are.
2041 ArdourButton* b = _invert_buttons.front ();
2043 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2044 b->set_active_state (Gtkmm2ext::ExplicitActive);
2045 } else if (_route->phase_invert().any()) {
2046 b->set_active_state (Gtkmm2ext::ImplicitActive);
2048 b->set_active_state (Gtkmm2ext::Off);
2053 /* One button per channel; just set active */
2056 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2057 (*i)->set_active (_route->phase_invert (j));
2064 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2066 if (ev->button == 1 && i < _invert_buttons.size()) {
2067 uint32_t const N = _route->input()->n_ports().n_audio ();
2068 if (N <= _max_invert_buttons) {
2069 /* left-click inverts phase so long as we have a button per channel */
2070 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2079 RouteUI::invert_press (GdkEventButton* ev)
2081 using namespace Menu_Helpers;
2083 uint32_t const N = _route->input()->n_ports().n_audio();
2084 if (N <= _max_invert_buttons && ev->button != 3) {
2085 /* If we have an invert button per channel, we only pop
2086 up a menu on right-click; left click is handled
2092 delete _invert_menu;
2093 _invert_menu = new Menu;
2094 _invert_menu->set_name ("ArdourContextMenu");
2095 MenuList& items = _invert_menu->items ();
2097 for (uint32_t i = 0; i < N; ++i) {
2098 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2099 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2100 ++_i_am_the_modifier;
2101 e->set_active (_route->phase_invert (i));
2102 --_i_am_the_modifier;
2105 _invert_menu->popup (0, ev->time);
2111 RouteUI::invert_menu_toggled (uint32_t c)
2113 if (_i_am_the_modifier) {
2117 _route->set_phase_invert (c, !_route->phase_invert (c));
2121 RouteUI::set_invert_sensitive (bool yn)
2123 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2124 (*b)->set_sensitive (yn);
2129 RouteUI::request_redraw ()
2132 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2136 /** The Route's gui_changed signal has been emitted */
2138 RouteUI::route_gui_changed (string what_changed)
2140 if (what_changed == "color") {
2141 if (set_color_from_route () == 0) {
2142 route_color_changed ();
2147 /** @return the color that this route should use; it maybe its own,
2148 or it maybe that of its route group.
2151 RouteUI::color () const
2153 RouteGroup* g = _route->route_group ();
2155 if (g && g->is_color()) {
2157 set_color_from_rgba (c, GroupTabs::group_color (g));
2165 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2167 _showing_sends_to = send_to;
2168 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2172 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2174 if (_route == send_to) {
2175 show_sends_button->set_active (true);
2176 send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2178 show_sends_button->set_active (false);
2179 send_blink_connection.disconnect ();
2184 RouteUI::route_group() const
2186 return _route->route_group();