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