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");
45 PBD::Signal1<void,StripableNotificationListPtr> ControlProtocolManager::StripableSelectionChanged;
47 ControlProtocolInfo::~ControlProtocolInfo ()
49 if (protocol && descriptor) {
50 descriptor->destroy (descriptor, protocol);
54 delete state; state = 0;
57 delete (Glib::Module*) descriptor->module;
62 ControlProtocolManager::ControlProtocolManager ()
66 ControlProtocolManager::~ControlProtocolManager()
68 Glib::Threads::Mutex::Lock lm (protocols_lock);
70 for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
74 control_protocols.clear ();
77 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
81 control_protocol_info.clear();
85 ControlProtocolManager::set_session (Session* s)
87 SessionHandlePtr::set_session (s);
90 Glib::Threads::Mutex::Lock lm (protocols_lock);
92 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
93 if ((*i)->requested || (*i)->mandatory) {
94 (void) activate (**i);
101 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
105 cpi.requested = true;
107 if ((cp = instantiate (cpi)) == 0) {
111 /* we split the set_state() and set_active() operations so that
112 protocols that need state to configure themselves (e.g. "What device
113 is connected, or supposed to be connected?") can get it before
114 actually starting any interaction.
118 /* force this by tweaking the internals of the state
121 cp->set_state (*cpi.state, Stateful::loading_state_version);
123 /* guarantee a call to
124 set_state() whether we have
125 existing state or not
127 cp->set_state (XMLNode(""), Stateful::loading_state_version);
130 if (cp->set_active (true)) {
131 error << string_compose (_("Control protocol support for %1 failed to activate"), cpi.name) << endmsg;
132 teardown (cpi, false);
139 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
141 cpi.requested = false;
142 return teardown (cpi, true);
146 ControlProtocolManager::session_going_away()
148 SessionHandlePtr::session_going_away ();
149 /* Session::destroy() will explicitly call drop_protocols() so we don't
150 * have to worry about that here.
155 ControlProtocolManager::drop_protocols ()
157 /* called explicitly by Session::destroy() so that we can clean up
158 * before the process cycle stops and ports vanish.
161 Glib::Threads::Mutex::Lock lm (protocols_lock);
163 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
167 control_protocols.clear ();
169 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
170 // mark existing protocols as requested
171 // otherwise the ControlProtocol instances are not recreated in set_session
172 if ((*p)->protocol) {
173 (*p)->requested = true;
175 ProtocolStatusChange (*p); /* EMIT SIGNAL */
181 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
183 /* CALLER MUST HOLD LOCK */
189 cpi.descriptor = get_descriptor (cpi.path);
191 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
193 if (cpi.descriptor == 0) {
194 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
198 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
200 if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
201 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
205 control_protocols.push_back (cpi.protocol);
207 ProtocolStatusChange (&cpi);
213 ControlProtocolManager::teardown (ControlProtocolInfo& cpi, bool lock_required)
217 /* we could still have a descriptor even if the protocol was
218 never instantiated. Close the associated module (shared
219 object/DLL) and make sure we forget about it.
222 if (cpi.descriptor) {
223 cerr << "Closing descriptor for CPI anyway\n";
224 delete (Glib::Module*) cpi.descriptor->module;
231 if (!cpi.descriptor) {
239 /* save current state */
242 cpi.state = new XMLNode (cpi.protocol->get_state());
243 cpi.state->set_property (X_("active"), false);
245 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
248 Glib::Threads::Mutex::Lock lm (protocols_lock);
249 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
250 if (p != control_protocols.end()) {
251 control_protocols.erase (p);
253 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
256 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
257 if (p != control_protocols.end()) {
258 control_protocols.erase (p);
260 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
267 /* the lock is only required when the protocol is torn down from the GUI.
268 * If a user disables a protocol, we take this as indicator to forget the
274 delete (Glib::Module*) cpi.descriptor->module;
275 /* cpi->descriptor is now inaccessible since dlclose() or equivalent
276 * has been performed, and the descriptor is (or could be) a static
277 * object made accessible by dlopen().
281 ProtocolStatusChange (&cpi);
287 ControlProtocolManager::load_mandatory_protocols ()
293 Glib::Threads::Mutex::Lock lm (protocols_lock);
295 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
296 if ((*i)->mandatory && ((*i)->protocol == 0)) {
297 DEBUG_TRACE (DEBUG::ControlProtocols,
298 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
305 ControlProtocolManager::discover_control_protocols ()
307 vector<std::string> cp_modules;
311 * Different build targets (Debug / Release etc) use different versions
312 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
313 * case the supplied search path contains multiple version(s) of a given
314 * module, only select the one(s) which match the current build target
317 Glib::PatternSpec dll_extension_pattern("*D.dll");
318 #elif defined (RDC_BUILD)
319 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
320 #elif defined (_WIN64)
321 Glib::PatternSpec dll_extension_pattern("*64.dll");
323 Glib::PatternSpec dll_extension_pattern("*32.dll");
326 Glib::PatternSpec dll_extension_pattern("*.dll");
329 Glib::PatternSpec so_extension_pattern("*.so");
330 Glib::PatternSpec dylib_extension_pattern("*.dylib");
332 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
333 dll_extension_pattern);
335 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
336 so_extension_pattern);
338 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
339 dylib_extension_pattern);
341 DEBUG_TRACE (DEBUG::ControlProtocols,
342 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
344 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
345 control_protocol_discover (*i);
350 ControlProtocolManager::control_protocol_discover (string path)
352 ControlProtocolDescriptor* descriptor;
355 /* don't load OS X shared objects that are just symlinks to the real thing.
358 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
363 if ((descriptor = get_descriptor (path)) != 0) {
365 if (!descriptor->probe (descriptor)) {
366 warning << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
369 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
371 cpi->descriptor = descriptor;
372 cpi->name = descriptor->name;
375 cpi->requested = false;
376 cpi->mandatory = descriptor->mandatory;
377 cpi->supports_feedback = descriptor->supports_feedback;
380 control_protocol_info.push_back (cpi);
382 DEBUG_TRACE (DEBUG::ControlProtocols,
383 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
390 ControlProtocolDescriptor*
391 ControlProtocolManager::get_descriptor (string path)
393 Glib::Module* module = new Glib::Module(path);
394 ControlProtocolDescriptor *descriptor = 0;
395 ControlProtocolDescriptor* (*dfunc)(void);
399 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
404 if (!module->get_symbol("protocol_descriptor", func)) {
405 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
406 error << Glib::Module::get_last_error() << endmsg;
411 dfunc = (ControlProtocolDescriptor* (*)(void))func;
412 descriptor = dfunc();
415 descriptor->module = (void*)module;
422 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
424 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
430 ControlProtocolManager::cpi_by_name (string name)
432 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
433 if (name == (*i)->name) {
441 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
444 XMLNodeConstIterator citer;
446 Glib::Threads::Mutex::Lock lm (protocols_lock);
448 clist = node.children();
450 for (citer = clist.begin(); citer != clist.end(); ++citer) {
451 XMLNode const * child = *citer;
453 if (child->name() == X_("Protocol")) {
457 if (!child->get_property (X_("active"), active) ||
458 !child->get_property (X_("name"), name)) {
462 ControlProtocolInfo* cpi = cpi_by_name (name);
465 std::cerr << "protocol " << name << " active ? " << active << std::endl;
469 cpi->state = new XMLNode (**citer);
473 cpi->requested = true;
477 cpi->state = new XMLNode (**citer);
478 cpi->state->set_property (X_("active"), false);
480 cpi->requested = false;
482 teardown (*cpi, false);
486 std::cerr << "protocol " << name << " not found\n";
495 ControlProtocolManager::get_state ()
497 XMLNode* root = new XMLNode (state_node_name);
498 Glib::Threads::Mutex::Lock lm (protocols_lock);
500 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
502 if ((*i)->protocol) {
503 XMLNode& child_state ((*i)->protocol->get_state());
504 child_state.set_property (X_("active"), true);
505 root->add_child_nocopy (child_state);
506 } else if ((*i)->state) {
507 XMLNode* child_state = new XMLNode (*(*i)->state);
508 child_state->set_property (X_("active"), false);
509 root->add_child_nocopy (*child_state);
511 XMLNode* child_state = new XMLNode (X_("Protocol"));
512 child_state->set_property (X_("name"), (*i)->name);
513 child_state->set_property (X_("active"), false);
514 root->add_child_nocopy (*child_state);
523 ControlProtocolManager&
524 ControlProtocolManager::instance ()
526 if (_instance == 0) {
527 _instance = new ControlProtocolManager ();
534 ControlProtocolManager::midi_connectivity_established ()
536 Glib::Threads::Mutex::Lock lm (protocols_lock);
538 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
539 (*p)->midi_connectivity_established ();
544 ControlProtocolManager::register_request_buffer_factories ()
546 Glib::Threads::Mutex::Lock lm (protocols_lock);
548 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
550 if ((*i)->descriptor == 0) {
551 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
555 if ((*i)->descriptor->request_buffer_factory) {
556 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);
562 ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp)
564 /* this sets up the (static) data structures owned by ControlProtocol
565 that are "shared" across all control protocols.
568 DEBUG_TRACE (DEBUG::Selection, string_compose ("Surface manager: selection changed, now %1 stripables\n", sp ? sp->size() : -1));
569 StripableSelectionChanged (sp); /* EMIT SIGNAL */
571 /* now give each protocol the chance to respond to the selection change
575 Glib::Threads::Mutex::Lock lm (protocols_lock);
577 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
578 DEBUG_TRACE (DEBUG::Selection, string_compose ("selection change notification for surface \"%1\"\n", (*p)->name()));
579 (*p)->stripable_selection_changed ();