#include <pbd/error.h>
#include <pbd/pathscanner.h>
-#include <ardour/control_protocol.h>
+#include "control_protocol.h"
+
+#include <ardour/session.h>
#include <ardour/control_protocol_manager.h>
+
+
+
using namespace ARDOUR;
using namespace PBD;
using namespace std;
#include "i18n.h"
ControlProtocolManager* ControlProtocolManager::_instance = 0;
+const string ControlProtocolManager::state_node_name = X_("ControlProtocols");
ControlProtocolManager::ControlProtocolManager ()
{
if (_instance == 0) {
_instance = this;
}
+
+ _session = 0;
}
ControlProtocolManager::~ControlProtocolManager()
}
void
-ControlProtocolManager::startup (Session& s)
+ControlProtocolManager::set_session (Session& s)
{
- list<ControlProtocolInfo *>::iterator i;
-
- for (i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ _session = &s;
+ _session->going_away.connect (mem_fun (*this, &ControlProtocolManager::drop_session));
- ControlProtocolInfo* cpi = (*i);
-
- if (cpi->name == "Tranzport") {
-
- cpi->descriptor = get_descriptor ((*i)->path);
-
- if (cpi->descriptor == 0) {
- error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi->name) << endmsg;
- continue;
- }
-
- if ((cpi->protocol = cpi->descriptor->initialize (cpi->descriptor, &s)) == 0) {
- error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi->name) << endmsg;
- continue;
- }
-
- {
- LockMonitor lm (protocols_lock, __LINE__, __FILE__);
- control_protocols.push_back (cpi->protocol);
- }
-
- cpi->protocol->init ();
- cpi->protocol->set_active (true);
+ for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ if ((*i)->requested || (*i)->mandatory) {
+ instantiate (**i);
+ (*i)->requested = false;
}
}
}
-ControlProtocol*
-ControlProtocolManager::instantiate (Session& session, string name)
+void
+ControlProtocolManager::drop_session ()
{
- list<ControlProtocolInfo *>::iterator i;
+ _session = 0;
- for (i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
- if ((*i)->name == name) {
- break;
+ {
+ LockMonitor lm (protocols_lock, __LINE__, __FILE__);
+ for (list<ControlProtocol*>::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) {
+ delete *p;
}
+ control_protocols.clear ();
}
+}
- if (i == control_protocol_info.end()) {
- error << string_compose (_("control protocol name \"%1\" is unknown"), name) << endmsg;
+ControlProtocol*
+ControlProtocolManager::instantiate (ControlProtocolInfo& cpi)
+{
+ if (_session == 0) {
return 0;
}
- ControlProtocolInfo* cpi = (*i);
+ cpi.descriptor = get_descriptor (cpi.path);
- cpi->descriptor = get_descriptor ((*i)->path);
-
- if (cpi->descriptor == 0) {
- error << string_compose (_("control protocol name \"%1\" has no descriptor"), name) << endmsg;
+ if (cpi.descriptor == 0) {
+ error << string_compose (_("control protocol name \"%1\" has no descriptor"), cpi.name) << endmsg;
return 0;
}
- if ((cpi->protocol = cpi->descriptor->initialize (cpi->descriptor, &session)) == 0) {
- error << string_compose (_("control protocol name \"%1\" could not be initialized"), name) << endmsg;
+ if ((cpi.protocol = cpi.descriptor->initialize (cpi.descriptor, _session)) == 0) {
+ error << string_compose (_("control protocol name \"%1\" could not be initialized"), cpi.name) << endmsg;
return 0;
}
LockMonitor lm (protocols_lock, __LINE__, __FILE__);
- control_protocols.push_back (cpi->protocol);
- return cpi->protocol;
+ control_protocols.push_back (cpi.protocol);
+
+ return cpi.protocol;
}
int
-ControlProtocolManager::teardown (string name)
+ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
{
- for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
- ControlProtocolInfo* cpi = *i;
+ if (!cpi.protocol) {
+ return 0;
+ }
- if (cpi->name == name && cpi->descriptor && cpi->protocol) {
- cpi->descriptor->destroy (cpi->descriptor, cpi->protocol);
-
- {
- LockMonitor lm (protocols_lock, __LINE__, __FILE__);
- list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi->protocol);
- if (p != control_protocols.end()) {
- control_protocols.erase (p);
- }
- }
+ if (!cpi.descriptor) {
+ return 0;
+ }
- cpi->protocol = 0;
- return 0;
- }
+ if (cpi.mandatory) {
+ return 0;
}
- return -1;
+ cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
+
+ {
+ LockMonitor lm (protocols_lock, __LINE__, __FILE__);
+ list<ControlProtocol*>::iterator p = find (control_protocols.begin(), control_protocols.end(), cpi.protocol);
+ if (p != control_protocols.end()) {
+ control_protocols.erase (p);
+ }
+ }
+
+ cpi.protocol = 0;
+ dlclose (cpi.descriptor->module);
+ return 0;
}
static bool protocol_filter (const string& str, void *arg)
return str[0] != '.' && (str.length() > 3 && str.find (".so") == (str.length() - 3));
}
+void
+ControlProtocolManager::load_mandatory_protocols ()
+{
+ if (_session == 0) {
+ return;
+ }
+
+ for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ if ((*i)->mandatory && ((*i)->protocol == 0)) {
+ info << string_compose (_("Instantiating mandatory control protocol %1"), (*i)->name) << endmsg;
+ instantiate (**i);
+ }
+ }
+}
+
void
ControlProtocolManager::discover_control_protocols (string path)
{
vector<string *> *found;
PathScanner scanner;
- cerr << "CP Manager looking for surfaces\n";
+ cerr << "looking for control protocols in " << path << endl;
found = scanner (path, protocol_filter, 0, false, true);
for (vector<string*>::iterator i = found->begin(); i != found->end(); ++i) {
- cerr << "CP Manager looking at " << **i << endl;
control_protocol_discover (**i);
delete *i;
}
if ((descriptor = get_descriptor (path)) != 0) {
- ControlProtocolInfo* info = new ControlProtocolInfo ();
+ ControlProtocolInfo* cpi = new ControlProtocolInfo ();
- info->descriptor = descriptor;
- info->name = descriptor->name;
- info->path = path;
-
- control_protocol_info.push_back (info);
+ if (!descriptor->probe (descriptor)) {
+ info << string_compose (_("Control protocol %1 not usable"), descriptor->name) << endmsg;
+ } else {
- cerr << "Found \"" << info->name << "\"\n";
+ cpi->descriptor = descriptor;
+ cpi->name = descriptor->name;
+ cpi->path = path;
+ cpi->protocol = 0;
+ cpi->requested = false;
+ cpi->mandatory = descriptor->mandatory;
+
+ control_protocol_info.push_back (cpi);
+
+ info << string_compose(_("Control surface protocol discovered: \"%1\""), cpi->name) << endmsg;
+ }
dlclose (descriptor->module);
-
- } else {
- cerr << "no descriptor\n";
}
return 0;
return descriptor;
}
+
+void
+ControlProtocolManager::foreach_known_protocol (sigc::slot<void,const ControlProtocolInfo*> method)
+{
+ for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ method (*i);
+ }
+}
+
+ControlProtocolInfo*
+ControlProtocolManager::cpi_by_name (string name)
+{
+ for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ if (name == (*i)->name) {
+ return *i;
+ }
+ }
+ return 0;
+}
+
+int
+ControlProtocolManager::set_state (const XMLNode& node)
+{
+ XMLNodeList clist;
+ XMLNodeConstIterator citer;
+ XMLProperty* prop;
+
+ clist = node.children();
+
+ for (citer = clist.begin(); citer != clist.end(); ++citer) {
+ if ((*citer)->name() == X_("Protocol")) {
+ prop = (*citer)->property (X_("active"));
+ if (prop && prop->value() == X_("yes")) {
+ if ((prop = (*citer)->property (X_("name"))) != 0) {
+ ControlProtocolInfo* cpi = cpi_by_name (prop->value());
+ if (cpi) {
+ if (_session) {
+ instantiate (*cpi);
+ } else {
+ cpi->requested = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+XMLNode&
+ControlProtocolManager::get_state (void)
+{
+ XMLNode* root = new XMLNode (state_node_name);
+ LockMonitor lm (protocols_lock, __LINE__, __FILE__);
+
+ for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
+ XMLNode* child = new XMLNode (X_("Protocol"));
+ child->add_property (X_("name"), (*i)->name);
+ child->add_property (X_("active"), (*i)->protocol ? "yes" : "no");
+ root->add_child_nocopy (*child);
+ }
+
+ return *root;
+}