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"
35 #include "ardour/selection.h"
36 #include "ardour/session.h"
38 using namespace ARDOUR;
44 ControlProtocolManager* ControlProtocolManager::_instance = 0;
45 const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
46 PBD::Signal1<void,StripableNotificationListPtr> ControlProtocolManager::StripableSelectionChanged;
48 ControlProtocolInfo::~ControlProtocolInfo ()
50 if (protocol && descriptor) {
51 descriptor->destroy (descriptor, protocol);
55 delete state; state = 0;
58 delete (Glib::Module*) descriptor->module;
63 ControlProtocolManager::ControlProtocolManager ()
67 ControlProtocolManager::~ControlProtocolManager()
69 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
71 for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
75 control_protocols.clear ();
78 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
82 control_protocol_info.clear();
86 ControlProtocolManager::set_session (Session* s)
88 SessionHandlePtr::set_session (s);
95 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
97 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
98 if ((*i)->requested || (*i)->mandatory) {
99 (void) activate (**i);
104 CoreSelection::StripableAutomationControls sac;
105 _session->selection().get_stripables (sac);
108 StripableNotificationListPtr v (new StripableNotificationList);
109 for (CoreSelection::StripableAutomationControls::iterator i = sac.begin(); i != sac.end(); ++i) {
110 if ((*i).stripable) {
111 v->push_back (boost::weak_ptr<Stripable> ((*i).stripable));
115 StripableSelectionChanged (v); /* EMIT SIGNAL */
121 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
125 cpi.requested = true;
127 if ((cp = instantiate (cpi)) == 0) {
131 /* we split the set_state() and set_active() operations so that
132 protocols that need state to configure themselves (e.g. "What device
133 is connected, or supposed to be connected?") can get it before
134 actually starting any interaction.
138 /* force this by tweaking the internals of the state
141 cp->set_state (*cpi.state, Stateful::loading_state_version);
143 /* guarantee a call to
144 set_state() whether we have
145 existing state or not
147 cp->set_state (XMLNode(""), Stateful::loading_state_version);
150 if (cp->set_active (true)) {
151 error << string_compose (_("Control protocol support for %1 failed to activate"), cpi.name) << endmsg;
152 teardown (cpi, false);
159 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
161 cpi.requested = false;
162 return teardown (cpi, true);
166 ControlProtocolManager::session_going_away()
168 SessionHandlePtr::session_going_away ();
169 /* Session::destroy() will explicitly call drop_protocols() so we don't
170 * have to worry about that here.
175 ControlProtocolManager::drop_protocols ()
177 /* called explicitly by Session::destroy() so that we can clean up
178 * before the process cycle stops and ports vanish.
181 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
183 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
187 control_protocols.clear ();
189 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
190 // mark existing protocols as requested
191 // otherwise the ControlProtocol instances are not recreated in set_session
192 if ((*p)->protocol) {
193 (*p)->requested = true;
195 ProtocolStatusChange (*p); /* EMIT SIGNAL */
201 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
203 /* CALLER MUST HOLD LOCK */
209 cpi.descriptor = get_descriptor (cpi.path);
211 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
213 if (cpi.descriptor == 0) {
214 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
218 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
220 if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
221 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
225 control_protocols.push_back (cpi.protocol);
227 ProtocolStatusChange (&cpi);
233 ControlProtocolManager::teardown (ControlProtocolInfo& cpi, bool lock_required)
237 /* we could still have a descriptor even if the protocol was
238 never instantiated. Close the associated module (shared
239 object/DLL) and make sure we forget about it.
242 if (cpi.descriptor) {
243 cerr << "Closing descriptor for CPI anyway\n";
244 delete (Glib::Module*) cpi.descriptor->module;
251 if (!cpi.descriptor) {
259 /* save current state */
262 cpi.state = new XMLNode (cpi.protocol->get_state());
263 cpi.state->set_property (X_("active"), false);
265 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
268 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
269 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
270 if (p != control_protocols.end()) {
271 control_protocols.erase (p);
273 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
276 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
277 if (p != control_protocols.end()) {
278 control_protocols.erase (p);
280 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
287 /* the lock is only required when the protocol is torn down from the GUI.
288 * If a user disables a protocol, we take this as indicator to forget the
294 delete (Glib::Module*) cpi.descriptor->module;
295 /* cpi->descriptor is now inaccessible since dlclose() or equivalent
296 * has been performed, and the descriptor is (or could be) a static
297 * object made accessible by dlopen().
301 ProtocolStatusChange (&cpi);
307 ControlProtocolManager::load_mandatory_protocols ()
313 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
315 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
316 if ((*i)->mandatory && ((*i)->protocol == 0)) {
317 DEBUG_TRACE (DEBUG::ControlProtocols,
318 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
325 ControlProtocolManager::discover_control_protocols ()
327 vector<std::string> cp_modules;
331 * Different build targets (Debug / Release etc) use different versions
332 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
333 * case the supplied search path contains multiple version(s) of a given
334 * module, only select the one(s) which match the current build target
337 Glib::PatternSpec dll_extension_pattern("*D.dll");
338 #elif defined (RDC_BUILD)
339 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
340 #elif defined (_WIN64)
341 Glib::PatternSpec dll_extension_pattern("*64.dll");
343 Glib::PatternSpec dll_extension_pattern("*32.dll");
346 Glib::PatternSpec dll_extension_pattern("*.dll");
349 Glib::PatternSpec so_extension_pattern("*.so");
350 Glib::PatternSpec dylib_extension_pattern("*.dylib");
352 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
353 dll_extension_pattern);
355 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
356 so_extension_pattern);
358 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
359 dylib_extension_pattern);
361 DEBUG_TRACE (DEBUG::ControlProtocols,
362 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
364 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
365 control_protocol_discover (*i);
370 ControlProtocolManager::control_protocol_discover (string path)
372 ControlProtocolDescriptor* descriptor;
375 /* don't load OS X shared objects that are just symlinks to the real thing.
378 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
383 if ((descriptor = get_descriptor (path)) != 0) {
385 if (!descriptor->probe (descriptor)) {
386 warning << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
389 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
391 cpi->descriptor = descriptor;
392 cpi->name = descriptor->name;
395 cpi->requested = false;
396 cpi->mandatory = descriptor->mandatory;
397 cpi->supports_feedback = descriptor->supports_feedback;
400 control_protocol_info.push_back (cpi);
402 DEBUG_TRACE (DEBUG::ControlProtocols,
403 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
410 ControlProtocolDescriptor*
411 ControlProtocolManager::get_descriptor (string path)
413 Glib::Module* module = new Glib::Module(path);
414 ControlProtocolDescriptor *descriptor = 0;
415 ControlProtocolDescriptor* (*dfunc)(void);
419 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
424 if (!module->get_symbol("protocol_descriptor", func)) {
425 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
426 error << Glib::Module::get_last_error() << endmsg;
431 dfunc = (ControlProtocolDescriptor* (*)(void))func;
432 descriptor = dfunc();
435 descriptor->module = (void*)module;
442 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
444 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
450 ControlProtocolManager::cpi_by_name (string name)
452 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
453 if (name == (*i)->name) {
461 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
464 XMLNodeConstIterator citer;
466 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
468 clist = node.children();
470 for (citer = clist.begin(); citer != clist.end(); ++citer) {
471 XMLNode const * child = *citer;
473 if (child->name() == X_("Protocol")) {
477 if (!child->get_property (X_("active"), active) ||
478 !child->get_property (X_("name"), name)) {
482 ControlProtocolInfo* cpi = cpi_by_name (name);
485 std::cerr << "protocol " << name << " active ? " << active << std::endl;
489 cpi->state = new XMLNode (**citer);
493 cpi->requested = true;
497 cpi->state = new XMLNode (**citer);
498 cpi->state->set_property (X_("active"), false);
500 cpi->requested = false;
502 teardown (*cpi, false);
506 std::cerr << "protocol " << name << " not found\n";
515 ControlProtocolManager::get_state ()
517 XMLNode* root = new XMLNode (state_node_name);
518 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
520 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
522 if ((*i)->protocol) {
523 XMLNode& child_state ((*i)->protocol->get_state());
524 child_state.set_property (X_("active"), true);
525 root->add_child_nocopy (child_state);
526 } else if ((*i)->state) {
527 XMLNode* child_state = new XMLNode (*(*i)->state);
528 child_state->set_property (X_("active"), false);
529 root->add_child_nocopy (*child_state);
531 XMLNode* child_state = new XMLNode (X_("Protocol"));
532 child_state->set_property (X_("name"), (*i)->name);
533 child_state->set_property (X_("active"), false);
534 root->add_child_nocopy (*child_state);
543 ControlProtocolManager&
544 ControlProtocolManager::instance ()
546 if (_instance == 0) {
547 _instance = new ControlProtocolManager ();
554 ControlProtocolManager::midi_connectivity_established ()
556 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
558 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
559 (*p)->midi_connectivity_established ();
564 ControlProtocolManager::register_request_buffer_factories ()
566 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
568 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
570 if ((*i)->descriptor == 0) {
571 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
575 if ((*i)->descriptor->request_buffer_factory) {
576 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);
582 ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp)
584 /* this sets up the (static) data structures owned by ControlProtocol
585 that are "shared" across all control protocols.
588 DEBUG_TRACE (DEBUG::Selection, string_compose ("Surface manager: selection changed, now %1 stripables\n", sp ? sp->size() : -1));
589 StripableSelectionChanged (sp); /* EMIT SIGNAL */
591 /* now give each protocol the chance to respond to the selection change
595 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
597 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
598 DEBUG_TRACE (DEBUG::Selection, string_compose ("selection change notification for surface \"%1\"\n", (*p)->name()));
599 (*p)->stripable_selection_changed ();