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;
415 Glib::Threads::Mutex::Lock lm (protocols_lock);
417 clist = node.children();
419 for (citer = clist.begin(); citer != clist.end(); ++citer) {
420 if ((*citer)->name() == X_("Protocol")) {
422 if ((prop = (*citer)->property (X_("active"))) == 0) {
426 bool active = string_is_affirmative (prop->value());
428 if ((prop = (*citer)->property (X_("name"))) == 0) {
432 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
435 cpi->state = new XMLNode (**citer);
441 cpi->requested = true;
447 cpi->requested = false;
458 ControlProtocolManager::get_state ()
460 XMLNode* root = new XMLNode (state_node_name);
461 Glib::Threads::Mutex::Lock lm (protocols_lock);
463 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
465 if ((*i)->protocol) {
466 XMLNode& child_state ((*i)->protocol->get_state());
467 child_state.add_property (X_("active"), "yes");
468 root->add_child_nocopy (child_state);
469 } else if ((*i)->state) {
470 XMLNode* child_state = new XMLNode (*(*i)->state);
471 child_state->add_property (X_("active"), "no");
472 root->add_child_nocopy (*child_state);
474 XMLNode* child_state = new XMLNode (X_("Protocol"));
475 child_state->add_property (X_("name"), (*i)->name);
476 child_state->add_property (X_("active"), "no");
477 root->add_child_nocopy (*child_state);
486 ControlProtocolManager&
487 ControlProtocolManager::instance ()
489 if (_instance == 0) {
490 _instance = new ControlProtocolManager ();
497 ControlProtocolManager::midi_connectivity_established ()
499 Glib::Threads::Mutex::Lock lm (protocols_lock);
501 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
502 (*p)->midi_connectivity_established ();
507 ControlProtocolManager::register_request_buffer_factories ()
509 Glib::Threads::Mutex::Lock lm (protocols_lock);
511 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
513 if ((*i)->descriptor == 0) {
514 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
518 if ((*i)->descriptor->request_buffer_factory) {
519 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);