ardour
io_processor.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2001 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 <list>
21 #include <string>
22 
23 #include "pbd/xml++.h"
24 #include "pbd/enumwriter.h"
25 
26 #include "ardour/chan_count.h"
27 #include "ardour/data_type.h"
28 #include "ardour/io.h"
29 #include "ardour/io_processor.h"
30 #include "ardour/processor.h"
31 #include "ardour/route.h"
32 #include "ardour/session_object.h"
33 #include "ardour/types.h"
34 
35 #include "i18n.h"
36 
37 using namespace std;
38 using namespace ARDOUR;
39 using namespace PBD;
40 
41 namespace ARDOUR { class Session; }
42 
43 /* create an IOProcessor that proxies to a new IO object */
44 
45 IOProcessor::IOProcessor (Session& s, bool with_input, bool with_output,
46  const string& proc_name, const string io_name, DataType dtype, bool sendish)
47  : Processor(s, proc_name)
48 {
49  /* these are true in this constructor whether we actually create the associated
50  IO objects or not.
51  */
52 
53  _own_input = true;
54  _own_output = true;
55 
56  if (with_input) {
57  _input.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Input, dtype, sendish));
58  }
59 
60  if (with_output) {
61  _output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype, sendish));
62  }
63 }
64 
65 /* create an IOProcessor that proxies to an existing IO object */
66 
68  const string& proc_name, DataType /*dtype*/)
69  : Processor(s, proc_name)
70  , _input (in)
71  , _output (out)
72 {
73  if (in) {
74  _own_input = false;
75  } else {
76  _own_input = true;
77  }
78 
79  if (out) {
80  _own_output = false;
81  } else {
82  _own_output = true;
83  }
84 }
85 
87 {
88 }
89 
90 void
92 {
93  /* CALLER MUST HOLD PROCESS LOCK */
94 
95  _input = io;
96  _own_input = false;
97 }
98 
99 void
101 {
102  /* CALLER MUST HOLD PROCESS LOCK */
103 
104  _output = io;
105  _own_output = false;
106 }
107 
108 XMLNode&
109 IOProcessor::state (bool full_state)
110 {
111  XMLNode& node (Processor::state (full_state));
112 
113  if (_own_input) {
114  node.add_property ("own-input", "yes");
115  if (_input) {
116  XMLNode& i (_input->state (full_state));
117  // i.name() = X_("output");
118  node.add_child_nocopy (i);
119  }
120  } else {
121  node.add_property ("own-input", "no");
122  if (_input) {
123  node.add_property ("input", _input->name());
124  }
125  }
126 
127  if (_own_output) {
128  node.add_property ("own-output", "yes");
129  if (_output) {
130  XMLNode& o (_output->state (full_state));
131  node.add_child_nocopy (o);
132  }
133  } else {
134  node.add_property ("own-output", "no");
135  if (_output) {
136  node.add_property ("output", _output->name());
137  }
138  }
139 
140  return node;
141 }
142 
143 int
144 IOProcessor::set_state (const XMLNode& node, int version)
145 {
146  if (version < 3000) {
147  return set_state_2X (node, version);
148  }
149 
150  const XMLProperty *prop;
151  const XMLNode *io_node = 0;
152 
153  Processor::set_state(node, version);
154 
155 
156  if ((prop = node.property ("own-input")) != 0) {
158  }
159 
160  if ((prop = node.property ("own-output")) != 0) {
162  }
163 
164  /* don't attempt to set state for a proxied IO that we don't own */
165 
166  XMLNodeList nlist = node.children();
167  XMLNodeIterator niter;
168  const string instr = enum_2_string (IO::Input);
169  const string outstr = enum_2_string (IO::Output);
170 
171  if (_own_input) {
172  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
173  const XMLProperty* prop;
174  if ((prop = (*niter)->property ("name")) != 0) {
175  if (_name == prop->value()) {
176  if ((prop = (*niter)->property ("direction")) != 0) {
177  if (prop->value() == instr) {
178  io_node = (*niter);
179  break;
180  }
181  }
182  }
183  }
184  }
185 
186  if (io_node) {
187  _input->set_state(*io_node, version);
188 
189  // legacy sessions: use IO name
190  if ((prop = node.property ("name")) == 0) {
191  set_name (_input->name());
192  }
193 
194  } else {
195  /* no input, which is OK */
196  }
197 
198  }
199 
200  if (_own_output) {
201  for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
202  if ((*niter)->name() == "IO") {
203  const XMLProperty* prop;
204  if ((prop = (*niter)->property ("name")) != 0) {
205  if (_name == prop->value()) {
206  if ((prop = (*niter)->property ("direction")) != 0) {
207  if (prop->value() == outstr) {
208  io_node = (*niter);
209  break;
210  }
211  }
212  }
213  }
214  }
215  }
216 
217  if (io_node) {
218  _output->set_state(*io_node, version);
219 
220  // legacy sessions: use IO name
221  if ((prop = node.property ("name")) == 0) {
222  set_name (_output->name());
223  }
224  } else {
225  /* no output, which is OK */
226  }
227  }
228 
229  return 0;
230 }
231 
232 int
233 IOProcessor::set_state_2X (const XMLNode& node, int version)
234 {
235  _own_input = _own_output = true;
236 
237  Processor::set_state_2X (node, version);
238 
239  return 0;
240 }
241 
242 void
244 {
245  if (_own_output && _output) {
246  _output->silence (nframes);
247  }
248 }
249 
250 void
252 {
253  if (_own_output && _output) {
254  _output->increment_port_buffer_offset (offset);
255  }
256 }
257 
258 ChanCount
260 {
261  return _output ? _output->n_ports() : ChanCount::ZERO;
262 }
263 
264 ChanCount
266 {
267  return _input ? _input->n_ports() : ChanCount::ZERO;
268 }
269 
270 bool
271 IOProcessor::set_name (const std::string& name)
272 {
273  bool ret = SessionObject::set_name (name);
274 
275  if (ret && _own_input && _input) {
276  ret = _input->set_name (name);
277  }
278 
279  if (ret && _own_output && _output) {
280  ret = _output->set_name (name);
281  }
282 
283  return ret;
284 }
285 
286 bool
288 {
289  return _output && _output->connected_to (other->input());
290 }
291 
292 void
294 {
295  if (_input) {
296  _input->disconnect (this);
297  }
298 
299  if (_output) {
300  _output->disconnect (this);
301  }
302 }
303 
309 void
310 IOProcessor::prepare_for_reset (XMLNode &state, const std::string& name)
311 {
312  state.add_property ("ignore-bitslot", "1");
313  state.add_property ("ignore-name", "1");
314 
315  XMLNode* io_node = state.child (IO::state_node_name.c_str());
316 
317  if (io_node) {
318  IO::prepare_for_reset (*io_node, name);
319  }
320 }
virtual ChanCount natural_output_streams() const
XMLNodeList::iterator XMLNodeIterator
Definition: xml++.h:48
IOProcessor(Session &, bool with_input, bool with_output, const std::string &proc_name, const std::string io_name="", ARDOUR::DataType default_type=DataType::AUDIO, bool sendish=false)
const std::string & value() const
Definition: xml++.h:159
static void prepare_for_reset(XMLNode &, const std::string &)
Definition: io.cc:965
#define enum_2_string(e)
Definition: enumwriter.h:97
void set_output(boost::shared_ptr< IO >)
uint32_t pframes_t
Definition: types.h:61
Definition: Beats.hpp:239
const XMLNodeList & children(const std::string &str=std::string()) const
Definition: xml++.cc:329
int set_state(const XMLNode &, int version)
Definition: processor.cc:173
boost::shared_ptr< IO > _output
Definition: io_processor.h:84
std::list< XMLNode * > XMLNodeList
Definition: xml++.h:44
int set_state(const XMLNode &, int version)
int64_t framecnt_t
Definition: types.h:76
XMLProperty * property(const char *)
Definition: xml++.cc:413
bool string_is_affirmative(const std::string &str)
Definition: convert.cc:282
Definition: amp.h:29
virtual bool set_name(const std::string &str)
bool set_name(const std::string &str)
virtual int set_state_2X(const XMLNode &, int version)
Definition: processor.cc:137
PBD::Property< std::string > _name
void set_input(boost::shared_ptr< IO >)
Definition: io_processor.cc:91
void silence(framecnt_t nframes)
virtual bool feeds(boost::shared_ptr< Route > other) const
virtual ChanCount natural_input_streams() const
XMLProperty * add_property(const char *name, const std::string &value)
XMLNode & state(bool full_state)
IO(Session &, const std::string &name, Direction, DataType default_type=DataType::AUDIO, bool sendish=false)
const char * name
void add_child_nocopy(XMLNode &)
Definition: xml++.cc:357
boost::shared_ptr< IO > _input
Definition: io_processor.h:83
Definition: xml++.h:95
virtual ~IOProcessor()
Definition: io_processor.cc:86
void increment_port_buffer_offset(pframes_t)
Definition: debug.h:30
boost::shared_ptr< IO > input() const
Definition: route.h:89
virtual XMLNode & state(bool full)
Definition: processor.cc:109
static const std::string state_node_name
Definition: io.h:70
static void prepare_for_reset(XMLNode &state, const std::string &name)
virtual int set_state_2X(const XMLNode &, int)
XMLNode * child(const char *) const
Definition: xml++.cc:309
static const ChanCount ZERO
Definition: chan_count.h:149