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/file_utils.h"
26 #include "pbd/error.h"
28 #include "control_protocol/control_protocol.h"
30 #include "ardour/debug.h"
31 #include "ardour/control_protocol_manager.h"
33 #include "ardour/search_paths.h"
36 using namespace ARDOUR;
42 ControlProtocolManager* ControlProtocolManager::_instance = 0;
43 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
45 ControlProtocolManager::ControlProtocolManager ()
49 ControlProtocolManager::~ControlProtocolManager()
51 Glib::Threads::Mutex::Lock lm (protocols_lock);
53 for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
57 control_protocols.clear ();
60 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
64 control_protocol_info.clear();
68 ControlProtocolManager::set_session (Session* s)
70 SessionHandlePtr::set_session (s);
73 Glib::Threads::Mutex::Lock lm (protocols_lock);
75 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
76 if ((*i)->requested || (*i)->mandatory) {
77 (void) activate (**i);
84 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
90 if ((cp = instantiate (cpi)) == 0) {
94 /* we split the set_state() and set_active() operations so that
95 protocols that need state to configure themselves (e.g. "What device
96 is connected, or supposed to be connected?") can get it before
97 actually starting any interaction.
101 /* force this by tweaking the internals of the state
104 cp->set_state (*cpi.state, Stateful::loading_state_version);
106 /* guarantee a call to
107 set_state() whether we have
108 existing state or not
110 cp->set_state (XMLNode(""), Stateful::loading_state_version);
113 cp->set_active (true);
119 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
121 cpi.requested = false;
122 return teardown (cpi);
126 ControlProtocolManager::session_going_away()
128 SessionHandlePtr::session_going_away ();
129 /* Session::destroy() will explicitly call drop_protocols() so we don't
130 * have to worry about that here.
135 ControlProtocolManager::drop_protocols ()
137 /* called explicitly by Session::destroy() so that we can clean up
138 * before the process cycle stops and ports vanish.
141 Glib::Threads::Mutex::Lock lm (protocols_lock);
143 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
147 control_protocols.clear ();
149 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
150 // mark existing protocols as requested
151 // otherwise the ControlProtocol instances are not recreated in set_session
152 if ((*p)->protocol) {
153 (*p)->requested = true;
160 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
162 /* CALLER MUST HOLD LOCK */
168 cpi.descriptor = get_descriptor (cpi.path);
170 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
172 if (cpi.descriptor == 0) {
173 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
177 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
179 if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
180 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
184 control_protocols.push_back (cpi.protocol);
186 ProtocolStatusChange (&cpi);
192 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
198 if (!cpi.descriptor) {
206 /* save current state */
209 cpi.state = new XMLNode (cpi.protocol->get_state());
210 cpi.state->add_property (X_("active"), "no");
212 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
215 Glib::Threads::Mutex::Lock lm (protocols_lock);
216 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
217 if (p != control_protocols.end()) {
218 control_protocols.erase (p);
220 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
227 delete (Glib::Module*)cpi.descriptor->module;
229 ProtocolStatusChange (&cpi);
235 ControlProtocolManager::load_mandatory_protocols ()
241 Glib::Threads::Mutex::Lock lm (protocols_lock);
243 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
244 if ((*i)->mandatory && ((*i)->protocol == 0)) {
245 DEBUG_TRACE (DEBUG::ControlProtocols,
246 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
253 ControlProtocolManager::discover_control_protocols ()
255 vector<std::string> cp_modules;
259 * Different build targets (Debug / Release etc) use different versions
260 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
261 * case the supplied search path contains multiple version(s) of a given
262 * module, only select the one(s) which match the current build target
265 Glib::PatternSpec dll_extension_pattern("*D.dll");
266 #elif defined (RDC_BUILD)
267 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
268 #elif defined (_WIN64)
269 Glib::PatternSpec dll_extension_pattern("*64.dll");
271 Glib::PatternSpec dll_extension_pattern("*32.dll");
274 Glib::PatternSpec dll_extension_pattern("*.dll");
277 Glib::PatternSpec so_extension_pattern("*.so");
278 Glib::PatternSpec dylib_extension_pattern("*.dylib");
280 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
281 dll_extension_pattern);
283 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
284 so_extension_pattern);
286 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
287 dylib_extension_pattern);
289 DEBUG_TRACE (DEBUG::ControlProtocols,
290 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
292 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
293 control_protocol_discover (*i);
298 ControlProtocolManager::control_protocol_discover (string path)
300 ControlProtocolDescriptor* descriptor;
303 /* don't load OS X shared objects that are just symlinks to the real thing.
306 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
311 if ((descriptor = get_descriptor (path)) != 0) {
313 if (!descriptor->probe (descriptor)) {
314 DEBUG_TRACE (DEBUG::ControlProtocols,
315 string_compose (_("Control protocol %1 not usable"), descriptor->name));
318 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
320 cpi->descriptor = descriptor;
321 cpi->name = descriptor->name;
324 cpi->requested = false;
325 cpi->mandatory = descriptor->mandatory;
326 cpi->supports_feedback = descriptor->supports_feedback;
329 control_protocol_info.push_back (cpi);
331 DEBUG_TRACE (DEBUG::ControlProtocols,
332 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
335 delete (Glib::Module*)descriptor->module;
341 ControlProtocolDescriptor*
342 ControlProtocolManager::get_descriptor (string path)
344 Glib::Module* module = new Glib::Module(path);
345 ControlProtocolDescriptor *descriptor = 0;
346 ControlProtocolDescriptor* (*dfunc)(void);
350 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
355 if (!module->get_symbol("protocol_descriptor", func)) {
356 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
357 error << Glib::Module::get_last_error() << endmsg;
362 dfunc = (ControlProtocolDescriptor* (*)(void))func;
363 descriptor = dfunc();
366 descriptor->module = (void*)module;
375 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
377 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
383 ControlProtocolManager::cpi_by_name (string name)
385 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
386 if (name == (*i)->name) {
394 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
397 XMLNodeConstIterator citer;
400 Glib::Threads::Mutex::Lock lm (protocols_lock);
402 clist = node.children();
404 for (citer = clist.begin(); citer != clist.end(); ++citer) {
405 if ((*citer)->name() == X_("Protocol")) {
407 if ((prop = (*citer)->property (X_("active"))) == 0) {
411 bool active = string_is_affirmative (prop->value());
413 if ((prop = (*citer)->property (X_("name"))) == 0) {
417 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
420 cpi->state = new XMLNode (**citer);
426 cpi->requested = true;
432 cpi->requested = false;
443 ControlProtocolManager::get_state ()
445 XMLNode* root = new XMLNode (state_node_name);
446 Glib::Threads::Mutex::Lock lm (protocols_lock);
448 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
450 if ((*i)->protocol) {
451 XMLNode& child_state ((*i)->protocol->get_state());
452 child_state.add_property (X_("active"), "yes");
453 root->add_child_nocopy (child_state);
454 } else if ((*i)->state) {
455 XMLNode* child_state = new XMLNode (*(*i)->state);
456 child_state->add_property (X_("active"), "no");
457 root->add_child_nocopy (*child_state);
459 XMLNode* child_state = new XMLNode (X_("Protocol"));
460 child_state->add_property (X_("name"), (*i)->name);
461 child_state->add_property (X_("active"), "no");
462 root->add_child_nocopy (*child_state);
471 ControlProtocolManager&
472 ControlProtocolManager::instance ()
474 if (_instance == 0) {
475 _instance = new ControlProtocolManager ();
482 ControlProtocolManager::midi_connectivity_established ()
484 Glib::Threads::Mutex::Lock lm (protocols_lock);
486 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
487 (*p)->midi_connectivity_established ();