summaryrefslogtreecommitdiff
path: root/libs/ardour/io.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour/io.cc')
-rw-r--r--libs/ardour/io.cc207
1 files changed, 197 insertions, 10 deletions
diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
index 9811cfed3a..f49692a910 100644
--- a/libs/ardour/io.cc
+++ b/libs/ardour/io.cc
@@ -515,8 +515,14 @@ IO::state (bool /*full_state*/)
}
int
-IO::set_state (const XMLNode& node)
+IO::set_state (const XMLNode& node, int version)
{
+ /* callers for version < 3000 need to call set_state_2X directly, as A3 IOs
+ * are input OR output, not both, so the direction needs to be specified
+ * by the caller.
+ */
+ assert (version >= 3000);
+
const XMLProperty* prop;
XMLNodeConstIterator iter;
LocaleGuard lg (X_("POSIX"));
@@ -547,19 +553,21 @@ IO::set_state (const XMLNode& node)
_direction = (Direction) string_2_enum (prop->value(), _direction);
}
- if (create_ports (node)) {
+ if (create_ports (node, version)) {
return -1;
}
if (connecting_legal) {
- if (make_connections (node)) {
+ if (make_connections (node, version, false)) {
return -1;
}
} else {
pending_state_node = new XMLNode (node);
+ pending_state_node_version = version;
+ pending_state_node_in = false;
connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
}
@@ -568,6 +576,58 @@ IO::set_state (const XMLNode& node)
}
int
+IO::set_state_2X (const XMLNode& node, int version, bool in)
+{
+ const XMLProperty* prop;
+ XMLNodeConstIterator iter;
+ LocaleGuard lg (X_("POSIX"));
+
+ /* force use of non-localized representation of decimal point,
+ since we use it a lot in XML files and so forth.
+ */
+
+ if (node.name() != state_node_name) {
+ error << string_compose(_("incorrect XML node \"%1\" passed to IO object"), node.name()) << endmsg;
+ return -1;
+ }
+
+ if ((prop = node.property ("name")) != 0) {
+ set_name (prop->value());
+ }
+
+ if ((prop = node.property (X_("default-type"))) != 0) {
+ _default_type = DataType(prop->value());
+ assert(_default_type != DataType::NIL);
+ }
+
+ if ((prop = node.property ("id")) != 0) {
+ _id = prop->value ();
+ }
+
+ _direction = in ? Input : Output;
+
+ if (create_ports (node, version)) {
+ return -1;
+ }
+
+ if (connecting_legal) {
+
+ if (make_connections_2X (node, version, in)) {
+ return -1;
+ }
+
+ } else {
+
+ pending_state_node = new XMLNode (node);
+ pending_state_node_version = version;
+ pending_state_node_in = in;
+ connection_legal_c = ConnectingLegal.connect (mem_fun (*this, &IO::connecting_became_legal));
+ }
+
+ return 0;
+}
+
+int
IO::connecting_became_legal ()
{
int ret;
@@ -576,7 +636,7 @@ IO::connecting_became_legal ()
connection_legal_c.disconnect ();
- ret = make_connections (*pending_state_node);
+ ret = make_connections (*pending_state_node, pending_state_node_version, pending_state_node_in);
delete pending_state_node;
pending_state_node = 0;
@@ -679,8 +739,36 @@ IO::find_possible_bundle (const string &desired_name)
}
int
-IO::get_port_counts (const XMLNode& node, ChanCount& n, boost::shared_ptr<Bundle>& c)
+IO::get_port_counts_2X (XMLNode const & node, int version, ChanCount& n, boost::shared_ptr<Bundle>& c)
+{
+ XMLProperty const * prop;
+ XMLNodeList children = node.children ();
+
+ uint32_t n_audio = 0;
+
+ for (XMLNodeIterator i = children.begin(); i != children.end(); ++i) {
+
+ if ((prop = node.property ("inputs")) != 0 && _direction == Input) {
+ n_audio = count (prop->value().begin(), prop->value().end(), '{');
+ } else if ((prop = node.property ("outputs")) != 0 && _direction == Output) {
+ n_audio = count (prop->value().begin(), prop->value().end(), '{');
+ }
+ }
+
+ ChanCount cnt;
+ cnt.set_audio (n_audio);
+ n = ChanCount::max (n, cnt);
+
+ return 0;
+}
+
+int
+IO::get_port_counts (const XMLNode& node, int version, ChanCount& n, boost::shared_ptr<Bundle>& c)
{
+ if (version < 3000) {
+ return get_port_counts_2X (node, version, n, c);
+ }
+
XMLProperty const * prop;
XMLNodeConstIterator iter;
uint32_t n_audio = 0;
@@ -728,13 +816,13 @@ IO::get_port_counts (const XMLNode& node, ChanCount& n, boost::shared_ptr<Bundle
}
int
-IO::create_ports (const XMLNode& node)
+IO::create_ports (const XMLNode& node, int version)
{
ChanCount n;
boost::shared_ptr<Bundle> c;
-
- get_port_counts (node, n, c);
-
+
+ get_port_counts (node, version, n, c);
+
if (ensure_ports (n, true, true, this)) {
error << string_compose(_("%1: cannot create I/O ports"), _name) << endmsg;
return -1;
@@ -746,8 +834,12 @@ IO::create_ports (const XMLNode& node)
}
int
-IO::make_connections (const XMLNode& node)
+IO::make_connections (const XMLNode& node, int version, bool in)
{
+ if (version < 3000) {
+ return make_connections_2X (node, version, in);
+ }
+
const XMLProperty* prop;
for (XMLNodeConstIterator i = node.children().begin(); i != node.children().end(); ++i) {
@@ -798,6 +890,101 @@ IO::make_connections (const XMLNode& node)
return 0;
}
+
+int
+IO::make_connections_2X (const XMLNode& node, int version, bool in)
+{
+ const XMLProperty* prop;
+
+ /* XXX: bundles ("connections" as was) */
+
+ if ((prop = node.property ("inputs")) != 0 && in) {
+
+ string::size_type ostart = 0;
+ string::size_type start = 0;
+ string::size_type end = 0;
+ int i = 0;
+ int n;
+ vector<string> ports;
+
+ string const str = prop->value ();
+
+ while ((start = str.find_first_of ('{', ostart)) != string::npos) {
+ start += 1;
+
+ if ((end = str.find_first_of ('}', start)) == string::npos) {
+ error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
+ return -1;
+ }
+
+ if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
+ error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
+
+ return -1;
+
+ } else if (n > 0) {
+
+
+ for (int x = 0; x < n; ++x) {
+ /* XXX: this is a bit of a hack; need to check if it's always valid */
+ string::size_type const p = ports[x].find ("/out");
+ if (p != string::npos) {
+ ports[x].replace (p, 4, "/audio_out");
+ }
+ nth(i)->connect (ports[x]);
+ }
+ }
+
+ ostart = end+1;
+ i++;
+ }
+
+ }
+
+ if ((prop = node.property ("outputs")) != 0 && !in) {
+
+ string::size_type ostart = 0;
+ string::size_type start = 0;
+ string::size_type end = 0;
+ int i = 0;
+ int n;
+ vector<string> ports;
+
+ string const str = prop->value ();
+
+ while ((start = str.find_first_of ('{', ostart)) != string::npos) {
+ start += 1;
+
+ if ((end = str.find_first_of ('}', start)) == string::npos) {
+ error << string_compose(_("IO: badly formed string in XML node for outputs \"%1\""), str) << endmsg;
+ return -1;
+ }
+
+ if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
+ error << string_compose(_("IO: bad output string in XML node \"%1\""), str) << endmsg;
+
+ return -1;
+
+ } else if (n > 0) {
+
+ for (int x = 0; x < n; ++x) {
+ /* XXX: this is a bit of a hack; need to check if it's always valid */
+ string::size_type const p = ports[x].find ("/in");
+ if (p != string::npos) {
+ ports[x].replace (p, 3, "/audio_in");
+ }
+ nth(i)->connect (ports[x]);
+ }
+ }
+
+ ostart = end+1;
+ i++;
+ }
+ }
+
+ return 0;
+}
+
int
IO::set_ports (const string& str)
{