From 5791d19a0f56c65ef7b89da80f4bcc3e1cee0c93 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 11 Oct 2007 17:24:49 +0000 Subject: 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 --- src/libs/engine/ClientBroadcaster.cpp | 10 +- src/libs/engine/ClientBroadcaster.hpp | 5 +- src/libs/engine/LADSPANode.cpp | 2 +- src/libs/engine/LADSPANode.hpp | 2 +- src/libs/engine/LV2Node.cpp | 12 +- src/libs/engine/LV2Node.hpp | 12 +- src/libs/engine/MidiNoteNode.cpp | 1 - src/libs/engine/NodeBase.cpp | 2 +- src/libs/engine/NodeBase.hpp | 20 +- src/libs/engine/NodeFactory.cpp | 336 +++++++++---------------- src/libs/engine/NodeFactory.hpp | 28 +-- src/libs/engine/NodeImpl.hpp | 2 +- src/libs/engine/ObjectSender.cpp | 2 +- src/libs/engine/PluginImpl.cpp | 27 ++ src/libs/engine/PluginImpl.hpp | 3 + src/libs/engine/events/CreateNodeEvent.cpp | 6 +- src/libs/engine/events/RequestPluginsEvent.cpp | 2 +- src/libs/engine/events/RequestPluginsEvent.hpp | 11 +- 18 files changed, 209 insertions(+), 274 deletions(-) (limited to 'src/libs') diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index df8e6c6f..67cf8dd9 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -100,12 +100,12 @@ ClientBroadcaster::send_error(const string& msg) } void -ClientBroadcaster::send_plugins_to(ClientInterface* client, const list& plugin_list) +ClientBroadcaster::send_plugins_to(ClientInterface* client, const NodeFactory::Plugins& plugins) { client->transfer_begin(); - for (list::const_iterator i = plugin_list.begin(); i != plugin_list.end(); ++i) { - const PluginImpl* const plugin = *i; + for (NodeFactory::Plugins::const_iterator i = plugins.begin(); i != plugins.end(); ++i) { + const PluginImpl* const plugin = i->second; client->new_plugin(plugin->uri(), plugin->type_uri(), plugin->name()); } @@ -114,10 +114,10 @@ ClientBroadcaster::send_plugins_to(ClientInterface* client, const list& plugin_list) +ClientBroadcaster::send_plugins(const NodeFactory::Plugins& plugins) { for (Clients::const_iterator c = _clients.begin(); c != _clients.end(); ++c) - send_plugins_to((*c).second, plugin_list); + send_plugins_to((*c).second, plugins); } diff --git a/src/libs/engine/ClientBroadcaster.hpp b/src/libs/engine/ClientBroadcaster.hpp index ecd19d34..73353588 100644 --- a/src/libs/engine/ClientBroadcaster.hpp +++ b/src/libs/engine/ClientBroadcaster.hpp @@ -26,6 +26,7 @@ #include #include "interface/ClientInterface.hpp" #include "types.hpp" +#include "NodeFactory.hpp" using std::string; @@ -62,7 +63,7 @@ public: // Error that isn't the direct result of a request void send_error(const string& msg); - void send_plugins(const std::list& plugin_list); + void send_plugins(const NodeFactory::Plugins& plugin_list); void send_patch(const PatchImpl* p, bool recursive); void send_node(const NodeImpl* node, bool recursive); void send_port(const PortImpl* port); @@ -81,7 +82,7 @@ public: void send_program_add(const string& node_path, int bank, int program, const string& name); void send_program_remove(const string& node_path, int bank, int program); - void send_plugins_to(ClientInterface*, const std::list& plugin_list); + void send_plugins_to(ClientInterface*, const NodeFactory::Plugins& plugin_list); private: typedef std::map Clients; diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp index 5ae567db..ee5da968 100644 --- a/src/libs/engine/LADSPANode.cpp +++ b/src/libs/engine/LADSPANode.cpp @@ -36,7 +36,7 @@ namespace Ingen { * Object is not usable until instantiate() is called with success. * (It _will_ crash!) */ -LADSPANode::LADSPANode(const PluginImpl* plugin, const string& path, bool polyphonic, PatchImpl* parent, const LADSPA_Descriptor* descriptor, SampleRate srate, size_t buffer_size) +LADSPANode::LADSPANode(PluginImpl* plugin, const string& path, bool polyphonic, PatchImpl* parent, const LADSPA_Descriptor* descriptor, SampleRate srate, size_t buffer_size) : NodeBase(plugin, path, polyphonic, parent, srate, buffer_size), _descriptor(descriptor), _instances(NULL) diff --git a/src/libs/engine/LADSPANode.hpp b/src/libs/engine/LADSPANode.hpp index 8675a6fd..6d6cd442 100644 --- a/src/libs/engine/LADSPANode.hpp +++ b/src/libs/engine/LADSPANode.hpp @@ -34,7 +34,7 @@ namespace Ingen { class LADSPANode : public NodeBase { public: - LADSPANode(const PluginImpl* plugin, + LADSPANode(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp index e3b6c06b..bfcc619a 100644 --- a/src/libs/engine/LV2Node.cpp +++ b/src/libs/engine/LV2Node.cpp @@ -40,12 +40,12 @@ namespace Ingen { * Object is not usable until instantiate() is called with success. * (It _will_ crash!) */ -LV2Node::LV2Node(const PluginImpl* plugin, - const string& name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate, - size_t buffer_size) +LV2Node::LV2Node(PluginImpl* plugin, + const string& name, + bool polyphonic, + PatchImpl* parent, + SampleRate srate, + size_t buffer_size) : NodeBase(plugin, name, polyphonic, parent, srate, buffer_size) , _lv2_plugin(plugin->slv2_plugin()) , _instances(NULL) diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp index 7fd9bf6d..dbd79671 100644 --- a/src/libs/engine/LV2Node.hpp +++ b/src/libs/engine/LV2Node.hpp @@ -34,12 +34,12 @@ namespace Ingen { class LV2Node : public NodeBase { public: - LV2Node(const PluginImpl* plugin, - const string& name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate, - size_t buffer_size); + LV2Node(PluginImpl* plugin, + const string& name, + bool polyphonic, + PatchImpl* parent, + SampleRate srate, + size_t buffer_size); virtual ~LV2Node(); diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp index 7604bc61..7b3c1c9e 100644 --- a/src/libs/engine/MidiNoteNode.cpp +++ b/src/libs/engine/MidiNoteNode.cpp @@ -41,7 +41,6 @@ MidiNoteNode::MidiNoteNode(const string& path, bool polyphonic, PatchImpl* paren : NodeBase(new PluginImpl(Plugin::Internal, "ingen:note_node"), path, polyphonic, parent, srate, buffer_size), _voices(new Raul::Array(_polyphony)), _prepared_voices(NULL), - _sustain(false) { _ports = new Raul::Array(5); diff --git a/src/libs/engine/NodeBase.cpp b/src/libs/engine/NodeBase.cpp index ca5d1fc0..78825e7a 100644 --- a/src/libs/engine/NodeBase.cpp +++ b/src/libs/engine/NodeBase.cpp @@ -33,7 +33,7 @@ using namespace std; namespace Ingen { -NodeBase::NodeBase(const PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) +NodeBase::NodeBase(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) : NodeImpl(parent, name, polyphonic), _plugin(plugin), _polyphony((polyphonic && parent) ? parent->internal_polyphony() : 1), diff --git a/src/libs/engine/NodeBase.hpp b/src/libs/engine/NodeBase.hpp index 5838614d..2671a5a0 100644 --- a/src/libs/engine/NodeBase.hpp +++ b/src/libs/engine/NodeBase.hpp @@ -48,12 +48,12 @@ namespace Shared { class NodeBase : public NodeImpl { public: - NodeBase(const PluginImpl* plugin, - const string& name, - bool poly, - PatchImpl* parent, - SampleRate rate, - size_t buffer_size); + NodeBase(PluginImpl* plugin, + const string& name, + bool poly, + PatchImpl* parent, + SampleRate rate, + size_t buffer_size); virtual ~NodeBase(); @@ -98,9 +98,9 @@ public: Raul::List* dependants() { return _dependants; } void dependants(Raul::List* l) { _dependants = l; } - virtual const Plugin* plugin() const; - virtual const PluginImpl* plugin_impl() const { return _plugin; } - virtual void plugin(const PluginImpl* pi) { _plugin = pi; } + virtual const Plugin* plugin() const; + virtual PluginImpl* plugin_impl() const { return _plugin; } + virtual void plugin(PluginImpl* pi) { _plugin = pi; } /** A node's parent is always a patch, so static cast should be safe */ inline PatchImpl* parent_patch() const { return (PatchImpl*)_parent; } @@ -108,7 +108,7 @@ public: protected: virtual void signal_input_ready(); - const PluginImpl* _plugin; + PluginImpl* _plugin; uint32_t _polyphony; SampleRate _srate; 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::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::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::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::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::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::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::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::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::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::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 diff --git a/src/libs/engine/NodeFactory.hpp b/src/libs/engine/NodeFactory.hpp index a956a938..6eceb0ee 100644 --- a/src/libs/engine/NodeFactory.hpp +++ b/src/libs/engine/NodeFactory.hpp @@ -32,7 +32,7 @@ #endif #include "types.hpp" -using std::string; using std::list; +using std::string; namespace Ingen { @@ -58,33 +58,31 @@ public: ~NodeFactory(); void load_plugins(); - NodeImpl* load_plugin(const PluginImpl* info, const string& name, bool polyphonic, PatchImpl* parent); + NodeImpl* load_plugin(PluginImpl* info, const string& name, bool polyphonic, PatchImpl* parent); - const list& plugins() { return _plugins; } + typedef std::map Plugins; + const Plugins& plugins() const { return _plugins; } - const PluginImpl* plugin(const string& uri); - const PluginImpl* plugin(const string& type, const string& lib, const string& label); // DEPRECATED + PluginImpl* plugin(const string& uri); + + /** DEPRECATED */ + PluginImpl* plugin(const string& type, const string& lib, const string& label); private: #ifdef HAVE_LADSPA void load_ladspa_plugins(); - NodeImpl* load_ladspa_plugin(const string& plugin_uri, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); + NodeImpl* load_ladspa_plugin(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); #endif #ifdef HAVE_SLV2 void load_lv2_plugins(); - NodeImpl* load_lv2_plugin(const string& plugin_uri, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); + NodeImpl* load_lv2_plugin(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); #endif - NodeImpl* load_internal_plugin(const string& plug_label, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); - - Glib::Module* library(const string& path); + void load_internal_plugins(); + NodeImpl* load_internal_plugin(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); - typedef std::map Libraries; - - Libraries _libraries; - list _internal_plugins; - list _plugins; // FIXME: make a map + Plugins _plugins; Ingen::Shared::World* _world; bool _has_loaded; diff --git a/src/libs/engine/NodeImpl.hpp b/src/libs/engine/NodeImpl.hpp index 39692cc9..3c6c95f3 100644 --- a/src/libs/engine/NodeImpl.hpp +++ b/src/libs/engine/NodeImpl.hpp @@ -149,7 +149,7 @@ public: /** Information about the Plugin this Node is an instance of. * Not the best name - not all nodes come from plugins (ie Patch) */ - virtual const PluginImpl* plugin_impl() const = 0; + virtual PluginImpl* plugin_impl() const = 0; /** Information about the Plugin this Node is an instance of. * Not the best name - not all nodes come from plugins (ie Patch) diff --git a/src/libs/engine/ObjectSender.cpp b/src/libs/engine/ObjectSender.cpp index 55dafaf4..4b2497e6 100644 --- a/src/libs/engine/ObjectSender.cpp +++ b/src/libs/engine/ObjectSender.cpp @@ -74,7 +74,7 @@ ObjectSender::send_patch(ClientInterface* client, const PatchImpl* patch, bool r void ObjectSender::send_node(ClientInterface* client, const NodeImpl* node, bool recursive) { - const PluginImpl* const plugin = node->plugin_impl(); + PluginImpl* const plugin = node->plugin_impl(); assert(node->path().length() > 0); diff --git a/src/libs/engine/PluginImpl.cpp b/src/libs/engine/PluginImpl.cpp index e8b090ef..dfff1031 100644 --- a/src/libs/engine/PluginImpl.cpp +++ b/src/libs/engine/PluginImpl.cpp @@ -15,14 +15,41 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "PluginImpl.hpp" #include "MidiNoteNode.hpp" #include "MidiTriggerNode.hpp" #include "MidiControlNode.hpp" #include "TransportNode.hpp" +using namespace std; + namespace Ingen { + +void +PluginImpl::load() +{ + if (!_module) { + cerr << "Loading " << _lib_path << endl; + _module = new Glib::Module(_lib_path, Glib::MODULE_BIND_LOCAL); + if (!(*_module)) + delete _module; + } +} + + +void +PluginImpl::unload() +{ + if (_module) { + cerr << "Unloading " << _lib_path << endl; + delete _module; + _module = NULL; + } +} + + NodeImpl* PluginImpl::instantiate(const string& name, bool polyphonic, Ingen::PatchImpl* parent, SampleRate srate, size_t buffer_size) { diff --git a/src/libs/engine/PluginImpl.hpp b/src/libs/engine/PluginImpl.hpp index 86d3cc5b..83814dc8 100644 --- a/src/libs/engine/PluginImpl.hpp +++ b/src/libs/engine/PluginImpl.hpp @@ -117,6 +117,9 @@ public: void slv2_plugin(SLV2Plugin p) { _slv2_plugin = p; } #endif + void load(); + void unload(); + NodeImpl* instantiate(const string& name, bool polyphonic, Ingen::PatchImpl* parent, SampleRate srate, size_t buffer_size); private: diff --git a/src/libs/engine/events/CreateNodeEvent.cpp b/src/libs/engine/events/CreateNodeEvent.cpp index a0a8d08f..dea1024b 100644 --- a/src/libs/engine/events/CreateNodeEvent.cpp +++ b/src/libs/engine/events/CreateNodeEvent.cpp @@ -78,9 +78,9 @@ CreateNodeEvent::pre_process() _patch = _engine.object_store()->find_patch(_path.parent()); - const PluginImpl* plugin = (_plugin_uri != "") - ? _engine.node_factory()->plugin(_plugin_uri) - : _engine.node_factory()->plugin(_plugin_type, _plugin_lib, _plugin_label); + PluginImpl* const plugin = (_plugin_uri != "") + ? _engine.node_factory()->plugin(_plugin_uri) + : _engine.node_factory()->plugin(_plugin_type, _plugin_lib, _plugin_label); if (_patch && plugin) { diff --git a/src/libs/engine/events/RequestPluginsEvent.cpp b/src/libs/engine/events/RequestPluginsEvent.cpp index 005048ea..8d7fc1ba 100644 --- a/src/libs/engine/events/RequestPluginsEvent.cpp +++ b/src/libs/engine/events/RequestPluginsEvent.cpp @@ -34,7 +34,7 @@ void RequestPluginsEvent::pre_process() { // Take a copy to send in the post processing thread (to avoid problems - // because std::list isn't thread safe) + // because std::map isn't thread safe) _plugins = _engine.node_factory()->plugins(); QueuedEvent::pre_process(); diff --git a/src/libs/engine/events/RequestPluginsEvent.hpp b/src/libs/engine/events/RequestPluginsEvent.hpp index ae6a77a9..f6b41d7a 100644 --- a/src/libs/engine/events/RequestPluginsEvent.hpp +++ b/src/libs/engine/events/RequestPluginsEvent.hpp @@ -18,19 +18,12 @@ #ifndef REQUESTPLUGINSEVENT_H #define REQUESTPLUGINSEVENT_H -#include -#include #include "QueuedEvent.hpp" -using std::string; +#include "NodeFactory.hpp" namespace Ingen { -class PluginImpl; class Responder; -namespace Shared { - class ClientInterface; -} using Shared::ClientInterface; - /** A request from a client to send notification of all objects (ie refresh). * @@ -45,7 +38,7 @@ public: void post_process(); private: - std::list _plugins; + NodeFactory::Plugins _plugins; }; -- cgit v1.2.1