summaryrefslogtreecommitdiffstats
path: root/src/engine/NodeFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/NodeFactory.cpp')
-rw-r--r--src/engine/NodeFactory.cpp707
1 files changed, 0 insertions, 707 deletions
diff --git a/src/engine/NodeFactory.cpp b/src/engine/NodeFactory.cpp
deleted file mode 100644
index 176d3f47..00000000
--- a/src/engine/NodeFactory.cpp
+++ /dev/null
@@ -1,707 +0,0 @@
-/* This file is part of Om. Copyright (C) 2006 Dave Robillard.
- *
- * Om is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * Om is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include "NodeFactory.h"
-#include "config.h"
-#include <cstdlib>
-#include <pthread.h>
-#include <dirent.h>
-#include <float.h>
-#include <cmath>
-#include <dlfcn.h>
-#include "AudioDriver.h"
-#include "MidiNoteNode.h"
-#include "MidiTriggerNode.h"
-#include "MidiControlNode.h"
-#include "AudioInputNode.h"
-#include "AudioOutputNode.h"
-#include "ControlInputNode.h"
-#include "ControlOutputNode.h"
-#include "MidiInputNode.h"
-#include "MidiOutputNode.h"
-#include "TransportNode.h"
-#include "PluginLibrary.h"
-#include "Plugin.h"
-#include "Patch.h"
-#include "Om.h"
-#include "OmApp.h"
-#ifdef HAVE_SLV2
-#include "LV2Plugin.h"
-#include <slv2/slv2.h>
-#endif
-#ifdef HAVE_LADSPA
-#include "LADSPAPlugin.h"
-#endif
-#ifdef HAVE_DSSI
-#include "DSSIPlugin.h"
-#endif
-
-using std::string;
-using std::cerr; using std::cout; using std::endl;
-
-
-namespace Om {
-
-
-/* I am perfectly aware that the vast majority of this class is a
- * vomit inducing nightmare at the moment ;)
- */
-
-
-
-NodeFactory::NodeFactory()
-: m_has_loaded(false)
-{
- pthread_mutex_init(&m_plugin_list_mutex, NULL);
-
- // Add builtin plugin types to m_internal_plugins list
- // FIXME: ewwww, definitely a better way to do this!
- //Plugin* pi = NULL;
-
- Patch* parent = new Patch("dummy", 1, NULL, 1, 1, 1);
-
- Node* n = NULL;
- n = new AudioInputNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new AudioOutputNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new ControlInputNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new ControlOutputNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new MidiInputNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new MidiOutputNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new MidiNoteNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new MidiTriggerNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new MidiControlNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
- n = new TransportNode("foo", 1, parent, 1, 1);
- m_internal_plugins.push_back(new Plugin(n->plugin()));
- delete n;
-
-
- delete parent;
-}
-
-
-NodeFactory::~NodeFactory()
-{
- for (list<Plugin*>::iterator i = m_plugins.begin(); i != m_plugins.end(); ++i)
- delete (*i);
-
- for (list<PluginLibrary*>::iterator i = m_libraries.begin(); i != m_libraries.end(); ++i) {
- (*i)->close();
- delete (*i);
- }
-}
-
-
-void
-NodeFactory::load_plugins()
-{
- // Only load if we havn't already, so every client connecting doesn't cause
- // this (expensive!) stuff to happen. Not the best solution - would be nice
- // if clients could refresh plugins list for whatever reason :/
- if (!m_has_loaded) {
- pthread_mutex_lock(&m_plugin_list_mutex);
-
- m_plugins.clear();
- m_plugins = m_internal_plugins;
-
-#if HAVE_SLV2
- load_lv2_plugins();
-#endif
-#if HAVE_DSSI
- load_dssi_plugins();
-#endif
-#if HAVE_LADSPA
- load_ladspa_plugins();
-#endif
-
- m_has_loaded = true;
-
- pthread_mutex_unlock(&m_plugin_list_mutex);
- }
-}
-
-
-/** Loads a plugin.
- *
- * Calls the load_*_plugin functions to actually do things, just a wrapper.
- */
-Node*
-NodeFactory::load_plugin(const Plugin* a_plugin, const string& name, size_t poly, Patch* parent)
-{
- assert(parent != NULL);
- assert(poly == 1 || poly == parent->internal_poly());
- assert(a_plugin);
-
- pthread_mutex_lock(&m_plugin_list_mutex);
-
- Node* r = NULL;
- Plugin* plugin = NULL;
-
- // Attempt to find the plugin in loaded DB
- if (a_plugin->type() != Plugin::Internal) {
- list<Plugin*>::iterator i;
- if (a_plugin->plug_label().length() == 0) {
- for (i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- if (a_plugin->uri() == (*i)->uri()) {
- plugin = *i;
- break;
- }
- }
- } else {
- for (i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- if (a_plugin->uri() == (*i)->uri()) {
- plugin = *i;
- break;
- }
- }
- }
-
- if (plugin == NULL)
- return NULL;
- }
-
- switch (a_plugin->type()) {
-#if HAVE_SLV2
- case Plugin::LV2:
- r = load_lv2_plugin(plugin->uri(), name, poly, parent);
- break;
-#endif
-#if HAVE_DSSI
- case Plugin::DSSI:
- r = load_dssi_plugin(plugin->uri(), name, poly, parent);
- break;
-#endif
-#if HAVE_LADSPA
- case Plugin::LADSPA:
- r = load_ladspa_plugin(plugin->uri(), name, poly, parent);
- break;
-#endif
- case Plugin::Internal:
- r = load_internal_plugin(a_plugin->uri(), name, poly, parent);
- break;
- default:
- cerr << "[NodeFactory] WARNING: Unknown plugin type." << endl;
- }
-
- pthread_mutex_unlock(&m_plugin_list_mutex);
-
- return r;
-}
-
-
-/** Loads an internal plugin.
- */
-Node*
-NodeFactory::load_internal_plugin(const string& uri, const string& name, size_t poly, Patch* parent)
-{
- assert(parent != NULL);
- assert(poly == 1 || poly == parent->internal_poly());
- assert(uri.length() > 3);
- assert(uri.substr(0, 3) == "om:");
-
- string plug_label = uri.substr(3);
-
- if (plug_label == "midi_input") {
- MidiInputNode* tn = new MidiInputNode(name, 1, parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return tn;
- } else if (plug_label == "midi_output") {
- MidiOutputNode* tn = new MidiOutputNode(name, 1, parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return tn;
- } else if (plug_label == "audio_input") {
- AudioInputNode* in = new AudioInputNode(name, poly, parent,
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return in;
- } else if (plug_label == "control_input") {
- ControlInputNode* in = new ControlInputNode(name, poly, parent,
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return in;
- } else if (plug_label == "audio_output") {
- AudioOutputNode* on = new AudioOutputNode(name, poly, parent,
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return on;
- } else if (plug_label == "control_output") {
- ControlOutputNode* on = new ControlOutputNode(name, poly, parent,
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return on;
- } else if (plug_label == "note_in" || plug_label == "midi_note_in") {
- MidiNoteNode* mn = new MidiNoteNode(name, poly, parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return mn;
- } else if (plug_label == "trigger_in" || plug_label == "midi_trigger_in") {
- MidiTriggerNode* mn = new MidiTriggerNode(name, 1, parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return mn;
- } else if (plug_label == "midi_control_in") {
- MidiControlNode* mn = new MidiControlNode(name, 1, parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return mn;
- } else if (plug_label == "transport") {
- TransportNode* tn = new TransportNode(name, 1, parent, om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- return tn;
- } else {
- cerr << "Unknown internal plugin type '" << plug_label << "'" << endl;
- }
-
- return NULL;
-}
-
-
-#ifdef HAVE_SLV2
-
-/** Loads information about all LV2 plugins into internal plugin database.
- */
-void
-NodeFactory::load_lv2_plugins()
-{
- SLV2List plugins = slv2_list_new();
- slv2_list_load_all(plugins);
-
- //cerr << "[NodeFactory] Found " << slv2_list_get_length(plugins) << " LV2 plugins." << endl;
-
- for (unsigned long i=0; i < slv2_list_get_length(plugins); ++i) {
-
- SLV2Plugin* lv2_plug = slv2_list_get_plugin_by_index(plugins, i);
-
-
- //om_plug->library(plugin_library);
-
- const char* uri = (const char*)slv2_plugin_get_uri(lv2_plug);
- //cerr << "LV2 plugin: " << uri << endl;
-
- bool found = false;
- for (list<Plugin*>::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- if (!strcmp((*i)->uri().c_str(), uri)) {
- cerr << "Warning: Duplicate LV2 plugin (" << uri << ").\nUsing "
- << (*i)->lib_path() << " version." << endl;
- found = true;
- break;
- }
- }
- if (!found) {
- //printf("[NodeFactory] Found LV2 plugin %s\n", uri);
- Plugin* om_plug = new Plugin();
- om_plug->type(Plugin::LV2);
- om_plug->slv2_plugin(lv2_plug);
- om_plug->uri(uri);
- // FIXME FIXME FIXME temporary hack
- om_plug->library(NULL);
- om_plug->lib_path("FIXMEpath");
- om_plug->plug_label("FIXMElabel");
- unsigned char* name = slv2_plugin_get_name(lv2_plug);
- om_plug->name((char*)name);
- free(name);
- om_plug->type(Plugin::LV2);
- m_plugins.push_back(om_plug);
- }
- }
-
- slv2_list_free(plugins);
-}
-
-
-/** Loads a LV2 plugin.
- * Returns 'poly' independant plugins as a Node*
- */
-Node*
-NodeFactory::load_lv2_plugin(const string& plug_uri,
- const string& node_name,
- size_t poly,
- Patch* parent)
-{
- // Find (Om) Plugin
- Plugin* plugin = NULL;
- list<Plugin*>::iterator i;
- for (i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- plugin = (*i);
- if ((*i)->uri() == plug_uri) break;
- }
-
- Node* n = NULL;
-
- if (plugin) {
- n = new Om::LV2Plugin(node_name, poly, parent, plugin->slv2_plugin(),
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- bool success = ((LV2Plugin*)n)->instantiate();
- if (!success) {
- delete n;
- n = NULL;
- }
- n->plugin(plugin);
- }
-
- return n;
-}
-
-#endif // HAVE_SLV2
-
-
-#if HAVE_DSSI
-
-/** Loads information about all DSSI plugins into internal plugin database.
- */
-void
-NodeFactory::load_dssi_plugins()
-{
- // FIXME: too much code duplication with load_ladspa_plugin
-
- char* env_dssi_path = getenv("DSSI_PATH");
- string dssi_path;
- if (!env_dssi_path) {
- cerr << "[NodeFactory] DSSI_PATH is empty. Assuming /usr/lib/dssi:/usr/local/lib/dssi:~/.dssi" << endl;
- dssi_path = string("/usr/lib/dssi:/usr/local/lib/dssi:").append(
- getenv("HOME")).append("/.dssi");
- } else {
- dssi_path = env_dssi_path;
- }
-
- DSSI_Descriptor_Function df = NULL;
- DSSI_Descriptor* descriptor = NULL;
-
- string dir;
- string full_lib_name;
-
- // Yep, this should use an sstream alright..
- while (dssi_path != "") {
- dir = dssi_path.substr(0, dssi_path.find(':'));
- if (dssi_path.find(':') != string::npos)
- dssi_path = dssi_path.substr(dssi_path.find(':')+1);
- else
- dssi_path = "";
-
- DIR* pdir = opendir(dir.c_str());
- if (pdir == NULL) {
- //cerr << "[NodeFactory] Unreadable directory in DSSI_PATH: " << dir.c_str() << endl;
- continue;
- }
-
- struct dirent* pfile;
- while ((pfile = readdir(pdir))) {
-
- if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
- continue;
-
- full_lib_name = dir +"/"+ pfile->d_name;
-
- // Load descriptor function
- // Loaded with LAZY here, will be loaded with NOW on node loading
- void* handle = dlopen(full_lib_name.c_str(), RTLD_LAZY);
- if (handle == NULL)
- continue;
-
- df = (DSSI_Descriptor_Function)dlsym(handle, "dssi_descriptor");
- if (df == NULL) {
- // Not a DSSI plugin library
- dlclose(handle);
- continue;
- }
-
- PluginLibrary* plugin_library = new PluginLibrary(full_lib_name);
- m_libraries.push_back(plugin_library);
-
- const LADSPA_Descriptor* ld = NULL;
-
- for (unsigned long i=0; (descriptor = (DSSI_Descriptor*)df(i)) != NULL; ++i) {
- ld = descriptor->LADSPA_Plugin;
- assert(ld != NULL);
- Plugin* plugin = new Plugin();
- assert(plugin_library != NULL);
- plugin->library(plugin_library);
- plugin->lib_path(dir + "/" + pfile->d_name);
- plugin->plug_label(ld->Label);
- plugin->name(ld->Name);
- plugin->type(Plugin::DSSI);
- plugin->id(ld->UniqueID);
-
- bool found = false;
- for (list<Plugin*>::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- if ((*i)->uri() == plugin->uri()) {
- cerr << "Warning: Duplicate DSSI plugin (" << plugin->lib_name() << ":"
- << plugin->plug_label() << ")" << " found.\nUsing " << (*i)->lib_path()
- << " version." << endl;
- found = true;
- break;
- }
- }
- if (!found)
- m_plugins.push_back(plugin);
- else
- delete plugin;
- }
-
- df = NULL;
- descriptor = NULL;
- dlclose(handle);
- }
- closedir(pdir);
- }
-}
-
-
-/** Creates a Node by instancing a DSSI plugin.
- */
-Node*
-NodeFactory::load_dssi_plugin(const string& uri,
- const string& name, size_t poly, Patch* parent)
-{
- // FIXME: awful code duplication here
-
- assert(uri != "");
- assert(name != "");
- assert(poly > 0);
-
- DSSI_Descriptor_Function df = NULL;
- const Plugin* plugin = NULL;
- Node* n = NULL;
- void* handle = NULL;
-
- // Attempt to find the lib
- list<Plugin*>::iterator i;
- for (i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- plugin = (*i);
- if (plugin->uri() == uri) break;
- }
-
- assert(plugin->id() != 0);
-
- if (i == m_plugins.end()) {
- cerr << "Did not find DSSI plugin " << uri << " in database." << endl;
- return NULL;
- } else {
- assert(plugin != NULL);
- plugin->library()->open();
- handle = plugin->library()->handle();
- assert(handle != NULL);
-
- // Load descriptor function
- dlerror();
- df = (DSSI_Descriptor_Function)dlsym(handle, "dssi_descriptor");
- if (df == NULL || dlerror() != NULL) {
- cerr << "Looks like this isn't a DSSI plugin." << endl;
- return NULL;
- }
- }
-
- // Attempt to find the plugin in lib
- DSSI_Descriptor* descriptor = NULL;
- for (unsigned long i=0; (descriptor = (DSSI_Descriptor*)df(i)) != NULL; ++i) {
- if (descriptor->LADSPA_Plugin != NULL
- && descriptor->LADSPA_Plugin->UniqueID == plugin->id()) {
- break;
- }
- }
-
- if (descriptor == NULL) {
- cerr << "Could not find plugin \"" << plugin->id() << "\" in " << plugin->lib_name() << endl;
- return NULL;
- }
-
- n = new DSSIPlugin(name, poly, parent, descriptor,
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- bool success = ((DSSIPlugin*)n)->instantiate();
- if (!success) {
- delete n;
- n = NULL;
- }
-
- n->plugin(plugin);
-
- return n;
-}
-#endif // HAVE_DSSI
-
-
-#ifdef HAVE_LADSPA
-/** Loads information about all LADSPA plugins into internal plugin database.
- */
-void
-NodeFactory::load_ladspa_plugins()
-{
- char* env_ladspa_path = getenv("LADSPA_PATH");
- string ladspa_path;
- if (!env_ladspa_path) {
- cerr << "[NodeFactory] LADSPA_PATH is empty. Assuming /usr/lib/ladspa:/usr/local/lib/ladspa:~/.ladspa" << endl;
- ladspa_path = string("/usr/lib/ladspa:/usr/local/lib/ladspa:").append(
- getenv("HOME")).append("/.ladspa");
- } else {
- ladspa_path = env_ladspa_path;
- }
-
- LADSPA_Descriptor_Function df = NULL;
- LADSPA_Descriptor* descriptor = NULL;
-
- string dir;
- string full_lib_name;
-
- // Yep, this should use an sstream alright..
- while (ladspa_path != "") {
- dir = ladspa_path.substr(0, ladspa_path.find(':'));
- if (ladspa_path.find(':') != string::npos)
- ladspa_path = ladspa_path.substr(ladspa_path.find(':')+1);
- else
- ladspa_path = "";
-
- DIR* pdir = opendir(dir.c_str());
- if (pdir == NULL) {
- //cerr << "[NodeFactory] Unreadable directory in LADSPA_PATH: " << dir.c_str() << endl;
- continue;
- }
-
- struct dirent* pfile;
- while ((pfile = readdir(pdir))) {
-
- if (!strcmp(pfile->d_name, ".") || !strcmp(pfile->d_name, ".."))
- continue;
-
- full_lib_name = dir +"/"+ pfile->d_name;
-
- // Load descriptor function
- // Loaded with LAZY here, will be loaded with NOW on node loading
- void* handle = dlopen(full_lib_name.c_str(), RTLD_LAZY);
- if (handle == NULL)
- continue;
-
- df = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
- if (df == NULL) {
- dlclose(handle);
- continue;
- }
-
- PluginLibrary* plugin_library = new PluginLibrary(full_lib_name);
- m_libraries.push_back(plugin_library);
-
- for (unsigned long i=0; (descriptor = (LADSPA_Descriptor*)df(i)) != NULL; ++i) {
- Plugin* plugin = new Plugin();
- assert(plugin_library != NULL);
- plugin->library(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);
-
- bool found = false;
- for (list<Plugin*>::const_iterator i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- if ((*i)->uri() == plugin->uri()) {
- cerr << "Warning: Duplicate LADSPA plugin " << plugin->uri()
- << " found.\nChoosing " << (*i)->lib_path()
- << " over " << plugin->lib_path() << endl;
- found = true;
- break;
- }
- }
- if (!found)
- m_plugins.push_back(plugin);
- else
- delete plugin;
- }
-
- df = NULL;
- descriptor = NULL;
- dlclose(handle);
- }
- closedir(pdir);
- }
-}
-
-
-/** Loads a LADSPA plugin.
- * Returns 'poly' independant plugins as a Node*
- */
-Node*
-NodeFactory::load_ladspa_plugin(const string& uri,
- const string& name, size_t poly, Patch* parent)
-{
- assert(uri != "");
- assert(name != "");
- assert(poly > 0);
-
- LADSPA_Descriptor_Function df = NULL;
- Plugin* plugin = NULL;
- Node* n = NULL;
- void* plugin_lib = NULL;
-
- // Attempt to find the lib
- list<Plugin*>::iterator i;
- for (i = m_plugins.begin(); i != m_plugins.end(); ++i) {
- plugin = (*i);
- if (plugin->uri() == uri) break;
- }
-
- assert(plugin->id() != 0);
-
- if (i == m_plugins.end()) {
- cerr << "Did not find LADSPA plugin " << uri << " in database." << endl;
- return NULL;
- } else {
- assert(plugin != NULL);
- plugin->library()->open();
- plugin_lib = plugin->library()->handle();
- assert(plugin_lib != NULL);
-
- // Load descriptor function
- dlerror();
- df = (LADSPA_Descriptor_Function)dlsym(plugin_lib, "ladspa_descriptor");
- if (df == NULL || dlerror() != NULL) {
- cerr << "Looks like this isn't a LADSPA plugin." << endl;
- return NULL;
- }
- }
-
- // Attempt to find the plugin in lib
- LADSPA_Descriptor* descriptor = NULL;
- for (unsigned long i=0; (descriptor = (LADSPA_Descriptor*)df(i)) != NULL; ++i) {
- if (descriptor->UniqueID == plugin->id()) {
- break;
- }
- }
-
- if (descriptor == NULL) {
- cerr << "Could not find plugin \"" << plugin->id() << "\" in " << plugin->lib_path() << endl;
- return NULL;
- }
-
- n = new LADSPAPlugin(name, poly, parent, descriptor,
- om->audio_driver()->sample_rate(), om->audio_driver()->buffer_size());
- bool success = ((LADSPAPlugin*)n)->instantiate();
- if (!success) {
- delete n;
- n = NULL;
- }
-
- n->plugin(plugin);
-
- return n;
-}
-
-
-#endif // HAVE_LADSPA
-
-
-} // namespace Om