2 Copyright (C) 2002 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.
22 #include <pbd/failed_constructor.h>
23 #include <ardour/ardour.h>
24 #include <ardour/bundle.h>
25 #include <pbd/xml++.h>
29 using namespace ARDOUR;
32 /** Construct a Bundle from an XML node.
33 * @param node XML node.
35 Bundle::Bundle (const XMLNode& node)
37 if (set_state (node)) {
38 throw failed_constructor();
42 /** Construct an InputBundle from an XML node.
43 * @param node XML node.
45 InputBundle::InputBundle (const XMLNode& node)
51 /** Construct an OutputBundle from an XML node.
52 * @param node XML node.
54 OutputBundle::OutputBundle (const XMLNode& node)
61 * @param name New name.
64 Bundle::set_name (string name, void *src)
70 /** Add an association between one of our channels and a JACK port.
71 * @param ch Channel index.
72 * @param portname JACK port name to associate with.
75 Bundle::add_port_to_channel (int ch, string portname)
78 Glib::Mutex::Lock lm (channels_lock);
79 _channels[ch].push_back (portname);
82 PortsChanged (ch); /* EMIT SIGNAL */
85 /** Disassociate a JACK port from one of our channels.
86 * @param ch Channel index.
87 * @param portname JACK port name to disassociate from.
91 Bundle::remove_port_from_channel (int ch, string portname)
96 Glib::Mutex::Lock lm (channels_lock);
97 PortList& pl = _channels[ch];
98 PortList::iterator i = find (pl.begin(), pl.end(), portname);
107 PortsChanged (ch); /* EMIT SIGNAL */
112 * @param ch Channel index.
113 * @return List of JACK ports that this channel is connected to.
115 const Bundle::PortList&
116 Bundle::channel_ports (int ch) const
118 Glib::Mutex::Lock lm (channels_lock);
119 return _channels[ch];
122 /** operator== for Bundles; they are equal if their channels are the same.
123 * @param other Bundle to compare with this one.
126 Bundle::operator== (const Bundle& other) const
128 return other._channels == _channels;
132 /** Set the number of channels.
133 * @param n New number of channels.
137 Bundle::set_nchannels (int n)
140 Glib::Mutex::Lock lm (channels_lock);
142 for (int i = 0; i < n; ++i) {
143 _channels.push_back (PortList());
147 ConfigurationChanged (); /* EMIT SIGNAL */
156 if (dynamic_cast<InputBundle *> (this)) {
157 node = new XMLNode ("InputConnection");
159 node = new XMLNode ("OutputConnection");
162 node->add_property ("name", _name);
164 for (vector<PortList>::iterator i = _channels.begin(); i != _channels.end(); ++i) {
168 for (vector<string>::iterator ii = (*i).begin(); ii != (*i).end(); ++ii) {
169 if (ii != (*i).begin()) {
177 node->add_property ("connections", str);
183 Bundle::set_state (const XMLNode& node)
185 const XMLProperty *prop;
187 if ((prop = node.property ("name")) == 0) {
188 error << _("Node for Connection has no \"name\" property") << endmsg;
192 _name = prop->value();
195 if ((prop = node.property ("connections")) == 0) {
196 error << _("Node for Connection has no \"connections\" property") << endmsg;
200 set_channels (prop->value());
205 /** Set up channels from an XML property string.
207 * @return 0 on success, -1 on error.
210 Bundle::set_channels (const string& str)
212 vector<string> ports;
217 if ((nchannels = count (str.begin(), str.end(), '{')) == 0) {
221 set_nchannels (nchannels);
223 string::size_type start, end, ostart;
230 while ((start = str.find_first_of ('{', ostart)) != string::npos) {
233 if ((end = str.find_first_of ('}', start)) == string::npos) {
234 error << string_compose(_("IO: badly formed string in XML node for inputs \"%1\""), str) << endmsg;
238 if ((n = parse_io_string (str.substr (start, end - start), ports)) < 0) {
239 error << string_compose(_("bad input string in XML node \"%1\""), str) << endmsg;
245 for (int x = 0; x < n; ++x) {
246 add_port_to_channel (i, ports[x]);
258 Bundle::parse_io_string (const string& str, vector<string>& ports)
260 string::size_type pos, opos;
262 if (str.length() == 0) {
271 while ((pos = str.find_first_of (',', opos)) != string::npos) {
272 ports.push_back (str.substr (opos, pos - opos));
276 if (opos < str.length()) {
277 ports.push_back (str.substr(opos));