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"
51 #include "ardour/audio_track.h"
52 #include "ardour/audioengine.h"
53 #include "ardour/filename_extensions.h"
54 #include "ardour/midi_track.h"
55 #include "ardour/internal_send.h"
56 #include "ardour/send.h"
57 #include "ardour/route.h"
58 #include "ardour/session.h"
59 #include "ardour/template_utils.h"
63 using namespace Gtkmm2ext;
64 using namespace ARDOUR;
65 using namespace ARDOUR_UI_UTILS;
69 uint32_t RouteUI::_max_invert_buttons = 3;
70 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
71 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
73 RouteUI::RouteUI (ARDOUR::Session* sess)
91 gui_object_state().remove_node (route_state_id());
94 _route.reset (); /* drop reference to route, so that it can be cleaned up */
95 route_connections.drop_connections ();
101 delete comment_window;
102 delete input_selector;
103 delete output_selector;
106 send_blink_connection.disconnect ();
107 rec_blink_connection.disconnect ();
113 self_destruct = true;
119 pre_fader_mute_check = 0;
120 post_fader_mute_check = 0;
121 listen_mute_check = 0;
124 solo_isolated_check = 0;
125 solo_isolated_led = 0;
129 denormal_menu_item = 0;
131 multiple_mute_change = false;
132 multiple_solo_change = false;
133 _i_am_the_modifier = 0;
138 setup_invert_buttons ();
140 mute_button = manage (new ArdourButton);
141 mute_button->set_name ("mute button");
142 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
144 solo_button = manage (new ArdourButton);
145 solo_button->set_name ("solo button");
146 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
147 solo_button->set_no_show_all (true);
149 rec_enable_button = manage (new ArdourButton);
150 rec_enable_button->set_name ("record enable button");
151 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton));
152 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
154 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
155 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
158 show_sends_button = manage (new ArdourButton);
159 show_sends_button->set_name ("send alert button");
160 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
162 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
163 monitor_input_button->set_name ("monitor button");
164 monitor_input_button->set_text (_("In"));
165 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
166 monitor_input_button->set_no_show_all (true);
168 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
169 monitor_disk_button->set_name ("monitor button");
170 monitor_disk_button->set_text (_("Disk"));
171 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
172 monitor_disk_button->set_no_show_all (true);
174 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
175 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
176 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
178 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
179 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
181 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
182 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
184 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
185 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
187 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
188 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
189 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
190 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
192 monitor_input_button->set_distinct_led_click (false);
193 monitor_disk_button->set_distinct_led_click (false);
195 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
196 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
198 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
199 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
201 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
207 route_connections.drop_connections ();
215 denormal_menu_item = 0;
219 RouteUI::self_delete ()
225 RouteUI::set_route (boost::shared_ptr<Route> rp)
231 if (set_color_from_route()) {
232 set_color (unique_random_color());
236 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
239 delete input_selector;
242 delete output_selector;
245 mute_button->set_controllable (_route->mute_control());
246 solo_button->set_controllable (_route->solo_control());
248 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
249 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context());
251 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
253 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
254 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
255 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
256 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
258 track()->TrackModeChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::track_mode_changed, this), gui_context());
259 track_mode_changed();
262 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
263 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
265 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
266 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
268 if (_session->writable() && is_track()) {
269 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
271 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
273 rec_enable_button->show();
274 rec_enable_button->set_controllable (t->rec_enable_control());
276 if (is_midi_track()) {
277 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
278 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
283 /* this will work for busses and tracks, and needs to be called to
284 set up the name entry/name label display.
288 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
289 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
291 update_monitoring_display ();
294 mute_button->unset_flags (Gtk::CAN_FOCUS);
295 solo_button->unset_flags (Gtk::CAN_FOCUS);
299 if (_route->is_monitor() || _route->is_master()) {
300 solo_button->hide ();
307 setup_invert_buttons ();
308 set_invert_button_state ();
310 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
311 bus_send_display_changed (s);
313 update_mute_display ();
314 update_solo_display ();
316 if (!ARDOUR_UI::config()->get_blink_rec_arm()) {
317 blink_rec_display(true); // set initial rec-en button state
320 route_color_changed();
324 RouteUI::polarity_changed ()
330 set_invert_button_state ();
334 RouteUI::mute_press (GdkEventButton* ev)
336 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
340 //if this is a binding action, let the ArdourButton handle it
341 if ( BindingProxy::is_bind_action(ev) )
344 multiple_mute_change = false;
346 if (Keyboard::is_context_menu_event (ev)) {
352 mute_menu->popup(0,ev->time);
358 if (Keyboard::is_button2_event (ev)) {
359 // button2-click is "momentary"
361 _mute_release = new SoloMuteRelease (_route->muted ());
364 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
366 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
368 /* toggle mute on everything (but
369 * exclude the master and monitor)
371 * because we are going to erase
372 * elements of the list we need to work
376 boost::shared_ptr<RouteList> copy (new RouteList);
378 *copy = *_session->get_routes ();
380 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
381 if ((*i)->is_master() || (*i)->is_monitor()) {
389 _mute_release->routes = copy;
393 _session->set_mute (copy, !_route->muted());
395 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
397 /* Primary-button1 applies change to the mix group even if it is not active
398 NOTE: Primary-button2 is MIDI learn.
401 boost::shared_ptr<RouteList> rl;
403 if (ev->button == 1) {
405 if (_route->route_group()) {
407 rl = _route->route_group()->route_list();
410 _mute_release->routes = rl;
413 rl.reset (new RouteList);
414 rl->push_back (_route);
418 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
423 /* plain click applies change to this route */
425 boost::shared_ptr<RouteList> rl (new RouteList);
426 rl->push_back (_route);
429 _mute_release->routes = rl;
432 _session->set_mute (rl, !_route->muted());
442 RouteUI::mute_release (GdkEventButton* /*ev*/)
446 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
447 delete _mute_release;
455 RouteUI::edit_output_configuration ()
457 if (output_selector == 0) {
459 boost::shared_ptr<Send> send;
460 boost::shared_ptr<IO> output;
462 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
463 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
464 output = send->output();
466 output = _route->output ();
469 output = _route->output ();
472 output_selector = new IOSelectorWindow (_session, output);
475 if (output_selector->is_visible()) {
476 output_selector->get_toplevel()->get_window()->raise();
478 output_selector->present ();
481 //output_selector->set_keep_above (true);
485 RouteUI::edit_input_configuration ()
487 if (input_selector == 0) {
488 input_selector = new IOSelectorWindow (_session, _route->input());
491 if (input_selector->is_visible()) {
492 input_selector->get_toplevel()->get_window()->raise();
494 input_selector->present ();
497 //input_selector->set_keep_above (true);
501 RouteUI::solo_press(GdkEventButton* ev)
503 /* ignore double/triple clicks */
505 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
509 //if this is a binding action, let the ArdourButton handle it
510 if ( BindingProxy::is_bind_action(ev) )
513 multiple_solo_change = false;
515 if (Keyboard::is_context_menu_event (ev)) {
517 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
518 ! (solo_safe_led && solo_safe_led->is_visible())) {
520 if (solo_menu == 0) {
524 solo_menu->popup (1, ev->time);
529 if (Keyboard::is_button2_event (ev)) {
531 // button2-click is "momentary"
532 _solo_release = new SoloMuteRelease (_route->self_soloed());
535 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
537 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
539 /* Primary-Tertiary-click applies change to all routes */
542 _solo_release->routes = _session->get_routes ();
546 if (Config->get_solo_control_is_listen_control()) {
547 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
549 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
552 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
554 // Primary-Secondary-click: exclusively solo this track
557 _solo_release->exclusive = true;
559 boost::shared_ptr<RouteList> routes = _session->get_routes();
561 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
562 if ((*i)->soloed ()) {
563 _solo_release->routes_on->push_back (*i);
565 _solo_release->routes_off->push_back (*i);
570 if (Config->get_solo_control_is_listen_control()) {
571 /* ??? we need a just_one_listen() method */
574 _session->set_just_one_solo (_route, true);
577 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
579 // shift-click: toggle solo isolated status
581 _route->set_solo_isolated (!_route->solo_isolated(), this);
582 delete _solo_release;
585 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
587 /* Primary-button1: solo mix group.
588 NOTE: Primary-button2 is MIDI learn.
591 /* Primary-button1 applies change to the mix group even if it is not active
592 NOTE: Primary-button2 is MIDI learn.
595 boost::shared_ptr<RouteList> rl;
597 if (ev->button == 1) {
599 if (_route->route_group()) {
601 rl = _route->route_group()->route_list();
604 _solo_release->routes = rl;
607 rl.reset (new RouteList);
608 rl->push_back (_route);
612 if (Config->get_solo_control_is_listen_control()) {
613 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
615 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
621 /* click: solo this route */
623 boost::shared_ptr<RouteList> rl (new RouteList);
624 rl->push_back (route());
627 _solo_release->routes = rl;
631 if (Config->get_solo_control_is_listen_control()) {
632 _session->set_listen (rl, !_route->listening_via_monitor());
634 _session->set_solo (rl, !_route->self_soloed());
644 RouteUI::solo_release (GdkEventButton* /*ev*/)
648 if (_solo_release->exclusive) {
652 if (Config->get_solo_control_is_listen_control()) {
653 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
655 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
659 delete _solo_release;
667 RouteUI::rec_enable_press(GdkEventButton* ev)
669 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
673 //if this is a binding action, let the ArdourButton handle it
674 if ( BindingProxy::is_bind_action(ev) )
677 if (!_session->engine().connected()) {
678 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
683 if (is_midi_track()) {
685 /* rec-enable button exits from step editing */
687 if (midi_track()->step_editing()) {
688 midi_track()->set_step_editing (false);
693 if (is_track() && rec_enable_button) {
695 if (Keyboard::is_button2_event (ev)) {
697 //rec arm does not have a momentary mode
700 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
703 _session->set_record_enabled (_session->get_routes(), !_route->record_enabled());
705 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
707 /* Primary-button1 applies change to the route group (even if it is not active)
708 NOTE: Primary-button2 is MIDI learn.
711 if (ev->button == 1) {
713 boost::shared_ptr<RouteList> rl;
715 if (_route->route_group()) {
717 rl = _route->route_group()->route_list();
720 rl.reset (new RouteList);
721 rl->push_back (_route);
725 _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
728 } else if (Keyboard::is_context_menu_event (ev)) {
730 /* do this on release */
734 boost::shared_ptr<RouteList> rl (new RouteList);
735 rl->push_back (route());
737 _session->set_record_enabled (rl, !_route->record_enabled());
745 RouteUI::monitoring_changed ()
747 update_monitoring_display ();
751 RouteUI::update_monitoring_display ()
757 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
763 MonitorState ms = t->monitoring_state();
765 if (t->monitoring_choice() & MonitorInput) {
766 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
768 if (ms & MonitoringInput) {
769 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
771 monitor_input_button->unset_active_state ();
775 if (t->monitoring_choice() & MonitorDisk) {
776 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
778 if (ms & MonitoringDisk) {
779 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
781 monitor_disk_button->unset_active_state ();
787 RouteUI::monitor_input_press(GdkEventButton*)
793 RouteUI::monitor_input_release(GdkEventButton* ev)
795 return monitor_release (ev, MonitorInput);
799 RouteUI::monitor_disk_press (GdkEventButton*)
805 RouteUI::monitor_disk_release (GdkEventButton* ev)
807 return monitor_release (ev, MonitorDisk);
811 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
813 if (ev->button != 1) {
817 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
824 boost::shared_ptr<RouteList> rl;
826 /* XXX for now, monitoring choices are orthogonal. cue monitoring
827 will follow in 3.X but requires mixing the input and playback (disk)
828 signal together, which requires yet more buffers.
831 if (t->monitoring_choice() & monitor_choice) {
832 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
834 /* this line will change when the options are non-orthogonal */
835 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
839 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
840 rl = _session->get_routes ();
842 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
843 if (_route->route_group() && _route->route_group()->is_monitoring()) {
844 rl = _route->route_group()->route_list();
846 rl.reset (new RouteList);
847 rl->push_back (route());
850 rl.reset (new RouteList);
851 rl->push_back (route());
855 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
861 RouteUI::build_record_menu ()
867 /* no rec-button context menu for non-MIDI tracks
870 if (is_midi_track()) {
871 record_menu = new Menu;
872 record_menu->set_name ("ArdourContextMenu");
874 using namespace Menu_Helpers;
875 MenuList& items = record_menu->items();
877 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
878 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
880 if (_route->record_enabled()) {
881 step_edit_item->set_sensitive (false);
884 step_edit_item->set_active (midi_track()->step_editing());
889 RouteUI::toggle_step_edit ()
891 if (!is_midi_track() || _route->record_enabled()) {
895 midi_track()->set_step_editing (step_edit_item->get_active());
899 RouteUI::step_edit_changed (bool yn)
902 if (rec_enable_button) {
903 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
906 start_step_editing ();
908 if (step_edit_item) {
909 step_edit_item->set_active (true);
914 if (rec_enable_button) {
915 rec_enable_button->unset_active_state ();
918 stop_step_editing ();
920 if (step_edit_item) {
921 step_edit_item->set_active (false);
927 RouteUI::rec_enable_release (GdkEventButton* ev)
929 if (Keyboard::is_context_menu_event (ev)) {
930 build_record_menu ();
932 record_menu->popup (1, ev->time);
941 RouteUI::build_sends_menu ()
943 using namespace Menu_Helpers;
945 sends_menu = new Menu;
946 sends_menu->set_name ("ArdourContextMenu");
947 MenuList& items = sends_menu->items();
950 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
954 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
958 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
962 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
966 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
970 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
973 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
977 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
980 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
981 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
982 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
987 RouteUI::create_sends (Placement p, bool include_buses)
989 _session->globally_add_internal_sends (_route, p, include_buses);
993 RouteUI::create_selected_sends (Placement p, bool include_buses)
995 boost::shared_ptr<RouteList> rlist (new RouteList);
996 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
998 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
999 RouteTimeAxisView* rtv;
1001 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1002 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1003 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1004 rlist->push_back (rui->route());
1010 _session->add_internal_sends (_route, p, rlist);
1014 RouteUI::set_sends_gain_from_track ()
1016 _session->globally_set_send_gains_from_track (_route);
1020 RouteUI::set_sends_gain_to_zero ()
1022 _session->globally_set_send_gains_to_zero (_route);
1026 RouteUI::set_sends_gain_to_unity ()
1028 _session->globally_set_send_gains_to_unity (_route);
1032 RouteUI::show_sends_press(GdkEventButton* ev)
1034 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1038 if (!is_track() && show_sends_button) {
1040 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1042 // do nothing on midi sigc::bind event
1045 } else if (Keyboard::is_context_menu_event (ev)) {
1047 if (sends_menu == 0) {
1048 build_sends_menu ();
1051 sends_menu->popup (0, ev->time);
1055 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1058 set_showing_sends_to (boost::shared_ptr<Route> ());
1060 set_showing_sends_to (_route);
1069 RouteUI::show_sends_release (GdkEventButton*)
1075 RouteUI::send_blink (bool onoff)
1077 if (!show_sends_button) {
1082 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1084 show_sends_button->unset_active_state ();
1088 Gtkmm2ext::ActiveState
1089 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1091 if (r->is_master() || r->is_monitor()) {
1092 return Gtkmm2ext::Off;
1095 if (Config->get_solo_control_is_listen_control()) {
1097 if (r->listening_via_monitor()) {
1098 return Gtkmm2ext::ExplicitActive;
1100 return Gtkmm2ext::Off;
1106 if (!r->self_soloed()) {
1107 return Gtkmm2ext::ImplicitActive;
1109 return Gtkmm2ext::ExplicitActive;
1112 return Gtkmm2ext::Off;
1116 Gtkmm2ext::ActiveState
1117 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1119 if (r->is_master() || r->is_monitor()) {
1120 return Gtkmm2ext::Off;
1123 if (r->solo_isolated()) {
1124 return Gtkmm2ext::ExplicitActive;
1126 return Gtkmm2ext::Off;
1130 Gtkmm2ext::ActiveState
1131 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1133 if (r->is_master() || r->is_monitor()) {
1134 return Gtkmm2ext::Off;
1137 if (r->solo_safe()) {
1138 return Gtkmm2ext::ExplicitActive;
1140 return Gtkmm2ext::Off;
1145 RouteUI::update_solo_display ()
1147 bool yn = _route->solo_safe ();
1149 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1150 solo_safe_check->set_active (yn);
1153 yn = _route->solo_isolated ();
1155 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1156 solo_isolated_check->set_active (yn);
1159 set_button_names ();
1161 if (solo_isolated_led) {
1162 if (_route->solo_isolated()) {
1163 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1165 solo_isolated_led->unset_active_state ();
1169 if (solo_safe_led) {
1170 if (_route->solo_safe()) {
1171 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1173 solo_safe_led->unset_active_state ();
1177 solo_button->set_active_state (solo_active_state (_route));
1179 /* some changes to solo status can affect mute display, so catch up
1182 update_mute_display ();
1186 RouteUI::solo_changed_so_update_mute ()
1188 update_mute_display ();
1192 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1194 if (r->is_monitor()) {
1195 return ActiveState(0);
1199 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1203 return Gtkmm2ext::ExplicitActive;
1204 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1205 /* master is NEVER muted by others */
1206 return Gtkmm2ext::ImplicitActive;
1208 /* no mute at all */
1209 return Gtkmm2ext::Off;
1216 return Gtkmm2ext::ExplicitActive;
1218 /* no mute at all */
1219 return Gtkmm2ext::Off;
1223 return ActiveState(0);
1227 RouteUI::update_mute_display ()
1233 mute_button->set_active_state (mute_active_state (_session, _route));
1237 RouteUI::route_rec_enable_changed ()
1239 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1240 update_monitoring_display ();
1244 RouteUI::session_rec_enable_changed ()
1246 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1247 update_monitoring_display ();
1251 RouteUI::blink_rec_display (bool blinkOn)
1253 if (!rec_enable_button || !_route) {
1256 if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1260 if (_route->record_enabled()) {
1261 switch (_session->record_status ()) {
1262 case Session::Recording:
1263 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1266 case Session::Disabled:
1267 case Session::Enabled:
1268 if ( ARDOUR_UI::config()->get_blink_rec_arm() )
1269 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1271 rec_enable_button->set_active_state ( ImplicitActive );
1276 if (step_edit_item) {
1277 step_edit_item->set_sensitive (false);
1281 rec_enable_button->unset_active_state ();
1283 if (step_edit_item) {
1284 step_edit_item->set_sensitive (true);
1289 check_rec_enable_sensitivity ();
1293 RouteUI::build_solo_menu (void)
1295 using namespace Menu_Helpers;
1297 solo_menu = new Menu;
1298 solo_menu->set_name ("ArdourContextMenu");
1299 MenuList& items = solo_menu->items();
1300 Gtk::CheckMenuItem* check;
1302 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1303 check->set_active (_route->solo_isolated());
1304 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1305 items.push_back (CheckMenuElem(*check));
1306 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1309 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1310 check->set_active (_route->solo_safe());
1311 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1312 items.push_back (CheckMenuElem(*check));
1313 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1316 //items.push_back (SeparatorElem());
1317 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1322 RouteUI::build_mute_menu(void)
1324 using namespace Menu_Helpers;
1326 mute_menu = new Menu;
1327 mute_menu->set_name ("ArdourContextMenu");
1329 MenuList& items = mute_menu->items();
1331 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1332 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1333 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1334 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1335 pre_fader_mute_check->show_all();
1337 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1338 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1339 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1340 items.push_back (CheckMenuElem(*post_fader_mute_check));
1341 post_fader_mute_check->show_all();
1343 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1344 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1345 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1346 items.push_back (CheckMenuElem(*listen_mute_check));
1347 listen_mute_check->show_all();
1349 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1350 init_mute_menu(MuteMaster::Main, main_mute_check);
1351 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1352 items.push_back (CheckMenuElem(*main_mute_check));
1353 main_mute_check->show_all();
1355 //items.push_back (SeparatorElem());
1356 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1358 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1362 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1364 check->set_active (_route->mute_points() & mp);
1368 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1370 if (check->get_active()) {
1371 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1373 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1378 RouteUI::muting_change ()
1380 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1383 MuteMaster::MutePoint current = _route->mute_points ();
1385 yn = (current & MuteMaster::PreFader);
1387 if (pre_fader_mute_check->get_active() != yn) {
1388 pre_fader_mute_check->set_active (yn);
1391 yn = (current & MuteMaster::PostFader);
1393 if (post_fader_mute_check->get_active() != yn) {
1394 post_fader_mute_check->set_active (yn);
1397 yn = (current & MuteMaster::Listen);
1399 if (listen_mute_check->get_active() != yn) {
1400 listen_mute_check->set_active (yn);
1403 yn = (current & MuteMaster::Main);
1405 if (main_mute_check->get_active() != yn) {
1406 main_mute_check->set_active (yn);
1411 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1413 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1417 bool view = solo_isolated_led->active_state();
1418 bool model = _route->solo_isolated();
1420 /* called BEFORE the view has changed */
1422 if (ev->button == 1) {
1423 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1426 /* disable isolate for all routes */
1427 DisplaySuspender ds;
1428 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1432 if (model == view) {
1434 /* flip just this route */
1436 boost::shared_ptr<RouteList> rl (new RouteList);
1437 rl->push_back (_route);
1438 DisplaySuspender ds;
1439 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1448 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1450 if (ev->button == 1) {
1451 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1457 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1459 bool view = check->get_active();
1460 bool model = _route->solo_isolated();
1462 /* called AFTER the view has changed */
1464 if (model != view) {
1465 _route->set_solo_isolated (view, this);
1470 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1472 _route->set_solo_safe (check->get_active(), this);
1475 /** Ask the user to choose a colour, and then apply that color to my route
1478 RouteUI::choose_color ()
1481 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1488 /** Set the route's own color. This may not be used for display if
1489 * the route is in a group which shares its color with its routes.
1492 RouteUI::set_color (const Gdk::Color & c)
1494 /* leave _color alone in the group case so that tracks can retain their
1495 * own pre-group colors.
1500 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1502 /* note: we use the route state ID here so that color is the same for both
1503 the time axis view and the mixer strip
1506 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1507 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1510 /** @return GUI state ID for things that are common to the route in all its representations */
1512 RouteUI::route_state_id () const
1514 return string_compose (X_("route %1"), _route->id().to_s());
1518 RouteUI::set_color_from_route ()
1520 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1528 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1531 _color.set_green (g);
1532 _color.set_blue (b);
1538 RouteUI::remove_this_route (bool apply_to_selection)
1540 if (apply_to_selection) {
1541 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1543 if ((route()->is_master() || route()->is_monitor()) &&
1544 !Config->get_allow_special_bus_removal()) {
1545 MessageDialog msg (_("That would be bad news ...."),
1549 msg.set_secondary_text (string_compose (_(
1550 "Removing the master or monitor bus is such a bad idea\n\
1551 that %1 is not going to allow it.\n\
1553 If you really want to do this sort of thing\n\
1554 edit your ardour.rc file to set the\n\
1555 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1562 vector<string> choices;
1566 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());
1568 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());
1571 choices.push_back (_("No, do nothing."));
1572 choices.push_back (_("Yes, remove it."));
1576 title = _("Remove track");
1578 title = _("Remove bus");
1581 Choice prompter (title, prompt, choices);
1583 if (prompter.run () == 1) {
1584 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1590 RouteUI::idle_remove_this_route (RouteUI *rui)
1592 DisplaySuspender ds;
1593 rui->_session->remove_route (rui->route());
1597 /** @return true if this name should be used for the route, otherwise false */
1599 RouteUI::verify_new_route_name (const std::string& name)
1601 if (name.find (':') == string::npos) {
1605 MessageDialog colon_msg (
1606 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1607 false, MESSAGE_QUESTION, BUTTONS_NONE
1610 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1611 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1613 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1617 RouteUI::route_rename ()
1619 ArdourPrompter name_prompter (true);
1624 name_prompter.set_title (_("Rename Track"));
1626 name_prompter.set_title (_("Rename Bus"));
1628 name_prompter.set_prompt (_("New name:"));
1629 name_prompter.set_initial_text (_route->name());
1630 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1631 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1632 name_prompter.show_all ();
1635 switch (name_prompter.run ()) {
1636 case Gtk::RESPONSE_ACCEPT:
1637 name_prompter.get_result (result);
1638 name_prompter.hide ();
1639 if (result.length()) {
1640 if (verify_new_route_name (result)) {
1641 _route->set_name (result);
1644 /* back to name prompter */
1648 /* nothing entered, just get out of here */
1663 RouteUI::property_changed (const PropertyChange& what_changed)
1665 if (what_changed.contains (ARDOUR::Properties::name)) {
1666 name_label.set_text (_route->name());
1671 RouteUI::toggle_comment_editor ()
1673 // if (ignore_toggle) {
1677 if (comment_window && comment_window->is_visible ()) {
1678 comment_window->hide ();
1680 open_comment_editor ();
1686 RouteUI::open_comment_editor ()
1688 if (comment_window == 0) {
1689 setup_comment_editor ();
1693 title = _route->name();
1694 title += _(": comment editor");
1696 comment_window->set_title (title);
1697 comment_window->present();
1701 RouteUI::setup_comment_editor ()
1703 comment_window = new ArdourWindow (""); // title will be reset to show route
1704 comment_window->set_skip_taskbar_hint (true);
1705 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1706 comment_window->set_default_size (400, 200);
1708 comment_area = manage (new TextView());
1709 comment_area->set_name ("MixerTrackCommentArea");
1710 comment_area->set_wrap_mode (WRAP_WORD);
1711 comment_area->set_editable (true);
1712 comment_area->get_buffer()->set_text (_route->comment());
1713 comment_area->show ();
1715 comment_window->add (*comment_area);
1719 RouteUI::comment_changed (void *src)
1721 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1724 ignore_comment_edit = true;
1726 comment_area->get_buffer()->set_text (_route->comment());
1728 ignore_comment_edit = false;
1733 RouteUI::comment_editor_done_editing ()
1735 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1737 string const str = comment_area->get_buffer()->get_text();
1738 if (str == _route->comment ()) {
1742 _route->set_comment (str, this);
1746 RouteUI::set_route_active (bool a, bool apply_to_selection)
1748 if (apply_to_selection) {
1749 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1751 _route->set_active (a, this);
1756 RouteUI::toggle_denormal_protection ()
1758 if (denormal_menu_item) {
1762 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1764 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1765 _route->set_denormal_protection (x);
1771 RouteUI::denormal_protection_changed ()
1773 if (denormal_menu_item) {
1774 denormal_menu_item->set_active (_route->denormal_protection());
1779 RouteUI::disconnect_input ()
1781 _route->input()->disconnect (this);
1785 RouteUI::disconnect_output ()
1787 _route->output()->disconnect (this);
1791 RouteUI::is_track () const
1793 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1796 boost::shared_ptr<Track>
1797 RouteUI::track() const
1799 return boost::dynamic_pointer_cast<Track>(_route);
1803 RouteUI::is_audio_track () const
1805 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1808 boost::shared_ptr<AudioTrack>
1809 RouteUI::audio_track() const
1811 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1815 RouteUI::is_midi_track () const
1817 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1820 boost::shared_ptr<MidiTrack>
1821 RouteUI::midi_track() const
1823 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1827 RouteUI::has_audio_outputs () const
1829 return (_route->n_outputs().n_audio() > 0);
1833 RouteUI::name() const
1835 return _route->name();
1839 RouteUI::map_frozen ()
1841 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1843 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1846 switch (at->freeze_state()) {
1847 case AudioTrack::Frozen:
1848 rec_enable_button->set_sensitive (false);
1851 rec_enable_button->set_sensitive (true);
1858 RouteUI::adjust_latency ()
1860 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1864 RouteUI::save_as_template ()
1867 std::string safe_name;
1870 path = ARDOUR::user_route_template_directory ();
1872 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1873 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1877 Prompter p (true); // modal
1879 p.set_title (_("Save As Template"));
1880 p.set_prompt (_("Template name:"));
1881 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1883 case RESPONSE_ACCEPT:
1890 p.get_result (name, true);
1892 safe_name = legalize_for_path (name);
1893 safe_name += template_suffix;
1895 path = Glib::build_filename (path, safe_name);
1897 _route->save_as_template (path, name);
1901 RouteUI::check_rec_enable_sensitivity ()
1903 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1904 rec_enable_button->set_sensitive (false);
1906 rec_enable_button->set_sensitive (true);
1909 update_monitoring_display ();
1913 RouteUI::parameter_changed (string const & p)
1915 /* this handles RC and per-session parameter changes */
1917 if (p == "disable-disarm-during-roll") {
1918 check_rec_enable_sensitivity ();
1919 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1920 set_button_names ();
1921 } else if (p == "auto-input") {
1922 update_monitoring_display ();
1923 } else if (p == "blink-rec-arm") {
1924 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
1925 rec_blink_connection.disconnect ();
1926 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1928 rec_blink_connection.disconnect ();
1929 RouteUI::blink_rec_display(false);
1935 RouteUI::step_gain_up ()
1937 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1941 RouteUI::page_gain_up ()
1943 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1947 RouteUI::step_gain_down ()
1949 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1953 RouteUI::page_gain_down ()
1955 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1959 RouteUI::open_remote_control_id_dialog ()
1961 ArdourDialog dialog (_("Remote Control ID"));
1962 SpinButton* spin = 0;
1964 dialog.get_vbox()->set_border_width (18);
1966 if (Config->get_remote_model() == UserOrdered) {
1967 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1969 HBox* hbox = manage (new HBox);
1970 hbox->set_spacing (6);
1971 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1972 spin = manage (new SpinButton);
1973 spin->set_digits (0);
1974 spin->set_increments (1, 10);
1975 spin->set_range (0, limit);
1976 spin->set_value (_route->remote_control_id());
1977 hbox->pack_start (*spin);
1978 dialog.get_vbox()->pack_start (*hbox);
1980 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1981 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1983 Label* l = manage (new Label());
1984 if (_route->is_master() || _route->is_monitor()) {
1985 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1986 "The remote control ID of %3 cannot be changed."),
1987 Glib::Markup::escape_text (_route->name()),
1988 _route->remote_control_id(),
1989 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1991 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1992 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1993 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1994 (is_track() ? _("track") : _("bus")),
1995 _route->remote_control_id(),
1996 "<span size=\"small\" style=\"italic\">",
1998 Glib::Markup::escape_text (_route->name()),
2001 dialog.get_vbox()->pack_start (*l);
2002 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
2006 int const r = dialog.run ();
2008 if (r == RESPONSE_ACCEPT && spin) {
2009 _route->set_remote_control_id (spin->get_value_as_int ());
2014 RouteUI::setup_invert_buttons ()
2016 /* remove old invert buttons */
2017 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
2018 _invert_button_box.remove (**i);
2021 _invert_buttons.clear ();
2023 if (!_route || !_route->input()) {
2027 uint32_t const N = _route->input()->n_ports().n_audio ();
2029 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2031 for (uint32_t i = 0; i < to_add; ++i) {
2032 ArdourButton* b = manage (new ArdourButton);
2033 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2034 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2036 b->set_name (X_("invert button"));
2039 b->set_text (string_compose (X_("Ø (%1)"), N));
2041 b->set_text (X_("Ø"));
2044 b->set_text (string_compose (X_("Ø%1"), i + 1));
2047 if (N <= _max_invert_buttons) {
2048 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));
2050 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2053 _invert_buttons.push_back (b);
2054 _invert_button_box.pack_start (*b);
2057 _invert_button_box.set_spacing (1);
2058 _invert_button_box.show_all ();
2062 RouteUI::set_invert_button_state ()
2064 uint32_t const N = _route->input()->n_ports().n_audio();
2065 if (N > _max_invert_buttons) {
2067 /* One button for many channels; explicit active if all channels are inverted,
2068 implicit active if some are, off if none are.
2071 ArdourButton* b = _invert_buttons.front ();
2073 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2074 b->set_active_state (Gtkmm2ext::ExplicitActive);
2075 } else if (_route->phase_invert().any()) {
2076 b->set_active_state (Gtkmm2ext::ImplicitActive);
2078 b->set_active_state (Gtkmm2ext::Off);
2083 /* One button per channel; just set active */
2086 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2087 (*i)->set_active (_route->phase_invert (j));
2094 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2096 if (ev->button == 1 && i < _invert_buttons.size()) {
2097 uint32_t const N = _route->input()->n_ports().n_audio ();
2098 if (N <= _max_invert_buttons) {
2099 /* left-click inverts phase so long as we have a button per channel */
2100 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2109 RouteUI::invert_press (GdkEventButton* ev)
2111 using namespace Menu_Helpers;
2113 uint32_t const N = _route->input()->n_ports().n_audio();
2114 if (N <= _max_invert_buttons && ev->button != 3) {
2115 /* If we have an invert button per channel, we only pop
2116 up a menu on right-click; left click is handled
2122 delete _invert_menu;
2123 _invert_menu = new Menu;
2124 _invert_menu->set_name ("ArdourContextMenu");
2125 MenuList& items = _invert_menu->items ();
2127 for (uint32_t i = 0; i < N; ++i) {
2128 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2129 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2130 ++_i_am_the_modifier;
2131 e->set_active (_route->phase_invert (i));
2132 --_i_am_the_modifier;
2135 _invert_menu->popup (0, ev->time);
2141 RouteUI::invert_menu_toggled (uint32_t c)
2143 if (_i_am_the_modifier) {
2147 _route->set_phase_invert (c, !_route->phase_invert (c));
2151 RouteUI::set_invert_sensitive (bool yn)
2153 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2154 (*b)->set_sensitive (yn);
2159 RouteUI::request_redraw ()
2162 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2166 /** The Route's gui_changed signal has been emitted */
2168 RouteUI::route_gui_changed (string what_changed)
2170 if (what_changed == "color") {
2171 if (set_color_from_route () == 0) {
2172 route_color_changed ();
2178 RouteUI::track_mode_changed (void)
2181 switch (track()->mode()) {
2182 case ARDOUR::NonLayered:
2183 case ARDOUR::Normal:
2184 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton));
2186 case ARDOUR::Destructive:
2187 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton|ArdourButton::RecTapeMode));
2190 rec_enable_button->queue_draw();
2193 /** @return the color that this route should use; it maybe its own,
2194 or it maybe that of its route group.
2197 RouteUI::color () const
2199 RouteGroup* g = _route->route_group ();
2201 if (g && g->is_color()) {
2203 set_color_from_rgba (c, GroupTabs::group_color (g));
2211 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2213 _showing_sends_to = send_to;
2214 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2218 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2220 if (_route == send_to) {
2221 show_sends_button->set_active (true);
2222 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2224 show_sends_button->set_active (false);
2225 send_blink_connection.disconnect ();
2230 RouteUI::route_group() const
2232 return _route->route_group();