diff options
author | David Robillard <d@drobilla.net> | 2007-10-22 03:48:28 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2007-10-22 03:48:28 +0000 |
commit | e9d99340c9ac29aaa7912db0554a88820c4a776a (patch) | |
tree | 2bb49de8b90d861330e8db50919a8137b10cc913 /src | |
parent | 5ae4d4d5e805e828b51b98767ac51da24c3b21f1 (diff) | |
download | ingen-e9d99340c9ac29aaa7912db0554a88820c4a776a.tar.gz ingen-e9d99340c9ac29aaa7912db0554a88820c4a776a.tar.bz2 ingen-e9d99340c9ac29aaa7912db0554a88820c4a776a.zip |
Rework plugin design (engine side) to be less crap.
Use LADSPA labels instead of munged friendly names to generate OSC paths.
Separate OSC paths/names from human friendly names (conceptually, still needs UI exposing).
git-svn-id: http://svn.drobilla.net/lad/ingen@898 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
38 files changed, 732 insertions, 410 deletions
diff --git a/src/common/interface/ClientInterface.hpp b/src/common/interface/ClientInterface.hpp index 426538aa..80044caf 100644 --- a/src/common/interface/ClientInterface.hpp +++ b/src/common/interface/ClientInterface.hpp @@ -75,6 +75,7 @@ public: virtual void new_plugin(const std::string& uri, const std::string& type_uri, + const std::string& symbol, const std::string& name) = 0; virtual void new_patch(const std::string& path, uint32_t poly) = 0; diff --git a/src/common/interface/Plugin.hpp b/src/common/interface/Plugin.hpp index 691fb523..716c240e 100644 --- a/src/common/interface/Plugin.hpp +++ b/src/common/interface/Plugin.hpp @@ -31,7 +31,6 @@ public: virtual Type type() const = 0; virtual const std::string& uri() const = 0; - virtual const std::string& name() const = 0; inline const char* type_uri() const { if (type() == LV2) return "ingen:LV2"; diff --git a/src/libs/client/OSCClientReceiver.cpp b/src/libs/client/OSCClientReceiver.cpp index bd0b5db9..6573c9bf 100644 --- a/src/libs/client/OSCClientReceiver.cpp +++ b/src/libs/client/OSCClientReceiver.cpp @@ -143,7 +143,7 @@ OSCClientReceiver::setup_callbacks() lo_server_thread_add_method(_st, "/ingen/ok", "i", response_ok_cb, this); lo_server_thread_add_method(_st, "/ingen/error", "is", response_error_cb, this); lo_server_thread_add_method(_st, "/ingen/num_plugins", "i", num_plugins_cb, this); - lo_server_thread_add_method(_st, "/ingen/plugin", "sss", plugin_cb, this); + lo_server_thread_add_method(_st, "/ingen/plugin", "ssss", plugin_cb, this); lo_server_thread_add_method(_st, "/ingen/new_patch", "si", new_patch_cb, this); lo_server_thread_add_method(_st, "/ingen/destroyed", "s", destroyed_cb, this); lo_server_thread_add_method(_st, "/ingen/patch_enabled", "s", patch_enabled_cb, this); @@ -380,8 +380,8 @@ OSCClientReceiver::_num_plugins_cb(const char* path, const char* types, lo_arg** int OSCClientReceiver::_plugin_cb(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg) { - assert(argc == 3 && !strcmp(types, "sss")); - new_plugin(&argv[0]->s, &argv[1]->s, &argv[2]->s); // type, uri + assert(argc == 4 && !strcmp(types, "ssss")); + new_plugin(&argv[0]->s, &argv[1]->s, &argv[2]->s, &argv[3]->s); // uri, type, symbol, name return 0; } diff --git a/src/libs/client/PluginModel.cpp b/src/libs/client/PluginModel.cpp index e819d04b..8a9ecc7d 100644 --- a/src/libs/client/PluginModel.cpp +++ b/src/libs/client/PluginModel.cpp @@ -38,14 +38,14 @@ Raul::RDF::World* PluginModel::_rdf_world = NULL; string PluginModel::default_node_name(SharedPtr<PatchModel> parent) { - string default_name = Raul::Path::nameify(_name); + string default_name = Raul::Path::nameify(_symbol); string name; char num_buf[3]; for (uint i=0; i < 99; ++i) { name = default_name; if (i != 0) { - snprintf(num_buf, 3, "%d", i+1); + snprintf(num_buf, 4, "_%d", i+1); name += num_buf; } if (!parent->find_child(name)) diff --git a/src/libs/client/PluginModel.hpp b/src/libs/client/PluginModel.hpp index ce268a06..56b33723 100644 --- a/src/libs/client/PluginModel.hpp +++ b/src/libs/client/PluginModel.hpp @@ -45,36 +45,36 @@ class NodeModel; class PluginModel : public Ingen::Shared::Plugin { public: - PluginModel(const string& uri, const string& type_uri, const string& name) - : _uri(uri) + PluginModel(const string& uri, const string& type_uri, const string& symbol, const string& name) + : _type(type_from_uri(type_uri)) + , _uri(uri) + , _symbol(symbol) , _name(name) { - set_type_from_uri(type_uri); #ifdef HAVE_SLV2 _slv2_plugin = slv2_plugins_get_by_uri(_slv2_plugins, uri.c_str()); #endif } - Type type() const { return _type; } - void type(Type t) { _type = t; } - const string& uri() const { return _uri; } - void uri(const string& s) { _uri = s; } - const string& name() const { return _name; } - void name(const string& s) { _name = s; } + Type type() const { return _type; } + const string& uri() const { return _uri; } + const string& name() const { return _name; } /** DEPRECATED */ - void set_type(const string& type_string) { - if (type_string == "LV2") _type = LV2; - else if (type_string == "LADSPA") _type = LADSPA; - else if (type_string == "Internal") _type = Internal; - else if (type_string == "Patch") _type = Patch; + Type type_from_string(const string& type_string) { + if (type_string == "LV2") return LV2; + else if (type_string == "LADSPA") return LADSPA; + else if (type_string == "Internal") return Internal; + else if (type_string == "Patch") return Patch; + else return Internal; // ? } - void set_type_from_uri(const string& type_uri) { + Type type_from_uri(const string& type_uri) { if (type_uri.substr(0, 6) != "ingen:") { cerr << "INVALID TYPE STRING!" << endl; + return Plugin::Internal; // ? } else { - set_type(type_uri.substr(6)); + return type_from_string(type_uri.substr(6)); } } @@ -99,9 +99,10 @@ public: static Raul::RDF::World* rdf_world() { return _rdf_world; } private: - Type _type; - string _uri; - string _name; + const Type _type; + const string _uri; + const string _symbol; + const string _name; #ifdef HAVE_SLV2 static SLV2World _slv2_world; diff --git a/src/libs/client/SigClientInterface.hpp b/src/libs/client/SigClientInterface.hpp index cefc3176..4e57a7ec 100644 --- a/src/libs/client/SigClientInterface.hpp +++ b/src/libs/client/SigClientInterface.hpp @@ -50,7 +50,7 @@ public: sigc::signal<void> signal_bundle_end; sigc::signal<void, string> signal_error; sigc::signal<void, uint32_t> signal_num_plugins; - sigc::signal<void, string, string, string> signal_new_plugin; + sigc::signal<void, string, string, string, string> signal_new_plugin; sigc::signal<void, string, uint32_t> signal_new_patch; sigc::signal<void, string, string, bool, uint32_t> signal_new_node; sigc::signal<void, string, string, bool> signal_new_port; @@ -98,8 +98,8 @@ protected: void error(const string& msg) { if (_enabled) signal_error.emit(msg); } - void new_plugin(const string& uri, const string& type_uri, const string& name) - { if (_enabled) signal_new_plugin.emit(uri, type_uri, name); } + void new_plugin(const string& uri, const string& type_uri, const string& symbol, const string& name) + { if (_enabled) signal_new_plugin.emit(uri, type_uri, symbol, name); } void new_patch(const string& path, uint32_t poly) { if (_enabled) signal_new_patch.emit(path, poly); } diff --git a/src/libs/client/Store.cpp b/src/libs/client/Store.cpp index b118b4e4..3068295a 100644 --- a/src/libs/client/Store.cpp +++ b/src/libs/client/Store.cpp @@ -399,9 +399,9 @@ Store::rename_event(const Path& old_path, const Path& new_path) } void -Store::new_plugin_event(const string& uri, const string& type_uri, const string& name) +Store::new_plugin_event(const string& uri, const string& type_uri, const string& symbol, const string& name) { - SharedPtr<PluginModel> p(new PluginModel(uri, type_uri, name)); + SharedPtr<PluginModel> p(new PluginModel(uri, type_uri, symbol, name)); add_plugin(p); resolve_plugin_orphans(p); } diff --git a/src/libs/client/Store.hpp b/src/libs/client/Store.hpp index 2849afc3..5dd4f34e 100644 --- a/src/libs/client/Store.hpp +++ b/src/libs/client/Store.hpp @@ -97,7 +97,7 @@ private: // Slots for SigClientInterface signals void destruction_event(const Path& path); void rename_event(const Path& old_path, const Path& new_path); - void new_plugin_event(const string& uri, const string& type_uri, const string& name); + void new_plugin_event(const string& uri, const string& type_uri, const string& symbol, const string& name); void new_patch_event(const Path& path, uint32_t poly); void new_node_event(const string& plugin_uri, const Path& node_path, bool is_polyphonic, uint32_t num_ports); void new_port_event(const Path& path, const string& data_type, bool is_output); diff --git a/src/libs/client/ThreadedSigClientInterface.hpp b/src/libs/client/ThreadedSigClientInterface.hpp index 0f300703..e5ec2741 100644 --- a/src/libs/client/ThreadedSigClientInterface.hpp +++ b/src/libs/client/ThreadedSigClientInterface.hpp @@ -90,8 +90,8 @@ public: void error(const string& msg) { push_sig(sigc::bind(error_slot, msg)); } - void new_plugin(const string& uri, const string& type_uri, const string& name) - { push_sig(sigc::bind(new_plugin_slot, uri, type_uri, name)); } + void new_plugin(const string& uri, const string& type_uri, const string& symbol, const string& name) + { push_sig(sigc::bind(new_plugin_slot, uri, type_uri, symbol, name)); } void new_patch(const string& path, uint32_t poly) { push_sig(sigc::bind(new_patch_slot, path, poly)); } @@ -159,7 +159,7 @@ private: sigc::slot<void, int32_t> response_ok_slot; sigc::slot<void, int32_t, string> response_error_slot; sigc::slot<void, string> error_slot; - sigc::slot<void, string, string, string> new_plugin_slot; + sigc::slot<void, string, string, string, string> new_plugin_slot; sigc::slot<void, string, uint32_t> new_patch_slot; sigc::slot<void, string, string, bool, int> new_node_slot; sigc::slot<void, string, string, bool> new_port_slot; diff --git a/src/libs/engine/ClientBroadcaster.cpp b/src/libs/engine/ClientBroadcaster.cpp index 67cf8dd9..16785b42 100644 --- a/src/libs/engine/ClientBroadcaster.cpp +++ b/src/libs/engine/ClientBroadcaster.cpp @@ -106,7 +106,7 @@ ClientBroadcaster::send_plugins_to(ClientInterface* client, const NodeFactory::P 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()); + client->new_plugin(plugin->uri(), plugin->type_uri(), plugin->symbol(), plugin->name()); } client->transfer_end(); diff --git a/src/libs/engine/Engine.hpp b/src/libs/engine/Engine.hpp index ca8f4f78..9bc43ec8 100644 --- a/src/libs/engine/Engine.hpp +++ b/src/libs/engine/Engine.hpp @@ -37,7 +37,6 @@ class MidiDriver; class OSCDriver; class NodeFactory; class ClientBroadcaster; -class PatchImpl; class ObjectStore; class EventSource; class PostProcessor; diff --git a/src/libs/engine/InternalPlugin.cpp b/src/libs/engine/InternalPlugin.cpp new file mode 100644 index 00000000..a068123d --- /dev/null +++ b/src/libs/engine/InternalPlugin.cpp @@ -0,0 +1,66 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <cassert> +#include "InternalPlugin.hpp" +#include "MidiNoteNode.hpp" +#include "MidiTriggerNode.hpp" +#include "MidiControlNode.hpp" +#include "TransportNode.hpp" + +namespace Ingen { + + +#if 0 +InternalPlugin::InternalPlugin(const InternalPlugin* const copy) +{ + _type = copy->_type; + _uri = copy->_uri; + _lib_path = copy->_lib_path; + _lib_name = copy->_lib_name; + _plug_label = copy->_plug_label; + _name = copy->_name; + _id = _id; + _module = copy->_module; +} +#endif + + +NodeImpl* +InternalPlugin::instantiate(const string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size) +{ + assert(_type == Internal); + + if (_uri == "ingen:note_node") { + return new MidiNoteNode(name, polyphonic, parent, srate, buffer_size); + } else if (_uri == "ingen:trigger_node") { + return new MidiTriggerNode(name, polyphonic, parent, srate, buffer_size); + } else if (_uri == "ingen:control_node") { + return new MidiControlNode(name, polyphonic, parent, srate, buffer_size); + } else if (_uri == "ingen:transport_node") { + return new TransportNode(name, polyphonic, parent, srate, buffer_size); + } else { + return NULL; + } +} + + +} // namespace Ingen diff --git a/src/libs/engine/InternalPlugin.hpp b/src/libs/engine/InternalPlugin.hpp new file mode 100644 index 00000000..6f1f6023 --- /dev/null +++ b/src/libs/engine/InternalPlugin.hpp @@ -0,0 +1,75 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INTERNALPLUGIN_H +#define INTERNALPLUGIN_H + +#include CONFIG_H_PATH + +#ifndef HAVE_SLV2 +#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." +#endif + +#include <cstdlib> +#include <glibmm/module.h> +#include <boost/utility.hpp> +#include <dlfcn.h> +#include <string> +#include <iostream> +#include <slv2/slv2.h> +#include "types.hpp" +#include "PluginImpl.hpp" + +namespace Ingen { + +class NodeImpl; + + +/** Implementation of an Internal plugin. + */ +class InternalPlugin : public PluginImpl +{ +public: + InternalPlugin(const std::string& uri, + const std::string& symbol, + const std::string& name) + : PluginImpl(Plugin::Internal, uri) + , _symbol(symbol) + , _name(name) + {} + + //InternalPlugin(const InternalPlugin* const copy); + + NodeImpl* instantiate(const std::string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size); + + const string symbol() const { return _symbol; } + const string name() const { return _name; } + +private: + const string _symbol; + const string _name; +}; + + +} // namespace Ingen + +#endif // INTERNALPLUGIN_H + diff --git a/src/libs/engine/LADSPANode.cpp b/src/libs/engine/LADSPANode.cpp index 24661a3d..71e40c9d 100644 --- a/src/libs/engine/LADSPANode.cpp +++ b/src/libs/engine/LADSPANode.cpp @@ -154,9 +154,9 @@ LADSPANode::instantiate() port_name[slash_index] = '-'; } - if (_descriptor->PortNames[j] != port_name) + /*if (_descriptor->PortNames[j] != port_name) cerr << "NOTICE: Translated LADSPA port name: " << - _descriptor->PortNames[j] << " -> " << port_name << endl; + _descriptor->PortNames[j] << " -> " << port_name << endl;*/ port_path = path() + "/" + port_name; diff --git a/src/libs/engine/LADSPAPlugin.cpp b/src/libs/engine/LADSPAPlugin.cpp new file mode 100644 index 00000000..a43baa9a --- /dev/null +++ b/src/libs/engine/LADSPAPlugin.cpp @@ -0,0 +1,75 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <cassert> +#include <ladspa.h> +#include <iostream> +#include "LADSPAPlugin.hpp" +#include "LADSPANode.hpp" +#include "NodeImpl.hpp" + +using namespace std; + +namespace Ingen { + + +NodeImpl* +LADSPAPlugin::instantiate(const string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size) +{ + assert(_id != 0); + + LADSPA_Descriptor_Function df = NULL; + LADSPANode* n = NULL; + + load(); // FIXME: unload at some point + assert(_module); + assert(*_module); + + if (!_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 library + LADSPA_Descriptor* descriptor = NULL; + for (unsigned long i=0; (descriptor = (LADSPA_Descriptor*)df(i)) != NULL; ++i) { + if (descriptor->UniqueID == _id) { + break; + } + } + + if (descriptor != NULL) { + n = new LADSPANode(this, name, polyphonic, parent, descriptor, srate, buffer_size); + + if ( ! n->instantiate() ) { + delete n; + n = NULL; + } + + } else { + cerr << "Could not find plugin \"" << _id << "\" in " << _library_path << endl; + } + + return n; +} + + +} // namespace Ingen diff --git a/src/libs/engine/LADSPAPlugin.hpp b/src/libs/engine/LADSPAPlugin.hpp new file mode 100644 index 00000000..59a6972b --- /dev/null +++ b/src/libs/engine/LADSPAPlugin.hpp @@ -0,0 +1,79 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LADSPAPLUGIN_H +#define LADSPAPLUGIN_H + +#include CONFIG_H_PATH + +#include <cstdlib> +#include <glibmm/module.h> +#include <boost/utility.hpp> +#include <dlfcn.h> +#include <string> +#include <iostream> +#include <raul/Path.hpp> +#include "types.hpp" +#include "PluginImpl.hpp" + +namespace Ingen { + +class NodeImpl; + + +/** Implementation of a LADSPA plugin (loaded shared library). + */ +class LADSPAPlugin : public PluginImpl +{ +public: + LADSPAPlugin(const std::string& library_path, + const std::string& uri, + unsigned long id, + const string& label, + const string& name) + : PluginImpl(Plugin::LADSPA, uri, library_path) + , _id(id) + , _label(label) + , _name(name) + {} + + NodeImpl* instantiate(const std::string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size); + + const std::string& label() const { return _label; } + unsigned long id() const { return _id; } + const string symbol() const { return Raul::Path::nameify(_label); } + const string name() const { return _name; } + + const string library_name() const { + return _library_path.substr(_library_path.find_last_of("/")+1); + } + +private: + const unsigned long _id; + const std::string _label; + const std::string _name; +}; + + +} // namespace Ingen + +#endif // LADSPAPLUGIN_H + diff --git a/src/libs/engine/LV2Node.cpp b/src/libs/engine/LV2Node.cpp index d901176f..13b842de 100644 --- a/src/libs/engine/LV2Node.cpp +++ b/src/libs/engine/LV2Node.cpp @@ -21,13 +21,13 @@ #include <stdint.h> #include <cmath> #include <raul/Maid.hpp> -#include "LV2Node.hpp" -#include "InputPort.hpp" -#include "OutputPort.hpp" -#include "PluginImpl.hpp" #include "AudioBuffer.hpp" +#include "InputPort.hpp" +#include "LV2Node.hpp" +#include "LV2Plugin.hpp" #include "MidiBuffer.hpp" #include "OSCBuffer.hpp" +#include "OutputPort.hpp" #include "ProcessContext.hpp" using namespace std; @@ -40,7 +40,7 @@ namespace Ingen { * Object is not usable until instantiate() is called with success. * (It _will_ crash!) */ -LV2Node::LV2Node(PluginImpl* plugin, +LV2Node::LV2Node(LV2Plugin* plugin, const string& name, bool polyphonic, PatchImpl* parent, diff --git a/src/libs/engine/LV2Node.hpp b/src/libs/engine/LV2Node.hpp index b0257bb8..4be1571d 100644 --- a/src/libs/engine/LV2Node.hpp +++ b/src/libs/engine/LV2Node.hpp @@ -22,10 +22,11 @@ #include <slv2/slv2.h> #include "types.hpp" #include "NodeBase.hpp" -#include "PluginImpl.hpp" namespace Ingen { +class LV2Plugin; + /** An instance of a LV2 plugin. * @@ -34,7 +35,7 @@ namespace Ingen { class LV2Node : public NodeBase { public: - LV2Node(PluginImpl* plugin, + LV2Node(LV2Plugin* plugin, const string& name, bool polyphonic, PatchImpl* parent, diff --git a/src/libs/engine/LV2Plugin.cpp b/src/libs/engine/LV2Plugin.cpp new file mode 100644 index 00000000..aaf6da61 --- /dev/null +++ b/src/libs/engine/LV2Plugin.cpp @@ -0,0 +1,74 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <cassert> +#include "LV2Plugin.hpp" +#include "LV2Node.hpp" +#include "NodeImpl.hpp" + +namespace Ingen { + + +const string +LV2Plugin::symbol() const +{ + string working = _uri; + if (working[working.length()-1] == '/') + working = working.substr(0, working.length()-1); + + while (working.length() > 0) { + size_t last_slash = working.find_last_of("/"); + const string symbol = working.substr(last_slash+1); + if ( (symbol[0] >= 'a' && symbol[0] <= 'z') + || (symbol[0] >= 'A' && symbol[0] <= 'Z') ) + return Path::nameify(symbol); + else + working = working.substr(0, last_slash); + } + + return "lv2_symbol"; +} + + +const string +LV2Plugin::name() const +{ + return slv2_plugin_get_name(_slv2_plugin); +} + + +NodeImpl* +LV2Plugin::instantiate(const string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size) +{ + load(); // FIXME: unload at some point + + LV2Node* n = new LV2Node(this, name, polyphonic, parent, srate, buffer_size); + + if ( ! n->instantiate() ) { + delete n; + n = NULL; + } + + return n; +} + + +} // namespace Ingen diff --git a/src/libs/engine/LV2Plugin.hpp b/src/libs/engine/LV2Plugin.hpp new file mode 100644 index 00000000..19f11732 --- /dev/null +++ b/src/libs/engine/LV2Plugin.hpp @@ -0,0 +1,76 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LV2PLUGIN_H +#define LV2PLUGIN_H + +#include CONFIG_H_PATH + +#ifndef HAVE_SLV2 +#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." +#endif + +#include <cstdlib> +#include <glibmm/module.h> +#include <boost/utility.hpp> +#include <dlfcn.h> +#include <string> +#include <iostream> +#include <slv2/slv2.h> +#include "types.hpp" +#include "PluginImpl.hpp" + +using std::string; +using Ingen::Shared::Plugin; + + +namespace Ingen { + +class PatchImpl; +class NodeImpl; + + +/** Implementation of an LV2 plugin (loaded shared library). + */ +class LV2Plugin : public PluginImpl +{ +public: + LV2Plugin(const string& uri) + : PluginImpl(Plugin::LV2, uri) + {} + + NodeImpl* instantiate(const string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size); + + const string symbol() const; + const string name() const; + + SLV2Plugin slv2_plugin() const { return _slv2_plugin; } + void slv2_plugin(SLV2Plugin p) { _slv2_plugin = p; } + +private: + SLV2Plugin _slv2_plugin; +}; + + +} // namespace Ingen + +#endif // LV2PLUGIN_H + diff --git a/src/libs/engine/Makefile.am b/src/libs/engine/Makefile.am index 91af96fc..bbc621ae 100644 --- a/src/libs/engine/Makefile.am +++ b/src/libs/engine/Makefile.am @@ -29,9 +29,9 @@ libingen_engine_la_SOURCES = \ BufferFactory.hpp \ ClientBroadcaster.cpp \ ClientBroadcaster.hpp \ + CompiledPatch.hpp \ ConnectionImpl.cpp \ ConnectionImpl.hpp \ - CompiledPatch.hpp \ Driver.hpp \ DuplexPort.cpp \ DuplexPort.hpp \ @@ -46,10 +46,16 @@ libingen_engine_la_SOURCES = \ GraphObjectImpl.hpp \ InputPort.cpp \ InputPort.hpp \ + InternalPlugin.cpp \ + InternalPlugin.hpp \ JackAudioDriver.cpp \ JackAudioDriver.hpp \ JackMidiDriver.cpp \ JackMidiDriver.hpp \ + LADSPAPlugin.cpp \ + LADSPAPlugin.hpp \ + LV2Plugin.cpp \ + LV2Plugin.hpp \ MidiBuffer.cpp \ MidiBuffer.hpp \ MidiControlNode.cpp \ @@ -71,7 +77,6 @@ libingen_engine_la_SOURCES = \ OSCDriver.hpp \ OSCEngineReceiver.cpp \ OSCEngineReceiver.hpp \ - Responder.hpp \ ObjectSender.cpp \ ObjectSender.hpp \ ObjectStore.cpp \ @@ -80,22 +85,24 @@ libingen_engine_la_SOURCES = \ OutputPort.hpp \ PatchImpl.cpp \ PatchImpl.hpp \ + PatchPlugin.hpp \ PluginImpl.cpp \ PluginImpl.hpp \ PortImpl.cpp \ PortImpl.hpp \ PostProcessor.cpp \ PostProcessor.hpp \ - ProcessContext.hpp \ ProcessContext.cpp \ - ProcessSlave.hpp \ + ProcessContext.hpp \ ProcessSlave.cpp \ + ProcessSlave.hpp \ QueuedEngineInterface.cpp \ QueuedEngineInterface.hpp \ QueuedEvent.cpp \ QueuedEvent.hpp \ QueuedEventSource.cpp \ QueuedEventSource.hpp \ + Responder.hpp \ ThreadManager.hpp \ TransportNode.cpp \ TransportNode.hpp \ diff --git a/src/libs/engine/MidiControlNode.cpp b/src/libs/engine/MidiControlNode.cpp index 250607b0..2d98b2b0 100644 --- a/src/libs/engine/MidiControlNode.cpp +++ b/src/libs/engine/MidiControlNode.cpp @@ -22,7 +22,7 @@ #include "MidiLearnEvent.hpp" #include "InputPort.hpp" #include "OutputPort.hpp" -#include "PluginImpl.hpp" +#include "InternalPlugin.hpp" #include "AudioBuffer.hpp" #include "ProcessContext.hpp" #include "util.hpp" @@ -30,44 +30,44 @@ namespace Ingen { -MidiControlNode::MidiControlNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) -: NodeBase(new PluginImpl(Plugin::Internal, "ingen:control_node"), path, false, parent, srate, buffer_size), - _learning(false) +MidiControlNode::MidiControlNode(const string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate, + size_t buffer_size) + : NodeBase(new InternalPlugin("ingen:control_node", "controller", "MIDI Controller") + , path, false, parent, srate, buffer_size) + , _learning(false) { _ports = new Raul::Array<PortImpl*>(7); - _midi_in_port = new InputPort(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size); + _midi_in_port = new InputPort(this, "input", 0, 1, DataType::MIDI, _buffer_size); _ports->at(0) = _midi_in_port; - _param_port = new InputPort(this, "ControllerNumber", 1, 1, DataType::CONTROL, 1); + _param_port = new InputPort(this, "controller", 1, 1, DataType::CONTROL, 1); _param_port->set_variable("ingen:minimum", 0.0f); _param_port->set_variable("ingen:maximum", 127.0f); _param_port->set_variable("ingen:default", 0.0f); _param_port->set_variable("ingen:integer", 1); _ports->at(1) = _param_port; - _log_port = new InputPort(this, "Logarithmic", 2, 1, DataType::CONTROL, 1); + _log_port = new InputPort(this, "logarithmic", 2, 1, DataType::CONTROL, 1); _log_port->set_variable("ingen:toggled", 1); _log_port->set_variable("ingen:default", 0.0f); _ports->at(2) = _log_port; - _min_port = new InputPort(this, "Min", 3, 1, DataType::CONTROL, 1); + _min_port = new InputPort(this, "minimum", 3, 1, DataType::CONTROL, 1); _min_port->set_variable("ingen:default", 0.0f); _ports->at(3) = _min_port; - _max_port = new InputPort(this, "Max", 4, 1, DataType::CONTROL, 1); + _max_port = new InputPort(this, "maximum", 4, 1, DataType::CONTROL, 1); _ports->at(4) = _max_port; - _audio_port = new OutputPort(this, "Out(AR)", 5, 1, DataType::AUDIO, _buffer_size); + _audio_port = new OutputPort(this, "ar_output", 5, 1, DataType::AUDIO, _buffer_size); _ports->at(5) = _audio_port; - _control_port = new OutputPort(this, "Out(CR)", 6, 1, DataType::CONTROL, 1); + _control_port = new OutputPort(this, "cr_output", 6, 1, DataType::CONTROL, 1); _ports->at(6) = _control_port; - - PluginImpl* p = const_cast<PluginImpl*>(_plugin); - p->plug_label("midi_control_in"); - assert(p->uri() == "ingen:control_node"); - p->name("Ingen Control Node (MIDI)"); } diff --git a/src/libs/engine/MidiNoteNode.cpp b/src/libs/engine/MidiNoteNode.cpp index 128b7a13..962043b5 100644 --- a/src/libs/engine/MidiNoteNode.cpp +++ b/src/libs/engine/MidiNoteNode.cpp @@ -20,56 +20,51 @@ #include <raul/midi_events.h> #include <cmath> #include <iostream> -#include "MidiNoteNode.hpp" -#include "MidiBuffer.hpp" #include "AudioBuffer.hpp" +#include "AudioDriver.hpp" #include "InputPort.hpp" +#include "InternalPlugin.hpp" +#include "MidiBuffer.hpp" +#include "MidiNoteNode.hpp" #include "OutputPort.hpp" -#include "PluginImpl.hpp" -#include "AudioDriver.hpp" #include "PatchImpl.hpp" #include "ProcessContext.hpp" #include "util.hpp" -using std::cerr; using std::cout; using std::endl; - +using namespace std; namespace Ingen { MidiNoteNode::MidiNoteNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) -: NodeBase(new PluginImpl(Plugin::Internal, "ingen:note_node"), path, polyphonic, parent, srate, buffer_size), - _voices(new Raul::Array<Voice>(_polyphony)), - _prepared_voices(NULL), - _sustain(false) + : NodeBase(new InternalPlugin("ingen:note_node", "note", "MIDI Note"), + path, polyphonic, parent, srate, buffer_size) + , _voices(new Raul::Array<Voice>(_polyphony)) + , _prepared_voices(NULL) + , _sustain(false) { _ports = new Raul::Array<PortImpl*>(5); - _midi_in_port = new InputPort(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size); + _midi_in_port = new InputPort(this, "input", 0, 1, DataType::MIDI, _buffer_size); _ports->at(0) = _midi_in_port; - _freq_port = new OutputPort(this, "Frequency", 1, _polyphony, DataType::AUDIO, _buffer_size); + _freq_port = new OutputPort(this, "frequency", 1, _polyphony, DataType::AUDIO, _buffer_size); _ports->at(1) = _freq_port; - _vel_port = new OutputPort(this, "Velocity", 2, _polyphony, DataType::AUDIO, _buffer_size); + _vel_port = new OutputPort(this, "velocity", 2, _polyphony, DataType::AUDIO, _buffer_size); _vel_port->set_variable("ingen:minimum", 0.0f); _vel_port->set_variable("ingen:maximum", 1.0f); _ports->at(2) = _vel_port; - _gate_port = new OutputPort(this, "Gate", 3, _polyphony, DataType::AUDIO, _buffer_size); + _gate_port = new OutputPort(this, "gate", 3, _polyphony, DataType::AUDIO, _buffer_size); _gate_port->set_variable("ingen:toggled", 1); _gate_port->set_variable("ingen:default", 0.0f); _ports->at(3) = _gate_port; - _trig_port = new OutputPort(this, "Trigger", 4, _polyphony, DataType::AUDIO, _buffer_size); + _trig_port = new OutputPort(this, "trigger", 4, _polyphony, DataType::AUDIO, _buffer_size); _trig_port->set_variable("ingen:toggled", 1); _trig_port->set_variable("ingen:default", 0.0f); _ports->at(4) = _trig_port; - - PluginImpl* p = const_cast<PluginImpl*>(_plugin); - p->plug_label("note_in"); - assert(p->uri() == "ingen:note_node"); - p->name("Ingen Note Node (MIDI, OSC)"); } diff --git a/src/libs/engine/MidiTriggerNode.cpp b/src/libs/engine/MidiTriggerNode.cpp index f179d7b0..4f099a1d 100644 --- a/src/libs/engine/MidiTriggerNode.cpp +++ b/src/libs/engine/MidiTriggerNode.cpp @@ -21,7 +21,7 @@ #include "AudioBuffer.hpp" #include "InputPort.hpp" #include "OutputPort.hpp" -#include "PluginImpl.hpp" +#include "InternalPlugin.hpp" #include "ProcessContext.hpp" #include "util.hpp" @@ -29,33 +29,29 @@ namespace Ingen { MidiTriggerNode::MidiTriggerNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) -: NodeBase(new PluginImpl(Plugin::Internal, "ingen:trigger_node"), path, false, parent, srate, buffer_size) + : NodeBase(new InternalPlugin("ingen:trigger_node", "trigger", "MIDI Trigger"), + path, false, parent, srate, buffer_size) { _ports = new Raul::Array<PortImpl*>(5); - _midi_in_port = new InputPort(this, "MIDIIn", 0, 1, DataType::MIDI, _buffer_size); + _midi_in_port = new InputPort(this, "input", 0, 1, DataType::MIDI, _buffer_size); _ports->at(0) = _midi_in_port; - _note_port = new InputPort(this, "NoteNumber", 1, 1, DataType::CONTROL, 1); + _note_port = new InputPort(this, "note", 1, 1, DataType::CONTROL, 1); _note_port->set_variable("ingen:minimum", 0.0f); _note_port->set_variable("ingen:maximum", 127.0f); _note_port->set_variable("ingen:default", 60.0f); _note_port->set_variable("ingen:integer", 1); _ports->at(1) = _note_port; - _gate_port = new OutputPort(this, "Gate", 2, 1, DataType::AUDIO, _buffer_size); + _gate_port = new OutputPort(this, "gate", 2, 1, DataType::AUDIO, _buffer_size); _ports->at(2) = _gate_port; - _trig_port = new OutputPort(this, "Trigger", 3, 1, DataType::AUDIO, _buffer_size); + _trig_port = new OutputPort(this, "trigger", 3, 1, DataType::AUDIO, _buffer_size); _ports->at(3) = _trig_port; - _vel_port = new OutputPort(this, "Velocity", 4, 1, DataType::AUDIO, _buffer_size); + _vel_port = new OutputPort(this, "velocity", 4, 1, DataType::AUDIO, _buffer_size); _ports->at(4) = _vel_port; - - PluginImpl* p = const_cast<PluginImpl*>(_plugin); - p->plug_label("trigger_in"); - assert(p->uri() == "ingen:trigger_node"); - p->name("Ingen Trigger Node (MIDI, OSC)"); } diff --git a/src/libs/engine/NodeFactory.cpp b/src/libs/engine/NodeFactory.cpp index 76f3e5fd..8312a221 100644 --- a/src/libs/engine/NodeFactory.cpp +++ b/src/libs/engine/NodeFactory.cpp @@ -28,14 +28,16 @@ #include "MidiTriggerNode.hpp" #include "MidiControlNode.hpp" #include "TransportNode.hpp" -#include "PluginImpl.hpp" #include "PatchImpl.hpp" -#ifdef HAVE_SLV2 -#include "LV2Node.hpp" -#include <slv2/slv2.h> -#endif +#include "InternalPlugin.hpp" #ifdef HAVE_LADSPA #include "LADSPANode.hpp" +#include "LADSPAPlugin.hpp" +#endif +#ifdef HAVE_SLV2 +#include <slv2/slv2.h> +#include "LV2Plugin.hpp" +#include "LV2Node.hpp" #endif using namespace std; @@ -43,12 +45,6 @@ using namespace std; namespace Ingen { -/* I am perfectly aware that the vast majority of this class is a - * vomit inducing nightmare at the moment ;) - */ - - - NodeFactory::NodeFactory(Ingen::Shared::World* world) : _world(world) , _has_loaded(false) @@ -69,7 +65,7 @@ NodeFactory::~NodeFactory() PluginImpl* NodeFactory::plugin(const string& uri) { - Plugins::const_iterator i = _plugins.find(uri); + const Plugins::const_iterator i = _plugins.find(uri); return ((i != _plugins.end()) ? i->second : NULL); } @@ -81,14 +77,16 @@ NodeFactory::plugin(const string& uri) PluginImpl* NodeFactory::plugin(const string& type, const string& lib, const string& label) { - if (type == "" || lib == "" || label == "") + if (type != "LADSPA" || lib == "" || label == "") return NULL; - 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; + for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) { + LADSPAPlugin* lp = dynamic_cast<LADSPAPlugin*>(i->second); + if (lp && lp->type_string() == type + && lp->library_name() == lib + && lp->label() == label) + return lp; + } cerr << "ERROR: Failed to find " << type << " plugin " << lib << " / " << label << endl; @@ -119,48 +117,23 @@ NodeFactory::load_plugins() _has_loaded = true; } - - //cerr << "[NodeFactory] # Plugins: " << _plugins.size() << endl; -} - - -/** Loads a plugin. - * - * Calls the load_*_plugin functions to actually do things, just a wrapper. - */ -NodeImpl* -NodeFactory::load_plugin(PluginImpl* plugin, - const string& name, - bool polyphonic, - PatchImpl* parent) -{ - assert(parent != NULL); - assert(plugin); - - NodeImpl* r = NULL; - - const SampleRate srate = parent->sample_rate(); - const size_t buffer_size = parent->buffer_size(); - - switch (plugin->type()) { -#ifdef HAVE_SLV2 - case Plugin::LV2: - r = load_lv2_plugin(plugin, name, polyphonic, parent, srate, buffer_size); - break; -#endif -#ifdef HAVE_LADSPA - case Plugin::LADSPA: - r = load_ladspa_plugin(plugin, name, polyphonic, parent, srate, buffer_size); - break; -#endif - case Plugin::Internal: - r = load_internal_plugin(plugin, name, polyphonic, parent, srate, buffer_size); - break; - default: - cerr << "[NodeFactory] WARNING: Unknown plugin type." << endl; + +#if 0 + for (Plugins::const_iterator i = _plugins.begin(); i != _plugins.end(); ++i) { + assert(Path::is_valid_name(i->second->symbol())); + cerr << "PLUGIN: " << i->second->uri() << " - " << i->second->symbol() + << " (" << i->second->name() << ")" << endl; + PatchImpl* parent = new PatchImpl(*_world->local_engine, "dummy", 1, NULL, 1, 1, 1); + NodeImpl* node = i->second->instantiate("foo", 0, parent, 48000, 512); + if (node) + for (uint32_t i=0; i < node->num_ports(); ++i) { + cerr << "\t" << node->port(i)->name() << endl; + } + cerr << endl; } +#endif - return r; + //cerr << "[NodeFactory] # Plugins: " << _plugins.size() << endl; } @@ -189,28 +162,7 @@ NodeFactory::load_internal_plugins() } -/** Loads an internal plugin. - */ -NodeImpl* -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(plugin->uri().length() > 6); - assert(plugin->uri().substr(0, 6) == "ingen:"); - - return plugin->instantiate(name, polyphonic, parent, srate, buffer_size); -} - - #ifdef HAVE_SLV2 - /** Loads information about all LV2 plugins into internal plugin database. */ void @@ -230,13 +182,13 @@ NodeFactory::load_lv2_plugins() assert(_plugins.find(uri) == _plugins.end()); #endif - PluginImpl* const plugin = new PluginImpl(Plugin::LV2, uri); + LV2Plugin* const plugin = new LV2Plugin(uri); plugin->slv2_plugin(lv2_plug); - plugin->lib_path(slv2_uri_to_path(slv2_plugin_get_library_uri(lv2_plug))); + plugin->library_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); + //plugin->name(name); free(name); _plugins.insert(make_pair(uri, plugin)); } else { @@ -247,40 +199,6 @@ NodeFactory::load_lv2_plugins() slv2_plugins_free(_world->slv2_world, plugins); } - - -/** Loads a LV2 plugin. - * Returns 'poly' independant plugins as a NodeImpl* - */ -NodeImpl* -NodeFactory::load_lv2_plugin(PluginImpl* plugin, - const string& node_name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate, - size_t buffer_size) -{ - assert(plugin); - assert(plugin->type() == Plugin::LV2); - - NodeImpl* 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; -} - #endif // HAVE_SLV2 @@ -354,20 +272,16 @@ NodeFactory::load_ladspa_plugins() const Plugins::const_iterator i = _plugins.find(uri); 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); + LADSPAPlugin* plugin = new LADSPAPlugin(lib_path, uri, + descriptor->UniqueID, + descriptor->Label, + descriptor->Name); _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; + cerr << "\tUsing " << i->second->library_path() << " over " << lib_path << endl; } } @@ -376,61 +290,6 @@ NodeFactory::load_ladspa_plugins() closedir(pdir); } } - - -/** Loads a LADSPA plugin. - * Returns 'poly' independant plugins as a NodeImpl* - */ -NodeImpl* -NodeFactory::load_ladspa_plugin(PluginImpl* plugin, - const string& name, - bool polyphonic, - PatchImpl* parent, - SampleRate srate, - size_t buffer_size) -{ - assert(plugin); - assert(plugin->type() == Plugin::LADSPA); - assert(plugin->id() != 0); - assert(name != ""); - - LADSPA_Descriptor_Function df = NULL; - NodeImpl* n = NULL; - - 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; - } - - // 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 LADSPANode(plugin, name, polyphonic, parent, descriptor, srate, buffer_size); - - bool success = ((LADSPANode*)n)->instantiate(); - if (!success) { - delete n; - n = NULL; - } - - return n; -} - - #endif // HAVE_LADSPA diff --git a/src/libs/engine/NodeFactory.hpp b/src/libs/engine/NodeFactory.hpp index 6eceb0ee..016839e9 100644 --- a/src/libs/engine/NodeFactory.hpp +++ b/src/libs/engine/NodeFactory.hpp @@ -24,7 +24,6 @@ #include <list> #include <map> #include <string> -#include <ladspa.h> #include <pthread.h> #include <glibmm/module.h> #ifdef HAVE_SLV2 @@ -57,8 +56,7 @@ public: NodeFactory(Ingen::Shared::World* world); ~NodeFactory(); - void load_plugins(); - NodeImpl* load_plugin(PluginImpl* info, const string& name, bool polyphonic, PatchImpl* parent); + void load_plugins(); typedef std::map<std::string,PluginImpl*> Plugins; const Plugins& plugins() const { return _plugins; } @@ -71,16 +69,13 @@ public: private: #ifdef HAVE_LADSPA void load_ladspa_plugins(); - 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(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); #endif void load_internal_plugins(); - NodeImpl* load_internal_plugin(PluginImpl* plugin, const string& name, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size); Plugins _plugins; diff --git a/src/libs/engine/OSCClientSender.cpp b/src/libs/engine/OSCClientSender.cpp index 365efeea..95bf520e 100644 --- a/src/libs/engine/OSCClientSender.cpp +++ b/src/libs/engine/OSCClientSender.cpp @@ -472,12 +472,16 @@ OSCClientSender::port_activity(const std::string& port_path) /** \page client_osc_namespace * <p> \b /ingen/plugin - Notification of the existance of a plugin - * \arg \b type (string) - Type of plugin ("LADSPA", "LV2", or "Internal") - * \arg \b uri (string) - Type of plugin ("LADSPA", "LV2", or "Internal") - * \arg \b name (string) - Descriptive human-readable name of plugin (ie "ADSR Envelope") + * \arg \b uri (string) - URI of plugin (e.g. http://example.org/filtermatic) + * \arg \b type (string) - Type of plugin (e.g. "ingen:LV2Plugin") + * \arg \b symbol (string) - Valid symbol for plugin (default symbol for nodes) (e.g. "adsr") + * \arg \b name (string) - Descriptive human-readable name of plugin (e.g. "ADSR Envelope") */ void -OSCClientSender::new_plugin(const std::string& uri, const std::string& type_uri, const std::string& name) +OSCClientSender::new_plugin(const std::string& uri, + const std::string& type_uri, + const std::string& symbol, + const std::string& name) { if (!_enabled) return; @@ -489,6 +493,7 @@ OSCClientSender::new_plugin(const std::string& uri, const std::string& type_uri, lo_message m = lo_message_new(); lo_message_add_string(m, uri.c_str()); lo_message_add_string(m, type_uri.c_str()); + lo_message_add_string(m, symbol.c_str()); lo_message_add_string(m, name.c_str()); if (_transfer) { diff --git a/src/libs/engine/OSCClientSender.hpp b/src/libs/engine/OSCClientSender.hpp index 5388140d..ec513b2e 100644 --- a/src/libs/engine/OSCClientSender.hpp +++ b/src/libs/engine/OSCClientSender.hpp @@ -77,6 +77,7 @@ public: virtual void new_plugin(const std::string& uri, const std::string& type_uri, + const std::string& symbol, const std::string& name); virtual void new_patch(const std::string& path, uint32_t poly); diff --git a/src/libs/engine/PatchImpl.cpp b/src/libs/engine/PatchImpl.cpp index 7c4e0a65..360b3838 100644 --- a/src/libs/engine/PatchImpl.cpp +++ b/src/libs/engine/PatchImpl.cpp @@ -21,7 +21,7 @@ #include "ThreadManager.hpp" #include "NodeImpl.hpp" #include "PatchImpl.hpp" -#include "PluginImpl.hpp" +#include "PatchPlugin.hpp" #include "PortImpl.hpp" #include "ConnectionImpl.hpp" #include "DuplexPort.hpp" @@ -34,19 +34,14 @@ namespace Ingen { PatchImpl::PatchImpl(Engine& engine, const string& path, uint32_t poly, PatchImpl* parent, SampleRate srate, size_t buffer_size, uint32_t internal_poly) -: NodeBase(new PluginImpl(Plugin::Patch, "ingen:patch"), path, poly, parent, srate, buffer_size), +: NodeBase(new PatchPlugin("http://example.org/FIXME", "patch", "Ingen Patch"), + path, poly, parent, srate, buffer_size), _engine(engine), _internal_poly(internal_poly), _compiled_patch(NULL), _process(false) { assert(internal_poly >= 1); - - //_plugin->plug_label("om_patch"); - //_plugin->name("Ingen Patch"); - - //std::cerr << "Creating patch " << _name << ", poly = " << poly - // << ", internal poly = " << internal_poly << std::endl; } diff --git a/src/libs/engine/PatchPlugin.hpp b/src/libs/engine/PatchPlugin.hpp new file mode 100644 index 00000000..3c2272eb --- /dev/null +++ b/src/libs/engine/PatchPlugin.hpp @@ -0,0 +1,78 @@ +/* This file is part of Ingen. + * Copyright (C) 2007 Dave Robillard <http://drobilla.net> + * + * Ingen 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. + * + * Ingen 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., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef INTERNALPLUGIN_H +#define INTERNALPLUGIN_H + +#include CONFIG_H_PATH + +#ifndef HAVE_SLV2 +#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." +#endif + +#include <cstdlib> +#include <glibmm/module.h> +#include <boost/utility.hpp> +#include <dlfcn.h> +#include <string> +#include <iostream> +#include <slv2/slv2.h> +#include "types.hpp" +#include "PluginImpl.hpp" + +namespace Ingen { + +class NodeImpl; + + +/** Implementation of a Patch plugin. + * + * Patches don't actually work like this yet... + */ +class PatchPlugin : public PluginImpl +{ +public: + PatchPlugin(const std::string& uri, + const std::string& symbol, + const std::string& name) + : PluginImpl(Plugin::Patch, uri) + {} + + //PatchPlugin(const PatchPlugin* const copy); + + NodeImpl* instantiate(const std::string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size) + { + return NULL; + } + + const string symbol() const { return "patch"; } + const string name() const { return "Ingen Patch"; } + +private: + const string _symbol; + const string _name; +}; + + +} // namespace Ingen + +#endif // INTERNALPLUGIN_H + diff --git a/src/libs/engine/PluginImpl.cpp b/src/libs/engine/PluginImpl.cpp index dfff1031..709f18bd 100644 --- a/src/libs/engine/PluginImpl.cpp +++ b/src/libs/engine/PluginImpl.cpp @@ -31,8 +31,8 @@ void PluginImpl::load() { if (!_module) { - cerr << "Loading " << _lib_path << endl; - _module = new Glib::Module(_lib_path, Glib::MODULE_BIND_LOCAL); + cerr << "Loading " << _library_path << " library" << endl; + _module = new Glib::Module(_library_path, Glib::MODULE_BIND_LOCAL); if (!(*_module)) delete _module; } @@ -43,30 +43,12 @@ void PluginImpl::unload() { if (_module) { - cerr << "Unloading " << _lib_path << endl; + cerr << "Unloading " << _library_path << endl; delete _module; _module = NULL; } } -NodeImpl* -PluginImpl::instantiate(const string& name, bool polyphonic, Ingen::PatchImpl* parent, SampleRate srate, size_t buffer_size) -{ - assert(_type == Internal); - - if (_uri == "ingen:note_node") { - return new MidiNoteNode(name, polyphonic, parent, srate, buffer_size); - } else if (_uri == "ingen:trigger_node") { - return new MidiTriggerNode(name, polyphonic, parent, srate, buffer_size); - } else if (_uri == "ingen:control_node") { - return new MidiControlNode(name, polyphonic, parent, srate, buffer_size); - } else if (_uri == "ingen:transport_node") { - return new TransportNode(name, polyphonic, parent, srate, buffer_size); - } else { - return NULL; - } -} - - } // namespace Ingen + diff --git a/src/libs/engine/PluginImpl.hpp b/src/libs/engine/PluginImpl.hpp index 83814dc8..9ad16ee3 100644 --- a/src/libs/engine/PluginImpl.hpp +++ b/src/libs/engine/PluginImpl.hpp @@ -26,11 +26,9 @@ #include <dlfcn.h> #include <string> #include <iostream> -#ifdef HAVE_SLV2 -#include <slv2/slv2.h> -#endif #include "types.hpp" #include "interface/Plugin.hpp" + using std::string; using Ingen::Shared::Plugin; @@ -40,57 +38,34 @@ class PatchImpl; class NodeImpl; -/** Representation of a plugin (of various types). +/** Implementation of a plugin (internal code, or a loaded shared library). * - * A Node is an instance of this, conceptually. - * FIXME: This whole thing is a filthy mess and needs a rewrite. Probably - * with derived classes for each plugin type. + * Conceptually, a Node is an instance of this. */ class PluginImpl : public Ingen::Shared::Plugin, public boost::noncopyable { public: - PluginImpl(Type type, const string& uri) - : _type(type) - , _uri(uri) - , _id(0) - , _module(NULL) -#ifdef HAVE_SLV2 - , _slv2_plugin(NULL) -#endif + PluginImpl(Type type, const string& uri, const string library_path="") + : _type(type) + , _uri(uri) + , _library_path(library_path) + , _module(NULL) {} - - PluginImpl(const PluginImpl* const copy) { - // Copying only allowed for Internal plugins. Bit of a hack, but - // allows the PluginInfo to be defined in the Node class which keeps - // things localized and convenient (FIXME?) - if (copy->_type != Internal) - exit(EXIT_FAILURE); - _type = copy->_type; - _uri = copy->_uri; - _lib_path = copy->_lib_path; - _lib_name = copy->_lib_name; - _plug_label = copy->_plug_label; - _name = copy->_name; - _id = _id; - _module = copy->_module; - } - Plugin::Type type() const { return _type; } - void type(Plugin::Type t) { _type = t; } - const string& lib_path() const { return _lib_path; } - void lib_path(const string& s) { _lib_path = s; _lib_name = _lib_path.substr(_lib_path.find_last_of("/")+1); } - string lib_name() const { return _lib_name; } - void lib_name(const string& s) { _lib_name = s; } - const string& plug_label() const { return _plug_label; } - void plug_label(const string& s) { _plug_label = s; } - const string& name() const { return _name; } - void name(const string& s) { _name = s; } - unsigned long id() const { return _id; } - void id(unsigned long i) { _id = i; } - const string& uri() const { return _uri; } - void uri(const string& s) { _uri = s; } - Glib::Module* module() const { return _module; } - void module(Glib::Module* module) { _module = module; } + virtual NodeImpl* instantiate(const std::string& name, + bool polyphonic, + Ingen::PatchImpl* parent, + SampleRate srate, + size_t buffer_size) = 0; + + virtual const string symbol() const = 0; + virtual const string name() const = 0; + + const std::string& library_path() const { return _library_path; } + void library_path(const std::string& s) { _library_path = s;} + + void load(); + void unload(); const char* type_string() const { if (_type == LADSPA) return "LADSPA"; @@ -100,42 +75,28 @@ public: else return ""; } - string type_uri() const { - return string("ingen:") + type_string(); + const string type_uri() const { + return string("ingen:").append(type_string()); } void set_type(const string& type_string) { - if (type_string == "LADSPA") _type = LADSPA; - else if (type_string == "LV2") _type = LV2; + if (type_string == "LADSPA") _type = LADSPA; + else if (type_string == "LV2") _type = LV2; else if (type_string == "Internal") _type = Internal; - else if (type_string == "Patch") _type = Patch; + else if (type_string == "Patch") _type = Patch; } - // FIXME: ew -#ifdef HAVE_SLV2 - SLV2Plugin slv2_plugin() const { return _slv2_plugin; } - 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); + Plugin::Type type() const { return _type; } + void type(Plugin::Type t) { _type = t; } + const string& uri() const { return _uri; } + Glib::Module* module() const { return _module; } + void module(Glib::Module* module) { _module = module; } -private: +protected: Plugin::Type _type; - string _uri; ///< LV2 only - string _lib_path; ///< LADSPA only - string _lib_name; ///< LADSPA only - string _plug_label; ///< LADSPA only - string _name; ///< LADSPA only - unsigned long _id; ///< LADSPA only - + const string _uri; + string _library_path; Glib::Module* _module; - -#ifdef HAVE_SLV2 - SLV2Plugin _slv2_plugin; -#endif }; diff --git a/src/libs/engine/TransportNode.cpp b/src/libs/engine/TransportNode.cpp index 6a9fa73d..e65719df 100644 --- a/src/libs/engine/TransportNode.cpp +++ b/src/libs/engine/TransportNode.cpp @@ -18,7 +18,7 @@ #include "TransportNode.hpp" #include <jack/transport.h> #include "OutputPort.hpp" -#include "PluginImpl.hpp" +#include "InternalPlugin.hpp" #include "JackAudioDriver.hpp" #include "PortImpl.hpp" #include "util.hpp" @@ -28,7 +28,8 @@ namespace Ingen { TransportNode::TransportNode(const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate, size_t buffer_size) -: NodeBase(new PluginImpl(Plugin::Internal, "ingen:transport_node"), path, false, parent, srate, buffer_size) +: NodeBase(new InternalPlugin("ingen:transport_node", "transport", "Transport Follower"), + path, false, parent, srate, buffer_size) { #if 0 _num_ports = 10; @@ -74,10 +75,6 @@ TransportNode::TransportNode(const string& path, bool polyphonic, PatchImpl* par // new PortInfo("Bar Tick", AUDIO, OUTPUT, 0, 0, 1), buffer_size); _ports.at(9) = bar_trig_port; #endif - PluginImpl* p = const_cast<PluginImpl*>(_plugin); - p->plug_label("transport"); - assert(p->uri() == "ingen:transport_node"); - p->name("Ingen Transport Node (BROKEN)"); } diff --git a/src/libs/engine/events/CreateNodeEvent.cpp b/src/libs/engine/events/CreateNodeEvent.cpp index dea1024b..ab9c6eaf 100644 --- a/src/libs/engine/events/CreateNodeEvent.cpp +++ b/src/libs/engine/events/CreateNodeEvent.cpp @@ -18,6 +18,7 @@ #include <raul/Maid.hpp> #include <raul/Path.hpp> #include <raul/Path.hpp> +#include "module/World.hpp" #include "CreateNodeEvent.hpp" #include "Responder.hpp" #include "PatchImpl.hpp" @@ -29,16 +30,17 @@ #include "ClientBroadcaster.hpp" #include "ObjectStore.hpp" #include "PortImpl.hpp" +#include "AudioDriver.hpp" namespace Ingen { CreateNodeEvent::CreateNodeEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& path, - const string& plugin_uri, bool poly) + const string& plugin_uri, bool polyphonic) : QueuedEvent(engine, responder, timestamp), _path(path), _plugin_uri(plugin_uri), - _poly(poly), + _polyphonic(polyphonic), _patch(NULL), _node(NULL), _compiled_patch(NULL), @@ -52,13 +54,13 @@ CreateNodeEvent::CreateNodeEvent(Engine& engine, SharedPtr<Responder> responder, * Do not use. */ CreateNodeEvent::CreateNodeEvent(Engine& engine, SharedPtr<Responder> responder, SampleCount timestamp, const string& path, - const string& plugin_type, const string& plugin_lib, const string& plugin_label, bool poly) + const string& plugin_type, const string& plugin_lib, const string& plugin_label, bool polyphonic) : QueuedEvent(engine, responder, timestamp), _path(path), _plugin_type(plugin_type), _plugin_lib(plugin_lib), _plugin_label(plugin_label), - _poly(poly), + _polyphonic(polyphonic), _patch(NULL), _node(NULL), _compiled_patch(NULL), @@ -84,7 +86,10 @@ CreateNodeEvent::pre_process() if (_patch && plugin) { - _node = _engine.node_factory()->load_plugin(plugin, _path.name(), _poly, _patch); + Glib::Mutex::Lock lock(_engine.world()->rdf_world->mutex()); + + _node = plugin->instantiate(_path.name(), _polyphonic, _patch, + _engine.audio_driver()->sample_rate(), _engine.audio_driver()->buffer_size()); if (_node != NULL) { _node->activate(); diff --git a/src/libs/engine/events/CreateNodeEvent.hpp b/src/libs/engine/events/CreateNodeEvent.hpp index 6c3f2a94..c3ef6313 100644 --- a/src/libs/engine/events/CreateNodeEvent.hpp +++ b/src/libs/engine/events/CreateNodeEvent.hpp @@ -68,7 +68,7 @@ private: string _plugin_type; string _plugin_lib; string _plugin_label; - bool _poly; + bool _polyphonic; PatchImpl* _patch; NodeImpl* _node; CompiledPatch* _compiled_patch; ///< Patch's new process order diff --git a/src/libs/engine/events/MidiLearnEvent.cpp b/src/libs/engine/events/MidiLearnEvent.cpp index c2f2c4e5..8d5b0658 100644 --- a/src/libs/engine/events/MidiLearnEvent.cpp +++ b/src/libs/engine/events/MidiLearnEvent.cpp @@ -65,7 +65,7 @@ MidiLearnEvent::execute(ProcessContext& context) // FIXME: this isn't very good at all. if (_node != NULL && _node->plugin_impl()->type() == Plugin::Internal - && _node->plugin_impl()->plug_label() == "midi_control_in") { + && _node->plugin_impl()->uri() == "ingen:control_node") { ((MidiControlNode*)_node)->learn(_response_event); } } diff --git a/src/libs/engine/events/NoteEvent.cpp b/src/libs/engine/events/NoteEvent.cpp index fb0347af..ff96e94c 100644 --- a/src/libs/engine/events/NoteEvent.cpp +++ b/src/libs/engine/events/NoteEvent.cpp @@ -71,14 +71,14 @@ NoteEvent::execute(ProcessContext& context) if (_node != NULL && _node->plugin()->type() == Plugin::Internal) { if (_on) { - if (_node->plugin_impl()->plug_label() == "note_in") + if (_node->plugin_impl()->uri() == "ingen:note_node") ((MidiNoteNode*)_node)->note_on(_note_num, _velocity, _time, context); - else if (_node->plugin_impl()->plug_label() == "trigger_in") + else if (_node->plugin_impl()->uri() == "ingen:trigger_node") ((MidiTriggerNode*)_node)->note_on(_note_num, _velocity, _time, context); } else { - if (_node->plugin_impl()->plug_label() == "note_in") + if (_node->plugin_impl()->uri() == "ingen:note_node") ((MidiNoteNode*)_node)->note_off(_note_num, _time, context); - else if (_node->plugin_impl()->plug_label() == "trigger_in") + else if (_node->plugin_impl()->uri() == "ingen:trigger_node") ((MidiTriggerNode*)_node)->note_off(_note_num, _time, context); } } diff --git a/src/libs/engine/events/RequestPluginEvent.cpp b/src/libs/engine/events/RequestPluginEvent.cpp index 21ad97d4..1c1df99e 100644 --- a/src/libs/engine/events/RequestPluginEvent.cpp +++ b/src/libs/engine/events/RequestPluginEvent.cpp @@ -67,7 +67,7 @@ RequestPluginEvent::post_process() _responder->respond_ok(); assert(_plugin->uri() == _uri); - _responder->client()->new_plugin(_uri, _plugin->type_uri(), _plugin->name()); + _responder->client()->new_plugin(_uri, _plugin->type_uri(), _plugin->symbol(), _plugin->name()); } else { _responder->respond_error("Unable to find client to send plugin."); |