diff options
Diffstat (limited to 'src/engine/NodeFactory.cpp')
-rw-r--r-- | src/engine/NodeFactory.cpp | 707 |
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 |