2 Copyright (C) 2000 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.
25 #include <sigc++/bind.h>
26 #include <pbd/xml++.h>
27 #include <pbd/enumwriter.h>
29 #include <ardour/timestamps.h>
30 #include <ardour/audioengine.h>
31 #include <ardour/route.h>
32 #include <ardour/buffer.h>
33 #include <ardour/insert.h>
34 #include <ardour/send.h>
35 #include <ardour/session.h>
36 #include <ardour/utils.h>
37 #include <ardour/configuration.h>
38 #include <ardour/cycle_timer.h>
39 #include <ardour/route_group.h>
40 #include <ardour/port.h>
41 #include <ardour/audio_port.h>
42 #include <ardour/ladspa_plugin.h>
43 #include <ardour/panner.h>
44 #include <ardour/dB.h>
45 #include <ardour/mix.h>
46 #include <ardour/amp.h>
47 #include <ardour/meter.h>
48 #include <ardour/buffer_set.h>
52 using namespace ARDOUR;
55 uint32_t Route::order_key_cnt = 0;
58 Route::Route (Session& sess, string name, int input_min, int input_max, int output_min, int output_max, Flag flg, DataType default_type)
59 : IO (sess, name, input_min, input_max, output_min, output_max, default_type),
61 _solo_control (X_("solo"), *this, ToggleControllable::SoloControl),
62 _mute_control (X_("mute"), *this, ToggleControllable::MuteControl)
67 Route::Route (Session& sess, const XMLNode& node, DataType default_type)
68 : IO (sess, *node.child ("IO"), default_type),
69 _solo_control (X_("solo"), *this, ToggleControllable::SoloControl),
70 _mute_control (X_("mute"), *this, ToggleControllable::MuteControl)
73 _set_state (node, false);
79 redirect_max_outs.reset();
83 _phase_invert = false;
84 order_keys[N_("signal")] = order_key_cnt++;
87 _meter_point = MeterPostFader;
91 _have_internal_generator = false;
93 _pending_declick = true;
94 _remote_control_id = 0;
99 _mute_affects_pre_fader = Config->get_mute_affects_pre_fader();
100 _mute_affects_post_fader = Config->get_mute_affects_post_fader();
101 _mute_affects_control_outs = Config->get_mute_affects_control_outs();
102 _mute_affects_main_outs = Config->get_mute_affects_main_outs();
105 desired_solo_gain = 1.0;
107 desired_mute_gain = 1.0;
111 input_changed.connect (mem_fun (this, &Route::input_change_handler));
112 output_changed.connect (mem_fun (this, &Route::output_change_handler));
117 clear_redirects (this);
120 delete _control_outs;
125 Route::set_remote_control_id (uint32_t id)
127 if (id != _remote_control_id) {
128 _remote_control_id = id;
129 RemoteControlIDChanged ();
134 Route::remote_control_id() const
136 return _remote_control_id;
140 Route::order_key (string name) const
142 OrderKeys::const_iterator i;
144 if ((i = order_keys.find (name)) == order_keys.end()) {
152 Route::set_order_key (string name, long n)
154 order_keys[name] = n;
155 _session.set_dirty ();
159 Route::inc_gain (gain_t fraction, void *src)
161 IO::inc_gain (fraction, src);
165 Route::set_gain (gain_t val, void *src)
167 if (src != 0 && _mix_group && src != _mix_group && _mix_group->is_active()) {
169 if (_mix_group->is_relative()) {
172 gain_t usable_gain = gain();
173 if (usable_gain < 0.000001f) {
174 usable_gain=0.000001f;
178 if (delta < 0.000001f) {
182 delta -= usable_gain;
184 if (delta == 0.0f) return;
186 gain_t factor = delta / usable_gain;
189 factor = _mix_group->get_max_factor(factor);
190 if (factor == 0.0f) {
195 factor = _mix_group->get_min_factor(factor);
196 if (factor == 0.0f) {
202 _mix_group->apply (&Route::inc_gain, factor, _mix_group);
206 _mix_group->apply (&Route::set_gain, val, _mix_group);
216 IO::set_gain (val, src);
219 /** Process this route for one (sub) cycle (process thread)
221 * @param bufs Scratch buffers to use for the signal path
222 * @param start_frame Initial transport frame
223 * @param end_frame Final transport frame
224 * @param nframes Number of frames to output (to ports)
225 * @param offset Output offset (of port buffers, for split cycles)
227 * Note that (end_frame - start_frame) may not be equal to nframes when the
228 * transport speed isn't 1.0 (eg varispeed).
231 Route::process_output_buffers (BufferSet& bufs,
232 nframes_t start_frame, nframes_t end_frame,
233 nframes_t nframes, nframes_t offset, bool with_redirects, int declick,
236 // This is definitely very audio-only for now
237 assert(_default_type == DataType::AUDIO);
239 RedirectList::iterator i;
240 bool post_fader_work = false;
241 bool mute_declick_applied = false;
247 gain_t* gab = _session.gain_automation_buffer();
249 switch (Config->get_monitoring_model()) {
250 case HardwareMonitoring:
251 case ExternalMonitoring:
258 declick = _pending_declick;
261 Glib::Mutex::Lock cm (control_outs_lock, Glib::TRY_LOCK);
271 Glib::Mutex::Lock dm (declick_lock, Glib::TRY_LOCK);
274 dmg = desired_mute_gain;
275 dsg = desired_solo_gain;
284 /* ----------------------------------------------------------------------------------------------------
285 GLOBAL DECLICK (for transport changes etc.)
286 -------------------------------------------------------------------------------------------------- */
289 Amp::run (bufs, nframes, 0.0, 1.0, false);
290 _pending_declick = 0;
291 } else if (declick < 0) {
292 Amp::run (bufs, nframes, 1.0, 0.0, false);
293 _pending_declick = 0;
296 /* no global declick */
298 if (solo_gain != dsg) {
299 Amp::run (bufs, nframes, solo_gain, dsg, false);
305 /* ----------------------------------------------------------------------------------------------------
306 INPUT METERING & MONITORING
307 -------------------------------------------------------------------------------------------------- */
309 if (meter && (_meter_point == MeterInput)) {
310 _meter->run(bufs, nframes);
313 if (!_soloed && _mute_affects_pre_fader && (mute_gain != dmg)) {
314 Amp::run (bufs, nframes, mute_gain, dmg, false);
316 mute_declick_applied = true;
319 if ((_meter_point == MeterInput) && co) {
321 solo_audible = dsg > 0;
322 mute_audible = dmg > 0;// || !_mute_affects_pre_fader;
324 if ( // muted by solo of another track
328 // muted by mute of this track
332 // rec-enabled but not s/w monitoring
334 // TODO: this is probably wrong
336 (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording()))
340 co->silence (nframes, offset);
344 co->deliver_output (bufs, start_frame, end_frame, nframes, offset);
349 /* ---------------------------------------------------------------------------------------------------
351 -------------------------------------------------------------------------------------------------- */
353 /* FIXME: Somewhere in these loops is where bufs.count() should go from n_inputs() to redirect_max_outs()
354 * (if they differ). Something explicit needs to be done here to make sure the list of redirects will
355 * give us what we need (possibly by inserting transparent 'translators' into the list to make it work) */
357 if (with_redirects) {
358 Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
360 if (mute_gain > 0 || !_mute_affects_pre_fader) {
361 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
362 switch ((*i)->placement()) {
364 (*i)->run (bufs, start_frame, end_frame, nframes, offset);
367 post_fader_work = true;
372 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
373 switch ((*i)->placement()) {
375 (*i)->silence (nframes, offset);
378 post_fader_work = true;
386 // FIXME: for now, just hope the redirects list did what it was supposed to
387 bufs.set_count(n_process_buffers());
390 if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_post_fader) {
391 Amp::run (bufs, nframes, mute_gain, dmg, false);
393 mute_declick_applied = true;
396 /* ----------------------------------------------------------------------------------------------------
397 PRE-FADER METERING & MONITORING
398 -------------------------------------------------------------------------------------------------- */
400 if (meter && (_meter_point == MeterPreFader)) {
401 _meter->run(bufs, nframes);
405 if ((_meter_point == MeterPreFader) && co) {
407 solo_audible = dsg > 0;
408 mute_audible = dmg > 0 || !_mute_affects_pre_fader;
410 if ( // muted by solo of another track
414 // muted by mute of this track
418 // rec-enabled but not s/w monitoring
420 (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording()))
424 co->silence (nframes, offset);
428 co->deliver_output (bufs, start_frame, end_frame, nframes, offset);
433 /* ----------------------------------------------------------------------------------------------------
435 -------------------------------------------------------------------------------------------------- */
437 /* if not recording or recording and requiring any monitor signal, then apply gain */
439 if ( // not recording
441 !(record_enabled() && _session.actively_recording()) ||
445 // h/w monitoring not in use
447 (!Config->get_monitoring_model() == HardwareMonitoring &&
449 // AND software monitoring required
451 Config->get_monitoring_model() == SoftwareMonitoring)) {
453 if (apply_gain_automation) {
456 for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
457 Sample* const sp = i->data(nframes);
459 for (nframes_t nx = 0; nx < nframes; ++nx) {
464 for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
465 Sample* const sp = i->data(nframes);
467 for (nframes_t nx = 0; nx < nframes; ++nx) {
473 if (apply_gain_automation && _session.transport_rolling() && nframes > 0) {
474 _effective_gain = gab[nframes-1];
479 /* manual (scalar) gain */
483 Amp::run (bufs, nframes, _gain, dg, _phase_invert);
486 } else if (_gain != 0 && (_phase_invert || _gain != 1.0)) {
488 /* no need to interpolate current gain value,
489 but its non-unity, so apply it. if the gain
490 is zero, do nothing because we'll ship silence
502 for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
503 Sample* const sp = i->data(nframes);
504 Session::apply_gain_to_buffer(sp,nframes,this_gain);
507 } else if (_gain == 0) {
508 for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
516 /* actively recording, no monitoring required; leave buffers as-is to save CPU cycles */
520 /* ----------------------------------------------------------------------------------------------------
522 -------------------------------------------------------------------------------------------------- */
524 /* note that post_fader_work cannot be true unless with_redirects was also true, so don't test both */
526 if (post_fader_work) {
528 Glib::RWLock::ReaderLock rm (redirect_lock, Glib::TRY_LOCK);
530 if (mute_gain > 0 || !_mute_affects_post_fader) {
531 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
532 switch ((*i)->placement()) {
536 (*i)->run (bufs, start_frame, end_frame, nframes, offset);
541 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
542 switch ((*i)->placement()) {
546 (*i)->silence (nframes, offset);
554 if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_control_outs) {
555 Amp::run (bufs, nframes, mute_gain, dmg, false);
557 mute_declick_applied = true;
560 /* ----------------------------------------------------------------------------------------------------
562 -------------------------------------------------------------------------------------------------- */
564 if ((_meter_point == MeterPostFader) && co) {
566 solo_audible = solo_gain > 0;
567 mute_audible = dmg > 0 || !_mute_affects_control_outs;
569 if ( // silent anyway
571 (_gain == 0 && !apply_gain_automation) ||
573 // muted by solo of another track
577 // muted by mute of this track
581 // recording but not s/w monitoring
583 (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording()))
587 co->silence (nframes, offset);
591 co->deliver_output (bufs, start_frame, end_frame, nframes, offset);
595 /* ----------------------------------------------------------------------
597 ----------------------------------------------------------------------*/
599 if (!_soloed && (mute_gain != dmg) && !mute_declick_applied && _mute_affects_main_outs) {
600 Amp::run (bufs, nframes, mute_gain, dmg, false);
602 mute_declick_applied = true;
605 /* ----------------------------------------------------------------------------------------------------
607 -------------------------------------------------------------------------------------------------- */
609 solo_audible = dsg > 0;
610 mute_audible = dmg > 0 || !_mute_affects_main_outs;
612 if (n_outputs().get(_default_type) == 0) {
616 } else if (no_monitor && record_enabled() && (!Config->get_auto_input() || _session.actively_recording())) {
618 IO::silence (nframes, offset);
622 if ( // silent anyway
624 (_gain == 0 && !apply_gain_automation) ||
626 // muted by solo of another track, but not using control outs for solo
628 (!solo_audible && (Config->get_solo_model() != SoloBus)) ||
630 // muted by mute of this track
636 /* don't use Route::silence() here, because that causes
637 all outputs (sends, port inserts, etc. to be silent).
640 if (_meter_point == MeterPostFader) {
641 peak_meter().reset();
644 IO::silence (nframes, offset);
648 deliver_output(bufs, start_frame, end_frame, nframes, offset);
654 /* ----------------------------------------------------------------------------------------------------
656 -------------------------------------------------------------------------------------------------- */
658 if (meter && (_meter_point == MeterPostFader)) {
659 if ((_gain == 0 && !apply_gain_automation) || dmg == 0) {
662 _meter->run(output_buffers(), nframes, offset);
668 Route::n_process_buffers ()
670 return max (n_inputs(), redirect_max_outs);
674 Route::passthru (nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset, int declick, bool meter_first)
676 BufferSet& bufs = _session.get_scratch_buffers(n_process_buffers());
680 collect_input (bufs, nframes, offset);
682 #define meter_stream meter_first
685 _meter->run(bufs, nframes);
686 meter_stream = false;
691 process_output_buffers (bufs, start_frame, end_frame, nframes, offset, true, declick, meter_stream);
697 Route::passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter)
699 process_output_buffers (_session.get_silent_buffers (n_process_buffers()), start_frame, end_frame, nframes, offset, true, declick, meter);
703 Route::set_solo (bool yn, void *src)
709 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
710 _mix_group->apply (&Route::set_solo, yn, _mix_group);
716 solo_changed (src); /* EMIT SIGNAL */
717 _solo_control.Changed (); /* EMIT SIGNAL */
722 Route::set_solo_mute (bool yn)
724 Glib::Mutex::Lock lm (declick_lock);
726 /* Called by Session in response to another Route being soloed.
729 desired_solo_gain = (yn?0.0:1.0);
733 Route::set_solo_safe (bool yn, void *src)
735 if (_solo_safe != yn) {
737 solo_safe_changed (src); /* EMIT SIGNAL */
742 Route::set_mute (bool yn, void *src)
745 if (_mix_group && src != _mix_group && _mix_group->is_active()) {
746 _mix_group->apply (&Route::set_mute, yn, _mix_group);
752 mute_changed (src); /* EMIT SIGNAL */
754 _mute_control.Changed (); /* EMIT SIGNAL */
756 Glib::Mutex::Lock lm (declick_lock);
757 desired_mute_gain = (yn?0.0f:1.0f);
762 Route::add_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams)
764 ChanCount old_rmo = redirect_max_outs;
766 if (!_session.engine().connected()) {
771 Glib::RWLock::WriterLock lm (redirect_lock);
773 boost::shared_ptr<PluginInsert> pi;
774 boost::shared_ptr<PortInsert> porti;
776 redirect->set_default_type(_default_type);
778 if ((pi = boost::dynamic_pointer_cast<PluginInsert>(redirect)) != 0) {
781 if (pi->input_streams() == ChanCount::ZERO) {
782 /* generator plugin */
783 _have_internal_generator = true;
786 } else if ((porti = boost::dynamic_pointer_cast<PortInsert>(redirect)) != 0) {
788 /* force new port inserts to start out with an i/o configuration
789 that matches this route's i/o configuration.
791 the "inputs" for the port are supposed to match the output
794 the "outputs" of the route should match the inputs of this
795 route. XXX shouldn't they match the number of active signal
796 streams at the point of insertion?
798 // FIXME: (yes, they should)
800 porti->ensure_io (n_outputs (), n_inputs(), false, this);
803 // Ensure peak vector sizes before the plugin is activated
804 ChanCount potential_max_streams = max(redirect->input_streams(), redirect->output_streams());
805 _meter->setup(potential_max_streams);
807 _redirects.push_back (redirect);
809 if (_reset_plugin_counts (err_streams)) {
810 _redirects.pop_back ();
811 _reset_plugin_counts (0); // it worked before we tried to add it ...
815 redirect->activate ();
816 redirect->active_changed.connect (mem_fun (*this, &Route::redirect_active_proxy));
819 if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
824 redirects_changed (src); /* EMIT SIGNAL */
829 Route::add_redirects (const RedirectList& others, void *src, uint32_t* err_streams)
831 ChanCount old_rmo = redirect_max_outs;
833 if (!_session.engine().connected()) {
838 Glib::RWLock::WriterLock lm (redirect_lock);
840 RedirectList::iterator existing_end = _redirects.end();
843 ChanCount potential_max_streams;
845 for (RedirectList::const_iterator i = others.begin(); i != others.end(); ++i) {
847 boost::shared_ptr<PluginInsert> pi;
849 if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
852 ChanCount m = max(pi->input_streams(), pi->output_streams());
853 if (m > potential_max_streams)
854 potential_max_streams = m;
857 // Ensure peak vector sizes before the plugin is activated
858 _meter->setup(potential_max_streams);
860 _redirects.push_back (*i);
862 if (_reset_plugin_counts (err_streams)) {
864 _redirects.erase (existing_end, _redirects.end());
865 _reset_plugin_counts (0); // it worked before we tried to add it ...
870 (*i)->active_changed.connect (mem_fun (*this, &Route::redirect_active_proxy));
874 if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
878 redirects_changed (src); /* EMIT SIGNAL */
883 Route::clear_redirects (void *src)
885 ChanCount old_rmo = redirect_max_outs;
887 if (!_session.engine().connected()) {
892 Glib::RWLock::WriterLock lm (redirect_lock);
893 RedirectList::iterator i;
894 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
895 (*i)->drop_references ();
900 if (redirect_max_outs != old_rmo) {
904 redirect_max_outs.reset();
905 _have_internal_generator = false;
906 redirects_changed (src); /* EMIT SIGNAL */
910 Route::remove_redirect (boost::shared_ptr<Redirect> redirect, void *src, uint32_t* err_streams)
912 ChanCount old_rmo = redirect_max_outs;
914 if (!_session.engine().connected()) {
918 redirect_max_outs.reset();
921 Glib::RWLock::WriterLock lm (redirect_lock);
922 RedirectList::iterator i;
923 bool removed = false;
925 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
926 if (*i == redirect) {
928 RedirectList::iterator tmp;
930 /* move along, see failure case for reset_plugin_counts()
931 where we may need to reinsert the redirect.
937 /* stop redirects that send signals to JACK ports
938 from causing noise as a result of no longer being
942 boost::shared_ptr<Send> send;
943 boost::shared_ptr<PortInsert> port_insert;
945 if ((send = boost::dynamic_pointer_cast<Send> (*i)) != 0) {
946 send->disconnect_inputs (this);
947 send->disconnect_outputs (this);
948 } else if ((port_insert = boost::dynamic_pointer_cast<PortInsert> (*i)) != 0) {
949 port_insert->disconnect_inputs (this);
950 port_insert->disconnect_outputs (this);
953 _redirects.erase (i);
966 if (_reset_plugin_counts (err_streams)) {
967 /* get back to where we where */
968 _redirects.insert (i, redirect);
969 /* we know this will work, because it worked before :) */
970 _reset_plugin_counts (0);
976 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
977 boost::shared_ptr<PluginInsert> pi;
979 if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
980 if (pi->is_generator()) {
986 _have_internal_generator = foo;
989 if (old_rmo != redirect_max_outs) {
993 redirect->drop_references ();
995 redirects_changed (src); /* EMIT SIGNAL */
1000 Route::reset_plugin_counts (uint32_t* lpc)
1002 Glib::RWLock::WriterLock lm (redirect_lock);
1003 return _reset_plugin_counts (lpc);
1008 Route::_reset_plugin_counts (uint32_t* err_streams)
1010 RedirectList::iterator r;
1013 map<Placement,list<InsertCount> > insert_map;
1014 nframes_t initial_streams;
1016 redirect_max_outs.reset();
1020 /* divide inserts up by placement so we get the signal flow
1021 properly modelled. we need to do this because the _redirects
1022 list is not sorted by placement, and because other reasons may
1023 exist now or in the future for this separate treatment.
1026 for (r = _redirects.begin(); r != _redirects.end(); ++r) {
1028 boost::shared_ptr<Insert> insert;
1030 /* do this here in case we bomb out before we get to the end of
1034 redirect_max_outs = max ((*r)->output_streams (), redirect_max_outs);
1036 if ((insert = boost::dynamic_pointer_cast<Insert>(*r)) != 0) {
1038 insert_map[insert->placement()].push_back (InsertCount (insert));
1040 /* reset plugin counts back to one for now so
1041 that we have a predictable, controlled
1042 state to try to configure.
1045 boost::shared_ptr<PluginInsert> pi;
1047 if ((pi = boost::dynamic_pointer_cast<PluginInsert>(insert)) != 0) {
1051 } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
1064 /* Now process each placement in order, checking to see if we
1065 can really do what has been requested.
1070 if (check_some_plugin_counts (insert_map[PreFader], n_inputs ().get(_default_type), err_streams)) {
1074 /* figure out the streams that will feed into PreFader */
1076 if (!insert_map[PreFader].empty()) {
1077 InsertCount& ic (insert_map[PreFader].back());
1078 initial_streams = ic.insert->compute_output_streams (ic.cnt);
1080 initial_streams = n_inputs ().get(_default_type);
1085 if (check_some_plugin_counts (insert_map[PostFader], initial_streams, err_streams)) {
1089 /* OK, everything can be set up correctly, so lets do it */
1091 apply_some_plugin_counts (insert_map[PreFader]);
1092 apply_some_plugin_counts (insert_map[PostFader]);
1094 /* recompute max outs of any redirect */
1098 redirect_max_outs.reset();
1099 RedirectList::iterator prev = _redirects.end();
1101 for (r = _redirects.begin(); r != _redirects.end(); prev = r, ++r) {
1102 boost::shared_ptr<Send> s;
1104 if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
1105 if (r == _redirects.begin()) {
1106 s->expect_inputs (n_inputs());
1108 s->expect_inputs ((*prev)->output_streams());
1112 redirect_max_outs = max ((*r)->output_streams(), redirect_max_outs);
1121 Route::apply_some_plugin_counts (list<InsertCount>& iclist)
1123 list<InsertCount>::iterator i;
1125 for (i = iclist.begin(); i != iclist.end(); ++i) {
1127 if ((*i).insert->configure_io ((*i).cnt, (*i).in, (*i).out)) {
1130 /* make sure that however many we have, they are all active */
1131 (*i).insert->activate ();
1138 Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inputs, uint32_t* err_streams)
1140 list<InsertCount>::iterator i;
1142 for (i = iclist.begin(); i != iclist.end(); ++i) {
1144 if (((*i).cnt = (*i).insert->can_support_input_configuration (required_inputs)) < 0) {
1146 *err_streams = required_inputs;
1151 (*i).in = required_inputs;
1152 (*i).out = (*i).insert->compute_output_streams ((*i).cnt);
1154 required_inputs = (*i).out;
1161 Route::copy_redirects (const Route& other, Placement placement, uint32_t* err_streams)
1163 ChanCount old_rmo = redirect_max_outs;
1169 RedirectList to_be_deleted;
1172 Glib::RWLock::WriterLock lm (redirect_lock);
1173 RedirectList::iterator tmp;
1174 RedirectList the_copy;
1176 the_copy = _redirects;
1178 /* remove all relevant redirects */
1180 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ) {
1184 if ((*i)->placement() == placement) {
1185 to_be_deleted.push_back (*i);
1186 _redirects.erase (i);
1192 /* now copy the relevant ones from "other" */
1194 for (RedirectList::const_iterator i = other._redirects.begin(); i != other._redirects.end(); ++i) {
1195 if ((*i)->placement() == placement) {
1196 _redirects.push_back (Redirect::clone (*i));
1200 /* reset plugin stream handling */
1202 if (_reset_plugin_counts (err_streams)) {
1204 /* FAILED COPY ATTEMPT: we have to restore order */
1206 /* delete all cloned redirects */
1208 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ) {
1213 if ((*i)->placement() == placement) {
1214 _redirects.erase (i);
1220 /* restore the natural order */
1222 _redirects = the_copy;
1223 redirect_max_outs = old_rmo;
1225 /* we failed, even though things are OK again */
1231 /* SUCCESSFUL COPY ATTEMPT: delete the redirects we removed pre-copy */
1232 to_be_deleted.clear ();
1236 if (redirect_max_outs != old_rmo || old_rmo == ChanCount::ZERO) {
1240 redirects_changed (this); /* EMIT SIGNAL */
1245 Route::all_redirects_flip ()
1247 Glib::RWLock::ReaderLock lm (redirect_lock);
1249 if (_redirects.empty()) {
1253 bool first_is_on = _redirects.front()->active();
1255 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1256 (*i)->set_active (!first_is_on, this);
1261 Route::all_redirects_active (bool state)
1263 Glib::RWLock::ReaderLock lm (redirect_lock);
1265 if (_redirects.empty()) {
1269 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1270 (*i)->set_active (state, this);
1274 struct RedirectSorter {
1275 bool operator() (boost::shared_ptr<const Redirect> a, boost::shared_ptr<const Redirect> b) {
1276 return a->sort_key() < b->sort_key();
1281 Route::sort_redirects (uint32_t* err_streams)
1284 RedirectSorter comparator;
1285 Glib::RWLock::WriterLock lm (redirect_lock);
1286 ChanCount old_rmo = redirect_max_outs;
1288 /* the sweet power of C++ ... */
1290 RedirectList as_it_was_before = _redirects;
1292 _redirects.sort (comparator);
1294 if (_reset_plugin_counts (err_streams)) {
1295 _redirects = as_it_was_before;
1296 redirect_max_outs = old_rmo;
1302 redirects_changed (this); /* EMIT SIGNAL */
1314 Route::get_template()
1316 return state(false);
1320 Route::state(bool full_state)
1322 XMLNode *node = new XMLNode("Route");
1323 RedirectList:: iterator i;
1327 node->add_property("flags", enum_2_string (_flags));
1330 node->add_property("default-type", _default_type.to_string());
1332 node->add_property("active", _active?"yes":"no");
1333 node->add_property("muted", _muted?"yes":"no");
1334 node->add_property("soloed", _soloed?"yes":"no");
1335 node->add_property("phase-invert", _phase_invert?"yes":"no");
1336 node->add_property("mute-affects-pre-fader", _mute_affects_pre_fader?"yes":"no");
1337 node->add_property("mute-affects-post-fader", _mute_affects_post_fader?"yes":"no");
1338 node->add_property("mute-affects-control-outs", _mute_affects_control_outs?"yes":"no");
1339 node->add_property("mute-affects-main-outs", _mute_affects_main_outs?"yes":"no");
1342 node->add_property("edit-group", _edit_group->name());
1345 node->add_property("mix-group", _mix_group->name());
1348 string order_string;
1349 OrderKeys::iterator x = order_keys.begin();
1351 while (x != order_keys.end()) {
1352 order_string += (*x).first;
1353 order_string += '=';
1354 snprintf (buf, sizeof(buf), "%ld", (*x).second);
1355 order_string += buf;
1359 if (x == order_keys.end()) {
1363 order_string += ':';
1365 node->add_property ("order-keys", order_string);
1367 node->add_child_nocopy (IO::state (full_state));
1368 node->add_child_nocopy (_solo_control.get_state ());
1369 node->add_child_nocopy (_mute_control.get_state ());
1371 if (_control_outs) {
1372 XMLNode* cnode = new XMLNode (X_("ControlOuts"));
1373 cnode->add_child_nocopy (_control_outs->state (full_state));
1374 node->add_child_nocopy (*cnode);
1377 if (_comment.length()) {
1378 XMLNode *cmt = node->add_child ("Comment");
1379 cmt->add_content (_comment);
1382 for (i = _redirects.begin(); i != _redirects.end(); ++i) {
1383 node->add_child_nocopy((*i)->state (full_state));
1387 node->add_child_copy (*_extra_xml);
1394 Route::set_deferred_state ()
1397 XMLNodeConstIterator niter;
1399 if (!deferred_state) {
1403 nlist = deferred_state->children();
1405 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
1406 add_redirect_from_xml (**niter);
1409 delete deferred_state;
1414 Route::add_redirect_from_xml (const XMLNode& node)
1416 const XMLProperty *prop;
1418 if (node.name() == "Send") {
1422 boost::shared_ptr<Send> send (new Send (_session, node));
1423 add_redirect (send, this);
1426 catch (failed_constructor &err) {
1427 error << _("Send construction failed") << endmsg;
1431 } else if (node.name() == "Insert") {
1434 if ((prop = node.property ("type")) != 0) {
1436 boost::shared_ptr<Insert> insert;
1438 if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "vst") {
1440 insert.reset (new PluginInsert(_session, node));
1442 } else if (prop->value() == "port") {
1445 insert.reset (new PortInsert (_session, node));
1449 error << string_compose(_("unknown Insert type \"%1\"; ignored"), prop->value()) << endmsg;
1452 add_redirect (insert, this);
1455 error << _("Insert XML node has no type property") << endmsg;
1459 catch (failed_constructor &err) {
1460 warning << _("insert could not be created. Ignored.") << endmsg;
1467 Route::set_state (const XMLNode& node)
1469 return _set_state (node, true);
1473 Route::_set_state (const XMLNode& node, bool call_base)
1476 XMLNodeConstIterator niter;
1478 XMLPropertyList plist;
1479 const XMLProperty *prop;
1481 if (node.name() != "Route"){
1482 error << string_compose(_("Bad node sent to Route::set_state() [%1]"), node.name()) << endmsg;
1486 if ((prop = node.property (X_("flags"))) != 0) {
1487 _flags = Flag (string_2_enum (prop->value(), _flags));
1492 if ((prop = node.property (X_("default-type"))) != 0) {
1493 _default_type = DataType(prop->value());
1494 assert(_default_type != DataType::NIL);
1497 if ((prop = node.property (X_("phase-invert"))) != 0) {
1498 set_phase_invert(prop->value()=="yes"?true:false, this);
1501 if ((prop = node.property (X_("active"))) != 0) {
1502 set_active (prop->value() == "yes");
1505 if ((prop = node.property (X_("muted"))) != 0) {
1506 bool yn = prop->value()=="yes"?true:false;
1508 /* force reset of mute status */
1512 mute_gain = desired_mute_gain;
1515 if ((prop = node.property (X_("soloed"))) != 0) {
1516 bool yn = prop->value()=="yes"?true:false;
1518 /* force reset of solo status */
1521 set_solo (yn, this);
1522 solo_gain = desired_solo_gain;
1525 if ((prop = node.property (X_("mute-affects-pre-fader"))) != 0) {
1526 _mute_affects_pre_fader = (prop->value()=="yes")?true:false;
1529 if ((prop = node.property (X_("mute-affects-post-fader"))) != 0) {
1530 _mute_affects_post_fader = (prop->value()=="yes")?true:false;
1533 if ((prop = node.property (X_("mute-affects-control-outs"))) != 0) {
1534 _mute_affects_control_outs = (prop->value()=="yes")?true:false;
1537 if ((prop = node.property (X_("mute-affects-main-outs"))) != 0) {
1538 _mute_affects_main_outs = (prop->value()=="yes")?true:false;
1541 if ((prop = node.property (X_("edit-group"))) != 0) {
1542 RouteGroup* edit_group = _session.edit_group_by_name(prop->value());
1543 if(edit_group == 0) {
1544 error << string_compose(_("Route %1: unknown edit group \"%2 in saved state (ignored)"), _name, prop->value()) << endmsg;
1546 set_edit_group(edit_group, this);
1550 if ((prop = node.property (X_("order-keys"))) != 0) {
1554 string::size_type colon, equal;
1555 string remaining = prop->value();
1557 while (remaining.length()) {
1559 if ((equal = remaining.find_first_of ('=')) == string::npos || equal == remaining.length()) {
1560 error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
1563 if (sscanf (remaining.substr (equal+1).c_str(), "%ld", &n) != 1) {
1564 error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
1567 set_order_key (remaining.substr (0, equal), n);
1571 colon = remaining.find_first_of (':');
1573 if (colon != string::npos) {
1574 remaining = remaining.substr (colon+1);
1581 nlist = node.children();
1583 if (deferred_state) {
1584 delete deferred_state;
1587 deferred_state = new XMLNode(X_("deferred state"));
1589 /* set parent class properties before anything else */
1591 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
1595 if (child->name() == IO::state_node_name && call_base) {
1597 IO::set_state (*child);
1602 for (niter = nlist.begin(); niter != nlist.end(); ++niter){
1606 if (child->name() == X_("Send")) {
1609 if (!IO::ports_legal) {
1611 deferred_state->add_child_copy (*child);
1614 add_redirect_from_xml (*child);
1617 } else if (child->name() == X_("Insert")) {
1619 if (!IO::ports_legal) {
1621 deferred_state->add_child_copy (*child);
1625 add_redirect_from_xml (*child);
1628 } else if (child->name() == X_("Automation")) {
1630 if ((prop = child->property (X_("path"))) != 0) {
1631 load_automation (prop->value());
1634 } else if (child->name() == X_("ControlOuts")) {
1636 string coutname = _name;
1637 coutname += _("[control]");
1639 _control_outs = new IO (_session, coutname);
1640 _control_outs->set_state (**(child->children().begin()));
1642 } else if (child->name() == X_("Comment")) {
1644 /* XXX this is a terrible API design in libxml++ */
1646 XMLNode *cmt = *(child->children().begin());
1647 _comment = cmt->content();
1649 } else if (child->name() == X_("extra")) {
1651 _extra_xml = new XMLNode (*child);
1653 } else if (child->name() == X_("controllable") && (prop = child->property("name")) != 0) {
1655 if (prop->value() == "solo") {
1656 _solo_control.set_state (*child);
1657 _session.add_controllable (&_solo_control);
1659 else if (prop->value() == "mute") {
1660 _mute_control.set_state (*child);
1661 _session.add_controllable (&_mute_control);
1666 if ((prop = node.property (X_("mix-group"))) != 0) {
1667 RouteGroup* mix_group = _session.mix_group_by_name(prop->value());
1668 if (mix_group == 0) {
1669 error << string_compose(_("Route %1: unknown mix group \"%2 in saved state (ignored)"), _name, prop->value()) << endmsg;
1671 set_mix_group(mix_group, this);
1679 Route::curve_reallocate ()
1681 // _gain_automation_curve.finish_resize ();
1682 // _pan_automation_curve.finish_resize ();
1686 Route::silence (nframes_t nframes, nframes_t offset)
1690 IO::silence (nframes, offset);
1692 if (_control_outs) {
1693 _control_outs->silence (nframes, offset);
1697 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
1700 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1701 boost::shared_ptr<PluginInsert> pi;
1702 if (!_active && (pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
1703 // skip plugins, they don't need anything when we're not active
1707 (*i)->silence (nframes, offset);
1710 if (nframes == _session.get_block_size() && offset == 0) {
1720 Route::set_control_outs (const vector<string>& ports)
1722 Glib::Mutex::Lock lm (control_outs_lock);
1723 vector<string>::const_iterator i;
1725 if (_control_outs) {
1726 delete _control_outs;
1730 if (ports.empty()) {
1734 string coutname = _name;
1735 coutname += _("[control]");
1737 _control_outs = new IO (_session, coutname);
1739 /* our control outs need as many outputs as we
1740 have audio outputs. we track the changes in ::output_change_handler().
1743 _control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().get(DataType::AUDIO)), true, this);
1749 Route::set_edit_group (RouteGroup *eg, void *src)
1752 if (eg == _edit_group) {
1757 _edit_group->remove (this);
1760 if ((_edit_group = eg) != 0) {
1761 _edit_group->add (this);
1764 _session.set_dirty ();
1765 edit_group_changed (src); /* EMIT SIGNAL */
1769 Route::drop_edit_group (void *src)
1772 _session.set_dirty ();
1773 edit_group_changed (src); /* EMIT SIGNAL */
1777 Route::set_mix_group (RouteGroup *mg, void *src)
1780 if (mg == _mix_group) {
1785 _mix_group->remove (this);
1788 if ((_mix_group = mg) != 0) {
1789 _mix_group->add (this);
1792 _session.set_dirty ();
1793 mix_group_changed (src); /* EMIT SIGNAL */
1797 Route::drop_mix_group (void *src)
1800 _session.set_dirty ();
1801 mix_group_changed (src); /* EMIT SIGNAL */
1805 Route::set_comment (string cmt, void *src)
1808 comment_changed (src);
1809 _session.set_dirty ();
1813 Route::feeds (boost::shared_ptr<Route> other)
1818 uint32_t no = self.n_outputs().get_total();
1819 uint32_t ni = other->n_inputs ().get_total();
1821 for (i = 0; i < no; ++i) {
1822 for (j = 0; j < ni; ++j) {
1823 if (self.output(i)->connected_to (other->input(j)->name())) {
1829 /* check Redirects which may also interconnect Routes */
1831 for (RedirectList::iterator r = _redirects.begin(); r != _redirects.end(); r++) {
1833 no = (*r)->n_outputs().get_total();
1835 for (i = 0; i < no; ++i) {
1836 for (j = 0; j < ni; ++j) {
1837 if ((*r)->output(i)->connected_to (other->input (j)->name())) {
1844 /* check for control room outputs which may also interconnect Routes */
1846 if (_control_outs) {
1848 no = _control_outs->n_outputs().get_total();
1850 for (i = 0; i < no; ++i) {
1851 for (j = 0; j < ni; ++j) {
1852 if (_control_outs->output(i)->connected_to (other->input (j)->name())) {
1863 Route::set_mute_config (mute_type t, bool onoff, void *src)
1867 _mute_affects_pre_fader = onoff;
1868 pre_fader_changed(src); /* EMIT SIGNAL */
1872 _mute_affects_post_fader = onoff;
1873 post_fader_changed(src); /* EMIT SIGNAL */
1877 _mute_affects_control_outs = onoff;
1878 control_outs_changed(src); /* EMIT SIGNAL */
1882 _mute_affects_main_outs = onoff;
1883 main_outs_changed(src); /* EMIT SIGNAL */
1889 Route::get_mute_config (mute_type t)
1895 onoff = _mute_affects_pre_fader;
1898 onoff = _mute_affects_post_fader;
1901 onoff = _mute_affects_control_outs;
1904 onoff = _mute_affects_main_outs;
1912 Route::set_active (bool yn)
1915 active_changed(); /* EMIT SIGNAL */
1919 Route::handle_transport_stopped (bool abort_ignored, bool did_locate, bool can_flush_redirects)
1921 nframes_t now = _session.transport_frame();
1924 Glib::RWLock::ReaderLock lm (redirect_lock);
1927 automation_snapshot (now);
1930 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
1932 if (Config->get_plugins_stop_with_transport() && can_flush_redirects) {
1933 (*i)->deactivate ();
1937 (*i)->transport_stopped (now);
1941 IO::transport_stopped (now);
1943 _roll_delay = _initial_delay;
1947 Route::input_change_handler (IOChange change, void *ignored)
1949 if (change & ConfigurationChanged) {
1950 reset_plugin_counts (0);
1955 Route::output_change_handler (IOChange change, void *ignored)
1957 if (change & ConfigurationChanged) {
1958 if (_control_outs) {
1959 _control_outs->ensure_io (ChanCount::ZERO, ChanCount(DataType::AUDIO, n_outputs().get(DataType::AUDIO)), true, this);
1962 reset_plugin_counts (0);
1967 Route::pans_required () const
1969 if (n_outputs().get(DataType::AUDIO) < 2) {
1973 return max (n_inputs ().get(DataType::AUDIO), static_cast<size_t>(redirect_max_outs.get(DataType::AUDIO)));
1977 Route::no_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
1978 bool session_state_changing, bool can_record, bool rec_monitors_input)
1980 if (n_outputs().get_total() == 0) {
1984 if (session_state_changing || !_active) {
1985 silence (nframes, offset);
1989 apply_gain_automation = false;
1991 if (n_inputs().get_total()) {
1992 passthru (start_frame, end_frame, nframes, offset, 0, false);
1994 silence (nframes, offset);
2001 Route::check_initial_delay (nframes_t nframes, nframes_t& offset, nframes_t& transport_frame)
2003 if (_roll_delay > nframes) {
2005 _roll_delay -= nframes;
2006 silence (nframes, offset);
2007 /* transport frame is not legal for caller to use */
2010 } else if (_roll_delay > 0) {
2012 nframes -= _roll_delay;
2014 silence (_roll_delay, offset);
2016 offset += _roll_delay;
2017 transport_frame += _roll_delay;
2026 Route::roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset, int declick,
2027 bool can_record, bool rec_monitors_input)
2030 Glib::RWLock::ReaderLock lm (redirect_lock, Glib::TRY_LOCK);
2032 // automation snapshot can also be called from the non-rt context
2033 // and it uses the redirect list, so we take the lock out here
2034 automation_snapshot (_session.transport_frame());
2038 if ((n_outputs().get_total() == 0 && _redirects.empty()) || n_inputs().get_total() == 0 || !_active) {
2039 silence (nframes, offset);
2043 nframes_t unused = 0;
2045 if ((nframes = check_initial_delay (nframes, offset, unused)) == 0) {
2051 apply_gain_automation = false;
2054 Glib::Mutex::Lock am (automation_lock, Glib::TRY_LOCK);
2056 if (am.locked() && _session.transport_rolling()) {
2058 if (gain_automation_playback()) {
2059 apply_gain_automation = _gain_automation_curve.rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
2064 passthru (start_frame, end_frame, nframes, offset, declick, false);
2070 Route::silent_roll (nframes_t nframes, nframes_t start_frame, nframes_t end_frame, nframes_t offset,
2071 bool can_record, bool rec_monitors_input)
2073 silence (nframes, offset);
2078 Route::toggle_monitor_input ()
2080 for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
2081 i->ensure_monitor_input( ! i->monitoring_input());
2086 Route::has_external_redirects () const
2088 boost::shared_ptr<const PortInsert> pi;
2090 for (RedirectList::const_iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
2091 if ((pi = boost::dynamic_pointer_cast<const PortInsert>(*i)) != 0) {
2093 for (PortSet::const_iterator port = pi->outputs().begin();
2094 port != pi->outputs().end(); ++port) {
2096 string port_name = port->name();
2097 string client_name = port_name.substr (0, port_name.find(':'));
2099 /* only say "yes" if the redirect is actually in use */
2101 if (client_name != "ardour" && pi->active()) {
2112 Route::flush_redirects ()
2114 /* XXX shouldn't really try to take this lock, since
2115 this is called from the RT audio thread.
2118 Glib::RWLock::ReaderLock lm (redirect_lock);
2120 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
2121 (*i)->deactivate ();
2127 Route::set_meter_point (MeterPoint p, void *src)
2129 if (_meter_point != p) {
2131 meter_change (src); /* EMIT SIGNAL */
2132 _session.set_dirty ();
2137 Route::update_total_latency ()
2141 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
2142 if ((*i)->active ()) {
2143 _own_latency += (*i)->latency ();
2147 set_port_latency (_own_latency);
2149 /* this (virtual) function is used for pure Routes,
2150 not derived classes like AudioTrack. this means
2151 that the data processed here comes from an input
2152 port, not prerecorded material, and therefore we
2153 have to take into account any input latency.
2156 _own_latency += input_latency ();
2158 return _own_latency;
2162 Route::set_latency_delay (nframes_t longest_session_latency)
2164 _initial_delay = longest_session_latency - _own_latency;
2166 if (_session.transport_stopped()) {
2167 _roll_delay = _initial_delay;
2172 Route::automation_snapshot (nframes_t now)
2174 IO::automation_snapshot (now);
2176 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
2177 (*i)->automation_snapshot (now);
2181 Route::ToggleControllable::ToggleControllable (std::string name, Route& s, ToggleType tp)
2182 : Controllable (name), route (s), type(tp)
2188 Route::ToggleControllable::set_value (float val)
2190 bool bval = ((val >= 0.5f) ? true: false);
2194 route.set_mute (bval, this);
2197 route.set_solo (bval, this);
2205 Route::ToggleControllable::get_value (void) const
2211 val = route.muted() ? 1.0f : 0.0f;
2214 val = route.soloed() ? 1.0f : 0.0f;
2224 Route::set_block_size (nframes_t nframes)
2226 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
2227 (*i)->set_block_size (nframes);
2232 Route::redirect_active_proxy (Redirect* ignored, void* ignored_src)
2234 _session.update_latency_compensation (false, false);
2238 Route::protect_automation ()
2240 switch (gain_automation_state()) {
2243 set_gain_automation_state (Off);
2249 switch (panner().automation_state ()) {
2252 panner().set_automation_state (Off);
2258 for (RedirectList::iterator i = _redirects.begin(); i != _redirects.end(); ++i) {
2259 boost::shared_ptr<PluginInsert> pi;
2260 if ((pi = boost::dynamic_pointer_cast<PluginInsert> (*i)) != 0) {
2261 pi->protect_automation ();
2267 Route::set_pending_declick (int declick)
2270 /* this call is not allowed to turn off a pending declick unless "force" is true */
2272 _pending_declick = declick;
2274 // cerr << _name << ": after setting to " << declick << " pending declick = " << _pending_declick << endl;
2276 _pending_declick = 0;