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)
90 _route.reset (); /* drop reference to route, so that it can be cleaned up */
91 route_connections.drop_connections ();
97 delete comment_window;
98 delete input_selector;
99 delete output_selector;
102 send_blink_connection.disconnect ();
103 rec_blink_connection.disconnect ();
109 self_destruct = true;
115 pre_fader_mute_check = 0;
116 post_fader_mute_check = 0;
117 listen_mute_check = 0;
120 solo_isolated_check = 0;
121 solo_isolated_led = 0;
125 denormal_menu_item = 0;
127 multiple_mute_change = false;
128 multiple_solo_change = false;
129 _i_am_the_modifier = 0;
134 setup_invert_buttons ();
136 mute_button = manage (new ArdourButton);
137 mute_button->set_name ("mute button");
138 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
140 solo_button = manage (new ArdourButton);
141 solo_button->set_name ("solo button");
142 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
143 solo_button->set_no_show_all (true);
145 rec_enable_button = manage (new ArdourButton);
146 rec_enable_button->set_name ("record enable button");
147 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton));
148 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
150 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
151 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
154 show_sends_button = manage (new ArdourButton);
155 show_sends_button->set_name ("send alert button");
156 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
158 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
159 monitor_input_button->set_name ("monitor button");
160 monitor_input_button->set_text (_("In"));
161 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
162 monitor_input_button->set_no_show_all (true);
164 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
165 monitor_disk_button->set_name ("monitor button");
166 monitor_disk_button->set_text (_("Disk"));
167 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
168 monitor_disk_button->set_no_show_all (true);
170 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
171 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
172 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
174 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
175 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
177 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
178 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
180 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
181 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
183 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
184 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
185 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
186 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
188 monitor_input_button->set_distinct_led_click (false);
189 monitor_disk_button->set_distinct_led_click (false);
191 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
192 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
194 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
195 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
197 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
203 route_connections.drop_connections ();
211 denormal_menu_item = 0;
215 RouteUI::self_delete ()
221 RouteUI::set_route (boost::shared_ptr<Route> rp)
227 if (set_color_from_route()) {
228 set_color (unique_random_color());
232 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
235 delete input_selector;
238 delete output_selector;
241 mute_button->set_controllable (_route->mute_control());
242 solo_button->set_controllable (_route->solo_control());
244 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
245 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
247 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
249 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
250 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
251 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
252 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
254 track()->TrackModeChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::track_mode_changed, this), gui_context());
255 track_mode_changed();
258 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
259 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
261 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
262 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
264 if (_session->writable() && is_track()) {
265 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
267 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
269 rec_enable_button->show();
270 rec_enable_button->set_controllable (t->rec_enable_control());
272 if (is_midi_track()) {
273 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
274 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
279 /* this will work for busses and tracks, and needs to be called to
280 set up the name entry/name label display.
284 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
285 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
287 update_monitoring_display ();
290 mute_button->unset_flags (Gtk::CAN_FOCUS);
291 solo_button->unset_flags (Gtk::CAN_FOCUS);
295 if (_route->is_monitor() || _route->is_master()) {
296 solo_button->hide ();
303 setup_invert_buttons ();
304 set_invert_button_state ();
306 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
307 bus_send_display_changed (s);
309 update_mute_display ();
310 update_solo_display ();
312 if (!ARDOUR_UI::config()->get_blink_rec_arm()) {
313 blink_rec_display(true); // set initial rec-en button state
316 route_color_changed();
320 RouteUI::polarity_changed ()
326 set_invert_button_state ();
330 RouteUI::mute_press (GdkEventButton* ev)
332 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
336 //if this is a binding action, let the ArdourButton handle it
337 if ( BindingProxy::is_bind_action(ev) )
340 multiple_mute_change = false;
342 if (Keyboard::is_context_menu_event (ev)) {
348 mute_menu->popup(0,ev->time);
354 if (Keyboard::is_button2_event (ev)) {
355 // button2-click is "momentary"
357 _mute_release = new SoloMuteRelease (_route->muted ());
360 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
362 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
364 /* toggle mute on everything (but
365 * exclude the master and monitor)
367 * because we are going to erase
368 * elements of the list we need to work
372 boost::shared_ptr<RouteList> copy (new RouteList);
374 *copy = *_session->get_routes ();
376 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
377 if ((*i)->is_master() || (*i)->is_monitor()) {
385 _mute_release->routes = copy;
389 _session->set_mute (copy, !_route->muted());
391 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
393 /* Primary-button1 applies change to the mix group even if it is not active
394 NOTE: Primary-button2 is MIDI learn.
397 boost::shared_ptr<RouteList> rl;
399 if (ev->button == 1) {
401 if (_route->route_group()) {
403 rl = _route->route_group()->route_list();
406 _mute_release->routes = rl;
409 rl.reset (new RouteList);
410 rl->push_back (_route);
414 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
419 /* plain click applies change to this route */
421 boost::shared_ptr<RouteList> rl (new RouteList);
422 rl->push_back (_route);
425 _mute_release->routes = rl;
428 _session->set_mute (rl, !_route->muted());
438 RouteUI::mute_release (GdkEventButton* /*ev*/)
442 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
443 delete _mute_release;
451 RouteUI::edit_output_configuration ()
453 if (output_selector == 0) {
455 boost::shared_ptr<Send> send;
456 boost::shared_ptr<IO> output;
458 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
459 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
460 output = send->output();
462 output = _route->output ();
465 output = _route->output ();
468 output_selector = new IOSelectorWindow (_session, output);
471 if (output_selector->is_visible()) {
472 output_selector->get_toplevel()->get_window()->raise();
474 output_selector->present ();
477 output_selector->set_keep_above (true);
481 RouteUI::edit_input_configuration ()
483 if (input_selector == 0) {
484 input_selector = new IOSelectorWindow (_session, _route->input());
487 if (input_selector->is_visible()) {
488 input_selector->get_toplevel()->get_window()->raise();
490 input_selector->present ();
493 input_selector->set_keep_above (true);
497 RouteUI::solo_press(GdkEventButton* ev)
499 /* ignore double/triple clicks */
501 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
505 //if this is a binding action, let the ArdourButton handle it
506 if ( BindingProxy::is_bind_action(ev) )
509 multiple_solo_change = false;
511 if (Keyboard::is_context_menu_event (ev)) {
513 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
514 ! (solo_safe_led && solo_safe_led->is_visible())) {
516 if (solo_menu == 0) {
520 solo_menu->popup (1, ev->time);
525 if (Keyboard::is_button2_event (ev)) {
527 // button2-click is "momentary"
528 _solo_release = new SoloMuteRelease (_route->self_soloed());
531 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
533 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
535 /* Primary-Tertiary-click applies change to all routes */
538 _solo_release->routes = _session->get_routes ();
542 if (Config->get_solo_control_is_listen_control()) {
543 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
545 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
548 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
550 // Primary-Secondary-click: exclusively solo this track
553 _solo_release->exclusive = true;
555 boost::shared_ptr<RouteList> routes = _session->get_routes();
557 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
558 if ((*i)->soloed ()) {
559 _solo_release->routes_on->push_back (*i);
561 _solo_release->routes_off->push_back (*i);
566 if (Config->get_solo_control_is_listen_control()) {
567 /* ??? we need a just_one_listen() method */
570 _session->set_just_one_solo (_route, true);
573 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
575 // shift-click: toggle solo isolated status
577 _route->set_solo_isolated (!_route->solo_isolated(), this);
578 delete _solo_release;
581 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
583 /* Primary-button1: solo mix group.
584 NOTE: Primary-button2 is MIDI learn.
587 /* Primary-button1 applies change to the mix group even if it is not active
588 NOTE: Primary-button2 is MIDI learn.
591 boost::shared_ptr<RouteList> rl;
593 if (ev->button == 1) {
595 if (_route->route_group()) {
597 rl = _route->route_group()->route_list();
600 _solo_release->routes = rl;
603 rl.reset (new RouteList);
604 rl->push_back (_route);
608 if (Config->get_solo_control_is_listen_control()) {
609 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
611 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
617 /* click: solo this route */
619 boost::shared_ptr<RouteList> rl (new RouteList);
620 rl->push_back (route());
623 _solo_release->routes = rl;
627 if (Config->get_solo_control_is_listen_control()) {
628 _session->set_listen (rl, !_route->listening_via_monitor());
630 _session->set_solo (rl, !_route->self_soloed());
640 RouteUI::solo_release (GdkEventButton* /*ev*/)
644 if (_solo_release->exclusive) {
648 if (Config->get_solo_control_is_listen_control()) {
649 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
651 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
655 delete _solo_release;
663 RouteUI::rec_enable_press(GdkEventButton* ev)
665 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
669 //if this is a binding action, let the ArdourButton handle it
670 if ( BindingProxy::is_bind_action(ev) )
673 if (!_session->engine().connected()) {
674 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
679 if (is_midi_track()) {
681 /* rec-enable button exits from step editing */
683 if (midi_track()->step_editing()) {
684 midi_track()->set_step_editing (false);
689 if (is_track() && rec_enable_button) {
691 if (Keyboard::is_button2_event (ev)) {
693 //rec arm does not have a momentary mode
696 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
699 _session->set_record_enabled (_session->get_routes(), !_route->record_enabled());
701 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
703 /* Primary-button1 applies change to the route group (even if it is not active)
704 NOTE: Primary-button2 is MIDI learn.
707 if (ev->button == 1) {
709 boost::shared_ptr<RouteList> rl;
711 if (_route->route_group()) {
713 rl = _route->route_group()->route_list();
716 rl.reset (new RouteList);
717 rl->push_back (_route);
721 _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
724 } else if (Keyboard::is_context_menu_event (ev)) {
726 /* do this on release */
730 boost::shared_ptr<RouteList> rl (new RouteList);
731 rl->push_back (route());
733 _session->set_record_enabled (rl, !_route->record_enabled());
741 RouteUI::monitoring_changed ()
743 update_monitoring_display ();
747 RouteUI::update_monitoring_display ()
753 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
759 MonitorState ms = t->monitoring_state();
761 if (t->monitoring_choice() & MonitorInput) {
762 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
764 if (ms & MonitoringInput) {
765 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
767 monitor_input_button->unset_active_state ();
771 if (t->monitoring_choice() & MonitorDisk) {
772 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
774 if (ms & MonitoringDisk) {
775 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
777 monitor_disk_button->unset_active_state ();
783 RouteUI::monitor_input_press(GdkEventButton*)
789 RouteUI::monitor_input_release(GdkEventButton* ev)
791 return monitor_release (ev, MonitorInput);
795 RouteUI::monitor_disk_press (GdkEventButton*)
801 RouteUI::monitor_disk_release (GdkEventButton* ev)
803 return monitor_release (ev, MonitorDisk);
807 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
809 if (ev->button != 1) {
813 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
820 boost::shared_ptr<RouteList> rl;
822 /* XXX for now, monitoring choices are orthogonal. cue monitoring
823 will follow in 3.X but requires mixing the input and playback (disk)
824 signal together, which requires yet more buffers.
827 if (t->monitoring_choice() & monitor_choice) {
828 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
830 /* this line will change when the options are non-orthogonal */
831 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
835 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
836 rl = _session->get_routes ();
838 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
839 if (_route->route_group() && _route->route_group()->is_monitoring()) {
840 rl = _route->route_group()->route_list();
842 rl.reset (new RouteList);
843 rl->push_back (route());
846 rl.reset (new RouteList);
847 rl->push_back (route());
851 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
857 RouteUI::build_record_menu ()
863 /* no rec-button context menu for non-MIDI tracks
866 if (is_midi_track()) {
867 record_menu = new Menu;
868 record_menu->set_name ("ArdourContextMenu");
870 using namespace Menu_Helpers;
871 MenuList& items = record_menu->items();
873 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
874 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
876 if (_route->record_enabled()) {
877 step_edit_item->set_sensitive (false);
880 step_edit_item->set_active (midi_track()->step_editing());
885 RouteUI::toggle_step_edit ()
887 if (!is_midi_track() || _route->record_enabled()) {
891 midi_track()->set_step_editing (step_edit_item->get_active());
895 RouteUI::step_edit_changed (bool yn)
898 if (rec_enable_button) {
899 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
902 start_step_editing ();
904 if (step_edit_item) {
905 step_edit_item->set_active (true);
910 if (rec_enable_button) {
911 rec_enable_button->unset_active_state ();
914 stop_step_editing ();
916 if (step_edit_item) {
917 step_edit_item->set_active (false);
923 RouteUI::rec_enable_release (GdkEventButton* ev)
925 if (Keyboard::is_context_menu_event (ev)) {
926 build_record_menu ();
928 record_menu->popup (1, ev->time);
937 RouteUI::build_sends_menu ()
939 using namespace Menu_Helpers;
941 sends_menu = new Menu;
942 sends_menu->set_name ("ArdourContextMenu");
943 MenuList& items = sends_menu->items();
946 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
950 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
954 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
958 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
962 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
966 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
969 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
973 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
976 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
977 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
978 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
983 RouteUI::create_sends (Placement p, bool include_buses)
985 _session->globally_add_internal_sends (_route, p, include_buses);
989 RouteUI::create_selected_sends (Placement p, bool include_buses)
991 boost::shared_ptr<RouteList> rlist (new RouteList);
992 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
994 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
995 RouteTimeAxisView* rtv;
997 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
998 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
999 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1000 rlist->push_back (rui->route());
1006 _session->add_internal_sends (_route, p, rlist);
1010 RouteUI::set_sends_gain_from_track ()
1012 _session->globally_set_send_gains_from_track (_route);
1016 RouteUI::set_sends_gain_to_zero ()
1018 _session->globally_set_send_gains_to_zero (_route);
1022 RouteUI::set_sends_gain_to_unity ()
1024 _session->globally_set_send_gains_to_unity (_route);
1028 RouteUI::show_sends_press(GdkEventButton* ev)
1030 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1034 if (!is_track() && show_sends_button) {
1036 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1038 // do nothing on midi sigc::bind event
1041 } else if (Keyboard::is_context_menu_event (ev)) {
1043 if (sends_menu == 0) {
1044 build_sends_menu ();
1047 sends_menu->popup (0, ev->time);
1051 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1054 set_showing_sends_to (boost::shared_ptr<Route> ());
1056 set_showing_sends_to (_route);
1065 RouteUI::show_sends_release (GdkEventButton*)
1071 RouteUI::send_blink (bool onoff)
1073 if (!show_sends_button) {
1078 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1080 show_sends_button->unset_active_state ();
1084 Gtkmm2ext::ActiveState
1085 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1087 if (r->is_master() || r->is_monitor()) {
1088 return Gtkmm2ext::Off;
1091 if (Config->get_solo_control_is_listen_control()) {
1093 if (r->listening_via_monitor()) {
1094 return Gtkmm2ext::ExplicitActive;
1096 return Gtkmm2ext::Off;
1102 if (!r->self_soloed()) {
1103 return Gtkmm2ext::ImplicitActive;
1105 return Gtkmm2ext::ExplicitActive;
1108 return Gtkmm2ext::Off;
1112 Gtkmm2ext::ActiveState
1113 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1115 if (r->is_master() || r->is_monitor()) {
1116 return Gtkmm2ext::Off;
1119 if (r->solo_isolated()) {
1120 return Gtkmm2ext::ExplicitActive;
1122 return Gtkmm2ext::Off;
1126 Gtkmm2ext::ActiveState
1127 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1129 if (r->is_master() || r->is_monitor()) {
1130 return Gtkmm2ext::Off;
1133 if (r->solo_safe()) {
1134 return Gtkmm2ext::ExplicitActive;
1136 return Gtkmm2ext::Off;
1141 RouteUI::update_solo_display ()
1143 bool yn = _route->solo_safe ();
1145 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1146 solo_safe_check->set_active (yn);
1149 yn = _route->solo_isolated ();
1151 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1152 solo_isolated_check->set_active (yn);
1155 set_button_names ();
1157 if (solo_isolated_led) {
1158 if (_route->solo_isolated()) {
1159 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1161 solo_isolated_led->unset_active_state ();
1165 if (solo_safe_led) {
1166 if (_route->solo_safe()) {
1167 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1169 solo_safe_led->unset_active_state ();
1173 solo_button->set_active_state (solo_active_state (_route));
1175 /* some changes to solo status can affect mute display, so catch up
1178 update_mute_display ();
1182 RouteUI::solo_changed_so_update_mute ()
1184 update_mute_display ();
1188 RouteUI::mute_changed(void* /*src*/)
1190 update_mute_display ();
1194 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1196 if (r->is_monitor()) {
1197 return ActiveState(0);
1201 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1205 return Gtkmm2ext::ExplicitActive;
1206 } else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1207 /* master is NEVER muted by others */
1208 return Gtkmm2ext::ImplicitActive;
1210 /* no mute at all */
1211 return Gtkmm2ext::Off;
1218 return Gtkmm2ext::ExplicitActive;
1220 /* no mute at all */
1221 return Gtkmm2ext::Off;
1225 return ActiveState(0);
1229 RouteUI::update_mute_display ()
1235 mute_button->set_active_state (mute_active_state (_session, _route));
1239 RouteUI::route_rec_enable_changed ()
1241 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1242 update_monitoring_display ();
1246 RouteUI::session_rec_enable_changed ()
1248 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1249 update_monitoring_display ();
1253 RouteUI::blink_rec_display (bool blinkOn)
1255 if (!rec_enable_button || !_route) {
1258 if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1262 if (_route->record_enabled()) {
1263 switch (_session->record_status ()) {
1264 case Session::Recording:
1265 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1268 case Session::Disabled:
1269 case Session::Enabled:
1270 if ( ARDOUR_UI::config()->get_blink_rec_arm() )
1271 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1273 rec_enable_button->set_active_state ( ImplicitActive );
1278 if (step_edit_item) {
1279 step_edit_item->set_sensitive (false);
1283 rec_enable_button->unset_active_state ();
1285 if (step_edit_item) {
1286 step_edit_item->set_sensitive (true);
1291 check_rec_enable_sensitivity ();
1295 RouteUI::build_solo_menu (void)
1297 using namespace Menu_Helpers;
1299 solo_menu = new Menu;
1300 solo_menu->set_name ("ArdourContextMenu");
1301 MenuList& items = solo_menu->items();
1302 Gtk::CheckMenuItem* check;
1304 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1305 check->set_active (_route->solo_isolated());
1306 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1307 items.push_back (CheckMenuElem(*check));
1308 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1311 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1312 check->set_active (_route->solo_safe());
1313 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1314 items.push_back (CheckMenuElem(*check));
1315 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1318 //items.push_back (SeparatorElem());
1319 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1324 RouteUI::build_mute_menu(void)
1326 using namespace Menu_Helpers;
1328 mute_menu = new Menu;
1329 mute_menu->set_name ("ArdourContextMenu");
1331 MenuList& items = mute_menu->items();
1333 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1334 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1335 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1336 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1337 pre_fader_mute_check->show_all();
1339 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1340 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1341 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1342 items.push_back (CheckMenuElem(*post_fader_mute_check));
1343 post_fader_mute_check->show_all();
1345 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1346 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1347 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1348 items.push_back (CheckMenuElem(*listen_mute_check));
1349 listen_mute_check->show_all();
1351 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1352 init_mute_menu(MuteMaster::Main, main_mute_check);
1353 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1354 items.push_back (CheckMenuElem(*main_mute_check));
1355 main_mute_check->show_all();
1357 //items.push_back (SeparatorElem());
1358 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1360 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1364 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1366 check->set_active (_route->mute_points() & mp);
1370 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1372 if (check->get_active()) {
1373 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1375 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1380 RouteUI::muting_change ()
1382 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1385 MuteMaster::MutePoint current = _route->mute_points ();
1387 yn = (current & MuteMaster::PreFader);
1389 if (pre_fader_mute_check->get_active() != yn) {
1390 pre_fader_mute_check->set_active (yn);
1393 yn = (current & MuteMaster::PostFader);
1395 if (post_fader_mute_check->get_active() != yn) {
1396 post_fader_mute_check->set_active (yn);
1399 yn = (current & MuteMaster::Listen);
1401 if (listen_mute_check->get_active() != yn) {
1402 listen_mute_check->set_active (yn);
1405 yn = (current & MuteMaster::Main);
1407 if (main_mute_check->get_active() != yn) {
1408 main_mute_check->set_active (yn);
1413 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1415 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1419 bool view = solo_isolated_led->active_state();
1420 bool model = _route->solo_isolated();
1422 /* called BEFORE the view has changed */
1424 if (ev->button == 1) {
1425 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1428 /* disable isolate for all routes */
1429 DisplaySuspender ds;
1430 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1434 if (model == view) {
1436 /* flip just this route */
1438 boost::shared_ptr<RouteList> rl (new RouteList);
1439 rl->push_back (_route);
1440 DisplaySuspender ds;
1441 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1450 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1452 if (ev->button == 1) {
1453 _route->set_solo_safe (!solo_safe_led->active_state(), this);
1459 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1461 bool view = check->get_active();
1462 bool model = _route->solo_isolated();
1464 /* called AFTER the view has changed */
1466 if (model != view) {
1467 _route->set_solo_isolated (view, this);
1472 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1474 _route->set_solo_safe (check->get_active(), this);
1477 /** Ask the user to choose a colour, and then apply that color to my route
1480 RouteUI::choose_color ()
1483 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1490 /** Set the route's own color. This may not be used for display if
1491 * the route is in a group which shares its color with its routes.
1494 RouteUI::set_color (const Gdk::Color & c)
1496 /* leave _color alone in the group case so that tracks can retain their
1497 * own pre-group colors.
1502 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1504 /* note: we use the route state ID here so that color is the same for both
1505 the time axis view and the mixer strip
1508 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1509 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1512 /** @return GUI state ID for things that are common to the route in all its representations */
1514 RouteUI::route_state_id () const
1516 return string_compose (X_("route %1"), _route->id().to_s());
1520 RouteUI::set_color_from_route ()
1522 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1530 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1533 _color.set_green (g);
1534 _color.set_blue (b);
1540 RouteUI::remove_this_route (bool apply_to_selection)
1542 if (apply_to_selection) {
1543 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1545 if ((route()->is_master() || route()->is_monitor()) &&
1546 !Config->get_allow_special_bus_removal()) {
1547 MessageDialog msg (_("That would be bad news ...."),
1551 msg.set_secondary_text (string_compose (_(
1552 "Removing the master or monitor bus is such a bad idea\n\
1553 that %1 is not going to allow it.\n\
1555 If you really want to do this sort of thing\n\
1556 edit your ardour.rc file to set the\n\
1557 \"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1564 vector<string> choices;
1568 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());
1570 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());
1573 choices.push_back (_("No, do nothing."));
1574 choices.push_back (_("Yes, remove it."));
1578 title = _("Remove track");
1580 title = _("Remove bus");
1583 Choice prompter (title, prompt, choices);
1585 if (prompter.run () == 1) {
1586 Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1592 RouteUI::idle_remove_this_route (RouteUI *rui)
1594 DisplaySuspender ds;
1595 rui->_session->remove_route (rui->route());
1599 /** @return true if this name should be used for the route, otherwise false */
1601 RouteUI::verify_new_route_name (const std::string& name)
1603 if (name.find (':') == string::npos) {
1607 MessageDialog colon_msg (
1608 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1609 false, MESSAGE_QUESTION, BUTTONS_NONE
1612 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1613 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1615 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1619 RouteUI::route_rename ()
1621 ArdourPrompter name_prompter (true);
1626 name_prompter.set_title (_("Rename Track"));
1628 name_prompter.set_title (_("Rename Bus"));
1630 name_prompter.set_prompt (_("New name:"));
1631 name_prompter.set_initial_text (_route->name());
1632 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1633 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1634 name_prompter.show_all ();
1637 switch (name_prompter.run ()) {
1638 case Gtk::RESPONSE_ACCEPT:
1639 name_prompter.get_result (result);
1640 name_prompter.hide ();
1641 if (result.length()) {
1642 if (verify_new_route_name (result)) {
1643 _route->set_name (result);
1646 /* back to name prompter */
1650 /* nothing entered, just get out of here */
1665 RouteUI::property_changed (const PropertyChange& what_changed)
1667 if (what_changed.contains (ARDOUR::Properties::name)) {
1668 name_label.set_text (_route->name());
1673 RouteUI::toggle_comment_editor ()
1675 // if (ignore_toggle) {
1679 if (comment_window && comment_window->is_visible ()) {
1680 comment_window->hide ();
1682 open_comment_editor ();
1688 RouteUI::open_comment_editor ()
1690 if (comment_window == 0) {
1691 setup_comment_editor ();
1695 title = _route->name();
1696 title += _(": comment editor");
1698 comment_window->set_title (title);
1699 comment_window->present();
1703 RouteUI::setup_comment_editor ()
1705 comment_window = new ArdourWindow (""); // title will be reset to show route
1706 comment_window->set_skip_taskbar_hint (true);
1707 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1708 comment_window->set_default_size (400, 200);
1710 comment_area = manage (new TextView());
1711 comment_area->set_name ("MixerTrackCommentArea");
1712 comment_area->set_wrap_mode (WRAP_WORD);
1713 comment_area->set_editable (true);
1714 comment_area->get_buffer()->set_text (_route->comment());
1715 comment_area->show ();
1717 comment_window->add (*comment_area);
1721 RouteUI::comment_changed (void *src)
1723 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1726 ignore_comment_edit = true;
1728 comment_area->get_buffer()->set_text (_route->comment());
1730 ignore_comment_edit = false;
1735 RouteUI::comment_editor_done_editing ()
1737 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1739 string const str = comment_area->get_buffer()->get_text();
1740 if (str == _route->comment ()) {
1744 _route->set_comment (str, this);
1748 RouteUI::set_route_active (bool a, bool apply_to_selection)
1750 if (apply_to_selection) {
1751 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1753 _route->set_active (a, this);
1758 RouteUI::toggle_denormal_protection ()
1760 if (denormal_menu_item) {
1764 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1766 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1767 _route->set_denormal_protection (x);
1773 RouteUI::denormal_protection_changed ()
1775 if (denormal_menu_item) {
1776 denormal_menu_item->set_active (_route->denormal_protection());
1781 RouteUI::disconnect_input ()
1783 _route->input()->disconnect (this);
1787 RouteUI::disconnect_output ()
1789 _route->output()->disconnect (this);
1793 RouteUI::is_track () const
1795 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1798 boost::shared_ptr<Track>
1799 RouteUI::track() const
1801 return boost::dynamic_pointer_cast<Track>(_route);
1805 RouteUI::is_audio_track () const
1807 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1810 boost::shared_ptr<AudioTrack>
1811 RouteUI::audio_track() const
1813 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1817 RouteUI::is_midi_track () const
1819 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1822 boost::shared_ptr<MidiTrack>
1823 RouteUI::midi_track() const
1825 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1829 RouteUI::has_audio_outputs () const
1831 return (_route->n_outputs().n_audio() > 0);
1835 RouteUI::name() const
1837 return _route->name();
1841 RouteUI::map_frozen ()
1843 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1845 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1848 switch (at->freeze_state()) {
1849 case AudioTrack::Frozen:
1850 rec_enable_button->set_sensitive (false);
1853 rec_enable_button->set_sensitive (true);
1860 RouteUI::adjust_latency ()
1862 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1866 RouteUI::save_as_template ()
1869 std::string safe_name;
1872 path = ARDOUR::user_route_template_directory ();
1874 if (g_mkdir_with_parents (path.c_str(), 0755)) {
1875 error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1879 Prompter p (true); // modal
1881 p.set_title (_("Save As Template"));
1882 p.set_prompt (_("Template name:"));
1883 p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1885 case RESPONSE_ACCEPT:
1892 p.get_result (name, true);
1894 safe_name = legalize_for_path (name);
1895 safe_name += template_suffix;
1897 path = Glib::build_filename (path, safe_name);
1899 _route->save_as_template (path, name);
1903 RouteUI::check_rec_enable_sensitivity ()
1905 if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1906 rec_enable_button->set_sensitive (false);
1908 rec_enable_button->set_sensitive (true);
1911 update_monitoring_display ();
1915 RouteUI::parameter_changed (string const & p)
1917 /* this handles RC and per-session parameter changes */
1919 if (p == "disable-disarm-during-roll") {
1920 check_rec_enable_sensitivity ();
1921 } else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1922 set_button_names ();
1923 } else if (p == "auto-input") {
1924 update_monitoring_display ();
1925 } else if (p == "blink-rec-arm") {
1926 if (ARDOUR_UI::config()->get_blink_rec_arm()) {
1927 rec_blink_connection.disconnect ();
1928 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
1930 rec_blink_connection.disconnect ();
1931 RouteUI::blink_rec_display(false);
1937 RouteUI::step_gain_up ()
1939 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1943 RouteUI::page_gain_up ()
1945 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1949 RouteUI::step_gain_down ()
1951 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1955 RouteUI::page_gain_down ()
1957 _route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1961 RouteUI::open_remote_control_id_dialog ()
1963 ArdourDialog dialog (_("Remote Control ID"));
1964 SpinButton* spin = 0;
1966 dialog.get_vbox()->set_border_width (18);
1968 if (Config->get_remote_model() == UserOrdered) {
1969 uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1971 HBox* hbox = manage (new HBox);
1972 hbox->set_spacing (6);
1973 hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1974 spin = manage (new SpinButton);
1975 spin->set_digits (0);
1976 spin->set_increments (1, 10);
1977 spin->set_range (0, limit);
1978 spin->set_value (_route->remote_control_id());
1979 hbox->pack_start (*spin);
1980 dialog.get_vbox()->pack_start (*hbox);
1982 dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1983 dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1985 Label* l = manage (new Label());
1986 if (_route->is_master() || _route->is_monitor()) {
1987 l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1988 "The remote control ID of %3 cannot be changed."),
1989 Glib::Markup::escape_text (_route->name()),
1990 _route->remote_control_id(),
1991 (_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1993 l->set_markup (string_compose (_("The remote control ID of %5 is: %2\n\n\n"
1994 "Remote Control IDs are currently determined by track/bus ordering in %6.\n\n"
1995 "%3Use the User Interaction tab of the Preferences window if you want to change this%4"),
1996 (is_track() ? _("track") : _("bus")),
1997 _route->remote_control_id(),
1998 "<span size=\"small\" style=\"italic\">",
2000 Glib::Markup::escape_text (_route->name()),
2003 dialog.get_vbox()->pack_start (*l);
2004 dialog.add_button (Stock::OK, RESPONSE_CANCEL);
2008 int const r = dialog.run ();
2010 if (r == RESPONSE_ACCEPT && spin) {
2011 _route->set_remote_control_id (spin->get_value_as_int ());
2016 RouteUI::setup_invert_buttons ()
2018 /* remove old invert buttons */
2019 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
2020 _invert_button_box.remove (**i);
2023 _invert_buttons.clear ();
2025 if (!_route || !_route->input()) {
2029 uint32_t const N = _route->input()->n_ports().n_audio ();
2031 uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
2033 for (uint32_t i = 0; i < to_add; ++i) {
2034 ArdourButton* b = manage (new ArdourButton);
2035 b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press), false);
2036 b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i), false);
2038 b->set_name (X_("invert button"));
2041 b->set_text (string_compose (X_("Ø (%1)"), N));
2043 b->set_text (X_("Ø"));
2046 b->set_text (string_compose (X_("Ø%1"), i + 1));
2049 if (N <= _max_invert_buttons) {
2050 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));
2052 UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
2055 _invert_buttons.push_back (b);
2056 _invert_button_box.pack_start (*b);
2059 _invert_button_box.set_spacing (1);
2060 _invert_button_box.show_all ();
2064 RouteUI::set_invert_button_state ()
2066 uint32_t const N = _route->input()->n_ports().n_audio();
2067 if (N > _max_invert_buttons) {
2069 /* One button for many channels; explicit active if all channels are inverted,
2070 implicit active if some are, off if none are.
2073 ArdourButton* b = _invert_buttons.front ();
2075 if (_route->phase_invert().count() == _route->phase_invert().size()) {
2076 b->set_active_state (Gtkmm2ext::ExplicitActive);
2077 } else if (_route->phase_invert().any()) {
2078 b->set_active_state (Gtkmm2ext::ImplicitActive);
2080 b->set_active_state (Gtkmm2ext::Off);
2085 /* One button per channel; just set active */
2088 for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
2089 (*i)->set_active (_route->phase_invert (j));
2096 RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
2098 if (ev->button == 1 && i < _invert_buttons.size()) {
2099 uint32_t const N = _route->input()->n_ports().n_audio ();
2100 if (N <= _max_invert_buttons) {
2101 /* left-click inverts phase so long as we have a button per channel */
2102 _route->set_phase_invert (i, !_invert_buttons[i]->get_active());
2111 RouteUI::invert_press (GdkEventButton* ev)
2113 using namespace Menu_Helpers;
2115 uint32_t const N = _route->input()->n_ports().n_audio();
2116 if (N <= _max_invert_buttons && ev->button != 3) {
2117 /* If we have an invert button per channel, we only pop
2118 up a menu on right-click; left click is handled
2124 delete _invert_menu;
2125 _invert_menu = new Menu;
2126 _invert_menu->set_name ("ArdourContextMenu");
2127 MenuList& items = _invert_menu->items ();
2129 for (uint32_t i = 0; i < N; ++i) {
2130 items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
2131 Gtk::CheckMenuItem* e = dynamic_cast<Gtk::CheckMenuItem*> (&items.back ());
2132 ++_i_am_the_modifier;
2133 e->set_active (_route->phase_invert (i));
2134 --_i_am_the_modifier;
2137 _invert_menu->popup (0, ev->time);
2143 RouteUI::invert_menu_toggled (uint32_t c)
2145 if (_i_am_the_modifier) {
2149 _route->set_phase_invert (c, !_route->phase_invert (c));
2153 RouteUI::set_invert_sensitive (bool yn)
2155 for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
2156 (*b)->set_sensitive (yn);
2161 RouteUI::request_redraw ()
2164 _route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
2168 /** The Route's gui_changed signal has been emitted */
2170 RouteUI::route_gui_changed (string what_changed)
2172 if (what_changed == "color") {
2173 if (set_color_from_route () == 0) {
2174 route_color_changed ();
2180 RouteUI::track_mode_changed (void)
2183 switch (track()->mode()) {
2184 case ARDOUR::NonLayered:
2185 case ARDOUR::Normal:
2186 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton));
2188 case ARDOUR::Destructive:
2189 rec_enable_button->set_elements ((ArdourButton::Element)(ArdourButton::Edge|ArdourButton::Body|ArdourButton::RecButton|ArdourButton::RecTapeMode));
2192 rec_enable_button->queue_draw();
2195 /** @return the color that this route should use; it maybe its own,
2196 or it maybe that of its route group.
2199 RouteUI::color () const
2201 RouteGroup* g = _route->route_group ();
2203 if (g && g->is_color()) {
2205 set_color_from_rgba (c, GroupTabs::group_color (g));
2213 RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2215 _showing_sends_to = send_to;
2216 BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2220 RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2222 if (_route == send_to) {
2223 show_sends_button->set_active (true);
2224 send_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2226 show_sends_button->set_active (false);
2227 send_blink_connection.disconnect ();
2232 RouteUI::route_group() const
2234 return _route->route_group();