2 * Copyright (C) 2001-2018 Paul Davis <paul@linuxaudiosystems.com>
3 * Copyright (C) 2007-2012 David Robillard <d@drobilla.net>
4 * Copyright (C) 2009-2010 Carl Hetherington <carl@carlh.net>
5 * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "pbd/xml++.h"
26 #include "pbd/enumwriter.h"
28 #include "ardour/chan_count.h"
29 #include "ardour/data_type.h"
30 #include "ardour/io.h"
31 #include "ardour/io_processor.h"
32 #include "ardour/processor.h"
33 #include "ardour/route.h"
34 #include "ardour/session_object.h"
35 #include "ardour/types.h"
40 using namespace ARDOUR;
43 namespace ARDOUR { class Session; }
45 /* create an IOProcessor that proxies to a new IO object */
47 IOProcessor::IOProcessor (Session& s, bool with_input, bool with_output,
48 const string& proc_name, const string io_name, DataType dtype, bool sendish)
49 : Processor(s, proc_name)
51 /* these are true in this constructor whether we actually create the associated
59 _input.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Input, dtype, sendish));
63 _output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype, sendish));
67 /* create an IOProcessor that proxies to an existing IO object */
69 IOProcessor::IOProcessor (Session& s, boost::shared_ptr<IO> in, boost::shared_ptr<IO> out,
70 const string& proc_name, DataType /*dtype*/)
71 : Processor(s, proc_name)
88 IOProcessor::~IOProcessor ()
93 IOProcessor::set_input (boost::shared_ptr<IO> io)
95 /* CALLER MUST HOLD PROCESS LOCK */
102 IOProcessor::set_output (boost::shared_ptr<IO> io)
104 /* CALLER MUST HOLD PROCESS LOCK */
111 IOProcessor::state ()
113 XMLNode& node (Processor::state ());
115 node.set_property ("own-input", _own_input);
119 XMLNode& i (_input->get_state ());
120 // i.name() = X_("output");
121 node.add_child_nocopy (i);
123 node.set_property ("input", _input->name ());
127 node.set_property ("own-output", _own_output);
131 XMLNode& o (_output->get_state ());
132 node.add_child_nocopy (o);
134 node.set_property ("output", _output->name ());
142 IOProcessor::set_state (const XMLNode& node, int version)
144 if (version < 3000) {
145 return set_state_2X (node, version);
148 XMLProperty const * prop;
149 const XMLNode *io_node = 0;
151 Processor::set_state(node, version);
153 bool ignore_name = node.property ("ignore-name");
155 node.get_property ("own-input", _own_input);
156 node.get_property ("own-output", _own_output);
158 /* don't attempt to set state for a proxied IO that we don't own */
160 XMLNodeList nlist = node.children();
161 XMLNodeIterator niter;
162 const string instr = enum_2_string (IO::Input);
163 const string outstr = enum_2_string (IO::Output);
166 if (_own_input && _input) {
167 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
168 if ((*niter)->get_property ("name", str) && (_name == str || ignore_name)) {
169 if ((*niter)->get_property ("direction", str) && str == instr) {
177 _input->set_state(*io_node, version);
179 // legacy sessions: use IO name
180 if ((prop = node.property ("name")) == 0) {
181 set_name (_input->name());
185 /* no input, which is OK */
190 if (_own_output && _output) {
191 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
192 if ((*niter)->name() == "IO") {
193 if ((*niter)->get_property ("name", str) && (_name == str || ignore_name)) {
194 if ((*niter)->get_property ("direction", str) && str == outstr) {
203 _output->set_state(*io_node, version);
205 // legacy sessions: use IO name
206 if ((prop = node.property ("name")) == 0) {
207 set_name (_output->name());
210 /* no output, which is OK */
218 IOProcessor::set_state_2X (const XMLNode& node, int version)
220 _own_input = _own_output = true;
222 Processor::set_state_2X (node, version);
228 IOProcessor::silence (samplecnt_t nframes, samplepos_t /* start_sample */)
230 if (_own_output && _output) {
231 _output->silence (nframes);
236 IOProcessor::natural_output_streams() const
238 return _output ? _output->n_ports() : ChanCount::ZERO;
242 IOProcessor::natural_input_streams () const
244 return _input ? _input->n_ports() : ChanCount::ZERO;
248 IOProcessor::set_name (const std::string& name)
250 bool ret = SessionObject::set_name (name);
252 if (ret && _own_input && _input) {
253 ret = _input->set_name (name);
256 if (ret && _own_output && _output) {
257 ret = _output->set_name (name);
264 IOProcessor::feeds (boost::shared_ptr<Route> other) const
266 return _output && _output->connected_to (other->input());
270 IOProcessor::disconnect ()
273 _input->disconnect (this);
277 _output->disconnect (this);
281 /** Set up the XML description of a send so that we will not
282 * reset its name or bitslot during ::set_state()
283 * @param state XML send state.
284 * @param session Session.
287 IOProcessor::prepare_for_reset (XMLNode &state, const std::string& name)
289 state.set_property ("ignore-bitslot", true);
290 state.set_property ("ignore-name", true);
292 XMLNodeList nlist = state.children();
293 XMLNodeIterator niter;
295 for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
296 if ((*niter)->name() == IO::state_node_name.c_str()) {
297 IO::prepare_for_reset (**niter, name);