redesign cross-thread registration/signalling system
[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 <glibmm/module.h>
21
22 #include <glibmm/fileutils.h>
23
24 #include "pbd/compose.h"
25 #include "pbd/event_loop.h"
26 #include "pbd/file_utils.h"
27 #include "pbd/error.h"
28
29 #include "control_protocol/control_protocol.h"
30
31 #include "ardour/debug.h"
32 #include "ardour/control_protocol_manager.h"
33
34 #include "ardour/search_paths.h"
35
36
37 using namespace ARDOUR;
38 using namespace std;
39 using namespace PBD;
40
41 #include "i18n.h"
42
43 ControlProtocolManager* ControlProtocolManager::_instance = 0;
44 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
45
46 ControlProtocolManager::ControlProtocolManager ()
47 {
48 }
49
50 ControlProtocolManager::~ControlProtocolManager()
51 {
52         Glib::Threads::Mutex::Lock lm (protocols_lock);
53
54         for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
55                 delete (*i);
56         }
57
58         control_protocols.clear ();
59
60
61         for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
62                 delete (*p);
63         }
64
65         control_protocol_info.clear();
66 }
67
68 void
69 ControlProtocolManager::set_session (Session* s)
70 {
71         SessionHandlePtr::set_session (s);
72
73         if (_session) {
74                 Glib::Threads::Mutex::Lock lm (protocols_lock);
75
76                 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
77                         if ((*i)->requested || (*i)->mandatory) {
78                                 (void) activate (**i);
79                         }
80                 }
81         }
82 }
83
84 int
85 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
86 {
87         ControlProtocol* cp;
88
89         cpi.requested = true;
90
91         if ((cp = instantiate (cpi)) == 0) {
92                 return -1;
93         }
94
95         /* we split the set_state() and set_active() operations so that
96            protocols that need state to configure themselves (e.g. "What device
97            is connected, or supposed to be connected?") can get it before
98            actually starting any interaction.
99         */
100
101         if (cpi.state) {
102                 /* force this by tweaking the internals of the state
103                  * XMLNode. Ugh.
104                  */
105                 cp->set_state (*cpi.state, Stateful::loading_state_version);
106         } else {
107                 /* guarantee a call to
108                    set_state() whether we have
109                    existing state or not
110                 */
111                 cp->set_state (XMLNode(""), Stateful::loading_state_version);
112         }
113
114         cp->set_active (true);
115
116         return 0;
117 }
118
119 int
120 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
121 {
122         cpi.requested = false;
123         return teardown (cpi);
124 }
125
126 void
127 ControlProtocolManager::session_going_away()
128 {
129         SessionHandlePtr::session_going_away ();
130         /* Session::destroy() will explicitly call drop_protocols() so we don't
131          * have to worry about that here.
132          */
133 }
134
135 void
136 ControlProtocolManager::drop_protocols ()
137 {
138         /* called explicitly by Session::destroy() so that we can clean up
139          * before the process cycle stops and ports vanish.
140          */
141
142         Glib::Threads::Mutex::Lock lm (protocols_lock);
143
144         for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
145                 delete *p;
146         }
147
148         control_protocols.clear ();
149
150         for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
151                 // mark existing protocols as requested
152                 // otherwise the ControlProtocol instances are not recreated in set_session
153                 if ((*p)->protocol) {
154                         (*p)->requested = true;
155                         (*p)->protocol = 0;
156                 }
157         }
158 }
159
160 ControlProtocol*
161 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
162 {
163         /* CALLER MUST HOLD LOCK */
164
165         if (_session == 0) {
166                 return 0;
167         }
168
169         cpi.descriptor = get_descriptor (cpi.path);
170
171         DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
172
173         if (cpi.descriptor == 0) {
174                 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
175                 return 0;
176         }
177
178         DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
179
180         if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
181                 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
182                 return 0;
183         }
184
185         control_protocols.push_back (cpi.protocol);
186
187         ProtocolStatusChange (&cpi);
188
189         return cpi.protocol;
190 }
191
192 int
193 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
194 {
195         if (!cpi.protocol) {
196                 return 0;
197         }
198
199         if (!cpi.descriptor) {
200                 return 0;
201         }
202
203         if (cpi.mandatory) {
204                 return 0;
205         }
206
207         /* save current state */
208
209         delete cpi.state;
210         cpi.state = new XMLNode (cpi.protocol->get_state());
211         cpi.state->add_property (X_("active"), "no");
212
213         cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
214
215         {
216                 Glib::Threads::Mutex::Lock lm (protocols_lock);
217                 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
218                 if (p != control_protocols.end()) {
219                         control_protocols.erase (p);
220                 } else {
221                         cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
222                 }
223         }
224
225         cpi.protocol = 0;
226         delete cpi.state;
227         cpi.state = 0;
228         delete (Glib::Module*)cpi.descriptor->module;
229
230         ProtocolStatusChange (&cpi);
231
232         return 0;
233 }
234
235 void
236 ControlProtocolManager::load_mandatory_protocols ()
237 {
238         if (_session == 0) {
239                 return;
240         }
241
242         Glib::Threads::Mutex::Lock lm (protocols_lock);
243
244         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
245                 if ((*i)->mandatory && ((*i)->protocol == 0)) {
246                         DEBUG_TRACE (DEBUG::ControlProtocols,
247                                      string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
248                         instantiate (**i);
249                 }
250         }
251 }
252
253 void
254 ControlProtocolManager::discover_control_protocols ()
255 {
256         vector<std::string> cp_modules;
257
258 #ifdef COMPILER_MSVC
259    /**
260     * Different build targets (Debug / Release etc) use different versions
261     * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
262     * case the supplied search path contains multiple version(s) of a given
263     * module, only select the one(s) which match the current build target
264     */
265         #if defined (_DEBUG)
266                 Glib::PatternSpec dll_extension_pattern("*D.dll");
267         #elif defined (RDC_BUILD)
268                 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
269         #elif defined (_WIN64)
270                 Glib::PatternSpec dll_extension_pattern("*64.dll");
271         #else
272                 Glib::PatternSpec dll_extension_pattern("*32.dll");
273         #endif
274 #else
275         Glib::PatternSpec dll_extension_pattern("*.dll");
276 #endif
277
278         Glib::PatternSpec so_extension_pattern("*.so");
279         Glib::PatternSpec dylib_extension_pattern("*.dylib");
280
281         find_files_matching_pattern (cp_modules, control_protocol_search_path (),
282                                      dll_extension_pattern);
283
284         find_files_matching_pattern (cp_modules, control_protocol_search_path (),
285                                      so_extension_pattern);
286
287         find_files_matching_pattern (cp_modules, control_protocol_search_path (),
288                                      dylib_extension_pattern);
289
290         DEBUG_TRACE (DEBUG::ControlProtocols,
291                      string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
292
293         for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
294                 control_protocol_discover (*i);
295         }
296 }
297
298 int
299 ControlProtocolManager::control_protocol_discover (string path)
300 {
301         ControlProtocolDescriptor* descriptor;
302
303 #ifdef __APPLE__
304         /* don't load OS X shared objects that are just symlinks to the real thing.
305          */
306
307         if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
308                 return 0;
309         }
310 #endif
311
312         if ((descriptor = get_descriptor (path)) != 0) {
313
314                 if (!descriptor->probe (descriptor)) {
315                         DEBUG_TRACE (DEBUG::ControlProtocols,
316                                      string_compose (_("Control protocol %1 not usable"), descriptor->name));
317                 } else {
318
319                         ControlProtocolInfo* cpi = new ControlProtocolInfo ();
320
321                         cpi->descriptor = descriptor;
322                         cpi->name = descriptor->name;
323                         cpi->path = path;
324                         cpi->protocol = 0;
325                         cpi->requested = false;
326                         cpi->mandatory = descriptor->mandatory;
327                         cpi->supports_feedback = descriptor->supports_feedback;
328                         cpi->state = 0;
329
330                         control_protocol_info.push_back (cpi);
331
332                         DEBUG_TRACE (DEBUG::ControlProtocols,
333                                      string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
334                 }
335
336                 delete (Glib::Module*)descriptor->module;
337         }
338
339         return 0;
340 }
341
342 ControlProtocolDescriptor*
343 ControlProtocolManager::get_descriptor (string path)
344 {
345         Glib::Module* module = new Glib::Module(path);
346         ControlProtocolDescriptor *descriptor = 0;
347         ControlProtocolDescriptor* (*dfunc)(void);
348         void* func = 0;
349
350         if (!(*module)) {
351                 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
352                 delete module;
353                 return 0;
354         }
355
356         if (!module->get_symbol("protocol_descriptor", func)) {
357                 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
358                 error << Glib::Module::get_last_error() << endmsg;
359                 delete module;
360                 return 0;
361         }
362
363         dfunc = (ControlProtocolDescriptor* (*)(void))func;
364         descriptor = dfunc();
365
366         if (descriptor) {
367                 descriptor->module = (void*)module;
368         } else {
369                 delete module;
370         }
371
372         return descriptor;
373 }
374
375 void
376 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
377 {
378         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
379                 method (*i);
380         }
381 }
382
383 ControlProtocolInfo*
384 ControlProtocolManager::cpi_by_name (string name)
385 {
386         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
387                 if (name == (*i)->name) {
388                         return *i;
389                 }
390         }
391         return 0;
392 }
393
394 int
395 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
396 {
397         XMLNodeList clist;
398         XMLNodeConstIterator citer;
399         XMLProperty* prop;
400
401         Glib::Threads::Mutex::Lock lm (protocols_lock);
402
403         clist = node.children();
404
405         for (citer = clist.begin(); citer != clist.end(); ++citer) {
406                 if ((*citer)->name() == X_("Protocol")) {
407
408                         if ((prop = (*citer)->property (X_("active"))) == 0) {
409                                 continue;
410                         }
411
412                         bool active = string_is_affirmative (prop->value());
413
414                         if ((prop = (*citer)->property (X_("name"))) == 0) {
415                                 continue;
416                         }
417
418                         ControlProtocolInfo* cpi = cpi_by_name (prop->value());
419
420                         if (cpi) {
421                                 cpi->state = new XMLNode (**citer);
422
423                                 if (active) {
424                                         if (_session) {
425                                                 instantiate (*cpi);
426                                         } else {
427                                                 cpi->requested = true;
428                                         }
429                                 } else {
430                                         if (_session) {
431                                                 teardown (*cpi);
432                                         } else {
433                                                 cpi->requested = false;
434                                         }
435                                 }
436                         }
437                 }
438         }
439
440         return 0;
441 }
442
443 XMLNode&
444 ControlProtocolManager::get_state ()
445 {
446         XMLNode* root = new XMLNode (state_node_name);
447         Glib::Threads::Mutex::Lock lm (protocols_lock);
448
449         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
450
451                 if ((*i)->protocol) {
452                         XMLNode& child_state ((*i)->protocol->get_state());
453                         child_state.add_property (X_("active"), "yes");
454                         root->add_child_nocopy (child_state);
455                 } else if ((*i)->state) {
456                         XMLNode* child_state = new XMLNode (*(*i)->state);
457                         child_state->add_property (X_("active"), "no");
458                         root->add_child_nocopy (*child_state);
459                 } else {
460                         XMLNode* child_state = new XMLNode (X_("Protocol"));
461                         child_state->add_property (X_("name"), (*i)->name);
462                         child_state->add_property (X_("active"), "no");
463                         root->add_child_nocopy (*child_state);
464                 }
465
466         }
467
468         return *root;
469 }
470
471
472 ControlProtocolManager&
473 ControlProtocolManager::instance ()
474 {
475         if (_instance == 0) {
476                 _instance = new ControlProtocolManager ();
477         }
478
479         return *_instance;
480 }
481
482 void
483 ControlProtocolManager::midi_connectivity_established ()
484 {
485         Glib::Threads::Mutex::Lock lm (protocols_lock);
486
487         for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
488                 (*p)->midi_connectivity_established ();
489         }
490 }
491
492 void
493 ControlProtocolManager::register_request_buffer_factories ()
494 {
495         Glib::Threads::Mutex::Lock lm (protocols_lock);
496
497         for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
498                 if ((*i)->descriptor->request_buffer_factory) {
499                         EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);
500                 }
501         }
502 }