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/control_protocol_search_path.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 ();
131 Glib::Threads::Mutex::Lock lm (protocols_lock);
133 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
137 control_protocols.clear ();
139 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
140 // mark existing protocols as requested
141 // otherwise the ControlProtocol instances are not recreated in set_session
142 if ((*p)->protocol) {
143 (*p)->requested = true;
151 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
153 /* CALLER MUST HOLD LOCK */
159 cpi.descriptor = get_descriptor (cpi.path);
161 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
163 if (cpi.descriptor == 0) {
164 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
168 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
170 if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
171 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
175 control_protocols.push_back (cpi.protocol);
177 ProtocolStatusChange (&cpi);
183 ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
189 if (!cpi.descriptor) {
197 /* save current state */
200 cpi.state = new XMLNode (cpi.protocol->get_state());
201 cpi.state->add_property (X_("active"), "no");
203 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
206 Glib::Threads::Mutex::Lock lm (protocols_lock);
207 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
208 if (p != control_protocols.end()) {
209 control_protocols.erase (p);
211 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
218 delete (Glib::Module*)cpi.descriptor->module;
220 ProtocolStatusChange (&cpi);
226 ControlProtocolManager::load_mandatory_protocols ()
232 Glib::Threads::Mutex::Lock lm (protocols_lock);
234 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
235 if ((*i)->mandatory && ((*i)->protocol == 0)) {
236 DEBUG_TRACE (DEBUG::ControlProtocols,
237 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
244 ControlProtocolManager::discover_control_protocols ()
246 vector<std::string> cp_modules;
248 Glib::PatternSpec so_extension_pattern("*.so");
249 Glib::PatternSpec dylib_extension_pattern("*.dylib");
251 find_matching_files_in_search_path (control_protocol_search_path (),
252 so_extension_pattern, cp_modules);
254 find_matching_files_in_search_path (control_protocol_search_path (),
255 dylib_extension_pattern, cp_modules);
257 DEBUG_TRACE (DEBUG::ControlProtocols,
258 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
260 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
261 control_protocol_discover (*i);
266 ControlProtocolManager::control_protocol_discover (string path)
268 ControlProtocolDescriptor* descriptor;
271 /* don't load OS X shared objects that are just symlinks to the real thing.
274 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
279 if ((descriptor = get_descriptor (path)) != 0) {
281 if (!descriptor->probe (descriptor)) {
282 DEBUG_TRACE (DEBUG::ControlProtocols,
283 string_compose (_("Control protocol %1 not usable"), descriptor->name));
286 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
288 cpi->descriptor = descriptor;
289 cpi->name = descriptor->name;
292 cpi->requested = false;
293 cpi->mandatory = descriptor->mandatory;
294 cpi->supports_feedback = descriptor->supports_feedback;
297 control_protocol_info.push_back (cpi);
299 DEBUG_TRACE (DEBUG::ControlProtocols,
300 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
303 delete (Glib::Module*)descriptor->module;
309 ControlProtocolDescriptor*
310 ControlProtocolManager::get_descriptor (string path)
312 Glib::Module* module = new Glib::Module(path);
313 ControlProtocolDescriptor *descriptor = 0;
314 ControlProtocolDescriptor* (*dfunc)(void);
318 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
323 if (!module->get_symbol("protocol_descriptor", func)) {
324 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
325 error << Glib::Module::get_last_error() << endmsg;
330 dfunc = (ControlProtocolDescriptor* (*)(void))func;
331 descriptor = dfunc();
334 descriptor->module = (void*)module;
343 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
345 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
351 ControlProtocolManager::cpi_by_name (string name)
353 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
354 if (name == (*i)->name) {
362 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
365 XMLNodeConstIterator citer;
368 Glib::Threads::Mutex::Lock lm (protocols_lock);
370 clist = node.children();
372 for (citer = clist.begin(); citer != clist.end(); ++citer) {
373 if ((*citer)->name() == X_("Protocol")) {
375 if ((prop = (*citer)->property (X_("active"))) == 0) {
379 bool active = string_is_affirmative (prop->value());
381 if ((prop = (*citer)->property (X_("name"))) == 0) {
385 ControlProtocolInfo* cpi = cpi_by_name (prop->value());
388 cpi->state = new XMLNode (**citer);
394 cpi->requested = true;
400 cpi->requested = false;
411 ControlProtocolManager::get_state ()
413 XMLNode* root = new XMLNode (state_node_name);
414 Glib::Threads::Mutex::Lock lm (protocols_lock);
416 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
418 if ((*i)->protocol) {
419 XMLNode& child_state ((*i)->protocol->get_state());
420 child_state.add_property (X_("active"), "yes");
421 root->add_child_nocopy (child_state);
422 } else if ((*i)->state) {
423 XMLNode* child_state = new XMLNode (*(*i)->state);
424 child_state->add_property (X_("active"), "no");
425 root->add_child_nocopy (*child_state);
427 XMLNode* child_state = new XMLNode (X_("Protocol"));
428 child_state->add_property (X_("name"), (*i)->name);
429 child_state->add_property (X_("active"), "no");
430 root->add_child_nocopy (*child_state);
439 ControlProtocolManager&
440 ControlProtocolManager::instance ()
442 if (_instance == 0) {
443 _instance = new ControlProtocolManager ();
450 ControlProtocolManager::midi_connectivity_established ()
452 Glib::Threads::Mutex::Lock lm (protocols_lock);
454 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
455 (*p)->midi_connectivity_established ();