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);
171 node.set_property ("type", "port");
172 node.set_property ("bitslot", _bitslot);
173 node.set_property ("latency", _measured_latency);
174 node.set_property ("block-size", _session.get_block_size());
180 PortInsert::set_state (const XMLNode& node, int version)
182 XMLNodeList nlist = node.children();
183 XMLNodeIterator niter;
184 XMLPropertyList plist;
186 const XMLNode* insert_node = &node;
188 // legacy sessions: search for child Redirect node
189 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
190 if ((*niter)->name() == "Redirect") {
191 insert_node = *niter;
196 IOProcessor::set_state (*insert_node, version);
198 std::string type_str;
199 if (!node.get_property ("type", type_str)) {
200 error << _("XML node describing port insert is missing the `type' field") << endmsg;
204 if (type_str != "port") {
205 error << _("non-port insert XML used for port plugin insert") << endmsg;
209 uint32_t blocksize = 0;
210 node.get_property ("block-size", blocksize);
212 //if the jack period is the same as when the value was saved, we can recall our latency..
213 if ( (_session.get_block_size() == blocksize) ) {
214 node.get_property ("latency", _measured_latency);
217 if (!node.property ("ignore-bitslot")) {
219 if (node.get_property ("bitslot", bitslot)) {
220 _session.unmark_insert_id (_bitslot);
222 _session.mark_insert_id (_bitslot);
224 _bitslot = _session.next_insert_id();
232 PortInsert::signal_latency() const
234 /* because we deliver and collect within the same cycle,
235 all I/O is necessarily delayed by at least frames_per_cycle().
237 if the return port for insert has its own latency, we
238 need to take that into account too.
241 if (_measured_latency == 0) {
242 return _session.engine().samples_per_cycle() + _input->signal_latency();
244 return _measured_latency;
248 /** Caller must hold process lock */
250 PortInsert::configure_io (ChanCount in, ChanCount out)
252 #ifndef PLATFORM_WINDOWS
253 assert (!AudioEngine::instance()->process_lock().trylock());
256 /* for an insert, processor input corresponds to IO output, and vice versa */
258 if (_input->ensure_io (in, false, this) != 0) {
262 if (_output->ensure_io (out, false, this) != 0) {
266 return Processor::configure_io (in, out);
270 PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
277 PortInsert::set_name (const std::string& name)
279 bool ret = Processor::set_name (name);
281 ret = (ret && _input->set_name (name) && _output->set_name (name));
287 PortInsert::activate ()
289 IOProcessor::activate ();
295 PortInsert::deactivate ()
297 IOProcessor::deactivate ();