Remove unnecessary 0 checks before delete; see http://www.parashift.com/c++-faq-lite...
[ardour.git] / libs / ardour / user_bundle.cc
1 #include <cassert>
2 #include <pbd/failed_constructor.h>
3 #include <pbd/compose.h>
4 #include <pbd/xml++.h>
5 #include "ardour/user_bundle.h"
6 #include "ardour/port_set.h"
7 #include "ardour/io.h"
8 #include "ardour/session.h"
9 #include "ardour/audioengine.h"
10 #include "i18n.h"
11
12 ARDOUR::UserBundle::UserBundle (std::string const & n)
13         : Bundle (n)
14 {
15
16 }
17
18 ARDOUR::UserBundle::UserBundle (XMLNode const & x, bool i)
19         : Bundle (i)
20 {
21         if (set_state (x)) {
22                 throw failed_constructor ();
23         }
24 }
25
26 ARDOUR::ChanCount
27 ARDOUR::UserBundle::nchannels () const
28 {
29         Glib::Mutex::Lock lm (_ports_mutex);
30         return ChanCount (type(), _ports.size ());
31 }
32
33 const ARDOUR::PortList&
34 ARDOUR::UserBundle::channel_ports (uint32_t n) const
35 {
36         assert (n < nchannels ().get (type()));
37
38         Glib::Mutex::Lock lm (_ports_mutex);
39         return _ports[n];
40 }
41
42 void
43 ARDOUR::UserBundle::add_port_to_channel (uint32_t c, std::string const & p)
44 {
45         assert (c < nchannels ().get (type()));
46         
47         PortsWillChange (c);
48
49         {
50                 Glib::Mutex::Lock lm (_ports_mutex);
51                 _ports[c].push_back (p);
52         }
53         
54         PortsHaveChanged (c);
55 }
56
57 void
58 ARDOUR::UserBundle::remove_port_from_channel (uint32_t c, std::string const & p)
59 {
60         assert (c < nchannels ().get (type()));
61
62         PortsWillChange (c);
63
64         {
65                 Glib::Mutex::Lock lm (_ports_mutex);
66                 PortList::iterator i = std::find (_ports[c].begin(), _ports[c].end(), p);
67                 if (i != _ports[c].end()) {
68                         _ports[c].erase (i);
69                 }
70         }
71         
72         PortsHaveChanged (c);
73 }
74
75 bool
76 ARDOUR::UserBundle::port_attached_to_channel (uint32_t c, std::string const & p) const
77 {
78         assert (c < nchannels ().get (type()));
79
80         Glib::Mutex::Lock lm (_ports_mutex);
81         return std::find (_ports[c].begin(), _ports[c].end(), p) != _ports[c].end();
82 }
83
84 void
85 ARDOUR::UserBundle::add_channel ()
86 {
87         ConfigurationWillChange ();
88
89         {
90                 Glib::Mutex::Lock lm (_ports_mutex);
91                 _ports.resize (_ports.size() + 1);
92         }
93         
94         ConfigurationHasChanged ();
95 }
96
97 void
98 ARDOUR::UserBundle::set_channels (uint32_t n)
99 {
100         ConfigurationWillChange ();
101
102         {
103                 Glib::Mutex::Lock lm (_ports_mutex);
104                 _ports.resize (n);
105         }
106
107         ConfigurationHasChanged ();
108 }
109
110 void
111 ARDOUR::UserBundle::remove_channel (uint32_t r)
112 {
113         assert (r < nchannels ().get (type()));
114
115         ConfigurationWillChange ();
116
117         {
118                 Glib::Mutex::Lock lm (_ports_mutex);
119                 _ports.erase (_ports.begin() + r, _ports.begin() + r + 1);
120         }
121
122         ConfigurationHasChanged ();
123 }
124
125 int
126 ARDOUR::UserBundle::set_state (XMLNode const & node)
127 {
128         XMLProperty const * name;
129         
130         if ((name = node.property ("name")) == 0) {
131                 PBD::error << _("Node for Bundle has no \"name\" property") << endmsg;
132                 return -1;
133         }
134
135         set_name (name->value ());
136
137         XMLNodeList const channels = node.children ();
138
139         int n = 0;
140         for (XMLNodeConstIterator i = channels.begin(); i != channels.end(); ++i) {
141
142                 if ((*i)->name() != "Channel") {
143                         PBD::error << string_compose (_("Unknown node \"%s\" in Bundle"), (*i)->name()) << endmsg;
144                         return -1;
145                 }
146
147                 add_channel ();
148
149                 XMLNodeList const ports = (*i)->children ();
150
151                 for (XMLNodeConstIterator j = ports.begin(); j != ports.end(); ++j) {
152                         if ((*j)->name() != "Port") {
153                                 PBD::error << string_compose (_("Unknown node \"%s\" in Bundle"), (*j)->name()) << endmsg;
154                                 return -1;
155                         }
156
157                         if ((name = (*j)->property ("name")) == 0) {
158                                 PBD::error << _("Node for Port has no \"name\" property") << endmsg;
159                                 return -1;
160                         } 
161                         
162                         add_port_to_channel (n, name->value ());
163                 }
164
165                 ++n;
166         }
167
168         return 0;
169 }
170
171 XMLNode&
172 ARDOUR::UserBundle::get_state ()
173 {
174         XMLNode *node;
175         
176         if (ports_are_inputs ()) {
177                 node = new XMLNode ("InputBundle");
178         } else {
179                 node = new XMLNode ("OutputBundle");
180         }
181
182         node->add_property ("name", name ());
183
184         for (std::vector<PortList>::iterator i = _ports.begin(); i != _ports.end(); ++i) {
185
186                 XMLNode* c = new XMLNode ("Channel");
187
188                 for (PortList::iterator j = i->begin(); j != i->end(); ++j) {
189                         XMLNode* p = new XMLNode ("Port");
190                         p->add_property ("name", *j);
191                         c->add_child_nocopy (*p);
192                 }
193
194                 node->add_child_nocopy (*c);
195         }
196
197         return *node;
198 }