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 cerr << "Tear down CPI module for " << cpi.name << endl;
242 delete (Glib::Module*) cpi.descriptor->module;
243 /* cpi->descriptor is now inaccessible since dlclose() or equivalent
244 * has been performed, and the descriptor is (or could be) a static
245 * object made accessible by dlopen().
249 ProtocolStatusChange (&cpi);
255 ControlProtocolManager::load_mandatory_protocols ()
261 Glib::Threads::Mutex::Lock lm (protocols_lock);
263 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
264 if ((*i)->mandatory && ((*i)->protocol == 0)) {
265 DEBUG_TRACE (DEBUG::ControlProtocols,
266 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
273 ControlProtocolManager::discover_control_protocols ()
275 vector<std::string> cp_modules;
279 * Different build targets (Debug / Release etc) use different versions
280 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
281 * case the supplied search path contains multiple version(s) of a given
282 * module, only select the one(s) which match the current build target
285 Glib::PatternSpec dll_extension_pattern("*D.dll");
286 #elif defined (RDC_BUILD)
287 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
288 #elif defined (_WIN64)
289 Glib::PatternSpec dll_extension_pattern("*64.dll");
291 Glib::PatternSpec dll_extension_pattern("*32.dll");
294 Glib::PatternSpec dll_extension_pattern("*.dll");
297 Glib::PatternSpec so_extension_pattern("*.so");
298 Glib::PatternSpec dylib_extension_pattern("*.dylib");
300 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
301 dll_extension_pattern);
303 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
304 so_extension_pattern);
306 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
307 dylib_extension_pattern);
309 DEBUG_TRACE (DEBUG::ControlProtocols,
310 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
312 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
313 control_protocol_discover (*i);
318 ControlProtocolManager::control_protocol_discover (string path)
320 ControlProtocolDescriptor* descriptor;
323 /* don't load OS X shared objects that are just symlinks to the real thing.
326 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
331 if ((descriptor = get_descriptor (path)) != 0) {
333 if (!descriptor->probe (descriptor)) {
334 DEBUG_TRACE (DEBUG::ControlProtocols,
335 string_compose (_("Control protocol %1 not usable"), descriptor->name));
338 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
340 cpi->descriptor = descriptor;
341 cpi->name = descriptor->name;
344 cpi->requested = false;
345 cpi->mandatory = descriptor->mandatory;
346 cpi->supports_feedback = descriptor->supports_feedback;
349 control_protocol_info.push_back (cpi);
351 DEBUG_TRACE (DEBUG::ControlProtocols,
352 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
359 ControlProtocolDescriptor*
360 ControlProtocolManager::get_descriptor (string path)
362 Glib::Module* module = new Glib::Module(path);
363 ControlProtocolDescriptor *descriptor = 0;
364 ControlProtocolDescriptor* (*dfunc)(void);
368 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
373 if (!module->get_symbol("protocol_descriptor", func)) {
374 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
375 error << Glib::Module::get_last_error() << endmsg;
380 dfunc = (ControlProtocolDescriptor* (*)(void))func;
381 descriptor = dfunc();
384 descriptor->module = (void*)module;
391 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
393 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
399 ControlProtocolManager::cpi_by_name (string name)
401 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
402 if (name == (*i)->name) {
410 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
413 XMLNodeConstIterator citer;
416 Glib::Threads::Mutex::Lock lm (protocols_lock);
418 clist = node.children();
420 for (citer = clist.begin(); citer != clist.end(); ++citer) {
421 if ((*citer)->name() == X_("Protocol")) {
423 if ((prop = (*citer)->property (X_("active"))) == 0) {
427 bool active = string_is_affirmative (prop->value());
429 if ((prop = (*citer)->property (X_("name"))) == 0) {
433 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
436 cpi->state = new XMLNode (**citer);
442 cpi->requested = true;
448 cpi->requested = false;
459 ControlProtocolManager::get_state ()
461 XMLNode* root = new XMLNode (state_node_name);
462 Glib::Threads::Mutex::Lock lm (protocols_lock);
464 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
466 if ((*i)->protocol) {
467 XMLNode& child_state ((*i)->protocol->get_state());
468 child_state.add_property (X_("active"), "yes");
469 root->add_child_nocopy (child_state);
470 } else if ((*i)->state) {
471 XMLNode* child_state = new XMLNode (*(*i)->state);
472 child_state->add_property (X_("active"), "no");
473 root->add_child_nocopy (*child_state);
475 XMLNode* child_state = new XMLNode (X_("Protocol"));
476 child_state->add_property (X_("name"), (*i)->name);
477 child_state->add_property (X_("active"), "no");
478 root->add_child_nocopy (*child_state);
487 ControlProtocolManager&
488 ControlProtocolManager::instance ()
490 if (_instance == 0) {
491 _instance = new ControlProtocolManager ();
498 ControlProtocolManager::midi_connectivity_established ()
500 Glib::Threads::Mutex::Lock lm (protocols_lock);
502 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
503 (*p)->midi_connectivity_established ();
508 ControlProtocolManager::register_request_buffer_factories ()
510 Glib::Threads::Mutex::Lock lm (protocols_lock);
512 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
514 if ((*i)->descriptor == 0) {
515 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
519 if ((*i)->descriptor->request_buffer_factory) {
520 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);