Move panner bypass state up to the PannerShell so that it is preserved even when...
[ardour2.git] / libs / ardour / port_insert.cc
blobc21f04364797e129814c4a2beb124861570b2d36
1 /*
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.
20 #include <string>
23 #include "pbd/failed_constructor.h"
24 #include "pbd/xml++.h"
26 #include "ardour/audioengine.h"
27 #include "ardour/audio_port.h"
28 #include "ardour/buffer_set.h"
29 #include "ardour/delivery.h"
30 #include "ardour/mtdm.h"
31 #include "ardour/plugin.h"
32 #include "ardour/port.h"
33 #include "ardour/port_insert.h"
34 #include "ardour/route.h"
35 #include "ardour/session.h"
36 #include "ardour/types.h"
38 #include "i18n.h"
40 using namespace std;
41 using namespace ARDOUR;
42 using namespace PBD;
44 PortInsert::PortInsert (Session& s, boost::shared_ptr<Pannable> pannable, boost::shared_ptr<MuteMaster> mm)
45 : IOProcessor (s, true, true, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
46 , _out (new Delivery (s, _output, pannable, mm, _name, Delivery::Insert))
48 _mtdm = 0;
49 _latency_detect = false;
50 _latency_flush_frames = false;
51 _measured_latency = 0;
54 PortInsert::~PortInsert ()
56 _session.unmark_insert_id (bitslot);
57 delete _mtdm;
60 void
61 PortInsert::start_latency_detection ()
63 if (_mtdm != 0) {
64 delete _mtdm;
67 _mtdm = new MTDM;
68 _latency_flush_frames = false;
69 _latency_detect = true;
70 _measured_latency = 0;
73 void
74 PortInsert::stop_latency_detection ()
76 _latency_flush_frames = signal_latency() + _session.engine().frames_per_cycle();
77 _latency_detect = false;
80 void
81 PortInsert::set_measured_latency (framecnt_t n)
83 _measured_latency = n;
86 framecnt_t
87 PortInsert::latency() const
89 /* because we deliver and collect within the same cycle,
90 all I/O is necessarily delayed by at least frames_per_cycle().
92 if the return port for insert has its own latency, we
93 need to take that into account too.
96 if (_measured_latency == 0) {
97 return _session.engine().frames_per_cycle() + _input->latency();
98 } else {
99 return _measured_latency;
103 void
104 PortInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool)
106 if (_output->n_ports().n_total() == 0) {
107 return;
110 if (_latency_detect) {
112 if (_input->n_ports().n_audio() != 0) {
114 AudioBuffer& outbuf (_output->ports().nth_audio_port(0)->get_audio_buffer (nframes));
115 Sample* in = _input->ports().nth_audio_port(0)->get_audio_buffer (nframes).data();
116 Sample* out = outbuf.data();
118 _mtdm->process (nframes, in, out);
120 outbuf.is_silent (false);
123 return;
125 } else if (_latency_flush_frames) {
127 /* wait for the entire input buffer to drain before picking up input again so that we can't
128 hear the remnants of whatever MTDM pumped into the pipeline.
131 silence (nframes);
133 if (_latency_flush_frames > nframes) {
134 _latency_flush_frames -= nframes;
135 } else {
136 _latency_flush_frames = 0;
139 return;
142 if (!_active && !_pending_active) {
143 /* deliver silence */
144 silence (nframes);
145 goto out;
148 _out->run (bufs, start_frame, end_frame, nframes, true);
149 _input->collect_input (bufs, nframes, ChanCount::ZERO);
151 out:
152 _active = _pending_active;
155 XMLNode&
156 PortInsert::get_state(void)
158 return state (true);
161 XMLNode&
162 PortInsert::state (bool full)
164 XMLNode& node = IOProcessor::state(full);
165 char buf[32];
166 node.add_property ("type", "port");
167 snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
168 node.add_property ("bitslot", buf);
169 snprintf (buf, sizeof (buf), "%" PRId64, _measured_latency);
170 node.add_property("latency", buf);
171 snprintf (buf, sizeof (buf), "%u", _session.get_block_size());
172 node.add_property("block_size", buf);
174 return node;
178 PortInsert::set_state (const XMLNode& node, int version)
180 XMLNodeList nlist = node.children();
181 XMLNodeIterator niter;
182 XMLPropertyList plist;
183 const XMLProperty *prop;
185 const XMLNode* insert_node = &node;
187 // legacy sessions: search for child Redirect node
188 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
189 if ((*niter)->name() == "Redirect") {
190 insert_node = *niter;
191 break;
195 IOProcessor::set_state (*insert_node, version);
197 if ((prop = node.property ("type")) == 0) {
198 error << _("XML node describing port insert is missing the `type' field") << endmsg;
199 return -1;
202 if (prop->value() != "port") {
203 error << _("non-port insert XML used for port plugin insert") << endmsg;
204 return -1;
207 uint32_t blocksize = 0;
208 if ((prop = node.property ("block_size")) != 0) {
209 sscanf (prop->value().c_str(), "%u", &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) && (prop = node.property ("latency")) != 0) {
214 uint32_t latency = 0;
215 sscanf (prop->value().c_str(), "%u", &latency);
216 _measured_latency = latency;
219 if ((prop = node.property ("bitslot")) == 0) {
220 bitslot = _session.next_insert_id();
221 } else {
222 _session.unmark_insert_id (bitslot);
223 sscanf (prop->value().c_str(), "%" PRIu32, &bitslot);
224 _session.mark_insert_id (bitslot);
227 return 0;
230 ARDOUR::framecnt_t
231 PortInsert::signal_latency() const
233 /* because we deliver and collect within the same cycle,
234 all I/O is necessarily delayed by at least frames_per_cycle().
236 if the return port for insert has its own latency, we
237 need to take that into account too.
240 if (_measured_latency == 0) {
241 return _session.engine().frames_per_cycle() + _input->signal_latency();
242 } else {
243 return _measured_latency;
247 /** Caller must hold process lock */
248 bool
249 PortInsert::configure_io (ChanCount in, ChanCount out)
251 assert (!AudioEngine::instance()->process_lock().trylock());
253 /* for an insert, processor input corresponds to IO output, and vice versa */
255 if (_input->ensure_io (in, false, this) != 0) {
256 return false;
259 if (_output->ensure_io (out, false, this) != 0) {
260 return false;
263 return Processor::configure_io (in, out);
266 bool
267 PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
269 out = in;
270 return true;
273 bool
274 PortInsert::set_name (const std::string& name)
276 bool ret = Processor::set_name (name);
278 ret = (ret && _input->set_name (name) && _output->set_name (name));
280 return ret;
283 void
284 PortInsert::activate ()
286 IOProcessor::activate ();
288 _out->activate ();
291 void
292 PortInsert::deactivate ()
294 IOProcessor::deactivate ();
296 _out->deactivate ();