2 Copyright (C) 2000,2007 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.
22 #include "pbd/xml++.h"
24 #include "ardour/audio_port.h"
25 #include "ardour/audioengine.h"
26 #include "ardour/delivery.h"
27 #include "ardour/io.h"
28 #include "ardour/mtdm.h"
29 #include "ardour/port_insert.h"
30 #include "ardour/session.h"
31 #include "ardour/types.h"
36 using namespace ARDOUR;
40 PortInsert::name_and_id_new_insert (Session& s, uint32_t& bitslot)
42 bitslot = s.next_insert_id ();
43 return string_compose (_("insert %1"), bitslot+ 1);
46 PortInsert::PortInsert (Session& s, boost::shared_ptr<Pannable> pannable, boost::shared_ptr<MuteMaster> mm)
47 : IOProcessor (s, true, true, name_and_id_new_insert (s, _bitslot), "", DataType::AUDIO, true)
48 , _out (new Delivery (s, _output, pannable, mm, _name, Delivery::Insert))
51 _latency_detect = false;
52 _latency_flush_frames = 0;
53 _measured_latency = 0;
56 PortInsert::~PortInsert ()
58 _session.unmark_insert_id (_bitslot);
63 PortInsert::set_pre_fader (bool p)
65 Processor::set_pre_fader (p);
66 _out->set_pre_fader (p);
70 PortInsert::start_latency_detection ()
73 _mtdm = new MTDM (_session.frame_rate());
74 _latency_flush_frames = 0;
75 _latency_detect = true;
76 _measured_latency = 0;
80 PortInsert::stop_latency_detection ()
82 _latency_flush_frames = signal_latency() + _session.engine().samples_per_cycle();
83 _latency_detect = false;
87 PortInsert::set_measured_latency (framecnt_t n)
89 _measured_latency = n;
93 PortInsert::latency() const
95 /* because we deliver and collect within the same cycle,
96 all I/O is necessarily delayed by at least frames_per_cycle().
98 if the return port for insert has its own latency, we
99 need to take that into account too.
102 if (_measured_latency == 0) {
103 return _session.engine().samples_per_cycle() + _input->latency();
105 return _measured_latency;
110 PortInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, double speed, pframes_t nframes, bool)
112 if (_output->n_ports().n_total() == 0) {
116 if (_latency_detect) {
118 if (_input->n_ports().n_audio() != 0) {
120 AudioBuffer& outbuf (_output->ports().nth_audio_port(0)->get_audio_buffer (nframes));
121 Sample* in = _input->ports().nth_audio_port(0)->get_audio_buffer (nframes).data();
122 Sample* out = outbuf.data();
124 _mtdm->process (nframes, in, out);
126 outbuf.set_written (true);
131 } else if (_latency_flush_frames) {
133 /* wait for the entire input buffer to drain before picking up input again so that we can't
134 hear the remnants of whatever MTDM pumped into the pipeline.
137 silence (nframes, start_frame);
139 if (_latency_flush_frames > nframes) {
140 _latency_flush_frames -= nframes;
142 _latency_flush_frames = 0;
148 if (!_active && !_pending_active) {
149 /* deliver silence */
150 silence (nframes, start_frame);
154 _out->run (bufs, start_frame, end_frame, speed, nframes, true);
155 _input->collect_input (bufs, nframes, ChanCount::ZERO);
158 _active = _pending_active;
162 PortInsert::get_state(void)
168 PortInsert::state (bool full)
170 XMLNode& node = IOProcessor::state(full);
172 node.add_property ("type", "port");
173 snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
174 node.add_property ("bitslot", buf);
175 snprintf (buf, sizeof (buf), "%" PRId64, _measured_latency);
176 node.add_property("latency", buf);
177 snprintf (buf, sizeof (buf), "%u", _session.get_block_size());
178 node.add_property("block-size", buf);
184 PortInsert::set_state (const XMLNode& node, int version)
186 XMLNodeList nlist = node.children();
187 XMLNodeIterator niter;
188 XMLPropertyList plist;
189 XMLProperty const * prop;
191 const XMLNode* insert_node = &node;
193 // legacy sessions: search for child Redirect node
194 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
195 if ((*niter)->name() == "Redirect") {
196 insert_node = *niter;
201 IOProcessor::set_state (*insert_node, version);
203 if ((prop = node.property ("type")) == 0) {
204 error << _("XML node describing port insert is missing the `type' field") << endmsg;
208 if (prop->value() != "port") {
209 error << _("non-port insert XML used for port plugin insert") << endmsg;
213 uint32_t blocksize = 0;
214 if ((prop = node.property ("block-size")) != 0) {
215 sscanf (prop->value().c_str(), "%u", &blocksize);
218 //if the jack period is the same as when the value was saved, we can recall our latency..
219 if ( (_session.get_block_size() == blocksize) && (prop = node.property ("latency")) != 0) {
220 uint32_t latency = 0;
221 sscanf (prop->value().c_str(), "%u", &latency);
222 _measured_latency = latency;
225 if (!node.property ("ignore-bitslot")) {
226 if ((prop = node.property ("bitslot")) == 0) {
227 _bitslot = _session.next_insert_id();
229 _session.unmark_insert_id (_bitslot);
230 sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot);
231 _session.mark_insert_id (_bitslot);
239 PortInsert::signal_latency() const
241 /* because we deliver and collect within the same cycle,
242 all I/O is necessarily delayed by at least frames_per_cycle().
244 if the return port for insert has its own latency, we
245 need to take that into account too.
248 if (_measured_latency == 0) {
249 return _session.engine().samples_per_cycle() + _input->signal_latency();
251 return _measured_latency;
255 /** Caller must hold process lock */
257 PortInsert::configure_io (ChanCount in, ChanCount out)
259 #ifndef PLATFORM_WINDOWS
260 assert (!AudioEngine::instance()->process_lock().trylock());
263 /* for an insert, processor input corresponds to IO output, and vice versa */
265 if (_input->ensure_io (in, false, this) != 0) {
269 if (_output->ensure_io (out, false, this) != 0) {
273 return Processor::configure_io (in, out);
277 PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
284 PortInsert::set_name (const std::string& name)
286 bool ret = Processor::set_name (name);
288 ret = (ret && _input->set_name (name) && _output->set_name (name));
294 PortInsert::activate ()
296 IOProcessor::activate ();
302 PortInsert::deactivate ()
304 IOProcessor::deactivate ();