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);
92 /* get selection info and set it before instantiating any
96 CoreSelection::StripableAutomationControls sac;
97 _session->selection().get_stripables (sac);
99 for (CoreSelection::StripableAutomationControls::iterator i = sac.begin(); i != sac.end(); ++i) {
100 if ((*i).stripable) {
101 cerr << "First selected being set to " << (*i).stripable->name() << endl;
102 ControlProtocol::set_first_selected_stripable ((*i).stripable);
107 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
110 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
111 if ((*i)->requested || (*i)->mandatory) {
112 (void) activate (**i);
119 ControlProtocolManager::activate (ControlProtocolInfo& cpi)
123 cpi.requested = true;
125 if ((cp = instantiate (cpi)) == 0) {
129 /* we split the set_state() and set_active() operations so that
130 protocols that need state to configure themselves (e.g. "What device
131 is connected, or supposed to be connected?") can get it before
132 actually starting any interaction.
136 /* force this by tweaking the internals of the state
139 cp->set_state (*cpi.state, Stateful::loading_state_version);
141 /* guarantee a call to
142 set_state() whether we have
143 existing state or not
145 cp->set_state (XMLNode(""), Stateful::loading_state_version);
148 if (cp->set_active (true)) {
149 error << string_compose (_("Control protocol support for %1 failed to activate"), cpi.name) << endmsg;
150 teardown (cpi, false);
157 ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
159 cpi.requested = false;
160 return teardown (cpi, true);
164 ControlProtocolManager::session_going_away()
166 SessionHandlePtr::session_going_away ();
167 /* Session::destroy() will explicitly call drop_protocols() so we don't
168 * have to worry about that here.
173 ControlProtocolManager::drop_protocols ()
175 /* called explicitly by Session::destroy() so that we can clean up
176 * before the process cycle stops and ports vanish.
179 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
181 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
185 control_protocols.clear ();
187 for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
188 // mark existing protocols as requested
189 // otherwise the ControlProtocol instances are not recreated in set_session
190 if ((*p)->protocol) {
191 (*p)->requested = true;
193 ProtocolStatusChange (*p); /* EMIT SIGNAL */
199 ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
201 /* CALLER MUST HOLD LOCK */
207 cpi.descriptor = get_descriptor (cpi.path);
209 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
211 if (cpi.descriptor == 0) {
212 error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
216 DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
218 if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
219 error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
223 control_protocols.push_back (cpi.protocol);
225 ProtocolStatusChange (&cpi);
231 ControlProtocolManager::teardown (ControlProtocolInfo& cpi, bool lock_required)
235 /* we could still have a descriptor even if the protocol was
236 never instantiated. Close the associated module (shared
237 object/DLL) and make sure we forget about it.
240 if (cpi.descriptor) {
241 cerr << "Closing descriptor for CPI anyway\n";
242 delete (Glib::Module*) cpi.descriptor->module;
249 if (!cpi.descriptor) {
257 /* save current state */
260 cpi.state = new XMLNode (cpi.protocol->get_state());
261 cpi.state->set_property (X_("active"), false);
263 cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
266 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
267 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
268 if (p != control_protocols.end()) {
269 control_protocols.erase (p);
271 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
274 list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
275 if (p != control_protocols.end()) {
276 control_protocols.erase (p);
278 cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
285 /* the lock is only required when the protocol is torn down from the GUI.
286 * If a user disables a protocol, we take this as indicator to forget the
292 delete (Glib::Module*) cpi.descriptor->module;
293 /* cpi->descriptor is now inaccessible since dlclose() or equivalent
294 * has been performed, and the descriptor is (or could be) a static
295 * object made accessible by dlopen().
299 ProtocolStatusChange (&cpi);
305 ControlProtocolManager::load_mandatory_protocols ()
311 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
313 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
314 if ((*i)->mandatory && ((*i)->protocol == 0)) {
315 DEBUG_TRACE (DEBUG::ControlProtocols,
316 string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
323 ControlProtocolManager::discover_control_protocols ()
325 vector<std::string> cp_modules;
329 * Different build targets (Debug / Release etc) use different versions
330 * of the 'C' runtime (which can't be 'mixed & matched'). Therefore, in
331 * case the supplied search path contains multiple version(s) of a given
332 * module, only select the one(s) which match the current build target
335 Glib::PatternSpec dll_extension_pattern("*D.dll");
336 #elif defined (RDC_BUILD)
337 Glib::PatternSpec dll_extension_pattern("*RDC.dll");
338 #elif defined (_WIN64)
339 Glib::PatternSpec dll_extension_pattern("*64.dll");
341 Glib::PatternSpec dll_extension_pattern("*32.dll");
344 Glib::PatternSpec dll_extension_pattern("*.dll");
347 Glib::PatternSpec so_extension_pattern("*.so");
348 Glib::PatternSpec dylib_extension_pattern("*.dylib");
350 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
351 dll_extension_pattern);
353 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
354 so_extension_pattern);
356 find_files_matching_pattern (cp_modules, control_protocol_search_path (),
357 dylib_extension_pattern);
359 DEBUG_TRACE (DEBUG::ControlProtocols,
360 string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
362 for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
363 control_protocol_discover (*i);
368 ControlProtocolManager::control_protocol_discover (string path)
370 ControlProtocolDescriptor* descriptor;
373 /* don't load OS X shared objects that are just symlinks to the real thing.
376 if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
381 if ((descriptor = get_descriptor (path)) != 0) {
383 if (!descriptor->probe (descriptor)) {
384 warning << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
387 ControlProtocolInfo* cpi = new ControlProtocolInfo ();
389 cpi->descriptor = descriptor;
390 cpi->name = descriptor->name;
393 cpi->requested = false;
394 cpi->mandatory = descriptor->mandatory;
395 cpi->supports_feedback = descriptor->supports_feedback;
398 control_protocol_info.push_back (cpi);
400 DEBUG_TRACE (DEBUG::ControlProtocols,
401 string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
408 ControlProtocolDescriptor*
409 ControlProtocolManager::get_descriptor (string path)
411 Glib::Module* module = new Glib::Module(path);
412 ControlProtocolDescriptor *descriptor = 0;
413 ControlProtocolDescriptor* (*dfunc)(void);
417 error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, Glib::Module::get_last_error()) << endmsg;
422 if (!module->get_symbol("protocol_descriptor", func)) {
423 error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
424 error << Glib::Module::get_last_error() << endmsg;
429 dfunc = (ControlProtocolDescriptor* (*)(void))func;
430 descriptor = dfunc();
433 descriptor->module = (void*)module;
440 ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
442 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
448 ControlProtocolManager::cpi_by_name (string name)
450 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
451 if (name == (*i)->name) {
459 ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
462 XMLNodeConstIterator citer;
464 Glib::Threads::RWLock::WriterLock lm (protocols_lock);
466 clist = node.children();
468 for (citer = clist.begin(); citer != clist.end(); ++citer) {
469 XMLNode const * child = *citer;
471 if (child->name() == X_("Protocol")) {
475 if (!child->get_property (X_("active"), active) ||
476 !child->get_property (X_("name"), name)) {
480 ControlProtocolInfo* cpi = cpi_by_name (name);
483 std::cerr << "protocol " << name << " active ? " << active << std::endl;
487 cpi->state = new XMLNode (**citer);
491 cpi->requested = true;
495 cpi->state = new XMLNode (**citer);
496 cpi->state->set_property (X_("active"), false);
498 cpi->requested = false;
500 teardown (*cpi, false);
504 std::cerr << "protocol " << name << " not found\n";
513 ControlProtocolManager::get_state ()
515 XMLNode* root = new XMLNode (state_node_name);
516 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
518 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
520 if ((*i)->protocol) {
521 XMLNode& child_state ((*i)->protocol->get_state());
522 child_state.set_property (X_("active"), true);
523 root->add_child_nocopy (child_state);
524 } else if ((*i)->state) {
525 XMLNode* child_state = new XMLNode (*(*i)->state);
526 child_state->set_property (X_("active"), false);
527 root->add_child_nocopy (*child_state);
529 XMLNode* child_state = new XMLNode (X_("Protocol"));
530 child_state->set_property (X_("name"), (*i)->name);
531 child_state->set_property (X_("active"), false);
532 root->add_child_nocopy (*child_state);
541 ControlProtocolManager&
542 ControlProtocolManager::instance ()
544 if (_instance == 0) {
545 _instance = new ControlProtocolManager ();
552 ControlProtocolManager::midi_connectivity_established ()
554 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
556 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
557 (*p)->midi_connectivity_established ();
562 ControlProtocolManager::register_request_buffer_factories ()
564 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
566 for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
568 if ((*i)->descriptor == 0) {
569 warning << string_compose (_("Control protocol \"%1\" has no descriptor"), (*i)->name) << endmsg;
573 if ((*i)->descriptor->request_buffer_factory) {
574 EventLoop::register_request_buffer_factory ((*i)->descriptor->name, (*i)->descriptor->request_buffer_factory);
580 ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp)
582 /* this sets up the (static) data structures owned by ControlProtocol
583 that are "shared" across all control protocols.
586 DEBUG_TRACE (DEBUG::Selection, string_compose ("Surface manager: selection changed, now %1 stripables\n", sp ? sp->size() : -1));
587 StripableSelectionChanged (sp); /* EMIT SIGNAL */
589 /* now give each protocol the chance to respond to the selection change
593 Glib::Threads::RWLock::ReaderLock lm (protocols_lock);
595 for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
596 DEBUG_TRACE (DEBUG::Selection, string_compose ("selection change notification for surface \"%1\"\n", (*p)->name()));
597 (*p)->stripable_selection_changed ();