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.
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"
32
#include "ardour/control_protocol_search_path.h"
34
using namespace ARDOUR;
40
ControlProtocolManager* ControlProtocolManager::_instance = 0;
41
const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
43
ControlProtocolManager::ControlProtocolManager ()
47
ControlProtocolManager::~ControlProtocolManager()
49
Glib::Threads::Mutex::Lock lm (protocols_lock);
51
for (list<ControlProtocol*>::iterator i = control_protocols.begin(); i != control_protocols.end(); ++i) {
55
control_protocols.clear ();
58
for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
62
control_protocol_info.clear();
66
ControlProtocolManager::set_session (Session* s)
68
SessionHandlePtr::set_session (s);
71
Glib::Threads::Mutex::Lock lm (protocols_lock);
73
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
74
if ((*i)->requested || (*i)->mandatory) {
77
(*i)->requested = false;
81
(*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
83
/* guarantee a call to
84
set_state() whether we have
87
(*i)->protocol->set_state (XMLNode(""), Stateful::loading_state_version);
96
ControlProtocolManager::session_going_away()
98
SessionHandlePtr::session_going_away ();
101
Glib::Threads::Mutex::Lock lm (protocols_lock);
103
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
107
control_protocols.clear ();
109
for (list<ControlProtocolInfo*>::iterator p = control_protocol_info.begin(); p != control_protocol_info.end(); ++p) {
110
// mark existing protocols as requested
111
// otherwise the ControlProtocol instances are not recreated in set_session
112
if ((*p)->protocol) {
113
(*p)->requested = true;
121
ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
123
/* CALLER MUST HOLD LOCK */
129
cpi.descriptor = get_descriptor (cpi.path);
131
DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("instantiating %1\n", cpi.name));
133
if (cpi.descriptor == 0) {
134
error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
138
DEBUG_TRACE (DEBUG::ControlProtocols, string_compose ("initializing %1\n", cpi.name));
140
if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
141
error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
145
control_protocols.push_back (cpi.protocol);
147
ProtocolStatusChange (&cpi);
153
ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
159
if (!cpi.descriptor) {
167
cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
170
Glib::Threads::Mutex::Lock lm (protocols_lock);
171
list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
172
if (p != control_protocols.end()) {
173
control_protocols.erase (p);
175
cerr << "Programming error: ControlProtocolManager::teardown() called for " << cpi.name << ", but it was not found in control_protocols" << endl;
182
dlclose (cpi.descriptor->module);
184
ProtocolStatusChange (&cpi);
190
ControlProtocolManager::load_mandatory_protocols ()
196
Glib::Threads::Mutex::Lock lm (protocols_lock);
198
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
199
if ((*i)->mandatory && ((*i)->protocol == 0)) {
200
DEBUG_TRACE (DEBUG::ControlProtocols,
201
string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name));
208
ControlProtocolManager::discover_control_protocols ()
210
vector<std::string> cp_modules;
212
Glib::PatternSpec so_extension_pattern("*.so");
213
Glib::PatternSpec dylib_extension_pattern("*.dylib");
215
find_matching_files_in_search_path (control_protocol_search_path (),
216
so_extension_pattern, cp_modules);
218
find_matching_files_in_search_path (control_protocol_search_path (),
219
dylib_extension_pattern, cp_modules);
221
DEBUG_TRACE (DEBUG::ControlProtocols,
222
string_compose (_("looking for control protocols in %1\n"), control_protocol_search_path().to_string()));
224
for (vector<std::string>::iterator i = cp_modules.begin(); i != cp_modules.end(); ++i) {
225
control_protocol_discover (*i);
230
ControlProtocolManager::control_protocol_discover (string path)
232
ControlProtocolDescriptor* descriptor;
235
/* don't load OS X shared objects that are just symlinks to the real thing.
238
if (path.find (".dylib") && Glib::file_test (path, Glib::FILE_TEST_IS_SYMLINK)) {
243
if ((descriptor = get_descriptor (path)) != 0) {
245
if (!descriptor->probe (descriptor)) {
246
DEBUG_TRACE (DEBUG::ControlProtocols,
247
string_compose (_("Control protocol %1 not usable"), descriptor->name));
250
ControlProtocolInfo* cpi = new ControlProtocolInfo ();
252
cpi->descriptor = descriptor;
253
cpi->name = descriptor->name;
256
cpi->requested = false;
257
cpi->mandatory = descriptor->mandatory;
258
cpi->supports_feedback = descriptor->supports_feedback;
261
control_protocol_info.push_back (cpi);
263
DEBUG_TRACE (DEBUG::ControlProtocols,
264
string_compose(_("Control surface protocol discovered: \"%1\"\n"), cpi->name));
267
dlclose (descriptor->module);
273
ControlProtocolDescriptor*
274
ControlProtocolManager::get_descriptor (string path)
277
ControlProtocolDescriptor *descriptor = 0;
278
ControlProtocolDescriptor* (*dfunc)(void);
281
if ((module = dlopen (path.c_str(), RTLD_NOW)) == 0) {
282
error << string_compose(_("ControlProtocolManager: cannot load module \"%1\" (%2)"), path, dlerror()) << endmsg;
287
dfunc = (ControlProtocolDescriptor* (*)(void)) dlsym (module, "protocol_descriptor");
289
if ((errstr = dlerror()) != 0) {
290
error << string_compose(_("ControlProtocolManager: module \"%1\" has no descriptor function."), path) << endmsg;
291
error << errstr << endmsg;
296
descriptor = dfunc();
298
descriptor->module = module;
307
ControlProtocolManager::foreach_known_protocol (boost::function<void(const ControlProtocolInfo*)> method)
309
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
315
ControlProtocolManager::cpi_by_name (string name)
317
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
318
if (name == (*i)->name) {
326
ControlProtocolManager::set_state (const XMLNode& node, int /*version*/)
329
XMLNodeConstIterator citer;
332
Glib::Threads::Mutex::Lock lm (protocols_lock);
334
clist = node.children();
336
for (citer = clist.begin(); citer != clist.end(); ++citer) {
337
if ((*citer)->name() == X_("Protocol")) {
339
if ((prop = (*citer)->property (X_("active"))) == 0) {
343
bool active = string_is_affirmative (prop->value());
345
if ((prop = (*citer)->property (X_("name"))) == 0) {
349
ControlProtocolInfo* cpi = cpi_by_name (prop->value());
352
cpi->state = new XMLNode (**citer);
358
cpi->requested = true;
364
cpi->requested = false;
375
ControlProtocolManager::get_state ()
377
XMLNode* root = new XMLNode (state_node_name);
378
Glib::Threads::Mutex::Lock lm (protocols_lock);
380
for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
384
if ((*i)->protocol) {
385
child = &((*i)->protocol->get_state());
386
child->add_property (X_("active"), "yes");
387
// should we update (*i)->state here? probably.
388
root->add_child_nocopy (*child);
389
} else if ((*i)->state) {
390
// keep ownership clear
391
root->add_child_copy (*(*i)->state);
393
child = new XMLNode (X_("Protocol"));
394
child->add_property (X_("name"), (*i)->name);
395
child->add_property (X_("active"), "no");
396
root->add_child_nocopy (*child);
404
ControlProtocolManager&
405
ControlProtocolManager::instance ()
407
if (_instance == 0) {
408
_instance = new ControlProtocolManager ();
415
ControlProtocolManager::midi_connectivity_established ()
417
Glib::Threads::Mutex::Lock lm (protocols_lock);
419
for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
420
(*p)->midi_connectivity_established ();