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) {
79 (*p)->protocol = 0; // protocol was already destroyed above.
83 control_protocol_info.clear();
87 ControlProtocolManager::set_session (Session* s)
89 SessionHandlePtr::set_session (s);
96 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
98 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
99 if ((*i)->requested || (*i)->mandatory) {
100 (void) activate (**i);
105 CoreSelection::StripableAutomationControls sac;
106 _session->selection().get_stripables (sac);
109 StripableNotificationListPtr v (new StripableNotificationList);
110 for (CoreSelection::StripableAutomationControls::iterator i = sac.begin(); i != sac.end(); ++i) {
111 if ((*i).stripable) {
112 v->push_back (boost::weak_ptr<Stripable> ((*i).stripable));
116 StripableSelectionChanged (v); /* EMIT SIGNAL */
122 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
126 cpi.requested = true;
128 if ((cp = instantiate (cpi)) == 0) {
132 /* we split the set_state() and set_active() operations so that
133 protocols that need state to configure themselves (e.g. "What device
134 is connected, or supposed to be connected?") can get it before
135 actually starting any interaction.
139 /* force this by tweaking the internals of the state
142 cp->set_state (*cpi.state, Stateful::loading_state_version);
144 /* guarantee a call to
145 set_state() whether we have
146 existing state or not
148 cp->set_state (XMLNode(""), Stateful::loading_state_version);
151 if (cp->set_active (true)) {
152 error << string_compose (_("Control protocol support for %1 failed to activate"), cpi.name) << endmsg;
153 teardown (cpi, false);
160 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
162 cpi.requested = false;
163 return teardown (cpi, true);
167 ControlProtocolManager::session_going_away()
169 SessionHandlePtr::session_going_away ();
170 /* Session::destroy() will explicitly call drop_protocols() so we don't
171 * have to worry about that here.
176 ControlProtocolManager::drop_protocols ()
178 /* called explicitly by Session::destroy() so that we can clean up
179 * before the process cycle stops and ports vanish.
182 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
184 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
188 control_protocols.clear ();
190 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
191 // mark existing protocols as requested
192 // otherwise the ControlProtocol instances are not recreated in set_session
193 if ((*p)->protocol) {
194 (*p)->requested = true;
196 ProtocolStatusChange (*p); /* EMIT SIGNAL */
202 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
204 /* CALLER MUST HOLD LOCK */
210 cpi.descriptor = get_descriptor (cpi.path);
212 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
214 if (cpi.descriptor == 0) {
215 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
219 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
221 if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
222 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
226 control_protocols.push_back (cpi.protocol);
228 ProtocolStatusChange (&cpi);
234 ControlProtocolManager::teardown (ControlProtocolInfo& cpi, bool lock_required)
238 /* we could still have a descriptor even if the protocol was
239 never instantiated. Close the associated module (shared
240 object/DLL) and make sure we forget about it.
243 if (cpi.descriptor) {
244 cerr << "Closing descriptor for CPI anyway\n";
245 delete (Glib::Module*) cpi.descriptor->module;
252 if (!cpi.descriptor) {
260 /* save current state */
263 cpi.state = new XMLNode (cpi.protocol->get_state());
264 cpi.state->set_property (X_("active"), false);
266 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
269 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
270 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
271 if (p != control_protocols.end()) {
272 control_protocols.erase (p);
274 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
277 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
278 if (p != control_protocols.end()) {
279 control_protocols.erase (p);
281 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
288 /* the lock is only required when the protocol is torn down from the GUI.
289 * If a user disables a protocol, we take this as indicator to forget the
295 delete (Glib::Module*) cpi.descriptor->module;
296 /* cpi->descriptor is now inaccessible since dlclose() or equivalent
297 * has been performed, and the descriptor is (or could be) a static
298 * object made accessible by dlopen().
302 ProtocolStatusChange (&cpi);
308 ControlProtocolManager::load_mandatory_protocols ()
314 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
316 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
317 if ((*i)->mandatory && ((*i)->protocol == 0)) {
318 DEBUG_TRACE (DEBUG::ControlProtocols,
319 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
326 ControlProtocolManager::discover_control_protocols ()
328 vector<std::string> cp_modules;
332 * Different build targets (Debug / Release etc) use different versions
333 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
334 * case the supplied search path contains multiple version(s) of a given
335 * module, only select the one(s) which match the current build target
338 Glib::PatternSpec dll_extension_pattern("*D.dll");
339 #elif defined (RDC_BUILD)
340 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
341 #elif defined (_WIN64)
342 Glib::PatternSpec dll_extension_pattern("*64.dll");
344 Glib::PatternSpec dll_extension_pattern("*32.dll");
347 Glib::PatternSpec dll_extension_pattern("*.dll");
350 Glib::PatternSpec so_extension_pattern("*.so");
351 Glib::PatternSpec dylib_extension_pattern("*.dylib");
353 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
354 dll_extension_pattern);
356 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
357 so_extension_pattern);
359 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
360 dylib_extension_pattern);
362 DEBUG_TRACE (DEBUG::ControlProtocols,
363 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
365 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
366 control_protocol_discover (*i);
371 ControlProtocolManager::control_protocol_discover (string path)
373 ControlProtocolDescriptor* descriptor;
376 /* don't load OS X shared objects that are just symlinks to the real thing.
379 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
384 if ((descriptor = get_descriptor (path)) != 0) {
386 if (!descriptor->probe (descriptor)) {
387 warning << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
390 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
392 cpi->descriptor = descriptor;
393 cpi->name = descriptor->name;
396 cpi->requested = false;
397 cpi->mandatory = descriptor->mandatory;
398 cpi->supports_feedback = descriptor->supports_feedback;
401 control_protocol_info.push_back (cpi);
403 DEBUG_TRACE (DEBUG::ControlProtocols,
404 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
411 ControlProtocolDescriptor*
412 ControlProtocolManager::get_descriptor (string path)
414 Glib::Module* module = new Glib::Module(path);
415 ControlProtocolDescriptor *descriptor = 0;
416 ControlProtocolDescriptor* (*dfunc)(void);
420 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
425 if (!module->get_symbol("protocol_descriptor", func)) {
426 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
427 error << Glib::Module::get_last_error() << endmsg;
432 dfunc = (ControlProtocolDescriptor* (*)(void))func;
433 descriptor = dfunc();
436 descriptor->module = (void*)module;
443 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
445 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
451 ControlProtocolManager::cpi_by_name (string name)
453 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
454 if (name == (*i)->name) {
462 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
465 XMLNodeConstIterator citer;
467 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
469 clist = node.children();
471 for (citer = clist.begin(); citer != clist.end(); ++citer) {
472 XMLNode const * child = *citer;
474 if (child->name() == X_("Protocol")) {
478 if (!child->get_property (X_("active"), active) ||
479 !child->get_property (X_("name"), name)) {
483 ControlProtocolInfo* cpi = cpi_by_name (name);
487 std::cerr << "protocol " << name << " active ? " << active << std::endl;
492 cpi->state = new XMLNode (**citer);
496 cpi->requested = true;
500 cpi->state = new XMLNode (**citer);
501 cpi->state->set_property (X_("active"), false);
503 cpi->requested = false;
505 teardown (*cpi, false);
509 std::cerr << "protocol " << name << " not found\n";
518 ControlProtocolManager::get_state ()
520 XMLNode* root = new XMLNode (state_node_name);
521 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
523 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
525 if ((*i)->protocol) {
526 XMLNode& child_state ((*i)->protocol->get_state());
527 child_state.set_property (X_("active"), true);
528 root->add_child_nocopy (child_state);
529 } else if ((*i)->state) {
530 XMLNode* child_state = new XMLNode (*(*i)->state);
531 child_state->set_property (X_("active"), false);
532 root->add_child_nocopy (*child_state);
534 XMLNode* child_state = new XMLNode (X_("Protocol"));
535 child_state->set_property (X_("name"), (*i)->name);
536 child_state->set_property (X_("active"), false);
537 root->add_child_nocopy (*child_state);
546 ControlProtocolManager&
547 ControlProtocolManager::instance ()
549 if (_instance == 0) {
550 _instance = new ControlProtocolManager ();
557 ControlProtocolManager::midi_connectivity_established ()
559 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
561 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
562 (*p)->midi_connectivity_established ();
567 ControlProtocolManager::register_request_buffer_factories ()
569 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
571 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
573 if ((*i)->descriptor == 0) {
574 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
578 if ((*i)->descriptor->request_buffer_factory) {
579 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);
585 ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp)
587 /* this sets up the (static) data structures owned by ControlProtocol
588 that are "shared" across all control protocols.
591 DEBUG_TRACE (DEBUG::Selection, string_compose ("Surface manager: selection changed, now %1 stripables\n", sp ? sp->size() : -1));
592 StripableSelectionChanged (sp); /* EMIT SIGNAL */
594 /* now give each protocol the chance to respond to the selection change
598 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
600 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
601 DEBUG_TRACE (DEBUG::Selection, string_compose ("selection change notification for surface \"%1\"\n", (*p)->name()));
602 (*p)->stripable_selection_changed ();