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)
199 if (!cpi.descriptor) {
207 /* save current state */
210 cpi.state = new XMLNode (cpi.protocol->get_state());
211 cpi.state->add_property (X_("active"), "no");
213 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
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);
221 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
228 delete (Glib::Module*)cpi.descriptor->module;
230 ProtocolStatusChange (&cpi);
236 ControlProtocolManager::load_mandatory_protocols ()
242 Glib::Threads::Mutex::Lock lm (protocols_lock);
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));
254 ControlProtocolManager::discover_control_protocols ()
256 vector<std::string> cp_modules;
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
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");
272 Glib::PatternSpec dll_extension_pattern("*32.dll");
275 Glib::PatternSpec dll_extension_pattern("*.dll");
278 Glib::PatternSpec so_extension_pattern("*.so");
279 Glib::PatternSpec dylib_extension_pattern("*.dylib");
281 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
282 dll_extension_pattern);
284 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
285 so_extension_pattern);
287 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
288 dylib_extension_pattern);
290 DEBUG_TRACE (DEBUG::ControlProtocols,
291 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
293 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
294 control_protocol_discover (*i);
299 ControlProtocolManager::control_protocol_discover (string path)
301 ControlProtocolDescriptor* descriptor;
304 /* don't load OS X shared objects that are just symlinks to the real thing.
307 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
312 if ((descriptor = get_descriptor (path)) != 0) {
314 if (!descriptor->probe (descriptor)) {
315 DEBUG_TRACE (DEBUG::ControlProtocols,
316 string_compose (_("Control protocol %1 not usable"), descriptor->name));
319 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
321 cpi->descriptor = descriptor;
322 cpi->name = descriptor->name;
325 cpi->requested = false;
326 cpi->mandatory = descriptor->mandatory;
327 cpi->supports_feedback = descriptor->supports_feedback;
330 control_protocol_info.push_back (cpi);
332 DEBUG_TRACE (DEBUG::ControlProtocols,
333 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
336 delete (Glib::Module*)descriptor->module;
342 ControlProtocolDescriptor*
343 ControlProtocolManager::get_descriptor (string path)
345 Glib::Module* module = new Glib::Module(path);
346 ControlProtocolDescriptor *descriptor = 0;
347 ControlProtocolDescriptor* (*dfunc)(void);
351 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
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;
363 dfunc = (ControlProtocolDescriptor* (*)(void))func;
364 descriptor = dfunc();
367 descriptor->module = (void*)module;
376 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
378 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
384 ControlProtocolManager::cpi_by_name (string name)
386 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
387 if (name == (*i)->name) {
395 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
398 XMLNodeConstIterator citer;
401 Glib::Threads::Mutex::Lock lm (protocols_lock);
403 clist = node.children();
405 for (citer = clist.begin(); citer != clist.end(); ++citer) {
406 if ((*citer)->name() == X_("Protocol")) {
408 if ((prop = (*citer)->property (X_("active"))) == 0) {
412 bool active = string_is_affirmative (prop->value());
414 if ((prop = (*citer)->property (X_("name"))) == 0) {
418 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
421 cpi->state = new XMLNode (**citer);
427 cpi->requested = true;
433 cpi->requested = false;
444 ControlProtocolManager::get_state ()
446 XMLNode* root = new XMLNode (state_node_name);
447 Glib::Threads::Mutex::Lock lm (protocols_lock);
449 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
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);
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);
472 ControlProtocolManager&
473 ControlProtocolManager::instance ()
475 if (_instance == 0) {
476 _instance = new ControlProtocolManager ();
483 ControlProtocolManager::midi_connectivity_established ()
485 Glib::Threads::Mutex::Lock lm (protocols_lock);
487 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
488 (*p)->midi_connectivity_established ();
493 ControlProtocolManager::register_request_buffer_factories ()
495 Glib::Threads::Mutex::Lock lm (protocols_lock);
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);