2 Copyright (C) 2000-2007 Paul Davis
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.
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.
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.
20 #include <glibmm/module.h>
22 #include <glibmm/fileutils.h>
24 #include "pbd/compose.h"
25 #include "pbd/event_loop.h"
26 #include "pbd/file_utils.h"
27 #include "pbd/error.h"
29 #include "control_protocol/control_protocol.h"
31 #include "ardour/debug.h"
32 #include "ardour/control_protocol_manager.h"
34 #include "ardour/search_paths.h"
37 using namespace ARDOUR;
43 ControlProtocolManager* ControlProtocolManager::_instance = 0;
44 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
46 ControlProtocolManager::ControlProtocolManager ()
50 ControlProtocolManager::~ControlProtocolManager()
52 Glib::Threads::Mutex::Lock lm (protocols_lock);
54 for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
58 control_protocols.clear ();
61 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
65 control_protocol_info.clear();
69 ControlProtocolManager::set_session (Session* s)
71 SessionHandlePtr::set_session (s);
74 Glib::Threads::Mutex::Lock lm (protocols_lock);
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);
85 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
91 if ((cp = instantiate (cpi)) == 0) {
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.
102 /* force this by tweaking the internals of the state
105 cp->set_state (*cpi.state, Stateful::loading_state_version);
107 /* guarantee a call to
108 set_state() whether we have
109 existing state or not
111 cp->set_state (XMLNode(""), Stateful::loading_state_version);
114 cp->set_active (true);
120 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
122 cpi.requested = false;
123 return teardown (cpi);
127 ControlProtocolManager::session_going_away()
129 SessionHandlePtr::session_going_away ();
130 /* Session::destroy() will explicitly call drop_protocols() so we don't
131 * have to worry about that here.
136 ControlProtocolManager::drop_protocols ()
138 /* called explicitly by Session::destroy() so that we can clean up
139 * before the process cycle stops and ports vanish.
142 Glib::Threads::Mutex::Lock lm (protocols_lock);
144 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
148 control_protocols.clear ();
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;
161 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
163 /* CALLER MUST HOLD LOCK */
169 cpi.descriptor = get_descriptor (cpi.path);
171 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
173 if (cpi.descriptor == 0) {
174 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
178 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
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;
185 control_protocols.push_back (cpi.protocol);
187 ProtocolStatusChange (&cpi);
193 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
197 /* we could still have a descriptor even if the protocol was
198 never instantiated. Close the associated module (shared
199 object/DLL) and make sure we forget about it.
202 if (cpi.descriptor) {
203 cerr << "Closing descriptor for CPI anyway\n";
204 delete (Glib::Module*) cpi.descriptor->module;
211 if (!cpi.descriptor) {
219 /* save current state */
222 cpi.state = new XMLNode (cpi.protocol->get_state());
223 cpi.state->add_property (X_("active"), "no");
225 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
228 Glib::Threads::Mutex::Lock lm (protocols_lock);
229 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
230 if (p != control_protocols.end()) {
231 control_protocols.erase (p);
233 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
241 delete (Glib::Module*) cpi.descriptor->module;
242 /* cpi->descriptor is now inaccessible since dlclose() or equivalent
243 * has been performed, and the descriptor is (or could be) a static
244 * object made accessible by dlopen().
248 ProtocolStatusChange (&cpi);
254 ControlProtocolManager::load_mandatory_protocols ()
260 Glib::Threads::Mutex::Lock lm (protocols_lock);
262 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
263 if ((*i)->mandatory && ((*i)->protocol == 0)) {
264 DEBUG_TRACE (DEBUG::ControlProtocols,
265 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
272 ControlProtocolManager::discover_control_protocols ()
274 vector<std::string> cp_modules;
278 * Different build targets (Debug / Release etc) use different versions
279 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
280 * case the supplied search path contains multiple version(s) of a given
281 * module, only select the one(s) which match the current build target
284 Glib::PatternSpec dll_extension_pattern("*D.dll");
285 #elif defined (RDC_BUILD)
286 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
287 #elif defined (_WIN64)
288 Glib::PatternSpec dll_extension_pattern("*64.dll");
290 Glib::PatternSpec dll_extension_pattern("*32.dll");
293 Glib::PatternSpec dll_extension_pattern("*.dll");
296 Glib::PatternSpec so_extension_pattern("*.so");
297 Glib::PatternSpec dylib_extension_pattern("*.dylib");
299 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
300 dll_extension_pattern);
302 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
303 so_extension_pattern);
305 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
306 dylib_extension_pattern);
308 DEBUG_TRACE (DEBUG::ControlProtocols,
309 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
311 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
312 control_protocol_discover (*i);
317 ControlProtocolManager::control_protocol_discover (string path)
319 ControlProtocolDescriptor* descriptor;
322 /* don't load OS X shared objects that are just symlinks to the real thing.
325 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
330 if ((descriptor = get_descriptor (path)) != 0) {
332 if (!descriptor->probe (descriptor)) {
333 DEBUG_TRACE (DEBUG::ControlProtocols,
334 string_compose (_("Control protocol %1 not usable"), descriptor->name));
337 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
339 cpi->descriptor = descriptor;
340 cpi->name = descriptor->name;
343 cpi->requested = false;
344 cpi->mandatory = descriptor->mandatory;
345 cpi->supports_feedback = descriptor->supports_feedback;
348 control_protocol_info.push_back (cpi);
350 DEBUG_TRACE (DEBUG::ControlProtocols,
351 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
358 ControlProtocolDescriptor*
359 ControlProtocolManager::get_descriptor (string path)
361 Glib::Module* module = new Glib::Module(path);
362 ControlProtocolDescriptor *descriptor = 0;
363 ControlProtocolDescriptor* (*dfunc)(void);
367 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
372 if (!module->get_symbol("protocol_descriptor", func)) {
373 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
374 error << Glib::Module::get_last_error() << endmsg;
379 dfunc = (ControlProtocolDescriptor* (*)(void))func;
380 descriptor = dfunc();
383 descriptor->module = (void*)module;
390 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
392 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
398 ControlProtocolManager::cpi_by_name (string name)
400 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
401 if (name == (*i)->name) {
409 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
412 XMLNodeConstIterator citer;
413 XMLProperty const * prop;
415 Glib::Threads::Mutex::Lock lm (protocols_lock);
417 clist = node.children();
419 for (citer = clist.begin(); citer != clist.end(); ++citer) {
420 XMLNode const * child = *citer;
422 if (child->name() == X_("Protocol")) {
424 if ((prop = child->property (X_("active"))) == 0) {
428 bool active = string_is_affirmative (prop->value());
430 if ((prop = child->property (X_("name"))) == 0) {
434 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
437 cpi->state = new XMLNode (**citer);
443 cpi->requested = true;
449 cpi->requested = false;
460 ControlProtocolManager::get_state ()
462 XMLNode* root = new XMLNode (state_node_name);
463 Glib::Threads::Mutex::Lock lm (protocols_lock);
465 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
467 if ((*i)->protocol) {
468 XMLNode& child_state ((*i)->protocol->get_state());
469 child_state.add_property (X_("active"), "yes");
470 root->add_child_nocopy (child_state);
471 } else if ((*i)->state) {
472 XMLNode* child_state = new XMLNode (*(*i)->state);
473 child_state->add_property (X_("active"), "no");
474 root->add_child_nocopy (*child_state);
476 XMLNode* child_state = new XMLNode (X_("Protocol"));
477 child_state->add_property (X_("name"), (*i)->name);
478 child_state->add_property (X_("active"), "no");
479 root->add_child_nocopy (*child_state);
488 ControlProtocolManager&
489 ControlProtocolManager::instance ()
491 if (_instance == 0) {
492 _instance = new ControlProtocolManager ();
499 ControlProtocolManager::midi_connectivity_established ()
501 Glib::Threads::Mutex::Lock lm (protocols_lock);
503 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
504 (*p)->midi_connectivity_established ();
509 ControlProtocolManager::register_request_buffer_factories ()
511 Glib::Threads::Mutex::Lock lm (protocols_lock);
513 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
515 if ((*i)->descriptor == 0) {
516 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
520 if ((*i)->descriptor->request_buffer_factory) {
521 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);