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