Remove over 500 unnecessary includes (including 54 of session.h).
[ardour.git] / libs / ardour / port_insert.cc
1 /*
2     Copyright (C) 2000,2007 Paul Davis
3
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.
8
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.
13
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.
17
18 */
19
20 #include <string>
21
22 #include "pbd/xml++.h"
23
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"
32
33 #include "i18n.h"
34
35 using namespace std;
36 using namespace ARDOUR;
37 using namespace PBD;
38
39 string
40 PortInsert::name_and_id_new_insert (Session& s, uint32_t& bitslot)
41 {
42         bitslot = s.next_insert_id ();
43         return string_compose (_("insert %1"), bitslot+ 1);
44 }
45
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), "")
48         , _out (new Delivery (s, _output, pannable, mm, _name, Delivery::Insert))
49 {
50         _mtdm = 0;
51         _latency_detect = false;
52         _latency_flush_frames = false;
53         _measured_latency = 0;
54 }
55
56 PortInsert::~PortInsert ()
57 {
58         _session.unmark_insert_id (_bitslot);
59         delete _mtdm;
60 }
61
62 void
63 PortInsert::start_latency_detection ()
64 {
65         if (_mtdm != 0) {
66                 delete _mtdm;
67         }
68
69         _mtdm = new MTDM;
70         _latency_flush_frames = false;
71         _latency_detect = true;
72         _measured_latency = 0;
73 }
74
75 void
76 PortInsert::stop_latency_detection ()
77 {
78         _latency_flush_frames = signal_latency() + _session.engine().frames_per_cycle();
79         _latency_detect = false;
80 }
81
82 void
83 PortInsert::set_measured_latency (framecnt_t n)
84 {
85         _measured_latency = n;
86 }
87
88 framecnt_t
89 PortInsert::latency() const
90 {
91         /* because we deliver and collect within the same cycle,
92            all I/O is necessarily delayed by at least frames_per_cycle().
93
94            if the return port for insert has its own latency, we
95            need to take that into account too.
96         */
97
98         if (_measured_latency == 0) {
99                 return _session.engine().frames_per_cycle() + _input->latency();
100         } else {
101                 return _measured_latency;
102         }
103 }
104
105 void
106 PortInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool)
107 {
108         if (_output->n_ports().n_total() == 0) {
109                 return;
110         }
111
112         if (_latency_detect) {
113
114                 if (_input->n_ports().n_audio() != 0) {
115
116                         AudioBuffer& outbuf (_output->ports().nth_audio_port(0)->get_audio_buffer (nframes));
117                         Sample* in = _input->ports().nth_audio_port(0)->get_audio_buffer (nframes).data();
118                         Sample* out = outbuf.data();
119
120                         _mtdm->process (nframes, in, out);
121
122                         outbuf.set_is_silent (false);
123                 }
124
125                 return;
126
127         } else if (_latency_flush_frames) {
128
129                 /* wait for the entire input buffer to drain before picking up input again so that we can't
130                    hear the remnants of whatever MTDM pumped into the pipeline.
131                 */
132
133                 silence (nframes);
134
135                 if (_latency_flush_frames > nframes) {
136                         _latency_flush_frames -= nframes;
137                 } else {
138                         _latency_flush_frames = 0;
139                 }
140
141                 return;
142         }
143
144         if (!_active && !_pending_active) {
145                 /* deliver silence */
146                 silence (nframes);
147                 goto out;
148         }
149
150         _out->run (bufs, start_frame, end_frame, nframes, true);
151         _input->collect_input (bufs, nframes, ChanCount::ZERO);
152
153   out:
154         _active = _pending_active;
155 }
156
157 XMLNode&
158 PortInsert::get_state(void)
159 {
160         return state (true);
161 }
162
163 XMLNode&
164 PortInsert::state (bool full)
165 {
166         XMLNode& node = IOProcessor::state(full);
167         char buf[32];
168         node.add_property ("type", "port");
169         snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot);
170         node.add_property ("bitslot", buf);
171         snprintf (buf, sizeof (buf), "%" PRId64, _measured_latency);
172         node.add_property("latency", buf);
173         snprintf (buf, sizeof (buf), "%u", _session.get_block_size());
174         node.add_property("block_size", buf);
175
176         return node;
177 }
178
179 int
180 PortInsert::set_state (const XMLNode& node, int version)
181 {
182         XMLNodeList nlist = node.children();
183         XMLNodeIterator niter;
184         XMLPropertyList plist;
185         const XMLProperty *prop;
186
187         const XMLNode* insert_node = &node;
188
189         // legacy sessions: search for child Redirect node
190         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
191                 if ((*niter)->name() == "Redirect") {
192                         insert_node = *niter;
193                         break;
194                 }
195         }
196
197         IOProcessor::set_state (*insert_node, version);
198
199         if ((prop = node.property ("type")) == 0) {
200                 error << _("XML node describing port insert is missing the `type' field") << endmsg;
201                 return -1;
202         }
203
204         if (prop->value() != "port") {
205                 error << _("non-port insert XML used for port plugin insert") << endmsg;
206                 return -1;
207         }
208
209         uint32_t blocksize = 0;
210         if ((prop = node.property ("block_size")) != 0) {
211                 sscanf (prop->value().c_str(), "%u", &blocksize);
212         }
213
214         //if the jack period is the same as when the value was saved, we can recall our latency..
215         if ( (_session.get_block_size() == blocksize) && (prop = node.property ("latency")) != 0) {
216                 uint32_t latency = 0;
217                 sscanf (prop->value().c_str(), "%u", &latency);
218                 _measured_latency = latency;
219         }
220
221         if (!node.property ("ignore-bitslot")) {
222                 if ((prop = node.property ("bitslot")) == 0) {
223                         _bitslot = _session.next_insert_id();
224                 } else {
225                         _session.unmark_insert_id (_bitslot);
226                         sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot);
227                         _session.mark_insert_id (_bitslot);
228                 }
229         }
230
231         return 0;
232 }
233
234 ARDOUR::framecnt_t
235 PortInsert::signal_latency() const
236 {
237         /* because we deliver and collect within the same cycle,
238            all I/O is necessarily delayed by at least frames_per_cycle().
239
240            if the return port for insert has its own latency, we
241            need to take that into account too.
242         */
243
244         if (_measured_latency == 0) {
245                 return _session.engine().frames_per_cycle() + _input->signal_latency();
246         } else {
247                 return _measured_latency;
248         }
249 }
250
251 /** Caller must hold process lock */
252 bool
253 PortInsert::configure_io (ChanCount in, ChanCount out)
254 {
255         assert (!AudioEngine::instance()->process_lock().trylock());
256
257         /* for an insert, processor input corresponds to IO output, and vice versa */
258
259         if (_input->ensure_io (in, false, this) != 0) {
260                 return false;
261         }
262
263         if (_output->ensure_io (out, false, this) != 0) {
264                 return false;
265         }
266
267         return Processor::configure_io (in, out);
268 }
269
270 bool
271 PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
272 {
273         out = in;
274         return true;
275 }
276
277 bool
278 PortInsert::set_name (const std::string& name)
279 {
280         bool ret = Processor::set_name (name);
281
282         ret = (ret && _input->set_name (name) && _output->set_name (name));
283
284         return ret;
285 }
286
287 void
288 PortInsert::activate ()
289 {
290         IOProcessor::activate ();
291
292         _out->activate ();
293 }
294
295 void
296 PortInsert::deactivate ()
297 {
298         IOProcessor::deactivate ();
299
300         _out->deactivate ();
301 }