2 Copyright (C) 2002-2006 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <gtkmm2ext/gtk_ui.h>
21 #include <gtkmm2ext/choice.h>
22 #include <gtkmm2ext/doi.h>
23 #include <gtkmm2ext/bindable_button.h>
24 #include <gtkmm2ext/barcontroller.h>
25 #include <gtkmm2ext/gtk_ui.h>
26 #include <gtkmm2ext/utils.h>
28 #include "ardour/route_group.h"
29 #include "ardour/dB.h"
30 #include "pbd/memento_command.h"
31 #include "pbd/stacktrace.h"
32 #include "pbd/controllable.h"
33 #include "pbd/enumwriter.h"
35 #include "ardour_ui.h"
38 #include "ardour_button.h"
42 #include "gui_thread.h"
43 #include "ardour_dialog.h"
44 #include "latency_gui.h"
45 #include "mixer_strip.h"
46 #include "automation_time_axis.h"
47 #include "route_time_axis.h"
48 #include "group_tabs.h"
50 #include "ui_config.h"
52 #include "ardour/audio_track.h"
53 #include "ardour/audioengine.h"
54 #include "ardour/filename_extensions.h"
55 #include "ardour/midi_track.h"
56 #include "ardour/internal_send.h"
57 #include "ardour/profile.h"
58 #include "ardour/send.h"
59 #include "ardour/route.h"
60 #include "ardour/session.h"
61 #include "ardour/template_utils.h"
65 using namespace Gtkmm2ext;
66 using namespace ARDOUR;
67 using namespace ARDOUR_UI_UTILS;
71 uint32_t RouteUI::_max_invert_buttons = 3;
72 PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
73 boost::weak_ptr<Route> RouteUI::_showing_sends_to;
75 RouteUI::RouteUI (ARDOUR::Session* sess)
93 gui_object_state().remove_node (route_state_id());
96 _route.reset (); /* drop reference to route, so that it can be cleaned up */
97 route_connections.drop_connections ();
103 delete comment_window;
104 delete input_selector;
105 delete output_selector;
108 send_blink_connection.disconnect ();
109 rec_blink_connection.disconnect ();
115 self_destruct = true;
121 pre_fader_mute_check = 0;
122 post_fader_mute_check = 0;
123 listen_mute_check = 0;
126 solo_isolated_check = 0;
127 solo_isolated_led = 0;
131 denormal_menu_item = 0;
133 multiple_mute_change = false;
134 multiple_solo_change = false;
135 _i_am_the_modifier = 0;
140 setup_invert_buttons ();
142 mute_button = manage (new ArdourButton);
143 mute_button->set_name ("mute button");
144 UI::instance()->set_tip (mute_button, _("Mute this track"), "");
146 solo_button = manage (new ArdourButton);
147 solo_button->set_name ("solo button");
148 UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
149 solo_button->set_no_show_all (true);
151 rec_enable_button = manage (new ArdourButton);
152 rec_enable_button->set_name ("record enable button");
153 rec_enable_button->set_icon (ArdourIcon::RecButton);
154 UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
156 if (UIConfiguration::instance().get_blink_rec_arm()) {
157 rec_blink_connection = Timers::blink_connect (sigc::mem_fun (*this, &RouteUI::blink_rec_display));
160 show_sends_button = manage (new ArdourButton);
161 show_sends_button->set_name ("send alert button");
162 UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
164 monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
165 monitor_input_button->set_name ("monitor button");
166 monitor_input_button->set_text (_("In"));
167 UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
168 monitor_input_button->set_no_show_all (true);
170 monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
171 monitor_disk_button->set_name ("monitor button");
172 monitor_disk_button->set_text (_("Disk"));
173 UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
174 monitor_disk_button->set_no_show_all (true);
176 _session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
177 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
178 _session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
180 _session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
181 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
183 rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
184 rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
186 show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
187 show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release), false);
189 solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
190 solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
191 mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
192 mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
194 monitor_input_button->set_distinct_led_click (false);
195 monitor_disk_button->set_distinct_led_click (false);
197 monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press), false);
198 monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release), false);
200 monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press), false);
201 monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release), false);
203 BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
209 route_connections.drop_connections ();
217 denormal_menu_item = 0;
221 RouteUI::self_delete ()
227 RouteUI::set_route (boost::shared_ptr<Route> rp)
233 if (set_color_from_route()) {
234 set_color (unique_random_color());
238 rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
241 delete input_selector;
244 delete output_selector;
247 mute_button->set_controllable (_route->mute_control());
248 solo_button->set_controllable (_route->solo_control());
250 _route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
251 _route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_mute_display, this), gui_context());
253 _route->comment_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::comment_changed, this, _1), gui_context());
255 _route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
256 _route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
257 _route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
258 _route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
260 track()->TrackModeChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::track_mode_changed, this), gui_context());
261 track_mode_changed();
264 _route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
265 _route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
267 _route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
268 _route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
270 if (_session->writable() && is_track()) {
271 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
273 t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
275 rec_enable_button->show();
276 rec_enable_button->set_controllable (t->rec_enable_control());
278 if (is_midi_track()) {
279 midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
280 boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
285 /* this will work for busses and tracks, and needs to be called to
286 set up the name entry/name label display.
290 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
291 t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
293 update_monitoring_display ();
296 mute_button->unset_flags (Gtk::CAN_FOCUS);
297 solo_button->unset_flags (Gtk::CAN_FOCUS);
301 if (_route->is_monitor() || _route->is_master()) {
302 solo_button->hide ();
309 setup_invert_buttons ();
310 set_invert_button_state ();
312 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
313 bus_send_display_changed (s);
315 update_mute_display ();
316 update_solo_display ();
318 if (!UIConfiguration::instance().get_blink_rec_arm()) {
319 blink_rec_display(true); // set initial rec-en button state
322 route_color_changed();
326 RouteUI::polarity_changed ()
332 set_invert_button_state ();
336 RouteUI::mute_press (GdkEventButton* ev)
338 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
342 //if this is a binding action, let the ArdourButton handle it
343 if ( BindingProxy::is_bind_action(ev) )
346 multiple_mute_change = false;
348 if (Keyboard::is_context_menu_event (ev)) {
354 mute_menu->popup(0,ev->time);
360 if (Keyboard::is_button2_event (ev)) {
361 // button2-click is "momentary"
363 _mute_release = new SoloMuteRelease (_route->muted ());
366 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
368 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
370 /* toggle mute on everything (but
371 * exclude the master and monitor)
373 * because we are going to erase
374 * elements of the list we need to work
378 boost::shared_ptr<RouteList> copy (new RouteList);
380 *copy = *_session->get_routes ();
382 for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
383 if ((*i)->is_master() || (*i)->is_monitor()) {
391 _mute_release->routes = copy;
395 _session->set_mute (copy, !_route->muted());
397 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
399 /* Primary-button1 applies change to the mix group even if it is not active
400 NOTE: Primary-button2 is MIDI learn.
403 boost::shared_ptr<RouteList> rl;
405 if (ev->button == 1) {
407 if (_route->route_group()) {
409 rl = _route->route_group()->route_list();
412 _mute_release->routes = rl;
415 rl.reset (new RouteList);
416 rl->push_back (_route);
420 _session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
425 /* plain click applies change to this route */
427 boost::shared_ptr<RouteList> rl (new RouteList);
428 rl->push_back (_route);
431 _mute_release->routes = rl;
434 _session->set_mute (rl, !_route->muted());
444 RouteUI::mute_release (GdkEventButton* /*ev*/)
448 _session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
449 delete _mute_release;
457 RouteUI::edit_output_configuration ()
459 if (output_selector == 0) {
461 boost::shared_ptr<Send> send;
462 boost::shared_ptr<IO> output;
464 if ((send = boost::dynamic_pointer_cast<Send>(_current_delivery)) != 0) {
465 if (!boost::dynamic_pointer_cast<InternalSend>(send)) {
466 output = send->output();
468 output = _route->output ();
471 output = _route->output ();
474 output_selector = new IOSelectorWindow (_session, output);
477 if (output_selector->is_visible()) {
478 output_selector->get_toplevel()->get_window()->raise();
480 output_selector->present ();
483 //output_selector->set_keep_above (true);
487 RouteUI::edit_input_configuration ()
489 if (input_selector == 0) {
490 input_selector = new IOSelectorWindow (_session, _route->input());
493 if (input_selector->is_visible()) {
494 input_selector->get_toplevel()->get_window()->raise();
496 input_selector->present ();
499 //input_selector->set_keep_above (true);
503 RouteUI::solo_press(GdkEventButton* ev)
505 /* ignore double/triple clicks */
507 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
511 //if this is a binding action, let the ArdourButton handle it
512 if ( BindingProxy::is_bind_action(ev) )
515 multiple_solo_change = false;
517 if (Keyboard::is_context_menu_event (ev)) {
519 if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
520 ! (solo_safe_led && solo_safe_led->is_visible())) {
522 if (solo_menu == 0) {
526 solo_menu->popup (1, ev->time);
531 if (Keyboard::is_button2_event (ev)) {
533 // button2-click is "momentary"
534 _solo_release = new SoloMuteRelease (_route->self_soloed());
537 if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
539 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
541 /* Primary-Tertiary-click applies change to all routes */
544 _solo_release->routes = _session->get_routes ();
548 if (Config->get_solo_control_is_listen_control()) {
549 _session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, false);
551 _session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, false);
554 } else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
556 // Primary-Secondary-click: exclusively solo this track
559 _solo_release->exclusive = true;
561 boost::shared_ptr<RouteList> routes = _session->get_routes();
563 for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
564 if ((*i)->soloed ()) {
565 _solo_release->routes_on->push_back (*i);
567 _solo_release->routes_off->push_back (*i);
572 if (Config->get_solo_control_is_listen_control()) {
573 /* ??? we need a just_one_listen() method */
576 _session->set_just_one_solo (_route, true);
579 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
581 // shift-click: toggle solo isolated status
583 _route->set_solo_isolated (!_route->solo_isolated(), this);
584 delete _solo_release;
587 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
589 /* Primary-button1: solo mix group.
590 NOTE: Primary-button2 is MIDI learn.
593 /* Primary-button1 applies change to the mix group even if it is not active
594 NOTE: Primary-button2 is MIDI learn.
597 boost::shared_ptr<RouteList> rl;
599 if (ev->button == 1) {
600 if (ARDOUR::Profile->get_mixbus() && _route->route_group()) {
602 rl = _route->route_group()->route_list();
605 _solo_release->routes = rl;
608 rl.reset (new RouteList);
609 rl->push_back (_route);
613 if (Config->get_solo_control_is_listen_control()) {
614 _session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
616 _session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
620 delete _solo_release;
625 /* click: solo this route */
627 boost::shared_ptr<RouteList> rl (new RouteList);
628 rl->push_back (route());
631 _solo_release->routes = rl;
635 if (Config->get_solo_control_is_listen_control()) {
636 _session->set_listen (rl, !_route->listening_via_monitor());
638 _session->set_solo (rl, !_route->self_soloed());
648 RouteUI::solo_release (GdkEventButton* /*ev*/)
652 if (_solo_release->exclusive) {
656 if (Config->get_solo_control_is_listen_control()) {
657 _session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, false);
659 _session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, false);
663 delete _solo_release;
671 RouteUI::rec_enable_press(GdkEventButton* ev)
673 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
677 //if this is a binding action, let the ArdourButton handle it
678 if ( BindingProxy::is_bind_action(ev) )
681 if (!_session->engine().connected()) {
682 MessageDialog msg (_("Not connected to AudioEngine - cannot engage record"));
687 if (is_midi_track()) {
689 /* rec-enable button exits from step editing */
691 if (midi_track()->step_editing()) {
692 midi_track()->set_step_editing (false);
697 if (is_track() && rec_enable_button) {
699 if (Keyboard::is_button2_event (ev)) {
701 //rec arm does not have a momentary mode
704 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
707 _session->set_record_enabled (_session->get_routes(), !_route->record_enabled());
709 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
711 /* Primary-button1 applies change to the route group (even if it is not active)
712 NOTE: Primary-button2 is MIDI learn.
715 if (ev->button == 1) {
717 boost::shared_ptr<RouteList> rl;
719 if (_route->route_group()) {
721 rl = _route->route_group()->route_list();
724 rl.reset (new RouteList);
725 rl->push_back (_route);
729 _session->set_record_enabled (rl, !_route->record_enabled(), Session::rt_cleanup, true);
732 } else if (Keyboard::is_context_menu_event (ev)) {
734 /* do this on release */
738 boost::shared_ptr<RouteList> rl (new RouteList);
739 rl->push_back (route());
741 _session->set_record_enabled (rl, !_route->record_enabled());
749 RouteUI::monitoring_changed ()
751 update_monitoring_display ();
755 RouteUI::update_monitoring_display ()
761 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
767 MonitorState ms = t->monitoring_state();
769 if (t->monitoring_choice() & MonitorInput) {
770 monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
772 if (ms & MonitoringInput) {
773 monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
775 monitor_input_button->unset_active_state ();
779 if (t->monitoring_choice() & MonitorDisk) {
780 monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
782 if (ms & MonitoringDisk) {
783 monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
785 monitor_disk_button->unset_active_state ();
791 RouteUI::monitor_input_press(GdkEventButton*)
797 RouteUI::monitor_input_release(GdkEventButton* ev)
799 return monitor_release (ev, MonitorInput);
803 RouteUI::monitor_disk_press (GdkEventButton*)
809 RouteUI::monitor_disk_release (GdkEventButton* ev)
811 return monitor_release (ev, MonitorDisk);
815 RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
817 if (ev->button != 1) {
821 boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
828 boost::shared_ptr<RouteList> rl;
830 /* XXX for now, monitoring choices are orthogonal. cue monitoring
831 will follow in 3.X but requires mixing the input and playback (disk)
832 signal together, which requires yet more buffers.
835 if (t->monitoring_choice() & monitor_choice) {
836 mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
838 /* this line will change when the options are non-orthogonal */
839 // mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
843 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
844 rl = _session->get_routes ();
846 } else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
847 if (_route->route_group() && _route->route_group()->is_monitoring()) {
848 rl = _route->route_group()->route_list();
850 rl.reset (new RouteList);
851 rl->push_back (route());
854 rl.reset (new RouteList);
855 rl->push_back (route());
859 _session->set_monitoring (rl, mc, Session::rt_cleanup, true);
865 RouteUI::build_record_menu ()
871 /* no rec-button context menu for non-MIDI tracks
874 if (is_midi_track()) {
875 record_menu = new Menu;
876 record_menu->set_name ("ArdourContextMenu");
878 using namespace Menu_Helpers;
879 MenuList& items = record_menu->items();
881 items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
882 step_edit_item = dynamic_cast<Gtk::CheckMenuItem*> (&items.back());
884 if (_route->record_enabled()) {
885 step_edit_item->set_sensitive (false);
888 step_edit_item->set_active (midi_track()->step_editing());
893 RouteUI::toggle_step_edit ()
895 if (!is_midi_track() || _route->record_enabled()) {
899 midi_track()->set_step_editing (step_edit_item->get_active());
903 RouteUI::step_edit_changed (bool yn)
906 if (rec_enable_button) {
907 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
910 start_step_editing ();
912 if (step_edit_item) {
913 step_edit_item->set_active (true);
918 if (rec_enable_button) {
919 rec_enable_button->unset_active_state ();
922 stop_step_editing ();
924 if (step_edit_item) {
925 step_edit_item->set_active (false);
931 RouteUI::rec_enable_release (GdkEventButton* ev)
933 if (Keyboard::is_context_menu_event (ev)) {
934 build_record_menu ();
936 record_menu->popup (1, ev->time);
945 RouteUI::build_sends_menu ()
947 using namespace Menu_Helpers;
949 sends_menu = new Menu;
950 sends_menu->set_name ("ArdourContextMenu");
951 MenuList& items = sends_menu->items();
954 MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
958 MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
962 MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
966 MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
970 MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
974 MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
977 MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
981 MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
984 items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
985 items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
986 items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
991 RouteUI::create_sends (Placement p, bool include_buses)
993 _session->globally_add_internal_sends (_route, p, include_buses);
997 RouteUI::create_selected_sends (Placement p, bool include_buses)
999 boost::shared_ptr<RouteList> rlist (new RouteList);
1000 TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
1002 for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
1003 RouteTimeAxisView* rtv;
1005 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
1006 if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
1007 if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
1008 rlist->push_back (rui->route());
1014 _session->add_internal_sends (_route, p, rlist);
1018 RouteUI::set_sends_gain_from_track ()
1020 _session->globally_set_send_gains_from_track (_route);
1024 RouteUI::set_sends_gain_to_zero ()
1026 _session->globally_set_send_gains_to_zero (_route);
1030 RouteUI::set_sends_gain_to_unity ()
1032 _session->globally_set_send_gains_to_unity (_route);
1036 RouteUI::show_sends_press(GdkEventButton* ev)
1038 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
1042 if (!is_track() && show_sends_button) {
1044 if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1046 // do nothing on midi sigc::bind event
1049 } else if (Keyboard::is_context_menu_event (ev)) {
1051 if (sends_menu == 0) {
1052 build_sends_menu ();
1055 sends_menu->popup (0, ev->time);
1059 boost::shared_ptr<Route> s = _showing_sends_to.lock ();
1062 set_showing_sends_to (boost::shared_ptr<Route> ());
1064 set_showing_sends_to (_route);
1073 RouteUI::show_sends_release (GdkEventButton*)
1079 RouteUI::send_blink (bool onoff)
1081 if (!show_sends_button) {
1086 show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
1088 show_sends_button->unset_active_state ();
1092 Gtkmm2ext::ActiveState
1093 RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1095 if (r->is_master() || r->is_monitor()) {
1096 return Gtkmm2ext::Off;
1099 if (Config->get_solo_control_is_listen_control()) {
1101 if (r->listening_via_monitor()) {
1102 return Gtkmm2ext::ExplicitActive;
1104 return Gtkmm2ext::Off;
1110 if (!r->self_soloed()) {
1111 return Gtkmm2ext::ImplicitActive;
1113 return Gtkmm2ext::ExplicitActive;
1116 return Gtkmm2ext::Off;
1120 Gtkmm2ext::ActiveState
1121 RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1123 if (r->is_master() || r->is_monitor()) {
1124 return Gtkmm2ext::Off;
1127 if (r->solo_isolated()) {
1128 return Gtkmm2ext::ExplicitActive;
1130 return Gtkmm2ext::Off;
1134 Gtkmm2ext::ActiveState
1135 RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1137 if (r->is_master() || r->is_monitor()) {
1138 return Gtkmm2ext::Off;
1141 if (r->solo_safe()) {
1142 return Gtkmm2ext::ExplicitActive;
1144 return Gtkmm2ext::Off;
1149 RouteUI::update_solo_display ()
1151 bool yn = _route->solo_safe ();
1153 if (solo_safe_check && solo_safe_check->get_active() != yn) {
1154 solo_safe_check->set_active (yn);
1157 yn = _route->solo_isolated ();
1159 if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1160 solo_isolated_check->set_active (yn);
1163 set_button_names ();
1165 if (solo_isolated_led) {
1166 if (_route->solo_isolated()) {
1167 solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1169 solo_isolated_led->unset_active_state ();
1173 if (solo_safe_led) {
1174 if (_route->solo_safe()) {
1175 solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1177 solo_safe_led->unset_active_state ();
1181 solo_button->set_active_state (solo_active_state (_route));
1183 /* some changes to solo status can affect mute display, so catch up
1186 update_mute_display ();
1190 RouteUI::solo_changed_so_update_mute ()
1192 update_mute_display ();
1196 RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1198 if (r->is_monitor()) {
1199 return ActiveState(0);
1203 if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1207 return Gtkmm2ext::ExplicitActive;
1208 } else if (r->muted_by_others()) {
1209 return Gtkmm2ext::ImplicitActive;
1211 /* no mute at all */
1212 return Gtkmm2ext::Off;
1219 return Gtkmm2ext::ExplicitActive;
1221 /* no mute at all */
1222 return Gtkmm2ext::Off;
1226 return ActiveState(0);
1230 RouteUI::update_mute_display ()
1236 mute_button->set_active_state (mute_active_state (_session, _route));
1240 RouteUI::route_rec_enable_changed ()
1242 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1243 update_monitoring_display ();
1247 RouteUI::session_rec_enable_changed ()
1249 blink_rec_display(true); //this lets the button change "immediately" rather than wait for the next blink
1250 update_monitoring_display ();
1254 RouteUI::blink_rec_display (bool blinkOn)
1256 if (!rec_enable_button || !_route) {
1259 if (boost::dynamic_pointer_cast<Send>(_current_delivery)) {
1263 if (_route->record_enabled()) {
1264 switch (_session->record_status ()) {
1265 case Session::Recording:
1266 rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1269 case Session::Disabled:
1270 case Session::Enabled:
1271 if ( UIConfiguration::instance().get_blink_rec_arm() )
1272 rec_enable_button->set_active_state ( blinkOn ? Gtkmm2ext::ExplicitActive : Gtkmm2ext::Off );
1274 rec_enable_button->set_active_state ( ImplicitActive );
1279 if (step_edit_item) {
1280 step_edit_item->set_sensitive (false);
1284 rec_enable_button->unset_active_state ();
1286 if (step_edit_item) {
1287 step_edit_item->set_sensitive (true);
1292 check_rec_enable_sensitivity ();
1296 RouteUI::build_solo_menu (void)
1298 using namespace Menu_Helpers;
1300 solo_menu = new Menu;
1301 solo_menu->set_name ("ArdourContextMenu");
1302 MenuList& items = solo_menu->items();
1303 Gtk::CheckMenuItem* check;
1305 check = new Gtk::CheckMenuItem(_("Solo Isolate"));
1306 check->set_active (_route->solo_isolated());
1307 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1308 items.push_back (CheckMenuElem(*check));
1309 solo_isolated_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1312 check = new Gtk::CheckMenuItem(_("Solo Safe"));
1313 check->set_active (_route->solo_safe());
1314 check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1315 items.push_back (CheckMenuElem(*check));
1316 solo_safe_check = dynamic_cast<Gtk::CheckMenuItem*>(&items.back());
1319 //items.push_back (SeparatorElem());
1320 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1325 RouteUI::build_mute_menu(void)
1327 using namespace Menu_Helpers;
1329 mute_menu = new Menu;
1330 mute_menu->set_name ("ArdourContextMenu");
1332 MenuList& items = mute_menu->items();
1334 pre_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Pre Fader Sends")));
1335 init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1336 pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1337 items.push_back (CheckMenuElem(*pre_fader_mute_check));
1338 pre_fader_mute_check->show_all();
1340 post_fader_mute_check = manage (new Gtk::CheckMenuItem(_("Post Fader Sends")));
1341 init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1342 post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1343 items.push_back (CheckMenuElem(*post_fader_mute_check));
1344 post_fader_mute_check->show_all();
1346 listen_mute_check = manage (new Gtk::CheckMenuItem(_("Control Outs")));
1347 init_mute_menu(MuteMaster::Listen, listen_mute_check);
1348 listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1349 items.push_back (CheckMenuElem(*listen_mute_check));
1350 listen_mute_check->show_all();
1352 main_mute_check = manage (new Gtk::CheckMenuItem(_("Main Outs")));
1353 init_mute_menu(MuteMaster::Main, main_mute_check);
1354 main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1355 items.push_back (CheckMenuElem(*main_mute_check));
1356 main_mute_check->show_all();
1358 //items.push_back (SeparatorElem());
1359 // items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1361 _route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1365 RouteUI::init_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1367 check->set_active (_route->mute_points() & mp);
1371 RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1373 if (check->get_active()) {
1374 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1376 _route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1381 RouteUI::muting_change ()
1383 ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1386 MuteMaster::MutePoint current = _route->mute_points ();
1388 yn = (current & MuteMaster::PreFader);
1390 if (pre_fader_mute_check->get_active() != yn) {
1391 pre_fader_mute_check->set_active (yn);
1394 yn = (current & MuteMaster::PostFader);
1396 if (post_fader_mute_check->get_active() != yn) {
1397 post_fader_mute_check->set_active (yn);
1400 yn = (current & MuteMaster::Listen);
1402 if (listen_mute_check->get_active() != yn) {
1403 listen_mute_check->set_active (yn);
1406 yn = (current & MuteMaster::Main);
1408 if (main_mute_check->get_active() != yn) {
1409 main_mute_check->set_active (yn);
1414 RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1416 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1420 bool view = solo_isolated_led->active_state();
1421 bool model = _route->solo_isolated();
1423 /* called BEFORE the view has changed */
1425 if (ev->button == 1) {
1426 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1429 /* disable isolate for all routes */
1430 DisplaySuspender ds;
1431 _session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1433 /* enable isolate for all routes */
1434 DisplaySuspender ds;
1435 _session->set_solo_isolated (_session->get_routes(), true, Session::rt_cleanup, true);
1440 if (model == view) {
1442 /* flip just this route */
1444 boost::shared_ptr<RouteList> rl (new RouteList);
1445 rl->push_back (_route);
1446 DisplaySuspender ds;
1447 _session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1456 RouteUI::solo_safe_button_release (GdkEventButton* ev)
1458 if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1462 bool view = solo_safe_led->active_state();
1463 bool model = _route->solo_safe();
1465 if (ev->button == 1) {
1466 if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1467 boost::shared_ptr<RouteList> rl (_session->get_routes());
1469 /* disable solo safe for all routes */
1470 DisplaySuspender ds;
1471 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1472 (*i)->set_solo_safe (false, this);
1475 /* enable solo safe for all routes */
1476 DisplaySuspender ds;
1477 for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
1478 (*i)->set_solo_safe (true, this);
1483 if (model == view) {
1484 /* flip just this route */
1485 _route->set_solo_safe (!view, this);
1494 RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1496 bool view = check->get_active();
1497 bool model = _route->solo_isolated();
1499 /* called AFTER the view has changed */
1501 if (model != view) {
1502 _route->set_solo_isolated (view, this);
1507 RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1509 _route->set_solo_safe (check->get_active(), this);
1512 /** Ask the user to choose a colour, and then apply that color to my route
1515 RouteUI::choose_color ()
1518 Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1525 /** Set the route's own color. This may not be used for display if
1526 * the route is in a group which shares its color with its routes.
1529 RouteUI::set_color (const Gdk::Color & c)
1531 /* leave _color alone in the group case so that tracks can retain their
1532 * own pre-group colors.
1537 snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1539 /* note: we use the route state ID here so that color is the same for both
1540 the time axis view and the mixer strip
1543 gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1544 _route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1547 /** @return GUI state ID for things that are common to the route in all its representations */
1549 RouteUI::route_state_id () const
1551 return string_compose (X_("route %1"), _route->id().to_s());
1555 RouteUI::set_color_from_route ()
1557 const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1565 sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1568 _color.set_green (g);
1569 _color.set_blue (b);
1574 /** @return true if this name should be used for the route, otherwise false */
1576 RouteUI::verify_new_route_name (const std::string& name)
1578 if (name.find (':') == string::npos) {
1582 MessageDialog colon_msg (
1583 _("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1584 false, MESSAGE_QUESTION, BUTTONS_NONE
1587 colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1588 colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1590 return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1594 RouteUI::route_rename ()
1596 ArdourPrompter name_prompter (true);
1601 name_prompter.set_title (_("Rename Track"));
1603 name_prompter.set_title (_("Rename Bus"));
1605 name_prompter.set_prompt (_("New name:"));
1606 name_prompter.set_initial_text (_route->name());
1607 name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1608 name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1609 name_prompter.show_all ();
1612 switch (name_prompter.run ()) {
1613 case Gtk::RESPONSE_ACCEPT:
1614 name_prompter.get_result (result);
1615 name_prompter.hide ();
1616 if (result.length()) {
1617 if (verify_new_route_name (result)) {
1618 _route->set_name (result);
1621 /* back to name prompter */
1625 /* nothing entered, just get out of here */
1640 RouteUI::property_changed (const PropertyChange& what_changed)
1642 if (what_changed.contains (ARDOUR::Properties::name)) {
1643 name_label.set_text (_route->name());
1648 RouteUI::toggle_comment_editor ()
1650 // if (ignore_toggle) {
1654 if (comment_window && comment_window->is_visible ()) {
1655 comment_window->hide ();
1657 open_comment_editor ();
1663 RouteUI::open_comment_editor ()
1665 if (comment_window == 0) {
1666 setup_comment_editor ();
1670 title = _route->name();
1671 title += _(": comment editor");
1673 comment_window->set_title (title);
1674 comment_window->present();
1678 RouteUI::setup_comment_editor ()
1680 comment_window = new ArdourWindow (""); // title will be reset to show route
1681 comment_window->set_skip_taskbar_hint (true);
1682 comment_window->signal_hide().connect (sigc::mem_fun(*this, &MixerStrip::comment_editor_done_editing));
1683 comment_window->set_default_size (400, 200);
1685 comment_area = manage (new TextView());
1686 comment_area->set_name ("MixerTrackCommentArea");
1687 comment_area->set_wrap_mode (WRAP_WORD);
1688 comment_area->set_editable (true);
1689 comment_area->get_buffer()->set_text (_route->comment());
1690 comment_area->show ();
1692 comment_window->add (*comment_area);
1696 RouteUI::comment_changed (void *src)
1698 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_changed, src)
1701 ignore_comment_edit = true;
1703 comment_area->get_buffer()->set_text (_route->comment());
1705 ignore_comment_edit = false;
1710 RouteUI::comment_editor_done_editing ()
1712 ENSURE_GUI_THREAD (*this, &MixerStrip::comment_editor_done_editing, src)
1714 string const str = comment_area->get_buffer()->get_text();
1715 if (str == _route->comment ()) {
1719 _route->set_comment (str, this);
1723 RouteUI::set_route_active (bool a, bool apply_to_selection)
1725 if (apply_to_selection) {
1726 ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1728 _route->set_active (a, this);
1733 RouteUI::toggle_denormal_protection ()
1735 if (denormal_menu_item) {
1739 ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1741 if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1742 _route->set_denormal_protection (x);
1748 RouteUI::denormal_protection_changed ()
1750 if (denormal_menu_item) {
1751 denormal_menu_item->set_active (_route->denormal_protection());
1756 RouteUI::disconnect_input ()
1758 _route->input()->disconnect (this);
1762 RouteUI::disconnect_output ()
1764 _route->output()->disconnect (this);
1768 RouteUI::is_track () const
1770 return boost::dynamic_pointer_cast<Track>(_route) != 0;
1773 boost::shared_ptr<Track>
1774 RouteUI::track() const
1776 return boost::dynamic_pointer_cast<Track>(_route);
1780 RouteUI::is_audio_track () const
1782 return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1785 boost::shared_ptr<AudioTrack>
1786 RouteUI::audio_track() const
1788 return boost::dynamic_pointer_cast<AudioTrack>(_route);
1792 RouteUI::is_midi_track () const
1794 return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1797 boost::shared_ptr<MidiTrack>
1798 RouteUI::midi_track() const
1800 return boost::dynamic_pointer_cast<MidiTrack>(_route);
1804 RouteUI::has_audio_outputs () const
1806 return (_route->n_outputs().n_audio() > 0);
1810 RouteUI::name() const
1812 return _route->name();
1816 RouteUI::map_frozen ()
1818 ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1820 AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1823 switch (at->freeze_state()) {
1824 case AudioTrack::Frozen:
1825 rec_enable_button->set_sensitive (false);
1828 rec_enable_button->set_sensitive (true);
1835 RouteUI::adjust_latency ()
1837 LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), AudioEngine::instance()->samples_per_cycle());
1841 RouteUI::process_save_template_prompter (ArdourPrompter& prompter, const std::string& dir)
1844 std::string safe_name;
1847 prompter.get_result (name, true);
1849 safe_name = legalize_for_path (name);
1850 safe_name += template_suffix;
1852 path = Glib::build_filename (dir, safe_name);
1854 if (Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
1855 bool overwrite = overwrite_file_dialog (prompter,
1856 _("Confirm Template Overwrite"),
1857 _("A template already exists with that name. Do you want to overwrite it?"));
1864 _route->save_as_template (path, name);
1870 RouteUI::save_as_template ()
1874 dir = ARDOUR::user_route_template_directory ();
1876 if (g_mkdir_with_parents (dir.c_str(), 0755)) {
1877 error << string_compose (_("Cannot create route template directory %1"), dir) << endmsg;
1881 ArdourPrompter prompter (true); // modal
1883 prompter.set_title (_("Save As Template"));
1884 prompter.set_prompt (_("Template name:"));
1885 prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1887 bool finished = false;
1889 switch (prompter.run()) {
1890 case RESPONSE_ACCEPT:
1891 finished = process_save_template_prompter (prompter, dir);
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 (UIConfiguration::instance().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 Gtkmm2ext::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 Gtkmm2ext::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_icon (ArdourIcon::RecButton);
2186 case ARDOUR::Destructive:
2187 rec_enable_button->set_icon (ArdourIcon::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();