2
Copyright (C) 2002-2006 Paul Davis
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
#include <gtkmm2ext/gtk_ui.h>
21
#include <gtkmm2ext/choice.h>
22
#include <gtkmm2ext/doi.h>
23
#include <gtkmm2ext/bindable_button.h>
24
#include <gtkmm2ext/barcontroller.h>
25
#include <gtkmm2ext/gtk_ui.h>
27
#include "ardour/route_group.h"
28
#include "ardour/dB.h"
29
#include "pbd/memento_command.h"
30
#include "pbd/stacktrace.h"
31
#include "pbd/controllable.h"
32
#include "pbd/enumwriter.h"
34
#include "ardour_ui.h"
37
#include "ardour_button.h"
41
#include "gui_thread.h"
42
#include "ardour_dialog.h"
43
#include "latency_gui.h"
44
#include "mixer_strip.h"
45
#include "automation_time_axis.h"
46
#include "route_time_axis.h"
47
#include "group_tabs.h"
49
#include "ardour/audio_track.h"
50
#include "ardour/audioengine.h"
51
#include "ardour/filename_extensions.h"
52
#include "ardour/midi_track.h"
53
#include "ardour/route.h"
54
#include "ardour/session.h"
55
#include "ardour/template_utils.h"
59
using namespace Gtkmm2ext;
60
using namespace ARDOUR;
63
uint32_t RouteUI::_max_invert_buttons = 3;
64
PBD::Signal1<void, boost::shared_ptr<Route> > RouteUI::BusSendDisplayChanged;
65
boost::weak_ptr<Route> RouteUI::_showing_sends_to;
67
RouteUI::RouteUI (ARDOUR::Session* sess)
80
_route.reset (); /* drop reference to route, so that it can be cleaned up */
81
route_connections.drop_connections ();
99
pre_fader_mute_check = 0;
100
post_fader_mute_check = 0;
101
listen_mute_check = 0;
104
solo_isolated_check = 0;
105
solo_isolated_led = 0;
109
denormal_menu_item = 0;
111
multiple_mute_change = false;
112
multiple_solo_change = false;
113
_i_am_the_modifier = 0;
115
setup_invert_buttons ();
117
mute_button = manage (new ArdourButton);
118
mute_button->set_name ("mute button");
119
UI::instance()->set_tip (mute_button, _("Mute this track"), "");
121
solo_button = manage (new ArdourButton);
122
solo_button->set_name ("solo button");
123
UI::instance()->set_tip (solo_button, _("Mute other (non-soloed) tracks"), "");
124
solo_button->set_no_show_all (true);
126
rec_enable_button = manage (new ArdourButton);
127
rec_enable_button->set_name ("record enable button");
128
rec_enable_button->set_tweaks (ArdourButton::ImplicitUsesSolidColor);
129
UI::instance()->set_tip (rec_enable_button, _("Enable recording on this track"), "");
131
show_sends_button = manage (new ArdourButton);
132
show_sends_button->set_name ("send alert button");
133
UI::instance()->set_tip (show_sends_button, _("make mixer strips show sends to this bus"), "");
135
monitor_input_button = manage (new ArdourButton (ArdourButton::default_elements));
136
monitor_input_button->set_name ("monitor button");
137
monitor_input_button->set_text (_("In"));
138
UI::instance()->set_tip (monitor_input_button, _("Monitor input"), "");
139
monitor_input_button->set_no_show_all (true);
141
monitor_disk_button = manage (new ArdourButton (ArdourButton::default_elements));
142
monitor_disk_button->set_name ("monitor button");
143
monitor_disk_button->set_text (_("Disk"));
144
UI::instance()->set_tip (monitor_disk_button, _("Monitor playback"), "");
145
monitor_disk_button->set_no_show_all (true);
147
_session->SoloChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::solo_changed_so_update_mute, this), gui_context());
148
_session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::check_rec_enable_sensitivity, this), gui_context());
149
_session->RecordStateChanged.connect (_session_connections, invalidator (*this), boost::bind (&RouteUI::session_rec_enable_changed, this), gui_context());
151
_session->config.ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
152
Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&RouteUI::parameter_changed, this, _1), gui_context());
154
rec_enable_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_press), false);
155
rec_enable_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::rec_enable_release), false);
157
show_sends_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_press), false);
158
show_sends_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::show_sends_release));
160
solo_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::solo_press), false);
161
solo_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::solo_release), false);
162
mute_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::mute_press), false);
163
mute_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::mute_release), false);
165
monitor_input_button->set_distinct_led_click (false);
166
monitor_disk_button->set_distinct_led_click (false);
168
monitor_input_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_press));
169
monitor_input_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_input_release));
171
monitor_disk_button->signal_button_press_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_press));
172
monitor_disk_button->signal_button_release_event().connect (sigc::mem_fun(*this, &RouteUI::monitor_disk_release));
174
BusSendDisplayChanged.connect_same_thread (*this, boost::bind(&RouteUI::bus_send_display_changed, this, _1));
180
route_connections.drop_connections ();
188
denormal_menu_item = 0;
192
RouteUI::self_delete ()
198
RouteUI::set_route (boost::shared_ptr<Route> rp)
204
if (set_color_from_route()) {
205
set_color (unique_random_color());
209
rp->DropReferences.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::self_delete, this), gui_context());
212
mute_button->set_controllable (_route->mute_control());
213
solo_button->set_controllable (_route->solo_control());
215
_route->active_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_active_changed, this), gui_context());
216
_route->mute_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::mute_changed, this, _1), gui_context());
218
_route->solo_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
219
_route->solo_safe_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
220
_route->listen_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
221
_route->solo_isolated_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::update_solo_display, this), gui_context());
223
_route->phase_invert_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::polarity_changed, this), gui_context());
224
_route->PropertyChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::property_changed, this, _1), gui_context());
226
_route->io_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::setup_invert_buttons, this), gui_context ());
227
_route->gui_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_gui_changed, this, _1), gui_context ());
229
if (_session->writable() && is_track()) {
230
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
232
t->RecordEnableChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::route_rec_enable_changed, this), gui_context());
234
rec_enable_button->show();
235
rec_enable_button->set_controllable (t->rec_enable_control());
237
if (is_midi_track()) {
238
midi_track()->StepEditStatusChange.connect (route_connections, invalidator (*this),
239
boost::bind (&RouteUI::step_edit_changed, this, _1), gui_context());
244
/* this will work for busses and tracks, and needs to be called to
245
set up the name entry/name label display.
248
update_rec_display ();
251
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
252
t->MonitoringChanged.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::monitoring_changed, this), gui_context());
254
update_monitoring_display ();
257
mute_button->unset_flags (Gtk::CAN_FOCUS);
258
solo_button->unset_flags (Gtk::CAN_FOCUS);
262
if (_route->is_monitor() || _route->is_master()) {
263
solo_button->hide ();
270
setup_invert_buttons ();
271
set_invert_button_state ();
273
boost::shared_ptr<Route> s = _showing_sends_to.lock ();
274
bus_send_display_changed (s);
276
update_mute_display ();
277
update_solo_display ();
281
RouteUI::polarity_changed ()
287
set_invert_button_state ();
291
RouteUI::mute_press (GdkEventButton* ev)
293
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
297
multiple_mute_change = false;
299
if (!_i_am_the_modifier) {
301
if (Keyboard::is_context_menu_event (ev)) {
307
mute_menu->popup(0,ev->time);
311
if (Keyboard::is_button2_event (ev)) {
312
// Primary-button2 click is the midi binding click
313
// button2-click is "momentary"
316
if (mute_button->on_button_press_event (ev)) {
320
_mute_release = new SoloMuteRelease (_route->muted ());
323
if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
325
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
327
/* toggle mute on everything (but
328
* exclude the master and monitor)
330
* because we are going to erase
331
* elements of the list we need to work
335
boost::shared_ptr<RouteList> copy (new RouteList);
337
*copy = *_session->get_routes ();
339
for (RouteList::iterator i = copy->begin(); i != copy->end(); ) {
340
if ((*i)->is_master() || (*i)->is_monitor()) {
348
_mute_release->routes = copy;
351
_session->set_mute (copy, !_route->muted());
353
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
355
/* Primary-button1 applies change to the mix group even if it is not active
356
NOTE: Primary-button2 is MIDI learn.
359
boost::shared_ptr<RouteList> rl;
361
if (ev->button == 1) {
363
if (_route->route_group()) {
365
rl = _route->route_group()->route_list();
368
_mute_release->routes = rl;
371
rl.reset (new RouteList);
372
rl->push_back (_route);
375
_session->set_mute (rl, !_route->muted(), Session::rt_cleanup, true);
380
/* plain click applies change to this route */
382
boost::shared_ptr<RouteList> rl (new RouteList);
383
rl->push_back (_route);
386
_mute_release->routes = rl;
389
_session->set_mute (rl, !_route->muted());
401
RouteUI::mute_release (GdkEventButton*)
403
if (!_i_am_the_modifier) {
405
_session->set_mute (_mute_release->routes, _mute_release->active, Session::rt_cleanup, true);
406
delete _mute_release;
415
RouteUI::solo_press(GdkEventButton* ev)
417
/* ignore double/triple clicks */
419
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
423
multiple_solo_change = false;
425
if (!_i_am_the_modifier) {
427
if (Keyboard::is_context_menu_event (ev)) {
429
if (! (solo_isolated_led && solo_isolated_led->is_visible()) ||
430
! (solo_safe_led && solo_safe_led->is_visible())) {
432
if (solo_menu == 0) {
436
solo_menu->popup (1, ev->time);
441
if (Keyboard::is_button2_event (ev)) {
443
// Primary-button2 click is the midi binding click
444
// button2-click is "momentary"
446
if (solo_button->on_button_press_event (ev)) {
450
_solo_release = new SoloMuteRelease (_route->self_soloed());
453
if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
455
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
457
/* Primary-Tertiary-click applies change to all routes */
460
_solo_release->routes = _session->get_routes ();
463
if (Config->get_solo_control_is_listen_control()) {
464
_session->set_listen (_session->get_routes(), !_route->listening_via_monitor(), Session::rt_cleanup, true);
466
_session->set_solo (_session->get_routes(), !_route->self_soloed(), Session::rt_cleanup, true);
469
} else if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) {
471
// Primary-Secondary-click: exclusively solo this track
474
_solo_release->exclusive = true;
476
boost::shared_ptr<RouteList> routes = _session->get_routes();
478
for (RouteList::iterator i = routes->begin(); i != routes->end(); ++i) {
479
if ((*i)->soloed ()) {
480
_solo_release->routes_on->push_back (*i);
482
_solo_release->routes_off->push_back (*i);
487
if (Config->get_solo_control_is_listen_control()) {
488
/* ??? we need a just_one_listen() method */
490
_session->set_just_one_solo (_route, true);
493
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
495
// shift-click: toggle solo isolated status
497
_route->set_solo_isolated (!_route->solo_isolated(), this);
498
delete _solo_release;
501
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
503
/* Primary-button1: solo mix group.
504
NOTE: Primary-button2 is MIDI learn.
507
/* Primary-button1 applies change to the mix group even if it is not active
508
NOTE: Primary-button2 is MIDI learn.
511
boost::shared_ptr<RouteList> rl;
513
if (ev->button == 1) {
515
if (_route->route_group()) {
517
rl = _route->route_group()->route_list();
520
_solo_release->routes = rl;
523
rl.reset (new RouteList);
524
rl->push_back (_route);
527
if (Config->get_solo_control_is_listen_control()) {
528
_session->set_listen (rl, !_route->listening_via_monitor(), Session::rt_cleanup, true);
530
_session->set_solo (rl, !_route->self_soloed(), Session::rt_cleanup, true);
536
/* click: solo this route */
538
boost::shared_ptr<RouteList> rl (new RouteList);
539
rl->push_back (route());
542
_solo_release->routes = rl;
545
if (Config->get_solo_control_is_listen_control()) {
546
_session->set_listen (rl, !_route->listening_via_monitor());
548
_session->set_solo (rl, !_route->self_soloed());
559
RouteUI::solo_release (GdkEventButton*)
561
if (!_i_am_the_modifier) {
565
if (_solo_release->exclusive) {
568
if (Config->get_solo_control_is_listen_control()) {
569
_session->set_listen (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
571
_session->set_solo (_solo_release->routes, _solo_release->active, Session::rt_cleanup, true);
575
delete _solo_release;
584
RouteUI::rec_enable_press(GdkEventButton* ev)
586
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
590
if (!_session->engine().connected()) {
591
MessageDialog msg (_("Not connected to JACK - cannot engage record"));
596
if (is_midi_track()) {
598
/* rec-enable button exits from step editing */
600
if (midi_track()->step_editing()) {
601
midi_track()->set_step_editing (false);
606
if (!_i_am_the_modifier && is_track() && rec_enable_button) {
608
if (Keyboard::is_button2_event (ev)) {
610
// do nothing on midi sigc::bind event
611
return rec_enable_button->on_button_press_event (ev);
613
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
615
_session->set_record_enabled (_session->get_routes(), !rec_enable_button->active_state());
617
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
619
/* Primary-button1 applies change to the route group (even if it is not active)
620
NOTE: Primary-button2 is MIDI learn.
623
if (ev->button == 1) {
625
boost::shared_ptr<RouteList> rl;
627
if (_route->route_group()) {
629
rl = _route->route_group()->route_list();
632
rl.reset (new RouteList);
633
rl->push_back (_route);
636
_session->set_record_enabled (rl, !rec_enable_button->active_state(), Session::rt_cleanup, true);
639
} else if (Keyboard::is_context_menu_event (ev)) {
641
/* do this on release */
645
boost::shared_ptr<RouteList> rl (new RouteList);
646
rl->push_back (route());
647
_session->set_record_enabled (rl, !rec_enable_button->active_state());
655
RouteUI::monitoring_changed ()
657
update_monitoring_display ();
661
RouteUI::update_monitoring_display ()
667
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
673
MonitorState ms = t->monitoring_state();
675
if (t->monitoring_choice() & MonitorInput) {
676
monitor_input_button->set_active_state (Gtkmm2ext::ExplicitActive);
678
if (ms & MonitoringInput) {
679
monitor_input_button->set_active_state (Gtkmm2ext::ImplicitActive);
681
monitor_input_button->unset_active_state ();
685
if (t->monitoring_choice() & MonitorDisk) {
686
monitor_disk_button->set_active_state (Gtkmm2ext::ExplicitActive);
688
if (ms & MonitoringDisk) {
689
monitor_disk_button->set_active_state (Gtkmm2ext::ImplicitActive);
691
monitor_disk_button->unset_active_state ();
697
RouteUI::monitor_input_press(GdkEventButton*)
703
RouteUI::monitor_input_release(GdkEventButton* ev)
705
return monitor_release (ev, MonitorInput);
709
RouteUI::monitor_disk_press (GdkEventButton*)
715
RouteUI::monitor_disk_release (GdkEventButton* ev)
717
return monitor_release (ev, MonitorDisk);
721
RouteUI::monitor_release (GdkEventButton* ev, MonitorChoice monitor_choice)
723
if (ev->button != 1) {
727
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
734
boost::shared_ptr<RouteList> rl;
736
/* XXX for now, monitoring choices are orthogonal. cue monitoring
737
will follow in 3.X but requires mixing the input and playback (disk)
738
signal together, which requires yet more buffers.
741
if (t->monitoring_choice() & monitor_choice) {
742
mc = MonitorChoice (t->monitoring_choice() & ~monitor_choice);
744
/* this line will change when the options are non-orthogonal */
745
// mc = MonitorChoice (t->monitoring_choice() | monitor_choice);
749
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
750
rl = _session->get_routes ();
752
} else if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
753
if (_route->route_group() && _route->route_group()->is_monitoring()) {
754
rl = _route->route_group()->route_list();
756
rl.reset (new RouteList);
757
rl->push_back (route());
760
rl.reset (new RouteList);
761
rl->push_back (route());
764
_session->set_monitoring (rl, mc, Session::rt_cleanup, true);
770
RouteUI::build_record_menu ()
776
/* no rec-button context menu for non-MIDI tracks
779
if (is_midi_track()) {
780
record_menu = new Menu;
781
record_menu->set_name ("ArdourContextMenu");
783
using namespace Menu_Helpers;
784
MenuList& items = record_menu->items();
786
items.push_back (CheckMenuElem (_("Step Entry"), sigc::mem_fun (*this, &RouteUI::toggle_step_edit)));
787
step_edit_item = dynamic_cast<CheckMenuItem*> (&items.back());
789
if (_route->record_enabled()) {
790
step_edit_item->set_sensitive (false);
793
step_edit_item->set_active (midi_track()->step_editing());
798
RouteUI::toggle_step_edit ()
800
if (!is_midi_track() || _route->record_enabled()) {
804
midi_track()->set_step_editing (step_edit_item->get_active());
808
RouteUI::step_edit_changed (bool yn)
811
if (rec_enable_button) {
812
rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
815
start_step_editing ();
817
if (step_edit_item) {
818
step_edit_item->set_active (true);
823
if (rec_enable_button) {
824
rec_enable_button->unset_active_state ();
827
stop_step_editing ();
829
if (step_edit_item) {
830
step_edit_item->set_active (false);
836
RouteUI::rec_enable_release (GdkEventButton* ev)
838
if (Keyboard::is_context_menu_event (ev)) {
839
build_record_menu ();
841
record_menu->popup (1, ev->time);
850
RouteUI::build_sends_menu ()
852
using namespace Menu_Helpers;
854
sends_menu = new Menu;
855
sends_menu->set_name ("ArdourContextMenu");
856
MenuList& items = sends_menu->items();
859
MenuElem(_("Assign all tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, false))
863
MenuElem(_("Assign all tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PreFader, true))
867
MenuElem(_("Assign all tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, false))
871
MenuElem(_("Assign all tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_sends), PostFader, true))
875
MenuElem(_("Assign selected tracks (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, false))
879
MenuElem(_("Assign selected tracks and buses (prefader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PreFader, true)));
882
MenuElem(_("Assign selected tracks (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, false))
886
MenuElem(_("Assign selected tracks and buses (postfader)"), sigc::bind (sigc::mem_fun (*this, &RouteUI::create_selected_sends), PostFader, true))
889
items.push_back (MenuElem(_("Copy track/bus gains to sends"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_from_track)));
890
items.push_back (MenuElem(_("Set sends gain to -inf"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_zero)));
891
items.push_back (MenuElem(_("Set sends gain to 0dB"), sigc::mem_fun (*this, &RouteUI::set_sends_gain_to_unity)));
896
RouteUI::create_sends (Placement p, bool include_buses)
898
_session->globally_add_internal_sends (_route, p, include_buses);
902
RouteUI::create_selected_sends (Placement p, bool include_buses)
904
boost::shared_ptr<RouteList> rlist (new RouteList);
905
TrackSelection& selected_tracks (ARDOUR_UI::instance()->the_editor().get_selection().tracks);
907
for (TrackSelection::iterator i = selected_tracks.begin(); i != selected_tracks.end(); ++i) {
908
RouteTimeAxisView* rtv;
910
if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
911
if ((rui = dynamic_cast<RouteUI*>(rtv)) != 0) {
912
if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(rui->route())) {
913
rlist->push_back (rui->route());
919
_session->add_internal_sends (_route, p, rlist);
923
RouteUI::set_sends_gain_from_track ()
925
_session->globally_set_send_gains_from_track (_route);
929
RouteUI::set_sends_gain_to_zero ()
931
_session->globally_set_send_gains_to_zero (_route);
935
RouteUI::set_sends_gain_to_unity ()
937
_session->globally_set_send_gains_to_unity (_route);
941
RouteUI::show_sends_press(GdkEventButton* ev)
943
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS ) {
947
if (!_i_am_the_modifier && !is_track() && show_sends_button) {
949
if (Keyboard::is_button2_event (ev) && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
951
// do nothing on midi sigc::bind event
954
} else if (Keyboard::is_context_menu_event (ev)) {
956
if (sends_menu == 0) {
960
sends_menu->popup (0, ev->time);
964
boost::shared_ptr<Route> s = _showing_sends_to.lock ();
967
set_showing_sends_to (boost::shared_ptr<Route> ());
969
set_showing_sends_to (_route);
978
RouteUI::show_sends_release (GdkEventButton*)
984
RouteUI::send_blink (bool onoff)
986
if (!show_sends_button) {
991
show_sends_button->set_active_state (Gtkmm2ext::ExplicitActive);
993
show_sends_button->unset_active_state ();
997
Gtkmm2ext::ActiveState
998
RouteUI::solo_active_state (boost::shared_ptr<Route> r)
1000
if (r->is_master() || r->is_monitor()) {
1001
return Gtkmm2ext::Off;
1004
if (Config->get_solo_control_is_listen_control()) {
1006
if (r->listening_via_monitor()) {
1007
return Gtkmm2ext::ExplicitActive;
1009
return Gtkmm2ext::Off;
1015
if (!r->self_soloed()) {
1016
return Gtkmm2ext::ImplicitActive;
1018
return Gtkmm2ext::ExplicitActive;
1021
return Gtkmm2ext::Off;
1025
Gtkmm2ext::ActiveState
1026
RouteUI::solo_isolate_active_state (boost::shared_ptr<Route> r)
1028
if (r->is_master() || r->is_monitor()) {
1029
return Gtkmm2ext::Off;
1032
if (r->solo_isolated()) {
1033
return Gtkmm2ext::ExplicitActive;
1035
return Gtkmm2ext::Off;
1039
Gtkmm2ext::ActiveState
1040
RouteUI::solo_safe_active_state (boost::shared_ptr<Route> r)
1042
if (r->is_master() || r->is_monitor()) {
1043
return Gtkmm2ext::Off;
1046
if (r->solo_safe()) {
1047
return Gtkmm2ext::ExplicitActive;
1049
return Gtkmm2ext::Off;
1054
RouteUI::update_solo_display ()
1056
bool yn = _route->solo_safe ();
1058
if (solo_safe_check && solo_safe_check->get_active() != yn) {
1059
solo_safe_check->set_active (yn);
1062
yn = _route->solo_isolated ();
1064
if (solo_isolated_check && solo_isolated_check->get_active() != yn) {
1065
solo_isolated_check->set_active (yn);
1068
set_button_names ();
1070
if (solo_isolated_led) {
1071
if (_route->solo_isolated()) {
1072
solo_isolated_led->set_active_state (Gtkmm2ext::ExplicitActive);
1074
solo_isolated_led->unset_active_state ();
1078
if (solo_safe_led) {
1079
if (_route->solo_safe()) {
1080
solo_safe_led->set_active_state (Gtkmm2ext::ExplicitActive);
1082
solo_safe_led->unset_active_state ();
1086
solo_button->set_active_state (solo_active_state (_route));
1088
/* some changes to solo status can affect mute display, so catch up
1091
update_mute_display ();
1095
RouteUI::solo_changed_so_update_mute ()
1097
update_mute_display ();
1101
RouteUI::mute_changed(void* /*src*/)
1103
update_mute_display ();
1107
RouteUI::mute_active_state (Session* s, boost::shared_ptr<Route> r)
1109
if (r->is_monitor()) {
1110
return ActiveState(0);
1114
if (Config->get_show_solo_mutes() && !Config->get_solo_control_is_listen_control ()) {
1118
return Gtkmm2ext::ExplicitActive;
1119
} else if (!r->is_master() && s->soloing() && !r->soloed() && !r->solo_isolated()) {
1120
/* master is NEVER muted by others */
1121
return Gtkmm2ext::ImplicitActive;
1123
/* no mute at all */
1124
return Gtkmm2ext::Off;
1131
return Gtkmm2ext::ExplicitActive;
1133
/* no mute at all */
1134
return Gtkmm2ext::Off;
1138
return ActiveState(0);
1142
RouteUI::update_mute_display ()
1148
mute_button->set_active_state (mute_active_state (_session, _route));
1152
RouteUI::route_rec_enable_changed ()
1154
update_rec_display ();
1155
update_monitoring_display ();
1159
RouteUI::session_rec_enable_changed ()
1161
update_rec_display ();
1162
update_monitoring_display ();
1166
RouteUI::update_rec_display ()
1168
if (!rec_enable_button || !_route) {
1172
if (_route->record_enabled()) {
1173
switch (_session->record_status ()) {
1174
case Session::Recording:
1175
rec_enable_button->set_active_state (Gtkmm2ext::ExplicitActive);
1178
case Session::Disabled:
1179
case Session::Enabled:
1180
rec_enable_button->set_active_state (Gtkmm2ext::ImplicitActive);
1185
if (step_edit_item) {
1186
step_edit_item->set_sensitive (false);
1190
rec_enable_button->unset_active_state ();
1192
if (step_edit_item) {
1193
step_edit_item->set_sensitive (true);
1198
check_rec_enable_sensitivity ();
1202
RouteUI::build_solo_menu (void)
1204
using namespace Menu_Helpers;
1206
solo_menu = new Menu;
1207
solo_menu->set_name ("ArdourContextMenu");
1208
MenuList& items = solo_menu->items();
1209
CheckMenuItem* check;
1211
check = new CheckMenuItem(_("Solo Isolate"));
1212
check->set_active (_route->solo_isolated());
1213
check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
1214
items.push_back (CheckMenuElem(*check));
1215
solo_isolated_check = dynamic_cast<CheckMenuItem*>(&items.back());
1218
check = new CheckMenuItem(_("Solo Safe"));
1219
check->set_active (_route->solo_safe());
1220
check->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_solo_safe), check));
1221
items.push_back (CheckMenuElem(*check));
1222
solo_safe_check = dynamic_cast<CheckMenuItem*>(&items.back());
1225
//items.push_back (SeparatorElem());
1226
// items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1231
RouteUI::build_mute_menu(void)
1233
using namespace Menu_Helpers;
1235
mute_menu = new Menu;
1236
mute_menu->set_name ("ArdourContextMenu");
1238
MenuList& items = mute_menu->items();
1240
pre_fader_mute_check = manage (new CheckMenuItem(_("Pre Fader")));
1241
init_mute_menu(MuteMaster::PreFader, pre_fader_mute_check);
1242
pre_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PreFader, pre_fader_mute_check));
1243
items.push_back (CheckMenuElem(*pre_fader_mute_check));
1244
pre_fader_mute_check->show_all();
1246
post_fader_mute_check = manage (new CheckMenuItem(_("Post Fader")));
1247
init_mute_menu(MuteMaster::PostFader, post_fader_mute_check);
1248
post_fader_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::PostFader, post_fader_mute_check));
1249
items.push_back (CheckMenuElem(*post_fader_mute_check));
1250
post_fader_mute_check->show_all();
1252
listen_mute_check = manage (new CheckMenuItem(_("Control Outs")));
1253
init_mute_menu(MuteMaster::Listen, listen_mute_check);
1254
listen_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Listen, listen_mute_check));
1255
items.push_back (CheckMenuElem(*listen_mute_check));
1256
listen_mute_check->show_all();
1258
main_mute_check = manage (new CheckMenuItem(_("Main Outs")));
1259
init_mute_menu(MuteMaster::Main, main_mute_check);
1260
main_mute_check->signal_toggled().connect(sigc::bind (sigc::mem_fun (*this, &RouteUI::toggle_mute_menu), MuteMaster::Main, main_mute_check));
1261
items.push_back (CheckMenuElem(*main_mute_check));
1262
main_mute_check->show_all();
1264
//items.push_back (SeparatorElem());
1265
// items.push_back (MenuElem (_("MIDI Bind"), sigc::mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
1267
_route->mute_points_changed.connect (route_connections, invalidator (*this), boost::bind (&RouteUI::muting_change, this), gui_context());
1271
RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
1273
check->set_active (_route->mute_points() & mp);
1277
RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
1279
if (check->get_active()) {
1280
_route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() | mp));
1282
_route->set_mute_points (MuteMaster::MutePoint (_route->mute_points() & ~mp));
1287
RouteUI::muting_change ()
1289
ENSURE_GUI_THREAD (*this, &RouteUI::muting_change)
1292
MuteMaster::MutePoint current = _route->mute_points ();
1294
yn = (current & MuteMaster::PreFader);
1296
if (pre_fader_mute_check->get_active() != yn) {
1297
pre_fader_mute_check->set_active (yn);
1300
yn = (current & MuteMaster::PostFader);
1302
if (post_fader_mute_check->get_active() != yn) {
1303
post_fader_mute_check->set_active (yn);
1306
yn = (current & MuteMaster::Listen);
1308
if (listen_mute_check->get_active() != yn) {
1309
listen_mute_check->set_active (yn);
1312
yn = (current & MuteMaster::Main);
1314
if (main_mute_check->get_active() != yn) {
1315
main_mute_check->set_active (yn);
1320
RouteUI::solo_isolate_button_release (GdkEventButton* ev)
1322
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
1326
bool view = solo_isolated_led->active_state();
1327
bool model = _route->solo_isolated();
1329
/* called BEFORE the view has changed */
1331
if (ev->button == 1) {
1332
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
1335
/* disable isolate for all routes */
1336
_session->set_solo_isolated (_session->get_routes(), false, Session::rt_cleanup, true);
1340
if (model == view) {
1342
/* flip just this route */
1344
boost::shared_ptr<RouteList> rl (new RouteList);
1345
rl->push_back (_route);
1346
_session->set_solo_isolated (rl, !view, Session::rt_cleanup, true);
1355
RouteUI::solo_safe_button_release (GdkEventButton* ev)
1357
if (ev->button == 1) {
1358
_route->set_solo_safe (!solo_safe_led->active_state(), this);
1365
RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
1367
bool view = check->get_active();
1368
bool model = _route->solo_isolated();
1370
/* called AFTER the view has changed */
1372
if (model != view) {
1373
_route->set_solo_isolated (view, this);
1378
RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
1380
_route->set_solo_safe (check->get_active(), this);
1383
/** Ask the user to choose a colour, and then set all selected tracks
1387
RouteUI::choose_color ()
1390
Gdk::Color const color = Gtkmm2ext::UI::instance()->get_color (_("Color Selection"), picked, &_color);
1393
ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (
1394
boost::bind (&RouteUI::set_color, _1, color)
1399
/** Set the route's own color. This may not be used for display if
1400
* the route is in a group which shares its color with its routes.
1403
RouteUI::set_color (const Gdk::Color & c)
1405
/* leave _color alone in the group case so that tracks can retain their
1406
* own pre-group colors.
1411
snprintf (buf, sizeof (buf), "%d:%d:%d", c.get_red(), c.get_green(), c.get_blue());
1413
/* note: we use the route state ID here so that color is the same for both
1414
the time axis view and the mixer strip
1417
gui_object_state().set_property<string> (route_state_id(), X_("color"), buf);
1418
_route->gui_changed ("color", (void *) 0); /* EMIT_SIGNAL */
1421
/** @return GUI state ID for things that are common to the route in all its representations */
1423
RouteUI::route_state_id () const
1425
return string_compose (X_("route %1"), _route->id().to_s());
1429
RouteUI::set_color_from_route ()
1431
const string str = gui_object_state().get_string (route_state_id(), X_("color"));
1439
sscanf (str.c_str(), "%d:%d:%d", &r, &g, &b);
1442
_color.set_green (g);
1443
_color.set_blue (b);
1449
RouteUI::remove_this_route (bool apply_to_selection)
1451
if (apply_to_selection) {
1452
ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteUI::remove_this_route, _1, false));
1454
if ((route()->is_master() || route()->is_monitor()) &&
1455
!Config->get_allow_special_bus_removal()) {
1456
MessageDialog msg (_("That would be bad news ...."),
1460
msg.set_secondary_text (string_compose (_(
1461
"Removing the master or monitor bus is such a bad idea\n\
1462
that %1 is not going to allow it.\n\
1464
If you really want to do this sort of thing\n\
1465
edit your ardour.rc file to set the\n\
1466
\"allow-special-bus-removal\" option to be \"yes\""), PROGRAM_NAME));
1473
vector<string> choices;
1477
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());
1479
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());
1482
choices.push_back (_("No, do nothing."));
1483
choices.push_back (_("Yes, remove it."));
1487
title = _("Remove track");
1489
title = _("Remove bus");
1492
Choice prompter (title, prompt, choices);
1494
if (prompter.run () == 1) {
1495
Glib::signal_idle().connect (sigc::bind (sigc::ptr_fun (&RouteUI::idle_remove_this_route), this));
1501
RouteUI::idle_remove_this_route (RouteUI *rui)
1503
rui->_session->remove_route (rui->route());
1507
/** @return true if this name should be used for the route, otherwise false */
1509
RouteUI::verify_new_route_name (const std::string& name)
1511
if (name.find (':') == string::npos) {
1515
MessageDialog colon_msg (
1516
_("The use of colons (':') is discouraged in track and bus names.\nDo you want to use this new name?"),
1517
false, MESSAGE_QUESTION, BUTTONS_NONE
1520
colon_msg.add_button (_("Use the new name"), Gtk::RESPONSE_ACCEPT);
1521
colon_msg.add_button (_("Re-edit the name"), Gtk::RESPONSE_CANCEL);
1523
return (colon_msg.run () == Gtk::RESPONSE_ACCEPT);
1527
RouteUI::route_rename ()
1529
ArdourPrompter name_prompter (true);
1534
name_prompter.set_title (_("Rename Track"));
1536
name_prompter.set_title (_("Rename Bus"));
1538
name_prompter.set_prompt (_("New name:"));
1539
name_prompter.set_initial_text (_route->name());
1540
name_prompter.add_button (_("Rename"), Gtk::RESPONSE_ACCEPT);
1541
name_prompter.set_response_sensitive (Gtk::RESPONSE_ACCEPT, false);
1542
name_prompter.show_all ();
1545
switch (name_prompter.run ()) {
1546
case Gtk::RESPONSE_ACCEPT:
1547
name_prompter.get_result (result);
1548
name_prompter.hide ();
1549
if (result.length()) {
1550
if (verify_new_route_name (result)) {
1551
_route->set_name (result);
1554
/* back to name prompter */
1558
/* nothing entered, just get out of here */
1573
RouteUI::property_changed (const PropertyChange& what_changed)
1575
if (what_changed.contains (ARDOUR::Properties::name)) {
1576
name_label.set_text (_route->name());
1581
RouteUI::set_route_active (bool a, bool apply_to_selection)
1583
if (apply_to_selection) {
1584
ARDOUR_UI::instance()->the_editor().get_selection().tracks.foreach_route_ui (boost::bind (&RouteTimeAxisView::set_route_active, _1, a, false));
1586
_route->set_active (a, this);
1591
RouteUI::toggle_denormal_protection ()
1593
if (denormal_menu_item) {
1597
ENSURE_GUI_THREAD (*this, &RouteUI::toggle_denormal_protection)
1599
if ((x = denormal_menu_item->get_active()) != _route->denormal_protection()) {
1600
_route->set_denormal_protection (x);
1606
RouteUI::denormal_protection_changed ()
1608
if (denormal_menu_item) {
1609
denormal_menu_item->set_active (_route->denormal_protection());
1614
RouteUI::disconnect_input ()
1616
_route->input()->disconnect (this);
1620
RouteUI::disconnect_output ()
1622
_route->output()->disconnect (this);
1626
RouteUI::is_track () const
1628
return boost::dynamic_pointer_cast<Track>(_route) != 0;
1631
boost::shared_ptr<Track>
1632
RouteUI::track() const
1634
return boost::dynamic_pointer_cast<Track>(_route);
1638
RouteUI::is_audio_track () const
1640
return boost::dynamic_pointer_cast<AudioTrack>(_route) != 0;
1643
boost::shared_ptr<AudioTrack>
1644
RouteUI::audio_track() const
1646
return boost::dynamic_pointer_cast<AudioTrack>(_route);
1650
RouteUI::is_midi_track () const
1652
return boost::dynamic_pointer_cast<MidiTrack>(_route) != 0;
1655
boost::shared_ptr<MidiTrack>
1656
RouteUI::midi_track() const
1658
return boost::dynamic_pointer_cast<MidiTrack>(_route);
1662
RouteUI::has_audio_outputs () const
1664
return (_route->n_outputs().n_audio() > 0);
1668
RouteUI::name() const
1670
return _route->name();
1674
RouteUI::map_frozen ()
1676
ENSURE_GUI_THREAD (*this, &RouteUI::map_frozen)
1678
AudioTrack* at = dynamic_cast<AudioTrack*>(_route.get());
1681
switch (at->freeze_state()) {
1682
case AudioTrack::Frozen:
1683
rec_enable_button->set_sensitive (false);
1686
rec_enable_button->set_sensitive (true);
1693
RouteUI::adjust_latency ()
1695
LatencyDialog dialog (_route->name() + _(" latency"), *(_route->output()), _session->frame_rate(), _session->engine().frames_per_cycle());
1699
RouteUI::save_as_template ()
1702
std::string safe_name;
1705
path = ARDOUR::user_route_template_directory ();
1707
if (g_mkdir_with_parents (path.c_str(), 0755)) {
1708
error << string_compose (_("Cannot create route template directory %1"), path) << endmsg;
1712
Prompter p (true); // modal
1714
p.set_title (_("Save As Template"));
1715
p.set_prompt (_("Template name:"));
1716
p.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
1718
case RESPONSE_ACCEPT:
1725
p.get_result (name, true);
1727
safe_name = legalize_for_path (name);
1728
safe_name += template_suffix;
1730
path = Glib::build_filename (path, safe_name);
1732
_route->save_as_template (path, name);
1736
RouteUI::check_rec_enable_sensitivity ()
1738
if (_session->transport_rolling() && rec_enable_button->active_state() && Config->get_disable_disarm_during_roll()) {
1739
rec_enable_button->set_sensitive (false);
1741
rec_enable_button->set_sensitive (true);
1744
update_monitoring_display ();
1748
RouteUI::parameter_changed (string const & p)
1750
/* this handles RC and per-session parameter changes */
1752
if (p == "disable-disarm-during-roll") {
1753
check_rec_enable_sensitivity ();
1754
} else if (p == "use-monitor-bus" || p == "solo-control-is-listen-control" || p == "listen-position") {
1755
set_button_names ();
1756
} else if (p == "auto-input") {
1757
update_monitoring_display ();
1762
RouteUI::step_gain_up ()
1764
_route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.1), this);
1768
RouteUI::page_gain_up ()
1770
_route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) + 0.5), this);
1774
RouteUI::step_gain_down ()
1776
_route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.1), this);
1780
RouteUI::page_gain_down ()
1782
_route->set_gain (dB_to_coefficient (accurate_coefficient_to_dB (_route->gain_control()->get_value()) - 0.5), this);
1786
RouteUI::open_remote_control_id_dialog ()
1788
ArdourDialog dialog (_("Remote Control ID"));
1789
SpinButton* spin = 0;
1791
dialog.get_vbox()->set_border_width (18);
1793
if (Config->get_remote_model() == UserOrdered) {
1794
uint32_t const limit = _session->ntracks() + _session->nbusses () + 4;
1796
HBox* hbox = manage (new HBox);
1797
hbox->set_spacing (6);
1798
hbox->pack_start (*manage (new Label (_("Remote control ID:"))));
1799
spin = manage (new SpinButton);
1800
spin->set_digits (0);
1801
spin->set_increments (1, 10);
1802
spin->set_range (0, limit);
1803
spin->set_value (_route->remote_control_id());
1804
hbox->pack_start (*spin);
1805
dialog.get_vbox()->pack_start (*hbox);
1807
dialog.add_button (Stock::CANCEL, RESPONSE_CANCEL);
1808
dialog.add_button (Stock::APPLY, RESPONSE_ACCEPT);
1810
Label* l = manage (new Label());
1811
if (_route->is_master() || _route->is_monitor()) {
1812
l->set_markup (string_compose (_("The remote control ID of %1 is: %2\n\n\n"
1813
"The remote control ID of %3 cannot be changed."),
1814
Glib::Markup::escape_text (_route->name()),
1815
_route->remote_control_id(),
1816
(_route->is_master() ? _("the master bus") : _("the monitor bus"))));
1818
l->set_markup (string_compose (_("The remote control ID of %6 is: %3\n\n\n"
1819
"Remote Control IDs are currently determined by track/bus ordering in %1\n\n"
1820
"%4Use the User Interaction tab of the Preferences window if you want to change this%5"),
1821
(Config->get_remote_model() == MixerOrdered ? _("the mixer") : _("the editor")),
1822
(is_track() ? _("track") : _("bus")),
1823
_route->remote_control_id(),
1824
"<span size=\"small\" style=\"italic\">",
1826
Glib::Markup::escape_text (_route->name())));
1828
dialog.get_vbox()->pack_start (*l);
1829
dialog.add_button (Stock::OK, RESPONSE_CANCEL);
1833
int const r = dialog.run ();
1835
if (r == RESPONSE_ACCEPT && spin) {
1836
_route->set_remote_control_id (spin->get_value_as_int ());
1841
RouteUI::setup_invert_buttons ()
1843
/* remove old invert buttons */
1844
for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i) {
1845
_invert_button_box.remove (**i);
1848
_invert_buttons.clear ();
1850
if (!_route || !_route->input()) {
1854
uint32_t const N = _route->input()->n_ports().n_audio ();
1856
uint32_t const to_add = (N <= _max_invert_buttons) ? N : 1;
1858
for (uint32_t i = 0; i < to_add; ++i) {
1859
ArdourButton* b = manage (new ArdourButton);
1860
b->set_size_request(20,20);
1861
b->signal_button_press_event().connect (sigc::mem_fun (*this, &RouteUI::invert_press));
1862
b->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_release), i));
1864
b->set_name (X_("invert button"));
1867
b->set_text (string_compose (X_("Ø (%1)"), N));
1869
b->set_text (X_("Ø"));
1872
b->set_text (string_compose (X_("Ø%1"), i + 1));
1875
if (N <= _max_invert_buttons) {
1876
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));
1878
UI::instance()->set_tip (*b, _("Click to show a menu of channels for inversion (phase reverse)"));
1881
_invert_buttons.push_back (b);
1882
_invert_button_box.pack_start (*b);
1885
_invert_button_box.set_spacing (1);
1886
_invert_button_box.show_all ();
1890
RouteUI::set_invert_button_state ()
1892
++_i_am_the_modifier;
1894
uint32_t const N = _route->input()->n_ports().n_audio();
1895
if (N > _max_invert_buttons) {
1897
/* One button for many channels; explicit active if all channels are inverted,
1898
implicit active if some are, off if none are.
1901
ArdourButton* b = _invert_buttons.front ();
1903
if (_route->phase_invert().count() == _route->phase_invert().size()) {
1904
b->set_active_state (Gtkmm2ext::ExplicitActive);
1905
} else if (_route->phase_invert().any()) {
1906
b->set_active_state (Gtkmm2ext::ImplicitActive);
1908
b->set_active_state (Gtkmm2ext::Off);
1913
/* One button per channel; just set active */
1916
for (vector<ArdourButton*>::iterator i = _invert_buttons.begin(); i != _invert_buttons.end(); ++i, ++j) {
1917
(*i)->set_active (_route->phase_invert (j));
1922
--_i_am_the_modifier;
1926
RouteUI::invert_release (GdkEventButton* ev, uint32_t i)
1928
if (ev->button == 1 && i < _invert_buttons.size()) {
1929
uint32_t const N = _route->input()->n_ports().n_audio ();
1930
if (N <= _max_invert_buttons) {
1931
/* left-click inverts phase so long as we have a button per channel */
1932
_route->set_phase_invert (i, !_invert_buttons[i]->get_active());
1941
RouteUI::invert_press (GdkEventButton* ev)
1943
using namespace Menu_Helpers;
1945
uint32_t const N = _route->input()->n_ports().n_audio();
1946
if (N <= _max_invert_buttons && ev->button != 3) {
1947
/* If we have an invert button per channel, we only pop
1948
up a menu on right-click; left click is handled
1954
delete _invert_menu;
1955
_invert_menu = new Menu;
1956
_invert_menu->set_name ("ArdourContextMenu");
1957
MenuList& items = _invert_menu->items ();
1959
for (uint32_t i = 0; i < N; ++i) {
1960
items.push_back (CheckMenuElem (string_compose (X_("Ø%1"), i + 1), sigc::bind (sigc::mem_fun (*this, &RouteUI::invert_menu_toggled), i)));
1961
CheckMenuItem* e = dynamic_cast<CheckMenuItem*> (&items.back ());
1962
++_i_am_the_modifier;
1963
e->set_active (_route->phase_invert (i));
1964
--_i_am_the_modifier;
1967
_invert_menu->popup (0, ev->time);
1973
RouteUI::invert_menu_toggled (uint32_t c)
1975
if (_i_am_the_modifier) {
1979
_route->set_phase_invert (c, !_route->phase_invert (c));
1983
RouteUI::set_invert_sensitive (bool yn)
1985
for (vector<ArdourButton*>::iterator b = _invert_buttons.begin(); b != _invert_buttons.end(); ++b) {
1986
(*b)->set_sensitive (yn);
1991
RouteUI::request_redraw ()
1994
_route->gui_changed ("track_height", (void *) 0); /* EMIT_SIGNAL */
1998
/** The Route's gui_changed signal has been emitted */
2000
RouteUI::route_gui_changed (string what_changed)
2002
if (what_changed == "color") {
2003
if (set_color_from_route () == 0) {
2004
route_color_changed ();
2009
/** @return the color that this route should use; it maybe its own,
2010
or it maybe that of its route group.
2013
RouteUI::color () const
2015
RouteGroup* g = _route->route_group ();
2017
if (g && g->is_color()) {
2018
return GroupTabs::group_color (g);
2025
RouteUI::set_showing_sends_to (boost::shared_ptr<Route> send_to)
2027
_showing_sends_to = send_to;
2028
BusSendDisplayChanged (send_to); /* EMIT SIGNAL */
2032
RouteUI::bus_send_display_changed (boost::shared_ptr<Route> send_to)
2034
if (_route == send_to) {
2035
show_sends_button->set_active (true);
2036
send_blink_connection = ARDOUR_UI::instance()->Blink.connect (sigc::mem_fun (*this, &RouteUI::send_blink));
2038
show_sends_button->set_active (false);
2039
send_blink_connection.disconnect ();
2044
RouteUI::route_group() const
2046
return _route->route_group();