summaryrefslogtreecommitdiffstats
path: root/src/libs/engine/NodeFactory.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2007-10-11 17:24:49 +0000
committerDavid Robillard <d@drobilla.net>2007-10-11 17:24:49 +0000
commit5791d19a0f56c65ef7b89da80f4bcc3e1cee0c93 (patch)
treede0a795658df184d29e4ed795c6b6b15c6e0454d /src/libs/engine/NodeFactory.cpp
parent058174f81f325521957cc6927667dfcf0d7346b4 (diff)
downloadingen-5791d19a0f56c65ef7b89da80f4bcc3e1cee0c93.tar.gz
ingen-5791d19a0f56c65ef7b89da80f4bcc3e1cee0c93.tar.bz2
ingen-5791d19a0f56c65ef7b89da80f4bcc3e1cee0c93.zip
Fix awful plugin loading situation.
Don't double-lookup plugins on discovery/load. O(log(n)) plugin searching instead of 2*O(n). Don't keep discovered LADSPA plugins loaded (until a node is instantiated). git-svn-id: http://svn.drobilla.net/lad/ingen@876 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/libs/engine/NodeFactory.cpp')
-rw-r--r--src/libs/engine/NodeFactory.cpp336
1 files changed, 125 insertions, 211 deletions
diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp
index c2b9536a..24d32929 100644
--- a/src/libs/engine/NodeFactory.cpp
+++ b/src/libs/engine/NodeFactory.cpp
@@ -53,86 +53,42 @@ NodeFactory::NodeFactory(Ingen::Shared::World* world)
: _world(world)
, _has_loaded(false)
{
- // Add builtin plugin types to _internal_plugins list
- // FIXME: ewwww, definitely a better way to do this!
-
- PatchImpl* parent = new PatchImpl(*world->local_engine, "dummy", 1, NULL, 1, 1, 1);
-
- NodeImpl* n = NULL;
- n = new MidiNoteNode("foo", 1, parent, 1, 1);
- _internal_plugins.push_back(new PluginImpl(n->plugin_impl()));
- delete n;
- n = new MidiTriggerNode("foo", 1, parent, 1, 1);
- _internal_plugins.push_back(new PluginImpl(n->plugin_impl()));
- delete n;
- n = new MidiControlNode("foo", 1, parent, 1, 1);
- _internal_plugins.push_back(new PluginImpl(n->plugin_impl()));
- delete n;
- n = new TransportNode("foo", 1, parent, 1, 1);
- _internal_plugins.push_back(new PluginImpl(n->plugin_impl()));
- delete n;
-
- delete parent;
}
NodeFactory::~NodeFactory()
{
- for (list<PluginImpl*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i)
- delete (*i);
- _plugins.clear();
-
- for (Libraries::iterator i = _libraries.begin(); i != _libraries.end(); ++i) {
- delete i->second;
- }
- _libraries.clear();
-}
-
-
-Glib::Module*
-NodeFactory::library(const string& path)
-{
- Glib::Module* plugin_library = NULL;
- Libraries::iterator library_i = _libraries.find(path);
- if (library_i != _libraries.end()) {
- plugin_library = library_i->second;
- assert(plugin_library);
- } else {
- plugin_library = new Glib::Module(path, Glib::MODULE_BIND_LOCAL);
- if (plugin_library && *plugin_library) {
- _libraries.insert(make_pair(path, plugin_library));
- return plugin_library;
- }
- }
+ for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i)
+ if (i->second->type() != Plugin::Internal)
+ delete i->second;
- return NULL;
+ _plugins.clear();
}
-const PluginImpl*
+PluginImpl*
NodeFactory::plugin(const string& uri)
{
- for (list<PluginImpl*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i)
- if ((*i)->uri() == uri)
- return (*i);
-
- return NULL;
+ Plugins::const_iterator i = _plugins.find(uri);
+ return ((i != _plugins.end()) ? i->second : NULL);
}
/** DEPRECATED: Find a plugin by type, lib, label.
*
- * Do not use.
+ * Slow. Evil. Do not use.
*/
-const PluginImpl*
+PluginImpl*
NodeFactory::plugin(const string& type, const string& lib, const string& label)
{
if (type == "" || lib == "" || label == "")
return NULL;
- for (list<PluginImpl*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i)
- if ((*i)->type_string() == type && (*i)->lib_name() == lib && (*i)->plug_label() == label)
- return (*i);
+ for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i)
+ if (i->second->type_string() == type
+ && i->second->lib_name() == lib
+ && i->second->plug_label() == label)
+ return i->second;
cerr << "ERROR: Failed to find " << type << " plugin " << lib << " / " << label << endl;
@@ -149,12 +105,14 @@ NodeFactory::load_plugins()
// this (expensive!) stuff to happen. Not the best solution - would be nice
// if clients could refresh plugins list for whatever reason :/
if (!_has_loaded) {
- _plugins.clear();
- _plugins = _internal_plugins;
+ _plugins.clear(); // FIXME: assert empty?
+
+ load_internal_plugins();
#ifdef HAVE_SLV2
load_lv2_plugins();
#endif
+
#ifdef HAVE_LADSPA
load_ladspa_plugins();
#endif
@@ -171,65 +129,32 @@ NodeFactory::load_plugins()
* Calls the load_*_plugin functions to actually do things, just a wrapper.
*/
NodeImpl*
-NodeFactory::load_plugin(const PluginImpl* a_plugin,
- const string& name,
- bool polyphonic,
- PatchImpl* parent)
+NodeFactory::load_plugin(PluginImpl* plugin,
+ const string& name,
+ bool polyphonic,
+ PatchImpl* parent)
{
assert(parent != NULL);
- assert(a_plugin);
+ assert(plugin);
NodeImpl* r = NULL;
- PluginImpl* plugin = NULL;
const SampleRate srate = parent->sample_rate();
const size_t buffer_size = parent->buffer_size();
- // FIXME FIXME FIXME: double lookup
-
- // Attempt to find the plugin in loaded DB
- if (a_plugin->type() != Plugin::Internal) {
-
- // DEPRECATED: Search by lib name / plug label
- if (a_plugin->uri().length() == 0) {
- assert(a_plugin->lib_name().length() > 0 && a_plugin->plug_label().length() > 0);
- //cerr << "Searching for: " << a_plugin->lib_name() << " : " << a_plugin->plug_label() << endl;
- for (list<PluginImpl*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- //cerr << (*i)->lib_name() << " : " << (*i)->plug_label() << endl;
- if (a_plugin->lib_name() == (*i)->lib_name() && a_plugin->plug_label() == (*i)->plug_label()) {
- plugin = *i;
- break;
- }
- }
- } else {
- // Search by URI
- for (list<PluginImpl*>::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- if (a_plugin->uri() == (*i)->uri()) {
- plugin = *i;
- break;
- }
- }
- }
-
- if (plugin == NULL) {
- cerr << "DID NOT FIND PLUGIN " << name << endl;
- return NULL;
- }
- }
-
- switch (a_plugin->type()) {
+ switch (plugin->type()) {
#ifdef HAVE_SLV2
case Plugin::LV2:
- r = load_lv2_plugin(plugin->uri(), name, polyphonic, parent, srate, buffer_size);
+ r = load_lv2_plugin(plugin, name, polyphonic, parent, srate, buffer_size);
break;
#endif
#ifdef HAVE_LADSPA
case Plugin::LADSPA:
- r = load_ladspa_plugin(plugin->uri(), name, polyphonic, parent, srate, buffer_size);
+ r = load_ladspa_plugin(plugin, name, polyphonic, parent, srate, buffer_size);
break;
#endif
case Plugin::Internal:
- r = load_internal_plugin(a_plugin->uri(), name, polyphonic, parent, srate, buffer_size);
+ r = load_internal_plugin(plugin, name, polyphonic, parent, srate, buffer_size);
break;
default:
cerr << "[NodeFactory] WARNING: Unknown plugin type." << endl;
@@ -239,25 +164,48 @@ NodeFactory::load_plugin(const PluginImpl* a_plugin,
}
+void
+NodeFactory::load_internal_plugins()
+{
+ // This is a touch gross...
+
+ PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1);
+
+ NodeImpl* n = NULL;
+ n = new MidiNoteNode("foo", 1, parent, 1, 1);
+ _plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
+ delete n;
+ n = new MidiTriggerNode("foo", 1, parent, 1, 1);
+ _plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
+ delete n;
+ n = new MidiControlNode("foo", 1, parent, 1, 1);
+ _plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
+ delete n;
+ n = new TransportNode("foo", 1, parent, 1, 1);
+ _plugins.insert(make_pair(n->plugin_impl()->uri(), n->plugin_impl()));
+ delete n;
+
+ delete parent;
+}
+
+
/** Loads an internal plugin.
*/
NodeImpl*
-NodeFactory::load_internal_plugin(const string& uri,
+NodeFactory::load_internal_plugin(PluginImpl* plugin,
const string& name,
bool polyphonic,
PatchImpl* parent,
SampleRate srate,
size_t buffer_size)
{
+ assert(plugin);
+ assert(plugin->type() == Plugin::Internal);
assert(parent != NULL);
- assert(uri.length() > 6);
- assert(uri.substr(0, 6) == "ingen:");
+ assert(plugin->uri().length() > 6);
+ assert(plugin->uri().substr(0, 6) == "ingen:");
- for (list<PluginImpl*>::iterator i = _internal_plugins.begin(); i != _internal_plugins.end(); ++i)
- if ((*i)->uri() == uri)
- return (*i)->instantiate(name, polyphonic, parent, srate, buffer_size);
-
- return NULL;
+ return plugin->instantiate(name, polyphonic, parent, srate, buffer_size);
}
@@ -276,37 +224,24 @@ NodeFactory::load_lv2_plugins()
SLV2Plugin lv2_plug = slv2_plugins_get_at(plugins, i);
- const char* uri = (const char*)slv2_plugin_get_uri(lv2_plug);
- assert(uri);
- //cerr << "\t" << uri << endl;
-
- PluginImpl* plug = NULL;
-
- bool found = false;
- for (list<PluginImpl*>::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- if (!strcmp((*i)->uri().c_str(), uri)) {
- plug = (*i);
- found = true;
- break;
- }
- }
-
- if (!found)
- plug = new PluginImpl(Plugin::LV2, uri);
-
- plug->slv2_plugin(lv2_plug);
- plug->module(NULL); // FIXME?
- plug->lib_path(slv2_uri_to_path(slv2_plugin_get_library_uri(lv2_plug)));
- char* name = slv2_plugin_get_name(lv2_plug);
- if (!name) {
+#ifndef NDEBUG
+ const string uri((const char*)slv2_plugin_get_uri(lv2_plug));
+ assert(_plugins.find(uri) == _plugins.end());
+#endif
+
+ PluginImpl* const plugin = new PluginImpl(Plugin::LV2, uri);
+
+ plugin->slv2_plugin(lv2_plug);
+ plugin->lib_path(slv2_uri_to_path(slv2_plugin_get_library_uri(lv2_plug)));
+ char* const name = slv2_plugin_get_name(lv2_plug);
+ if (name) {
+ plugin->name(name);
+ free(name);
+ _plugins.insert(make_pair(uri, plugin));
+ } else {
cerr << "ERROR: LV2 Plugin " << uri << " has no name. Ignoring." << endl;
continue;
}
- plug->name(name);
- free(name);
-
- if (!found)
- _plugins.push_back(plug);
}
slv2_plugins_free(_world->slv2_world, plugins);
@@ -317,36 +252,31 @@ NodeFactory::load_lv2_plugins()
* Returns 'poly' independant plugins as a NodeImpl*
*/
NodeImpl*
-NodeFactory::load_lv2_plugin(const string& plug_uri,
+NodeFactory::load_lv2_plugin(PluginImpl* plugin,
const string& node_name,
bool polyphonic,
PatchImpl* parent,
SampleRate srate,
size_t buffer_size)
{
- // Find (internal) Plugin
- PluginImpl* plugin = NULL;
- list<PluginImpl*>::iterator i;
- for (i = _plugins.begin(); i != _plugins.end(); ++i) {
- plugin = (*i);
- if ((*i)->uri() == plug_uri) break;
- }
-
+ assert(plugin);
+ assert(plugin->type() == Plugin::LV2);
+
NodeImpl* n = NULL;
- if (plugin) {
- n = new LV2Node(plugin, node_name, polyphonic, parent, srate, buffer_size);
-
- Glib::Mutex::Lock lock(_world->rdf_world->mutex());
-
- const bool success = ((LV2Node*)n)->instantiate();
-
- if (!success) {
- delete n;
- n = NULL;
- }
+ plugin->load(); // FIXME: unload
+
+ n = new LV2Node(plugin, node_name, polyphonic, parent, srate, buffer_size);
+
+ Glib::Mutex::Lock lock(_world->rdf_world->mutex());
+
+ const bool success = ((LV2Node*)n)->instantiate();
+
+ if (!success) {
+ delete n;
+ n = NULL;
}
-
+
return n;
}
@@ -369,12 +299,9 @@ NodeFactory::load_ladspa_plugins()
ladspa_path = env_ladspa_path;
}
- string dir;
- string full_lib_name;
-
// Yep, this should use an sstream alright..
while (ladspa_path != "") {
- dir = ladspa_path.substr(0, ladspa_path.find(':'));
+ const string dir = ladspa_path.substr(0, ladspa_path.find(':'));
if (ladspa_path.find(':') != string::npos)
ladspa_path = ladspa_path.substr(ladspa_path.find(':')+1);
else
@@ -395,26 +322,25 @@ NodeFactory::load_ladspa_plugins()
if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
continue;
- full_lib_name = dir +"/"+ pfile->d_name;
+ const string lib_path = dir +"/"+ pfile->d_name;
// Ignore stupid libtool files. Kludge alert.
- if (full_lib_name.substr(full_lib_name.length()-3) == ".la") {
+ if (lib_path.substr(lib_path.length()-3) == ".la") {
//cerr << "WARNING: Skipping stupid libtool file " << pfile->d_name << endl;
continue;
}
- Glib::Module* plugin_library = library(full_lib_name);
- if (!plugin_library) {
- cerr << "WARNING: Failed to load library " << full_lib_name << endl;
+ Glib::Module* plugin_library = new Glib::Module(lib_path, Glib::MODULE_BIND_LOCAL);
+ if (!plugin_library || !(*plugin_library)) {
+ cerr << "WARNING: Failed to load LADSPA library " << lib_path << endl;
continue;
}
bool found = plugin_library->get_symbol("ladspa_descriptor", (void*&)df);
if (!found || !df) {
cerr << "WARNING: Non-LADSPA library found in LADSPA path: " <<
- full_lib_name << endl;
+ lib_path << endl;
// Not a LADSPA plugin library
- _libraries.erase(full_lib_name);
delete plugin_library;
continue;
}
@@ -422,32 +348,29 @@ NodeFactory::load_ladspa_plugins()
for (unsigned long i=0; (descriptor = (LADSPA_Descriptor*)df(i)) != NULL; ++i) {
char id_str[11];
snprintf(id_str, 11, "%lu", descriptor->UniqueID);
- string uri = string("ladspa:").append(id_str);
- PluginImpl* plugin = new PluginImpl(Plugin::LADSPA, uri);
+ const string uri = string("ladspa:").append(id_str);
- assert(plugin_library != NULL);
- plugin->module(plugin_library);
- plugin->lib_path(dir + "/" + pfile->d_name);
- plugin->plug_label(descriptor->Label);
- plugin->name(descriptor->Name);
- plugin->type(Plugin::LADSPA);
- plugin->id(descriptor->UniqueID);
+ const Plugins::const_iterator i = _plugins.find(uri);
- bool found = false;
- for (list<PluginImpl*>::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
- if ((*i)->uri() == plugin->uri()) {
- cerr << "Warning: Duplicate LADSPA plugin " << plugin->uri()
- << " found.\n Choosing " << (*i)->lib_path()
- << " over " << plugin->lib_path() << endl;
- found = true;
- break;
- }
+ if (i == _plugins.end()) {
+ PluginImpl* plugin = new PluginImpl(Plugin::LADSPA, uri);
+
+ assert(plugin_library != NULL);
+ plugin->module(NULL);
+ plugin->lib_path(lib_path);
+ plugin->plug_label(descriptor->Label);
+ plugin->name(descriptor->Name);
+ plugin->type(Plugin::LADSPA);
+ plugin->id(descriptor->UniqueID);
+
+ _plugins.insert(make_pair(uri, plugin));
+ } else {
+ cerr << "Warning: Duplicate LADSPA plugin " << uri << " found." << endl;
+ cerr << "\tUsing " << i->second->lib_path() << " over " << lib_path << endl;
}
- if (!found)
- _plugins.push_back(plugin);
- else
- delete plugin;
}
+
+ delete plugin_library;
}
closedir(pdir);
}
@@ -458,37 +381,28 @@ NodeFactory::load_ladspa_plugins()
* Returns 'poly' independant plugins as a NodeImpl*
*/
NodeImpl*
-NodeFactory::load_ladspa_plugin(const string& uri,
+NodeFactory::load_ladspa_plugin(PluginImpl* plugin,
const string& name,
bool polyphonic,
PatchImpl* parent,
SampleRate srate,
size_t buffer_size)
{
- assert(uri != "");
+ assert(plugin);
+ assert(plugin->type() == Plugin::LADSPA);
+ assert(plugin->id() != 0);
assert(name != "");
LADSPA_Descriptor_Function df = NULL;
- PluginImpl* plugin = NULL;
NodeImpl* n = NULL;
-
- // Attempt to find the lib
- list<PluginImpl*>::iterator i;
- for (i = _plugins.begin(); i != _plugins.end(); ++i) {
- plugin = (*i);
- if (plugin->uri() == uri) break;
- }
- assert(plugin->id() != 0);
-
- if (i == _plugins.end()) {
- cerr << "Did not find LADSPA plugin " << uri << " in database." << endl;
+ plugin->load(); // FIXME: unload
+ assert(plugin->module());
+ assert(*plugin->module());
+
+ if (!plugin->module()->get_symbol("ladspa_descriptor", (void*&)df)) {
+ cerr << "Looks like this isn't a LADSPA plugin." << endl;
return NULL;
- } else {
- if (!plugin->module()->get_symbol("ladspa_descriptor", (void*&)df)) {
- cerr << "Looks like this isn't a LADSPA plugin." << endl;
- return NULL;
- }
}
// Attempt to find the plugin in lib