Part 1 of loading 2.X sessions; some things work, some things don't, hacks a-plenty.
[ardour.git] / libs / ardour / control_protocol_manager.cc
1 /*
2     Copyright (C) 2000-2007 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 <dlfcn.h>
21
22 #include "pbd/compose.h"
23 #include "pbd/file_utils.h"
24 #include "pbd/error.h"
25
26 #include "control_protocol/control_protocol.h"
27
28 #include "ardour/session.h"
29 #include "ardour/control_protocol_manager.h"
30 #include "ardour/control_protocol_search_path.h"
31
32 using namespace ARDOUR;
33 using namespace std;
34 using namespace PBD;
35
36 #include "i18n.h"
37
38 ControlProtocolManager* ControlProtocolManager::_instance = 0;
39 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
40
41 ControlProtocolManager::ControlProtocolManager ()
42         : _session (0)
43 {
44
45 }
46
47 ControlProtocolManager::~ControlProtocolManager()
48 {
49         Glib::Mutex::Lock lm (protocols_lock);
50
51         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
52                 delete (*i);
53         }
54
55         control_protocols.clear ();
56
57
58         for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
59                 delete (*p);
60         }
61
62         control_protocol_info.clear();
63 }
64
65 void
66 ControlProtocolManager::set_session (Session& s)
67 {
68         _session = &s;
69         _session->GoingAway.connect (mem_fun (*this, &ControlProtocolManager::drop_session));
70
71         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
72                 if ((*i)->requested || (*i)->mandatory) {
73                         instantiate (**i);
74                         (*i)->requested = false;
75
76                         if ((*i)->protocol && (*i)->state) {
77                                 (*i)->protocol->set_state (*(*i)->state);
78                         }
79                 }
80         }
81 }
82
83 void
84 ControlProtocolManager::drop_session ()
85 {
86         _session = 0;
87
88         {
89                 Glib::Mutex::Lock lm (protocols_lock);
90                 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
91                         delete *p;
92                 }
93                 control_protocols.clear ();
94
95                 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
96                         // otherwise the ControlProtocol instances are not recreated in set_session
97                         if ((*p)->protocol) {
98                                 (*p)->requested = true;
99                                 (*p)->protocol = 0;
100                         }
101                 }
102         }
103 }
104
105 ControlProtocol*
106 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
107 {
108         if (_session == 0) {
109                 return 0;
110         }
111
112         cpi.descriptor = get_descriptor (cpi.path);
113
114         if (cpi.descriptor == 0) {
115                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
116                 return 0;
117         }
118
119         if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
120                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
121                 return 0;
122         }
123
124         Glib::Mutex::Lock lm (protocols_lock);
125         control_protocols.push_back (cpi.protocol);
126
127         return cpi.protocol;
128 }
129
130 int
131 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
132 {
133         if (!cpi.protocol) {
134                 return 0;
135         }
136
137         if (!cpi.descriptor) {
138                 return 0;
139         }
140
141         if (cpi.mandatory) {
142                 return 0;
143         }
144
145         cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
146
147         {
148                 Glib::Mutex::Lock lm (protocols_lock);
149                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
150                 if (p != control_protocols.end()) {
151                         control_protocols.erase (p);
152                 } else {
153                         cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
154                 }
155
156                 list<ControlProtocolInfo*>::iterator p2 = find (control_protocol_info.begin(), control_protocol_info.end(), &cpi);
157                 if (p2 != control_protocol_info.end()) {
158                         control_protocol_info.erase (p2);
159                 } else {
160                         cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocol_info" << endl;
161                 }
162         }
163
164         cpi.protocol = 0;
165         dlclose (cpi.descriptor->module);
166         return 0;
167 }
168
169 void
170 ControlProtocolManager::load_mandatory_protocols ()
171 {
172         if (_session == 0) {
173                 return;
174         }
175
176         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
177                 if ((*i)->mandatory && ((*i)->protocol == 0)) {
178                         info << string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name) << endmsg;
179                         instantiate (**i);
180                 }
181         }
182 }
183
184 void
185 ControlProtocolManager::discover_control_protocols ()
186 {
187         vector<sys::path> cp_modules;
188
189         Glib::PatternSpec so_extension_pattern("*.so");
190         Glib::PatternSpec dylib_extension_pattern("*.dylib");
191
192         find_matching_files_in_search_path (control_protocol_search_path (),
193                         so_extension_pattern, cp_modules);
194
195         find_matching_files_in_search_path (control_protocol_search_path (),
196                         dylib_extension_pattern, cp_modules);
197
198         info << string_compose (_("looking for control protocols in %1"), control_protocol_search_path().to_string()) << endmsg;
199
200         for (vector<sys::path>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
201                 control_protocol_discover ((*i).to_string());
202         }
203 }
204
205 int
206 ControlProtocolManager::control_protocol_discover (string path)
207 {
208         ControlProtocolDescriptor* descriptor;
209
210         if ((descriptor = get_descriptor (path)) != 0) {
211
212                 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
213
214                 if (!descriptor->probe (descriptor)) {
215                         info << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
216                 } else {
217
218                         cpi->descriptor = descriptor;
219                         cpi->name = descriptor->name;
220                         cpi->path = path;
221                         cpi->protocol = 0;
222                         cpi->requested = false;
223                         cpi->mandatory = descriptor->mandatory;
224                         cpi->supports_feedback = descriptor->supports_feedback;
225                         cpi->state = 0;
226
227                         control_protocol_info.push_back (cpi);
228
229                         info << string_compose(_("Control surface protocol discovered: \"%1\""), cpi->name) << endmsg;
230                 }
231
232                 dlclose (descriptor->module);
233         }
234
235         return 0;
236 }
237
238 ControlProtocolDescriptor*
239 ControlProtocolManager::get_descriptor (string path)
240 {
241         void *module;
242         ControlProtocolDescriptor *descriptor = 0;
243         ControlProtocolDescriptor* (*dfunc)(void);
244         const char *errstr;
245
246         if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
247                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
248                 return 0;
249         }
250
251
252         dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
253
254         if ((errstr = dlerror()) != 0) {
255                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
256                 error << errstr << endmsg;
257                 dlclose (module);
258                 return 0;
259         }
260
261         descriptor = dfunc();
262         if (descriptor) {
263                 descriptor->module = module;
264         } else {
265                 dlclose (module);
266         }
267
268         return descriptor;
269 }
270
271 void
272 ControlProtocolManager::foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*> method)
273 {
274         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
275                 method (*i);
276         }
277 }
278
279 ControlProtocolInfo*
280 ControlProtocolManager::cpi_by_name (string name)
281 {
282         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
283                 if (name == (*i)->name) {
284                         return *i;
285                 }
286         }
287         return 0;
288 }
289
290 int
291 ControlProtocolManager::set_state (const XMLNode& node, int version)
292 {
293         XMLNodeList clist;
294         XMLNodeConstIterator citer;
295         XMLProperty* prop;
296
297         clist = node.children();
298
299         for (citer = clist.begin(); citer != clist.end(); ++citer) {
300                 if ((*citer)->name() == X_("Protocol")) {
301
302                         prop = (*citer)->property (X_("active"));
303
304                         if (prop && string_is_affirmative (prop->value())) {
305                                 if ((prop = (*citer)->property (X_("name"))) != 0) {
306                                         ControlProtocolInfo* cpi = cpi_by_name (prop->value());
307                                         if (cpi) {
308                                                 if (!(*citer)->children().empty()) {
309                                                         cpi->state = (*citer)->children().front ();
310                                                 } else {
311                                                         cpi->state = 0;
312                                                 }
313
314                                                 if (_session) {
315                                                         instantiate (*cpi);
316                                                 } else {
317                                                         cpi->requested = true;
318                                                 }
319                                         }
320                                 }
321                         }
322                 }
323         }
324         return 0;
325 }
326
327 XMLNode&
328 ControlProtocolManager::get_state (void)
329 {
330         XMLNode* root = new XMLNode (state_node_name);
331         Glib::Mutex::Lock lm (protocols_lock);
332
333         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
334
335                 XMLNode * child;
336
337                 if ((*i)->protocol) {
338                         child = &((*i)->protocol->get_state());
339                         child->add_property (X_("active"), "yes");
340                         // should we update (*i)->state here?  probably.
341                         root->add_child_nocopy (*child);
342                 }
343                 else if ((*i)->state) {
344                         // keep ownership clear
345                         root->add_child_copy (*(*i)->state);
346                 }
347                 else {
348                         child = new XMLNode (X_("Protocol"));
349                         child->add_property (X_("name"), (*i)->name);
350                         child->add_property (X_("active"), "no");
351                         root->add_child_nocopy (*child);
352                 }
353         }
354
355         return *root;
356 }
357
358 void
359 ControlProtocolManager::set_protocol_states (const XMLNode& node)
360 {
361         XMLNodeList nlist;
362         XMLNodeConstIterator niter;
363         XMLProperty* prop;
364
365         nlist = node.children();
366
367         for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
368
369                 XMLNode* child = (*niter);
370
371                 if ((prop = child->property ("name")) == 0) {
372                         error << _("control protocol XML node has no name property. Ignored.") << endmsg;
373                         continue;
374                 }
375
376                 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
377
378                 if (!cpi) {
379                         warning << string_compose (_("control protocol \"%1\" is not known. Ignored"), prop->value()) << endmsg;
380                         continue;
381                 }
382
383                 /* copy the node so that ownership is clear */
384
385                 cpi->state = new XMLNode (*child);
386         }
387 }
388
389 ControlProtocolManager&
390 ControlProtocolManager::instance ()
391 {
392         if (_instance == 0) {
393                 _instance = new ControlProtocolManager ();
394         }
395
396         return *_instance;
397 }