From 059f20c9666234f2be01498ee04f1e7ee795ba8f Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 6 Mar 2010 10:23:19 +0000 Subject: Save Ingen patches as working standard LV2 plugin bundles. This allows you to create an Ingen patch in Ingen running as a Jack client, save it, then load that patch as an LV2 plugin in any LV2 compliant host. Eliminate (hopefully) all static data in the engine (for multiple instantiations in a single process). More API/ABI stable interface for Ingen::Shared::World. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2533 a436a847-0d15-0410-975c-d299462d15a1 --- src/bindings/ingen_bindings.cpp | 4 +- src/client/ClientStore.cpp | 26 +-- src/client/ClientStore.hpp | 8 +- src/client/DeprecatedLoader.cpp | 58 +++--- src/client/DeprecatedLoader.hpp | 11 +- src/client/HTTPClientReceiver.cpp | 10 +- src/client/HTTPEngineSender.cpp | 4 +- src/client/HTTPEngineSender.hpp | 2 +- src/client/NodeModel.cpp | 13 +- src/client/NodeModel.hpp | 19 +- src/client/ObjectModel.cpp | 8 +- src/client/ObjectModel.hpp | 10 +- src/client/PatchModel.cpp | 6 +- src/client/PatchModel.hpp | 4 +- src/client/PluginModel.cpp | 7 +- src/client/PluginModel.hpp | 4 + src/client/PluginUI.cpp | 20 +- src/client/PortModel.cpp | 17 +- src/client/PortModel.hpp | 7 +- src/common/interface/Node.hpp | 1 - src/engine/BufferFactory.cpp | 32 ++- src/engine/BufferFactory.hpp | 9 +- src/engine/ClientBroadcaster.hpp | 1 - src/engine/ConnectionImpl.cpp | 2 +- src/engine/Context.hpp | 1 + src/engine/ControlBindings.cpp | 24 ++- src/engine/ControlBindings.hpp | 7 +- src/engine/Driver.hpp | 8 +- src/engine/DuplexPort.cpp | 2 +- src/engine/Engine.cpp | 37 ++-- src/engine/Engine.hpp | 30 ++- src/engine/EventSource.cpp | 1 - src/engine/GraphObjectImpl.cpp | 7 +- src/engine/GraphObjectImpl.hpp | 5 +- src/engine/HTTPClientSender.cpp | 6 +- src/engine/HTTPEngineReceiver.cpp | 10 +- src/engine/InputPort.cpp | 6 +- src/engine/InternalPlugin.cpp | 15 +- src/engine/InternalPlugin.hpp | 7 +- src/engine/JackDriver.cpp | 21 +- src/engine/JackDriver.hpp | 2 +- src/engine/LADSPANode.cpp | 2 +- src/engine/LADSPAPlugin.cpp | 6 +- src/engine/LADSPAPlugin.hpp | 12 +- src/engine/LV2Info.cpp | 20 +- src/engine/LV2Info.hpp | 2 +- src/engine/LV2Node.cpp | 8 +- src/engine/LV2Plugin.cpp | 7 +- src/engine/MessageContext.cpp | 6 +- src/engine/NodeFactory.cpp | 37 ++-- src/engine/NodeImpl.cpp | 2 +- src/engine/ObjectSender.cpp | 4 +- src/engine/OutputPort.cpp | 4 +- src/engine/PatchImpl.cpp | 9 +- src/engine/PatchPlugin.hpp | 10 +- src/engine/PluginImpl.hpp | 7 +- src/engine/PortImpl.cpp | 12 +- src/engine/PortImpl.hpp | 2 + src/engine/QueuedEngineInterface.cpp | 2 +- src/engine/ThreadManager.hpp | 8 +- src/engine/events/CreateNode.cpp | 4 +- src/engine/events/CreatePatch.cpp | 2 +- src/engine/events/CreatePort.cpp | 2 +- src/engine/events/Delete.cpp | 14 +- src/engine/events/Delete.hpp | 3 +- src/engine/events/RequestMetadata.cpp | 6 +- src/engine/events/SendBinding.cpp | 2 +- src/engine/events/SendPortValue.cpp | 2 +- src/engine/events/SetMetadata.cpp | 4 +- src/engine/events/SetPortValue.cpp | 12 +- src/engine/ingen_engine.cpp | 12 +- src/engine/ingen_http.cpp | 6 +- src/engine/ingen_jack.cpp | 8 +- src/engine/ingen_lv2.cpp | 369 +++++++++++++++++++++++++++------- src/engine/ingen_osc.cpp | 6 +- src/engine/internals/Controller.cpp | 21 +- src/engine/internals/Controller.hpp | 10 +- src/engine/internals/Delay.cpp | 18 +- src/engine/internals/Delay.hpp | 11 +- src/engine/internals/Note.cpp | 21 +- src/engine/internals/Note.hpp | 11 +- src/engine/internals/Trigger.cpp | 18 +- src/engine/internals/Trigger.hpp | 10 +- src/engine/wscript | 38 ++-- src/gui/App.cpp | 28 +-- src/gui/App.hpp | 12 +- src/gui/ConnectWindow.cpp | 26 +-- src/gui/LoadRemotePatchWindow.cpp | 6 +- src/gui/NodeModule.cpp | 2 +- src/gui/PatchCanvas.cpp | 7 +- src/gui/Port.cpp | 5 +- src/gui/PropertiesWindow.cpp | 5 +- src/gui/ThreadedLoader.cpp | 16 +- src/gui/ThreadedLoader.hpp | 2 +- src/ingen/main.cpp | 88 +++----- src/module/World.cpp | 141 ++++++++++++- src/module/World.hpp | 68 ++++--- src/module/ingen_module.cpp | 38 +--- src/module/ingen_module.hpp | 6 +- src/serialisation/Parser.cpp | 148 ++++++++------ src/serialisation/Parser.hpp | 13 ++ src/serialisation/Serialiser.cpp | 55 +++-- src/serialisation/serialisation.cpp | 8 +- src/shared/Builder.cpp | 7 +- src/shared/Builder.hpp | 8 +- src/shared/LV2Features.cpp | 1 - src/shared/LV2Object.cpp | 8 +- src/shared/LV2Object.hpp | 5 +- src/shared/LV2URIMap.cpp | 22 +- src/shared/LV2URIMap.hpp | 5 +- src/shared/ResourceImpl.cpp | 8 +- src/shared/ResourceImpl.hpp | 11 +- src/shared/runtime_paths.cpp | 33 ++- src/shared/runtime_paths.hpp | 2 + src/shared/wscript | 1 + 115 files changed, 1251 insertions(+), 776 deletions(-) (limited to 'src') diff --git a/src/bindings/ingen_bindings.cpp b/src/bindings/ingen_bindings.cpp index 913416c8..a16890cd 100644 --- a/src/bindings/ingen_bindings.cpp +++ b/src/bindings/ingen_bindings.cpp @@ -43,8 +43,8 @@ ingen_module_load() { void script_iteration(Ingen::Shared::World* world) { - if (world->local_engine) - world->local_engine->main_iteration(); + if (world->local_engine()) + world->local_engine()->main_iteration(); } } // extern "C" diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index fd73c4b5..82c87e1e 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -37,8 +37,10 @@ using namespace Shared; namespace Client { -ClientStore::ClientStore(SharedPtr engine, SharedPtr emitter) - : _engine(engine) +ClientStore::ClientStore(SharedPtr uris, + SharedPtr engine, SharedPtr emitter) + : _uris(uris) + , _engine(engine) , _emitter(emitter) , _plugins(new Plugins()) { @@ -257,14 +259,12 @@ ClientStore::put(const URI& uri, const Resource::Properties& properties) bool is_path = Path::is_valid(uri.str()); bool is_meta = ResourceImpl::is_meta_uri(uri); - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - if (!(is_path || is_meta)) { - const Atom& type = properties.find(uris.rdf_type)->second; + const Atom& type = properties.find(_uris->rdf_type)->second; if (type.type() == Atom::URI) { const URI& type_uri = type.get_uri(); if (Plugin::type_from_uri(type_uri) != Plugin::NIL) { - SharedPtr p(new PluginModel(uri, type_uri, properties)); + SharedPtr p(new PluginModel(uris(), uri, type_uri, properties)); add_plugin(p); return; } @@ -289,24 +289,24 @@ ClientStore::put(const URI& uri, const Resource::Properties& properties) bool is_patch, is_node, is_port, is_output; PortType data_type(PortType::UNKNOWN); - ResourceImpl::type(properties, is_patch, is_node, is_port, is_output, data_type); + ResourceImpl::type(uris(), properties, is_patch, is_node, is_port, is_output, data_type); if (is_patch) { - SharedPtr model(new PatchModel(path)); + SharedPtr model(new PatchModel(uris(), path)); model->set_properties(properties); add_object(model); } else if (is_node) { - const Resource::Properties::const_iterator p = properties.find(uris.rdf_instanceOf); + const Resource::Properties::const_iterator p = properties.find(_uris->rdf_instanceOf); SharedPtr plug; if (p->second.is_valid() && p->second.type() == Atom::URI) { if (!(plug = plugin(p->second.get_uri()))) { LOG(warn) << "Unable to find plugin " << p->second.get_uri() << endl; plug = SharedPtr( - new PluginModel(p->second.get_uri(), uris.ingen_nil, Resource::Properties())); + new PluginModel(uris(), p->second.get_uri(), _uris->ingen_nil, Resource::Properties())); add_plugin(plug); } - SharedPtr n(new NodeModel(plug, path)); + SharedPtr n(new NodeModel(uris(), plug, path)); n->set_properties(properties); add_object(n); } else { @@ -315,9 +315,9 @@ ClientStore::put(const URI& uri, const Resource::Properties& properties) } else if (is_port) { if (data_type != PortType::UNKNOWN) { PortModel::Direction pdir = is_output ? PortModel::OUTPUT : PortModel::INPUT; - const Resource::Properties::const_iterator i = properties.find(uris.lv2_index); + const Resource::Properties::const_iterator i = properties.find(_uris->lv2_index); if (i != properties.end() && i->second.type() == Atom::INT) { - SharedPtr p(new PortModel(path, i->second.get_int32(), data_type, pdir)); + SharedPtr p(new PortModel(uris(), path, i->second.get_int32(), data_type, pdir)); p->set_properties(properties); add_object(p); } else { diff --git a/src/client/ClientStore.hpp b/src/client/ClientStore.hpp index 35dabdcf..ac77e6ab 100644 --- a/src/client/ClientStore.hpp +++ b/src/client/ClientStore.hpp @@ -52,8 +52,9 @@ class ConnectionModel; */ class ClientStore : public Shared::Store, public Shared::CommonInterface, public sigc::trackable { public: - ClientStore(SharedPtr engine=SharedPtr(), - SharedPtr emitter=SharedPtr()); + ClientStore(SharedPtr uris, + SharedPtr engine=SharedPtr(), + SharedPtr emitter=SharedPtr()); SharedPtr plugin(const Raul::URI& uri); SharedPtr object(const Raul::Path& path); @@ -66,6 +67,8 @@ public: SharedPtr plugins() { return _plugins; } void set_plugins(SharedPtr p) { _plugins = p; } + Shared::LV2URIMap& uris() { return *_uris.get(); } + // CommonInterface bool new_object(const Shared::GraphObject* object); void put(const Raul::URI& path, const Shared::Resource::Properties& properties); @@ -99,6 +102,7 @@ private: bool attempt_connection(const Raul::Path& src_port_path, const Raul::Path& dst_port_path); + SharedPtr _uris; SharedPtr _engine; SharedPtr _emitter; diff --git a/src/client/DeprecatedLoader.cpp b/src/client/DeprecatedLoader.cpp index ac71a32d..a9c7f895 100644 --- a/src/client/DeprecatedLoader.cpp +++ b/src/client/DeprecatedLoader.cpp @@ -212,15 +212,13 @@ DeprecatedLoader::load_patch(const Glib::ustring& filename, size_t poly = 0; - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - /* Use parameter overridden polyphony, if given */ - GraphObject::Properties::iterator poly_param = initial_data.find(uris.ingen_polyphony); + GraphObject::Properties::iterator poly_param = initial_data.find(_uris->ingen_polyphony); if (poly_param != initial_data.end() && poly_param->second.type() == Atom::INT) poly = poly_param->second.get_int32(); - if (initial_data.find(uris.ingen_document) == initial_data.end()) - initial_data.insert(make_pair(uris.ingen_document, filename)); + if (initial_data.find(_uris->ingen_document) == initial_data.end()) + initial_data.insert(make_pair(_uris->ingen_document, filename)); xmlDocPtr doc = xmlParseFile(filename.c_str()); @@ -284,8 +282,8 @@ DeprecatedLoader::load_patch(const Glib::ustring& filename, // Create it, if we're not merging if (!existing && !path.is_root()) { Resource::Properties props; - props.insert(make_pair(uris.rdf_type, uris.ingen_Patch)); - props.insert(make_pair(uris.ingen_polyphony, Atom((int32_t)poly))); + props.insert(make_pair(_uris->rdf_type, _uris->ingen_Patch)); + props.insert(make_pair(_uris->ingen_polyphony, Atom((int32_t)poly))); _engine->put(path, props); for (GraphObject::Properties::const_iterator i = initial_data.begin(); i != initial_data.end(); ++i) _engine->set_property(path, i->first, i->second); @@ -330,7 +328,7 @@ DeprecatedLoader::load_patch(const Glib::ustring& filename, for ( ; i != pm->controls().end(); ++i) { const float value = i->value(); _engine->set_property(translate_load_path(i->port_path().str()), - uris.ingen_value, Atom(value)); + _uris->ingen_value, Atom(value)); } } else { LOG(warn) << "Unknown preset `" << pm->name() << "'" << endl; @@ -347,7 +345,7 @@ DeprecatedLoader::load_patch(const Glib::ustring& filename, // _engine->set_property(subject, i->first, i->second); if (!existing) - _engine->set_property(path, uris.ingen_enabled, (bool)true); + _engine->set_property(path, _uris->ingen_enabled, (bool)true); _load_path_translations.clear(); @@ -439,8 +437,6 @@ DeprecatedLoader::load_node(const Path& parent, xmlDocPtr doc, const xmlNodePtr return false; } - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - // Compatibility hacks for old patches that represent patch ports as nodes if (plugin_uri.empty()) { bool is_port = false; @@ -450,23 +446,23 @@ DeprecatedLoader::load_node(const Path& parent, xmlDocPtr doc, const xmlNodePtr if (plugin_type == "Internal") { is_port = true; if (plugin_label == "audio_input") { - props.insert(make_pair(uris.rdf_type, uris.lv2_AudioPort)); - props.insert(make_pair(uris.rdf_type, uris.lv2_InputPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_AudioPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_InputPort)); } else if (plugin_label == "audio_output") { - props.insert(make_pair(uris.rdf_type, uris.lv2_AudioPort)); - props.insert(make_pair(uris.rdf_type, uris.lv2_OutputPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_AudioPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_OutputPort)); } else if (plugin_label == "control_input") { - props.insert(make_pair(uris.rdf_type, uris.lv2_ControlPort)); - props.insert(make_pair(uris.rdf_type, uris.lv2_InputPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_ControlPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_InputPort)); } else if (plugin_label == "control_output" ) { - props.insert(make_pair(uris.rdf_type, uris.lv2_ControlPort)); - props.insert(make_pair(uris.rdf_type, uris.lv2_OutputPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_ControlPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_OutputPort)); } else if (plugin_label == "midi_input") { - props.insert(make_pair(uris.rdf_type, uris.lv2ev_EventPort)); - props.insert(make_pair(uris.rdf_type, uris.lv2_InputPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2ev_EventPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_InputPort)); } else if (plugin_label == "midi_output" ) { - props.insert(make_pair(uris.rdf_type, uris.lv2ev_EventPort)); - props.insert(make_pair(uris.rdf_type, uris.lv2_OutputPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2ev_EventPort)); + props.insert(make_pair(_uris->rdf_type, _uris->lv2_OutputPort)); } else { is_port = false; } @@ -523,11 +519,11 @@ DeprecatedLoader::load_node(const Path& parent, xmlDocPtr doc, const xmlNodePtr plugin_uri = "om:" + plugin_type + ":" + library_name + ":" + plugin_label; Resource::Properties props; - props.insert(make_pair(uris.rdf_type, uris.ingen_Node)); - props.insert(make_pair(uris.rdf_instanceOf, Atom(Atom::URI, plugin_uri))); + props.insert(make_pair(_uris->rdf_type, _uris->ingen_Node)); + props.insert(make_pair(_uris->rdf_instanceOf, Atom(Atom::URI, plugin_uri))); _engine->put(path, props); - _engine->set_property(path, uris.ingen_polyphonic, bool(polyphonic)); + _engine->set_property(path, _uris->ingen_polyphonic, bool(polyphonic)); for (GraphObject::Properties::const_iterator i = initial_data.begin(); i != initial_data.end(); ++i) _engine->set_property(path, i->first, i->second); @@ -538,10 +534,10 @@ DeprecatedLoader::load_node(const Path& parent, xmlDocPtr doc, const xmlNodePtr // Not deprecated } else { Resource::Properties props; - props.insert(make_pair(uris.rdf_type, uris.ingen_Node)); - props.insert(make_pair(uris.rdf_instanceOf, Atom(Atom::URI, plugin_uri))); + props.insert(make_pair(_uris->rdf_type, _uris->ingen_Node)); + props.insert(make_pair(_uris->rdf_instanceOf, Atom(Atom::URI, plugin_uri))); _engine->put(path, props); - _engine->set_property(path, uris.ingen_polyphonic, bool(polyphonic)); + _engine->set_property(path, _uris->ingen_polyphonic, bool(polyphonic)); for (GraphObject::Properties::const_iterator i = initial_data.begin(); i != initial_data.end(); ++i) _engine->set_property(path, i->first, i->second); return true; @@ -562,15 +558,13 @@ DeprecatedLoader::load_subpatch(const string& base_filename, const Path& parent, size_t poly = 0; GraphObject::Properties initial_data; - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - while (cur != NULL) { key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); if ((!xmlStrcmp(cur->name, (const xmlChar*)"name"))) { name = (const char*)key; } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"polyphony"))) { - initial_data.insert(make_pair(uris.ingen_polyphony, (int)poly)); + initial_data.insert(make_pair(_uris->ingen_polyphony, (int)poly)); } else if ((!xmlStrcmp(cur->name, (const xmlChar*)"filename"))) { filename = Glib::build_filename(base_filename, (const char*)key); } else { // Don't know what this tag is, add it as variable diff --git a/src/client/DeprecatedLoader.hpp b/src/client/DeprecatedLoader.hpp index 79878107..1fbb0c7e 100644 --- a/src/client/DeprecatedLoader.hpp +++ b/src/client/DeprecatedLoader.hpp @@ -33,6 +33,9 @@ namespace Raul { class Path; } namespace Ingen { + +namespace Shared { class LV2URIMap; } + namespace Client { class PresetModel; // defined in DeprecatedLoader.cpp @@ -45,8 +48,11 @@ class PresetModel; // defined in DeprecatedLoader.cpp class DeprecatedLoader { public: - DeprecatedLoader(SharedPtr engine) - : _engine(engine) + DeprecatedLoader( + SharedPtr uris, + SharedPtr engine) + : _uris(uris) + , _engine(engine) { assert(_engine); } @@ -64,6 +70,7 @@ private: std::string nameify_if_invalid(const std::string& name); std::string translate_load_path(const std::string& path); + SharedPtr _uris; SharedPtr _engine; /// Translations of paths from the loading file to actual paths (for deprecated patches) diff --git a/src/client/HTTPClientReceiver.cpp b/src/client/HTTPClientReceiver.cpp index 72d5a369..a85b3573 100644 --- a/src/client/HTTPClientReceiver.cpp +++ b/src/client/HTTPClientReceiver.cpp @@ -133,7 +133,7 @@ HTTPClientReceiver::close_session() void HTTPClientReceiver::update(const std::string& str) { - LOG(info) << _world->parser->parse_update(_world, _target.get(), str, _url); + LOG(info) << _world->parser()->parse_update(_world, _target.get(), str, _url); } void @@ -188,7 +188,7 @@ HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, voi } else { Glib::Mutex::Lock lock(me->_mutex); me->_target->response_ok(0); - me->_world->parser->parse_string(me->_world, me->_target.get(), + me->_world->parser()->parse_string(me->_world, me->_target.get(), Glib::ustring(msg->response_body->data), me->_url); } @@ -198,7 +198,7 @@ HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, voi } else { Glib::Mutex::Lock lock(me->_mutex); me->_target->response_ok(0); - me->_world->parser->parse_string(me->_world, me->_target.get(), + me->_world->parser()->parse_string(me->_world, me->_target.get(), Glib::ustring(msg->response_body->data), Glib::ustring("/patch/")); } @@ -226,9 +226,9 @@ HTTPClientReceiver::message_callback(SoupSession* session, SoupMessage* msg, voi void HTTPClientReceiver::start(bool dump) { - Glib::Mutex::Lock lock(_world->rdf_world->mutex()); + Glib::Mutex::Lock lock(_world->rdf_world()->mutex()); - if (!_world->parser) + if (!_world->parser()) _world->load("ingen_serialisation"); SoupMessage* msg = soup_message_new("GET", (_url + "/stream").c_str()); diff --git a/src/client/HTTPEngineSender.cpp b/src/client/HTTPEngineSender.cpp index dbe89b14..7c13f839 100644 --- a/src/client/HTTPEngineSender.cpp +++ b/src/client/HTTPEngineSender.cpp @@ -33,8 +33,8 @@ using namespace Shared; namespace Client { -HTTPEngineSender::HTTPEngineSender(const World* world, const URI& engine_url) - : _world(*world->rdf_world) +HTTPEngineSender::HTTPEngineSender(World* world, const URI& engine_url) + : _world(*world->rdf_world()) , _engine_url(engine_url) , _id(0) , _enabled(true) diff --git a/src/client/HTTPEngineSender.hpp b/src/client/HTTPEngineSender.hpp index 944079de..79271852 100644 --- a/src/client/HTTPEngineSender.hpp +++ b/src/client/HTTPEngineSender.hpp @@ -43,7 +43,7 @@ class HTTPClientReceiver; class HTTPEngineSender : public Shared::EngineInterface { public: - HTTPEngineSender(const Shared::World* world, const Raul::URI& engine_url); + HTTPEngineSender(Shared::World* world, const Raul::URI& engine_url); ~HTTPEngineSender(); Raul::URI uri() const { return _engine_url; } diff --git a/src/client/NodeModel.cpp b/src/client/NodeModel.cpp index bed43e7a..8be906d9 100644 --- a/src/client/NodeModel.cpp +++ b/src/client/NodeModel.cpp @@ -30,8 +30,8 @@ namespace Ingen { namespace Client { -NodeModel::NodeModel(SharedPtr plugin, const Path& path) - : ObjectModel(path) +NodeModel::NodeModel(Shared::LV2URIMap& uris, SharedPtr plugin, const Path& path) + : ObjectModel(uris, path) , _plugin_uri(plugin->uri()) , _plugin(plugin) , _num_values(0) @@ -40,8 +40,8 @@ NodeModel::NodeModel(SharedPtr plugin, const Path& path) { } -NodeModel::NodeModel(const URI& plugin_uri, const Path& path) - : ObjectModel(path) +NodeModel::NodeModel(Shared::LV2URIMap& uris, const URI& plugin_uri, const Path& path) + : ObjectModel(uris, path) , _plugin_uri(plugin_uri) , _num_values(0) , _min_values(0) @@ -206,14 +206,13 @@ NodeModel::default_port_value_range(SharedPtr port, float& min, float void NodeModel::port_value_range(SharedPtr port, float& min, float& max) const { - const Shared::LV2URIMap& uris = Shared::LV2URIMap::instance(); assert(port->parent().get() == this); default_port_value_range(port, min, max); // Possibly overriden - const Atom& min_atom = port->get_property(uris.lv2_minimum); - const Atom& max_atom = port->get_property(uris.lv2_maximum); + const Atom& min_atom = port->get_property(_uris.lv2_minimum); + const Atom& max_atom = port->get_property(_uris.lv2_maximum); if (min_atom.type() == Atom::FLOAT) min = min_atom.get_float(); if (max_atom.type() == Atom::FLOAT) diff --git a/src/client/NodeModel.hpp b/src/client/NodeModel.hpp index c1eb91e7..d13caf88 100644 --- a/src/client/NodeModel.hpp +++ b/src/client/NodeModel.hpp @@ -32,6 +32,9 @@ namespace Raul { class Path; } namespace Ingen { + +namespace Shared { class LV2URIMap; } + namespace Client { class PluginModel; @@ -71,8 +74,8 @@ public: protected: friend class ClientStore; - NodeModel(const Raul::URI& plugin_uri, const Raul::Path& path); - NodeModel(SharedPtr plugin, const Raul::Path& path); + NodeModel(Shared::LV2URIMap& uris, const Raul::URI& plugin_uri, const Raul::Path& path); + NodeModel(Shared::LV2URIMap& uris, SharedPtr plugin, const Raul::Path& path); NodeModel(const Raul::Path& path); void add_child(SharedPtr c); @@ -86,14 +89,14 @@ protected: virtual void clear(); - Ports _ports; ///< Vector of ports (not a Table to preserve order) - Raul::URI _plugin_uri; ///< Plugin URI (if PluginModel is unknown) - SharedPtr _plugin; ///< The plugin this node is an instance of + Ports _ports; ///< Vector of ports (not a Table to preserve order) + Raul::URI _plugin_uri; ///< Plugin URI (if PluginModel is unknown) + SharedPtr _plugin; ///< The plugin this node is an instance of private: - mutable uint32_t _num_values; ///< Size of _min_values and _max_values - mutable float* _min_values; ///< Port min values (cached for LV2) - mutable float* _max_values; ///< Port max values (cached for LV2) + mutable uint32_t _num_values; ///< Size of _min_values and _max_values + mutable float* _min_values; ///< Port min values (cached for LV2) + mutable float* _max_values; ///< Port max values (cached for LV2) }; diff --git a/src/client/ObjectModel.cpp b/src/client/ObjectModel.cpp index a2423ab8..c449bf12 100644 --- a/src/client/ObjectModel.cpp +++ b/src/client/ObjectModel.cpp @@ -27,9 +27,9 @@ namespace Ingen { namespace Client { -ObjectModel::ObjectModel(const Path& path) - : ResourceImpl(path) - , _meta(ResourceImpl::meta_uri(path)) +ObjectModel::ObjectModel(Shared::LV2URIMap& uris, const Raul::Path& path) + : ResourceImpl(uris, path) + , _meta(uris, ResourceImpl::meta_uri(path)) , _path(path) , _symbol((path == Path::root()) ? "root" : path.symbol()) { @@ -76,7 +76,7 @@ ObjectModel::get_property(const Raul::URI& key) const bool ObjectModel::polyphonic() const { - const Raul::Atom& polyphonic = get_property(Shared::LV2URIMap::instance().ingen_polyphonic); + const Raul::Atom& polyphonic = get_property(_uris.ingen_polyphonic); return (polyphonic.is_valid() && polyphonic.get_bool()); } diff --git a/src/client/ObjectModel.hpp b/src/client/ObjectModel.hpp index 2c1fd23e..0a108cb9 100644 --- a/src/client/ObjectModel.hpp +++ b/src/client/ObjectModel.hpp @@ -31,6 +31,9 @@ #include "shared/ResourceImpl.hpp" namespace Ingen { + +namespace Shared { class LV2URIMap; } + namespace Client { class ClientStore; @@ -79,7 +82,7 @@ public: protected: friend class ClientStore; - ObjectModel(const Raul::Path& path); + ObjectModel(Shared::LV2URIMap& uris, const Raul::Path& path); virtual void set_path(const Raul::Path& p); virtual void set_parent(SharedPtr p); @@ -89,12 +92,11 @@ protected: virtual void set(SharedPtr model); ResourceImpl _meta; - SharedPtr _parent; private: - Raul::Path _path; - Raul::Symbol _symbol; + Raul::Path _path; + Raul::Symbol _symbol; }; diff --git a/src/client/PatchModel.cpp b/src/client/PatchModel.cpp index 94557bd0..e7d30665 100644 --- a/src/client/PatchModel.cpp +++ b/src/client/PatchModel.cpp @@ -160,7 +160,7 @@ PatchModel::remove_connection(const Shared::Port* src_port, const Shared::Port* bool PatchModel::enabled() const { - const Raul::Atom& enabled = get_property(Shared::LV2URIMap::instance().ingen_enabled); + const Raul::Atom& enabled = get_property(_uris.ingen_enabled); return (enabled.is_valid() && enabled.get_bool()); } @@ -168,7 +168,7 @@ PatchModel::enabled() const uint32_t PatchModel::internal_poly() const { - const Raul::Atom& poly = get_property(Shared::LV2URIMap::instance().ingen_polyphony); + const Raul::Atom& poly = get_property(_uris.ingen_polyphony); return poly.is_valid() ? poly.get_int32() : 1; } @@ -176,7 +176,7 @@ PatchModel::internal_poly() const bool PatchModel::polyphonic() const { - const Raul::Atom& poly = get_property(Shared::LV2URIMap::instance().ingen_polyphonic); + const Raul::Atom& poly = get_property(_uris.ingen_polyphonic); return poly.is_valid() && poly.get_bool(); } diff --git a/src/client/PatchModel.hpp b/src/client/PatchModel.hpp index e3baa3eb..d4c564d2 100644 --- a/src/client/PatchModel.hpp +++ b/src/client/PatchModel.hpp @@ -76,8 +76,8 @@ public: private: friend class ClientStore; - PatchModel(const Raul::Path& patch_path) - : NodeModel("http://drobilla.net/ns/ingen#Patch", patch_path) + PatchModel(Shared::LV2URIMap& uris, const Raul::Path& patch_path) + : NodeModel(uris, "http://drobilla.net/ns/ingen#Patch", patch_path) , _connections(new Connections()) , _editable(true) { diff --git a/src/client/PluginModel.cpp b/src/client/PluginModel.cpp index b50513ce..4805c2bc 100644 --- a/src/client/PluginModel.cpp +++ b/src/client/PluginModel.cpp @@ -40,8 +40,9 @@ SLV2Plugins PluginModel::_slv2_plugins = NULL; Redland::World* PluginModel::_rdf_world = NULL; -PluginModel::PluginModel(const URI& uri, const URI& type_uri, const Resource::Properties& properties) - : ResourceImpl(uri) +PluginModel::PluginModel(Shared::LV2URIMap& uris, + const URI& uri, const URI& type_uri, const Resource::Properties& properties) + : ResourceImpl(uris, uri) , _type(type_from_uri(type_uri.str())) { add_properties(properties); @@ -69,7 +70,7 @@ PluginModel::get_property(const URI& key) const return val; // No lv2:symbol from data or engine, invent one - if (key == Shared::LV2URIMap::instance().lv2_symbol) { + if (key == _uris.lv2_symbol) { const URI& uri = this->uri(); size_t last_slash = uri.find_last_of('/'); size_t last_hash = uri.find_last_of('#'); diff --git a/src/client/PluginModel.hpp b/src/client/PluginModel.hpp index 4d54cd53..82397550 100644 --- a/src/client/PluginModel.hpp +++ b/src/client/PluginModel.hpp @@ -30,6 +30,9 @@ #include "shared/ResourceImpl.hpp" namespace Ingen { + +namespace Shared { class LV2URIMap; } + namespace Client { class PatchModel; @@ -46,6 +49,7 @@ class PluginModel : public Ingen::Shared::Plugin { public: PluginModel( + Shared::LV2URIMap& uris, const Raul::URI& uri, const Raul::URI& type_uri, const Shared::Resource::Properties& properties); diff --git a/src/client/PluginUI.cpp b/src/client/PluginUI.cpp index f943e54f..b19211e6 100644 --- a/src/client/PluginUI.cpp +++ b/src/client/PluginUI.cpp @@ -55,7 +55,7 @@ lv2_ui_write(LV2UI_Controller controller, SharedPtr port = ui->node()->ports()[port_index]; - SharedPtr map = ui->world()->uris; + const Shared::LV2URIMap& uris = *ui->world()->uris().get(); // float (special case, always 0) if (format == 0) { @@ -63,18 +63,18 @@ lv2_ui_write(LV2UI_Controller controller, if (*(float*)buffer == port->value().get_float()) return; // do nothing (handle stupid plugin UIs that feed back) - ui->world()->engine->set_property(port->path(), map->ingen_value, Atom(*(float*)buffer)); + ui->world()->engine()->set_property(port->path(), uris.ingen_value, Atom(*(float*)buffer)); - } else if (format == map->ui_format_events.id) { + } else if (format == uris.ui_format_events.id) { LV2_Event_Buffer* buf = (LV2_Event_Buffer*)buffer; LV2_Event_Iterator iter; uint8_t* data; lv2_event_begin(&iter, buf); while (lv2_event_is_valid(&iter)) { LV2_Event* const ev = lv2_event_get(&iter, &data); - if (ev->type == map->midi_event.id) { + if (ev->type == uris.midi_event.id) { // FIXME: bundle multiple events by writing an entire buffer here - ui->world()->engine->set_property(port->path(), map->ingen_value, + ui->world()->engine()->set_property(port->path(), uris.ingen_value, Atom("http://lv2plug.in/ns/ext/midi#MidiEvent", ev->size, data)); } else { warn << "Unable to send event type " << ev->type << @@ -84,11 +84,11 @@ lv2_ui_write(LV2UI_Controller controller, lv2_event_increment(&iter); } - } else if (format == map->object_transfer.id) { + } else if (format == uris.object_transfer.id) { LV2_Object* buf = (LV2_Object*)buffer; Raul::Atom val; - Shared::LV2Object::to_atom(buf, val); - ui->world()->engine->set_property(port->path(), map->ingen_value, val); + Shared::LV2Object::to_atom(uris, buf, val); + ui->world()->engine()->set_property(port->path(), uris.ingen_value, val); } else { warn << "Unknown value format " << format @@ -122,7 +122,7 @@ PluginUI::create(Ingen::Shared::World* world, Glib::Mutex::Lock lock(PluginModel::rdf_world()->mutex()); SharedPtr ret; - SLV2Value gtk_gui_uri = slv2_value_new_uri(world->slv2_world, + SLV2Value gtk_gui_uri = slv2_value_new_uri(world->slv2_world(), "http://lv2plug.in/ns/extensions/ui#GtkUI"); SLV2UIs uis = slv2_plugin_get_uis(plugin); @@ -141,7 +141,7 @@ PluginUI::create(Ingen::Shared::World* world, if (ui) { info << "Found GTK Plugin UI: " << slv2_ui_get_uri(ui) << endl; ret = SharedPtr(new PluginUI(world, node)); - ret->_features = world->lv2_features->lv2_features(node.get()); + ret->_features = world->lv2_features()->lv2_features(node.get()); SLV2UIInstance inst = slv2_ui_instantiate( plugin, ui, lv2_ui_write, ret.get(), ret->_features->array()); diff --git a/src/client/PortModel.cpp b/src/client/PortModel.cpp index e23a0e1a..80934cad 100644 --- a/src/client/PortModel.cpp +++ b/src/client/PortModel.cpp @@ -28,7 +28,7 @@ PortModel::set_property(const Raul::URI& uri, const Raul::Atom& value) { Raul::Atom& ret = ObjectModel::set_property(uri, value); - if (uri == Shared::LV2URIMap::instance().ingen_value) + if (uri == _uris.ingen_value) this->value(value); return ret; } @@ -37,14 +37,14 @@ PortModel::set_property(const Raul::URI& uri, bool PortModel::supports(const Raul::URI& value_type) const { - return has_property(Shared::LV2URIMap::instance().obj_supports, value_type); + return has_property(_uris.obj_supports, value_type); } bool PortModel::port_property(const std::string& uri) const { - return has_property(Shared::LV2URIMap::instance().lv2_portProperty, Raul::URI(uri)); + return has_property(_uris.lv2_portProperty, Raul::URI(uri)); } @@ -65,5 +65,16 @@ PortModel::set(SharedPtr model) } +bool +PortModel::has_context(const Raul::URI& uri) +{ + const Raul::Atom& context = get_property(_uris.ctx_context); + if (uri == _uris.ctx_AudioContext && !context.is_valid()) + return true; + else + return context == uri; +} + + } // namespace Client } // namespace Ingen diff --git a/src/client/PortModel.hpp b/src/client/PortModel.hpp index 02305e1a..dc864ffe 100644 --- a/src/client/PortModel.hpp +++ b/src/client/PortModel.hpp @@ -58,6 +58,8 @@ public: bool is_integer() const { return port_property("http://lv2plug.in/ns/lv2core#integer"); } bool is_toggle() const { return port_property("http://lv2plug.in/ns/lv2core#toggled"); } + bool has_context(const Raul::URI& context); + inline bool operator==(const PortModel& pm) const { return (path() == pm.path()); } Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value); @@ -84,8 +86,9 @@ public: private: friend class ClientStore; - PortModel(const Raul::Path& path, uint32_t index, Shared::PortType type, Direction dir) - : ObjectModel(path) + PortModel(Shared::LV2URIMap& uris, + const Raul::Path& path, uint32_t index, Shared::PortType type, Direction dir) + : ObjectModel(uris, path) , _index(index) , _direction(dir) , _current_val(0.0f) diff --git a/src/common/interface/Node.hpp b/src/common/interface/Node.hpp index 7a1a6280..4a700a12 100644 --- a/src/common/interface/Node.hpp +++ b/src/common/interface/Node.hpp @@ -21,7 +21,6 @@ #include #include "GraphObject.hpp" -#include namespace Ingen { namespace Shared { diff --git a/src/engine/BufferFactory.cpp b/src/engine/BufferFactory.cpp index 83030c70..318a1422 100644 --- a/src/engine/BufferFactory.cpp +++ b/src/engine/BufferFactory.cpp @@ -32,11 +32,31 @@ namespace Ingen { using namespace Shared; -BufferFactory::BufferFactory(Engine& engine, SharedPtr map) +BufferFactory::BufferFactory(Engine& engine, SharedPtr a_uris) : _engine(engine) - , _map(map) + , _uris(a_uris) , _silent_buffer(NULL) { + assert(_uris); +} + + +BufferFactory::~BufferFactory() +{ + free_list(_free_audio.get()); + free_list(_free_control.get()); + free_list(_free_event.get()); + free_list(_free_object.get()); +} + + +void +BufferFactory::free_list(Buffer* head) +{ + Buffer* next = head->_next; + delete head; + if (next) + free_list(next); } @@ -87,7 +107,7 @@ BufferFactory::get(Shared::PortType type, size_t size, bool force_create) } if (!try_head) { - if (ThreadManager::current_thread_id() != THREAD_PROCESS) { + if (!ThreadManager::thread_is(THREAD_PROCESS)) { return create(type, size); } else { assert(false); @@ -113,12 +133,12 @@ BufferFactory::create(Shared::PortType type, size_t size) if (type.is_control()) { AudioBuffer* ret = new AudioBuffer(*this, type, size); - ret->object()->type = _map->object_class_vector.id; - ((LV2_Vector_Body*)ret->object()->body)->elem_type = _map->object_class_float32.id; + ret->object()->type = _uris->object_class_vector.id; + ((LV2_Vector_Body*)ret->object()->body)->elem_type = _uris->object_class_float32.id; buffer = ret; } else if (type.is_audio()) { AudioBuffer* ret = new AudioBuffer(*this, type, size); - ret->object()->type = _map->object_class_float32.id; + ret->object()->type = _uris->object_class_float32.id; buffer = ret; } else if (type.is_events()) { buffer = new EventBuffer(*this, size); diff --git a/src/engine/BufferFactory.hpp b/src/engine/BufferFactory.hpp index 44213c52..344b946d 100644 --- a/src/engine/BufferFactory.hpp +++ b/src/engine/BufferFactory.hpp @@ -37,7 +37,8 @@ namespace Shared { class LV2URIMap; } class BufferFactory { public: - BufferFactory(Engine& engine, SharedPtr map); + BufferFactory(Engine& engine, SharedPtr uris); + ~BufferFactory(); typedef boost::intrusive_ptr Ref; @@ -50,6 +51,8 @@ public: void set_block_length(SampleCount block_length); + Shared::LV2URIMap& uris() { assert(_uris); return *_uris.get(); } + private: friend class Buffer; void recycle(Buffer* buf); @@ -67,6 +70,8 @@ private: } } + void free_list(Buffer* head); + Raul::AtomicPtr _free_audio; Raul::AtomicPtr _free_control; Raul::AtomicPtr _free_event; @@ -74,7 +79,7 @@ private: Glib::Mutex _mutex; Engine& _engine; - SharedPtr _map; + SharedPtr _uris; Ref _silent_buffer; }; diff --git a/src/engine/ClientBroadcaster.hpp b/src/engine/ClientBroadcaster.hpp index c72fef74..02a7fe41 100644 --- a/src/engine/ClientBroadcaster.hpp +++ b/src/engine/ClientBroadcaster.hpp @@ -26,7 +26,6 @@ #include "interface/ClientInterface.hpp" #include "NodeFactory.hpp" -#include using namespace std; namespace Ingen { diff --git a/src/engine/ConnectionImpl.cpp b/src/engine/ConnectionImpl.cpp index 8fa770f7..495a97c2 100644 --- a/src/engine/ConnectionImpl.cpp +++ b/src/engine/ConnectionImpl.cpp @@ -127,7 +127,7 @@ ConnectionImpl::queue(Context& context) bool ConnectionImpl::can_connect(const OutputPort* src, const InputPort* dst) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = src->bufs().uris(); return ( ( (src->is_a(PortType::CONTROL) || src->is_a(PortType::AUDIO)) && (dst->is_a(PortType::CONTROL) || dst->is_a(PortType::AUDIO))) diff --git a/src/engine/Context.hpp b/src/engine/Context.hpp index 2a3bd7ca..6ef24346 100644 --- a/src/engine/Context.hpp +++ b/src/engine/Context.hpp @@ -20,6 +20,7 @@ #include "EventSink.hpp" #include "tuning.hpp" +#include "types.hpp" namespace Ingen { diff --git a/src/engine/ControlBindings.cpp b/src/engine/ControlBindings.cpp index ead1e6ea..e861d2ed 100644 --- a/src/engine/ControlBindings.cpp +++ b/src/engine/ControlBindings.cpp @@ -18,6 +18,8 @@ #include #include "raul/log.hpp" #include "raul/midi_events.h" +#include "shared/LV2URIMap.hpp" +#include "module/World.hpp" #include "events/SendPortValue.hpp" #include "events/SendBinding.hpp" #include "AudioBuffer.hpp" @@ -36,9 +38,8 @@ using namespace Raul; namespace Ingen { -ControlBindings::ControlBindings(Engine& engine, SharedPtr map) +ControlBindings::ControlBindings(Engine& engine) : _engine(engine) - , _map(map) , _learn_port(NULL) , _bindings(new Bindings()) , _feedback(new EventBuffer(*_engine.buffer_factory(), 1024)) // FIXME: size @@ -55,8 +56,8 @@ ControlBindings::~ControlBindings() ControlBindings::Key ControlBindings::port_binding(PortImpl* port) { - const Shared::LV2URIMap& uris = Shared::LV2URIMap::instance(); - const Raul::Atom& binding = port->get_property(uris.ingen_controlBinding); + const Shared::LV2URIMap& uris = *_engine.world()->uris().get(); + const Raul::Atom& binding = port->get_property(uris.ingen_controlBinding); Key key; if (binding.type() == Atom::DICT) { const Atom::DictValue& dict = binding.get_dict(); @@ -114,6 +115,7 @@ ControlBindings::port_binding_changed(ProcessContext& context, PortImpl* port) void ControlBindings::port_value_changed(ProcessContext& context, PortImpl* port) { + const Shared::LV2URIMap& uris = *_engine.world()->uris().get(); Key key = port_binding(port); if (key) { int16_t value = port_value_to_control(port, key.type); @@ -150,7 +152,7 @@ ControlBindings::port_value_changed(ProcessContext& context, PortImpl* port) break; } if (size > 0) - _feedback->append(0, 0, _map->midi_event.id, size, buf); + _feedback->append(0, 0, uris.midi_event.id, size, buf); } } @@ -166,7 +168,7 @@ ControlBindings::learn(PortImpl* port) Raul::Atom ControlBindings::control_to_port_value(PortImpl* port, Type type, int16_t value) { - const Shared::LV2URIMap& uris = Shared::LV2URIMap::instance(); + const Shared::LV2URIMap& uris = *_engine.world()->uris().get(); // TODO: cache these to avoid the lookup float min = port->get_property(uris.lv2_minimum).get_float(); @@ -203,7 +205,7 @@ ControlBindings::port_value_to_control(PortImpl* port, Type type) if (port->value().type() != Atom::FLOAT) return 0; - const Shared::LV2URIMap& uris = Shared::LV2URIMap::instance(); + const Shared::LV2URIMap& uris = *_engine.world()->uris().get(); // TODO: cache these to avoid the lookup float min = port->get_property(uris.lv2_minimum).get_float(); @@ -259,7 +261,7 @@ ControlBindings::set_port_value(ProcessContext& context, PortImpl* port, Type ty bool ControlBindings::bind(ProcessContext& context, Key key) { - const Shared::LV2URIMap& uris = Shared::LV2URIMap::instance(); + const Shared::LV2URIMap& uris = *context.engine().world()->uris().get(); assert(_learn_port); if (key.type == MIDI_NOTE) { bool toggled = _learn_port->has_property(uris.lv2_portProperty, uris.lv2_toggled); @@ -336,12 +338,14 @@ ControlBindings::pre_process(ProcessContext& context, EventBuffer* buffer) SharedPtr bindings = _bindings; _feedback->clear(); + const Shared::LV2URIMap& uris = *context.engine().world()->uris().get(); + // Learn from input if necessary if (_learn_port) { for (buffer->rewind(); buffer->get_event(&frames, &subframes, &type, &size, &buf); buffer->increment()) { - if (type != _map->midi_event.id) + if (type != uris.midi_event.id) continue; const Key key = midi_event_key(size, buf, value); @@ -358,7 +362,7 @@ ControlBindings::pre_process(ProcessContext& context, EventBuffer* buffer) for (buffer->rewind(); buffer->get_event(&frames, &subframes, &type, &size, &buf); buffer->increment()) { - if (type != _map->midi_event.id) + if (type != uris.midi_event.id) continue; const Key key = midi_event_key(size, buf, value); diff --git a/src/engine/ControlBindings.hpp b/src/engine/ControlBindings.hpp index 1b684b9a..f5878908 100644 --- a/src/engine/ControlBindings.hpp +++ b/src/engine/ControlBindings.hpp @@ -56,7 +56,7 @@ public: typedef std::map Bindings; - ControlBindings(Engine& engine, SharedPtr map); + ControlBindings(Engine& engine); ~ControlBindings(); void learn(PortImpl* port); @@ -88,9 +88,8 @@ private: Raul::Atom control_to_port_value(PortImpl* port, Type type, int16_t value); int16_t port_value_to_control(PortImpl* port, Type type); - Engine& _engine; - SharedPtr _map; - PortImpl* _learn_port; + Engine& _engine; + PortImpl* _learn_port; SharedPtr _bindings; EventBuffer* _feedback; diff --git a/src/engine/Driver.hpp b/src/engine/Driver.hpp index 3712b93b..35fb4997 100644 --- a/src/engine/Driver.hpp +++ b/src/engine/Driver.hpp @@ -77,13 +77,13 @@ public: virtual ~Driver() {} /** Activate driver (begin processing graph and events). */ - virtual void activate() = 0; + virtual void activate() {} /** Deactivate driver (stop processing graph and events). */ - virtual void deactivate() = 0; + virtual void deactivate() {} /** Return true iff driver is activated (processing graph and events). */ - virtual bool is_activated() const = 0; + virtual bool is_activated() const { return true; } /** Create a port ready to be inserted with add_input (non realtime). * May return NULL if the Driver can not create the port for some reason. @@ -97,7 +97,7 @@ public: virtual void add_port(DriverPort* port) = 0; /** Remove a system visible port. */ - virtual Raul::List::Node* remove_port(const Raul::Path& path) = 0; + virtual Raul::Deletable* remove_port(const Raul::Path& path, Ingen::DriverPort** port=NULL) = 0; /** Return true iff this driver supports the given type of I/O */ virtual bool supports(Shared::PortType port_type, Shared::EventType event_type) = 0; diff --git a/src/engine/DuplexPort.cpp b/src/engine/DuplexPort.cpp index a78da58a..da7dabf1 100644 --- a/src/engine/DuplexPort.cpp +++ b/src/engine/DuplexPort.cpp @@ -50,7 +50,7 @@ DuplexPort::DuplexPort( , _is_output(is_output) { assert(PortImpl::_parent == parent); - set_property(Shared::LV2URIMap::instance().ingen_polyphonic, polyphonic); + set_property(bufs.uris().ingen_polyphonic, polyphonic); } diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index dd25485a..a17a58c0 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -58,22 +58,23 @@ using namespace Shared; bool ThreadManager::single_threaded = true; -Engine::Engine(Ingen::Shared::World* world) - : _world(world) +Engine::Engine(Ingen::Shared::World* a_world) + : _world(a_world) , _maid(new Raul::Maid(maid_queue_size)) , _post_processor(new PostProcessor(*this, post_processor_queue_size)) , _broadcaster(new ClientBroadcaster()) - , _node_factory(new NodeFactory(world)) + , _node_factory(new NodeFactory(a_world)) , _message_context(new MessageContext(*this)) - , _buffer_factory(new BufferFactory(*this, world->uris)) - , _control_bindings(new ControlBindings(*this, world->uris)) + , _buffer_factory(new BufferFactory(*this, a_world->uris())) + //, _buffer_factory(NULL) + , _control_bindings(new ControlBindings(*this)) , _quit_flag(false) , _activated(false) { - if (world->store) { - assert(PtrCast(world->store)); + if (a_world->store()) { + assert(PtrCast(a_world->store())); } else { - world->store = SharedPtr(new EngineStore()); + a_world->set_store(SharedPtr(new EngineStore())); } } @@ -101,7 +102,7 @@ Engine::~Engine() SharedPtr Engine::engine_store() const { - return PtrCast(_world->store); + return PtrCast(_world->store()); } @@ -137,13 +138,6 @@ Engine::main_iteration() } -Ingen::QueuedEngineInterface* -Engine::new_local_interface() -{ - return new Ingen::QueuedEngineInterface(*this, Ingen::event_queue_size); -} - - void Engine::add_event_source(SharedPtr source) { @@ -164,18 +158,23 @@ execute_and_delete_event(ProcessContext& context, QueuedEvent* ev) bool Engine::activate() { + if (_activated) + return true; + assert(_driver); + //assert(ThreadManager::single_threaded == true); + ThreadManager::single_threaded = true; _buffer_factory->set_block_length(_driver->block_length()); _message_context->Thread::start(); - uint32_t parallelism = _world->conf->option("parallelism").get_int32(); + uint32_t parallelism = _world->conf()->option("parallelism").get_int32(); for (EventSources::iterator i = _event_sources.begin(); i != _event_sources.end(); ++i) (*i)->activate_source(); - const LV2URIMap& uris = *world()->uris; + const LV2URIMap& uris = *world()->uris().get(); // Create root patch PatchImpl* root_patch = _driver->root_patch(); @@ -185,7 +184,7 @@ Engine::activate() root_patch->meta().set_property(uris.ingen_polyphony, Raul::Atom(int32_t(1))); root_patch->set_property(uris.rdf_type, uris.ingen_Node); root_patch->activate(*_buffer_factory); - _world->store->add(root_patch); + _world->store()->add(root_patch); root_patch->compiled_patch(root_patch->compile()); _driver->set_root_patch(root_patch); diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index e575db50..fe5f34e6 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -61,7 +61,7 @@ class QueuedEvent; * * \ingroup engine */ -class Engine : boost::noncopyable +class Engine : public boost::noncopyable { public: Engine(Ingen::Shared::World* world); @@ -78,32 +78,30 @@ public: virtual bool activate(); virtual void deactivate(); - void process_events(ProcessContext& context); + virtual void process_events(ProcessContext& context); virtual bool activated() { return _activated; } - BufferFactory* buffer_factory() const { return _buffer_factory; } - ClientBroadcaster* broadcaster() const { return _broadcaster; } - ControlBindings* control_bindings() const { return _control_bindings; } - Driver* driver() const { return _driver.get(); } - MessageContext* message_context() const { return _message_context; } - NodeFactory* node_factory() const { return _node_factory; } - PostProcessor* post_processor() const { return _post_processor; } - Raul::Maid* maid() const { return _maid; } + virtual BufferFactory* buffer_factory() const { return _buffer_factory; } + virtual ClientBroadcaster* broadcaster() const { return _broadcaster; } + virtual ControlBindings* control_bindings() const { return _control_bindings; } + virtual Driver* driver() const { return _driver.get(); } + virtual MessageContext* message_context() const { return _message_context; } + virtual NodeFactory* node_factory() const { return _node_factory; } + virtual PostProcessor* post_processor() const { return _post_processor; } + virtual Raul::Maid* maid() const { return _maid; } - SharedPtr engine_store() const; + virtual SharedPtr engine_store() const; virtual void set_driver(SharedPtr driver) { _driver = driver; } virtual void add_event_source(SharedPtr source); - Ingen::QueuedEngineInterface* new_local_interface(); - - Ingen::Shared::World* world() { return _world; } + virtual Ingen::Shared::World* world() { return _world; } typedef std::vector ProcessSlaves; - inline const ProcessSlaves& process_slaves() const { return _process_slaves; } - inline ProcessSlaves& process_slaves() { return _process_slaves; } + virtual const ProcessSlaves& process_slaves() const { return _process_slaves; } + virtual ProcessSlaves& process_slaves() { return _process_slaves; } private: typedef std::set< SharedPtr > EventSources; diff --git a/src/engine/EventSource.cpp b/src/engine/EventSource.cpp index c51b580a..9e1f2741 100644 --- a/src/engine/EventSource.cpp +++ b/src/engine/EventSource.cpp @@ -31,7 +31,6 @@ EventSource::EventSource(size_t queue_size) : _blocking_semaphore(0) { Thread::set_context(THREAD_PRE_PROCESS); - assert(context() == THREAD_PRE_PROCESS); set_name("EventSource"); } diff --git a/src/engine/GraphObjectImpl.cpp b/src/engine/GraphObjectImpl.cpp index d67755b5..3db53ba7 100644 --- a/src/engine/GraphObjectImpl.cpp +++ b/src/engine/GraphObjectImpl.cpp @@ -28,12 +28,13 @@ namespace Ingen { using namespace Shared; -GraphObjectImpl::GraphObjectImpl(GraphObjectImpl* parent, const Symbol& symbol) - : ResourceImpl(parent ? parent->path().child(symbol) : Raul::Path::root()) +GraphObjectImpl::GraphObjectImpl(Shared::LV2URIMap& uris, + GraphObjectImpl* parent, const Symbol& symbol) + : ResourceImpl(uris, parent ? parent->path().child(symbol) : Raul::Path::root()) , _parent(parent) , _path(parent ? parent->path().child(symbol) : "/") , _symbol(symbol) - , _meta(ResourceImpl::meta_uri(uri())) + , _meta(uris, ResourceImpl::meta_uri(uri())) { } diff --git a/src/engine/GraphObjectImpl.hpp b/src/engine/GraphObjectImpl.hpp index 854fdab1..9a9a9b73 100644 --- a/src/engine/GraphObjectImpl.hpp +++ b/src/engine/GraphObjectImpl.hpp @@ -32,6 +32,8 @@ namespace Raul { class Maid; } namespace Ingen { +namespace Shared { class LV2URIMap; } + class PatchImpl; class Context; class ProcessContext; @@ -98,7 +100,8 @@ public: virtual bool apply_poly(Raul::Maid& maid, uint32_t poly) = 0; protected: - GraphObjectImpl(GraphObjectImpl* parent, const Raul::Symbol& symbol); + GraphObjectImpl(Shared::LV2URIMap& uris, + GraphObjectImpl* parent, const Raul::Symbol& symbol); GraphObjectImpl* _parent; Raul::Path _path; diff --git a/src/engine/HTTPClientSender.cpp b/src/engine/HTTPClientSender.cpp index 20bc8ee2..338b4394 100644 --- a/src/engine/HTTPClientSender.cpp +++ b/src/engine/HTTPClientSender.cpp @@ -59,10 +59,10 @@ HTTPClientSender::put(const URI& uri, const string path = (uri.substr(0, 6) == "path:/") ? uri.substr(6) : uri.str(); const string full_uri = _url + "/" + path; - Redland::Model model(*_engine.world()->rdf_world); + Redland::Model model(*_engine.world()->rdf_world()); for (Resource::Properties::const_iterator i = properties.begin(); i != properties.end(); ++i) model.add_statement( - Redland::Resource(*_engine.world()->rdf_world, path), + Redland::Resource(*_engine.world()->rdf_world(), path), i->first.str(), AtomRDF::atom_to_node(model, i->second)); @@ -111,7 +111,7 @@ void HTTPClientSender::set_property(const URI& subject, const URI& key, const Atom& value) { #if 0 - Redland::Node node = AtomRDF::atom_to_node(*_engine.world()->rdf_world, value); + Redland::Node node = AtomRDF::atom_to_node(*_engine.world()->rdf_world(), value); const string msg = string( "@prefix rdf: .\n" "@prefix ingen: .\n" diff --git a/src/engine/HTTPEngineReceiver.cpp b/src/engine/HTTPEngineReceiver.cpp index 662b23eb..e24b9076 100644 --- a/src/engine/HTTPEngineReceiver.cpp +++ b/src/engine/HTTPEngineReceiver.cpp @@ -55,7 +55,7 @@ HTTPEngineReceiver::HTTPEngineReceiver(Engine& engine, uint16_t port) LOG(info) << "Started HTTP server on port " << soup_server_get_port(_server) << endl; - if (!engine.world()->parser || !engine.world()->serialiser) + if (!engine.world()->parser() || !engine.world()->serialiser()) engine.world()->load("ingen_serialisation"); Thread::set_name("HTTPEngineReceiver"); @@ -99,7 +99,7 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const { HTTPEngineReceiver* me = (HTTPEngineReceiver*)data; - SharedPtr store = me->_engine.world()->store; + SharedPtr store = me->_engine.world()->store(); if (!store) { soup_message_set_status (msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; @@ -110,7 +110,7 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const path = path.substr(0, path.length()-1); } - SharedPtr serialiser = me->_engine.world()->serialiser; + SharedPtr serialiser = me->_engine.world()->serialiser(); const string base_uri = "path:/"; const char* mime_type = "text/plain"; @@ -180,7 +180,7 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const } // Get serialiser - SharedPtr serialiser = me->_engine.world()->serialiser; + SharedPtr serialiser = me->_engine.world()->serialiser(); if (!serialiser) { soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); soup_message_set_response(msg, "text/plain", SOUP_MEMORY_STATIC, @@ -200,7 +200,7 @@ HTTPEngineReceiver::message_callback(SoupServer* server, SoupMessage* msg, const Glib::RWLock::WriterLock lock(store->lock()); // Get parser - SharedPtr parser = me->_engine.world()->parser; + SharedPtr parser = me->_engine.world()->parser(); if (!parser) { soup_message_set_status(msg, SOUP_STATUS_INTERNAL_SERVER_ERROR); return; diff --git a/src/engine/InputPort.cpp b/src/engine/InputPort.cpp index 95af5725..dae9b43c 100644 --- a/src/engine/InputPort.cpp +++ b/src/engine/InputPort.cpp @@ -49,7 +49,7 @@ InputPort::InputPort(BufferFactory& bufs, : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) , _num_connections(0) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); if (!dynamic_cast(parent)) add_property(uris.rdf_type, uris.lv2_InputPort); @@ -81,7 +81,7 @@ InputPort::apply_poly(Maid& maid, uint32_t poly) bool InputPort::get_buffers(BufferFactory& bufs, Raul::Array* buffers, uint32_t poly) { - size_t num_connections = (ThreadManager::current_thread_id() == THREAD_PROCESS) + size_t num_connections = (ThreadManager::thread_is(THREAD_PROCESS)) ? _connections.size() : _num_connections; if (buffer_type() == PortType::AUDIO && num_connections == 0) { @@ -91,7 +91,7 @@ InputPort::get_buffers(BufferFactory& bufs, Raul::Array* buf return false; } else if (num_connections == 1) { - if (ThreadManager::current_thread_id() == THREAD_PROCESS) { + if (ThreadManager::thread_is(THREAD_PROCESS)) { if (!_connections.front()->must_mix() && !_connections.front()->must_queue()) { // Single non-mixing conneciton, use buffers directly for (uint32_t v = 0; v < poly; ++v) diff --git a/src/engine/InternalPlugin.cpp b/src/engine/InternalPlugin.cpp index 802ec955..fdb0cd96 100644 --- a/src/engine/InternalPlugin.cpp +++ b/src/engine/InternalPlugin.cpp @@ -32,11 +32,11 @@ namespace Ingen { using namespace Internals; -InternalPlugin::InternalPlugin(const std::string& uri, const std::string& symbol) - : PluginImpl(Plugin::Internal, uri) +InternalPlugin::InternalPlugin(Shared::LV2URIMap& uris, + const std::string& uri, const std::string& symbol) + : PluginImpl(uris, Plugin::Internal, uri) , _symbol(symbol) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); set_property(uris.rdf_type, uris.ingen_Internal); } @@ -53,14 +53,15 @@ InternalPlugin::instantiate(BufferFactory& bufs, const SampleCount srate = engine.driver()->sample_rate(); const string uri_str = uri().str(); + if (uri_str == NS_INTERNALS "Controller") { - return new ControllerNode(bufs, name, polyphonic, parent, srate); + return new ControllerNode(this, bufs, name, polyphonic, parent, srate); } else if (uri_str == NS_INTERNALS "Delay") { - return new DelayNode(bufs, name, polyphonic, parent, srate); + return new DelayNode(this, bufs, name, polyphonic, parent, srate); } else if (uri_str == NS_INTERNALS "Note") { - return new NoteNode(bufs, name, polyphonic, parent, srate); + return new NoteNode(this, bufs, name, polyphonic, parent, srate); } else if (uri_str == NS_INTERNALS "Trigger") { - return new TriggerNode(bufs, name, polyphonic, parent, srate); + return new TriggerNode(this, bufs, name, polyphonic, parent, srate); } else { return NULL; } diff --git a/src/engine/InternalPlugin.hpp b/src/engine/InternalPlugin.hpp index d1c0e76e..cd2dff2d 100644 --- a/src/engine/InternalPlugin.hpp +++ b/src/engine/InternalPlugin.hpp @@ -20,10 +20,6 @@ #include "ingen-config.h" -#ifndef HAVE_SLV2 -#error "This file requires SLV2, but HAVE_SLV2 is not defined. Please report." -#endif - #include #include #include @@ -44,7 +40,8 @@ class BufferFactory; class InternalPlugin : public PluginImpl { public: - InternalPlugin(const std::string& uri, const std::string& symbol); + InternalPlugin(Shared::LV2URIMap& uris, + const std::string& uri, const std::string& symbol); NodeImpl* instantiate(BufferFactory& bufs, const std::string& name, diff --git a/src/engine/JackDriver.cpp b/src/engine/JackDriver.cpp index 6c66cba3..6e973e1f 100644 --- a/src/engine/JackDriver.cpp +++ b/src/engine/JackDriver.cpp @@ -192,7 +192,7 @@ JackDriver::JackDriver(Engine& engine) , _process_context(engine) , _root_patch(NULL) { - _midi_event_type = _engine.world()->uris->uri_to_id( + _midi_event_type = _engine.world()->uris()->uri_to_id( NULL, "http://lv2plug.in/ns/ext/midi#MidiEvent"); } @@ -274,8 +274,8 @@ JackDriver::activate() } if (!_client) - attach(_engine.world()->conf->option("jack-server").get_string(), - _engine.world()->conf->option("jack-client").get_string(), NULL); + attach(_engine.world()->conf()->option("jack-server").get_string(), + _engine.world()->conf()->option("jack-client").get_string(), NULL); jack_set_process_callback(_client, process_cb, this); @@ -338,14 +338,19 @@ JackDriver::add_port(DriverPort* port) * * It is the callers responsibility to delete the returned port. */ -Raul::List::Node* -JackDriver::remove_port(const Path& path) +Raul::Deletable* +JackDriver::remove_port(const Path& path, DriverPort** port) { ThreadManager::assert_thread(THREAD_PROCESS); - for (Raul::List::iterator i = _ports.begin(); i != _ports.end(); ++i) - if ((*i)->patch_port()->path() == path) - return (Raul::List::Node*)(_ports.erase(i)); + for (Raul::List::iterator i = _ports.begin(); i != _ports.end(); ++i) { + if ((*i)->patch_port()->path() == path) { + Raul::List::Node* node = _ports.erase(i); + if (port) + *port = node->elem(); + return node; + } + } LOG(warn) << "Unable to find port " << path << endl; return NULL; diff --git a/src/engine/JackDriver.hpp b/src/engine/JackDriver.hpp index e2450d06..5ecdbfaf 100644 --- a/src/engine/JackDriver.hpp +++ b/src/engine/JackDriver.hpp @@ -97,7 +97,7 @@ public: void add_port(DriverPort* port); DriverPort* driver_port(const Raul::Path& path); - Raul::List::Node* remove_port(const Raul::Path& path); + Raul::Deletable* remove_port(const Raul::Path& path, DriverPort** port=NULL); PatchImpl* root_patch() { return _root_patch; } void set_root_patch(PatchImpl* patch) { _root_patch = patch; } diff --git a/src/engine/LADSPANode.cpp b/src/engine/LADSPANode.cpp index ddcb774f..dd1f9370 100644 --- a/src/engine/LADSPANode.cpp +++ b/src/engine/LADSPANode.cpp @@ -133,7 +133,7 @@ LADSPANode::apply_poly(Raul::Maid& maid, uint32_t poly) bool LADSPANode::instantiate(BufferFactory& bufs) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); if (!_ports) _ports = new Raul::Array(_descriptor->PortCount); diff --git a/src/engine/LADSPAPlugin.cpp b/src/engine/LADSPAPlugin.cpp index 94ff36d2..59774bb9 100644 --- a/src/engine/LADSPAPlugin.cpp +++ b/src/engine/LADSPAPlugin.cpp @@ -31,17 +31,17 @@ namespace Ingen { LADSPAPlugin::LADSPAPlugin( + Shared::LV2URIMap& uris, const std::string& library_path, const std::string& uri, unsigned long id, const std::string& label, const std::string& name) - : PluginImpl(Plugin::LADSPA, uri, library_path) + : PluginImpl(uris, Plugin::LADSPA, uri, library_path) , _id(id) , _label(label) , _name(name) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); set_property(uris.rdf_type, uris.ingen_LADSPAPlugin); set_property(uris.lv2_symbol, Symbol::symbolify(label)); set_property(uris.doap_name, name); @@ -51,7 +51,7 @@ LADSPAPlugin::LADSPAPlugin( const Raul::Atom& LADSPAPlugin::get_property(const Raul::URI& uri) const { - if (uri == Shared::LV2URIMap::instance().doap_name) + if (uri == _uris.doap_name) return _name; else return ResourceImpl::get_property(uri); diff --git a/src/engine/LADSPAPlugin.hpp b/src/engine/LADSPAPlugin.hpp index 0d0b91ce..f5ae672a 100644 --- a/src/engine/LADSPAPlugin.hpp +++ b/src/engine/LADSPAPlugin.hpp @@ -37,11 +37,13 @@ class NodeImpl; class LADSPAPlugin : public PluginImpl { public: - LADSPAPlugin(const std::string& library_path, - const std::string& uri, - unsigned long id, - const std::string& label, - const std::string& name); + LADSPAPlugin( + Shared::LV2URIMap& uris, + const std::string& library_path, + const std::string& uri, + unsigned long id, + const std::string& label, + const std::string& name); NodeImpl* instantiate(BufferFactory& bufs, const std::string& name, diff --git a/src/engine/LV2Info.cpp b/src/engine/LV2Info.cpp index 774828dd..2e57e9a2 100644 --- a/src/engine/LV2Info.cpp +++ b/src/engine/LV2Info.cpp @@ -31,22 +31,22 @@ using namespace std; namespace Ingen { LV2Info::LV2Info(Ingen::Shared::World* world) - : input_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_INPUT)) - , output_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_OUTPUT)) - , control_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_CONTROL)) - , audio_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_AUDIO)) - , event_class(slv2_value_new_uri(world->slv2_world, SLV2_PORT_CLASS_EVENT)) - , value_port_class(slv2_value_new_uri(world->slv2_world, LV2_OBJECT_URI "#ValuePort")) - , message_port_class(slv2_value_new_uri(world->slv2_world, LV2_OBJECT_URI "#MessagePort")) + : input_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_INPUT)) + , output_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_OUTPUT)) + , control_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_CONTROL)) + , audio_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_AUDIO)) + , event_class(slv2_value_new_uri(world->slv2_world(), SLV2_PORT_CLASS_EVENT)) + , value_port_class(slv2_value_new_uri(world->slv2_world(), LV2_OBJECT_URI "#ValuePort")) + , message_port_class(slv2_value_new_uri(world->slv2_world(), LV2_OBJECT_URI "#MessagePort")) , _world(world) { assert(world); - world->lv2_features->add_feature(LV2_EVENT_URI, + world->lv2_features()->add_feature(LV2_EVENT_URI, SharedPtr(new EventFeature())); - world->lv2_features->add_feature(LV2_BLOB_SUPPORT_URI, + world->lv2_features()->add_feature(LV2_BLOB_SUPPORT_URI, SharedPtr(new BlobFeature())); - world->lv2_features->add_feature(LV2_RESIZE_PORT_URI, + world->lv2_features()->add_feature(LV2_RESIZE_PORT_URI, SharedPtr(new ResizeFeature())); } diff --git a/src/engine/LV2Info.hpp b/src/engine/LV2Info.hpp index 1044098a..2ba0ef20 100644 --- a/src/engine/LV2Info.hpp +++ b/src/engine/LV2Info.hpp @@ -54,7 +54,7 @@ public: SLV2Value message_port_class; Ingen::Shared::World& world() { return *_world; } - SLV2World lv2_world() { return _world->slv2_world; } + SLV2World lv2_world() { return _world->slv2_world(); } private: Ingen::Shared::World* _world; diff --git a/src/engine/LV2Node.cpp b/src/engine/LV2Node.cpp index be16e76d..cc3e3ca0 100644 --- a/src/engine/LV2Node.cpp +++ b/src/engine/LV2Node.cpp @@ -138,7 +138,7 @@ LV2Node::apply_poly(Raul::Maid& maid, uint32_t poly) bool LV2Node::instantiate(BufferFactory& bufs) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); SharedPtr info = _lv2_plugin->lv2_info(); SLV2Plugin plug = _lv2_plugin->slv2_plugin(); @@ -148,7 +148,7 @@ LV2Node::instantiate(BufferFactory& bufs) _ports = new Raul::Array(num_ports, NULL); _instances = new Instances(_polyphony, SharedPtr()); - _features = info->world().lv2_features->lv2_features(this); + _features = info->world().lv2_features()->lv2_features(this); uint32_t port_buffer_size = 0; SLV2Value ctx_ext_uri = slv2_value_new_uri(info->lv2_world(), LV2_CONTEXT_MESSAGE); @@ -309,8 +309,8 @@ LV2Node::instantiate(BufferFactory& bufs) SLV2Values types = slv2_port_get_value(plug, id, supports_pred); for (uint32_t i = 0; i < slv2_values_size(types); ++i) { SLV2Value type = slv2_values_get_at(types, i); - std::cout << path() << " port " << id << " supports " << - slv2_value_as_uri(type) << std::endl; + Raul::info << path() << " port " << id << " supports " << + slv2_value_as_uri(type) << std::endl; if (slv2_value_is_uri(type)) { port->add_property(uris.obj_supports, Raul::URI(slv2_value_as_uri(type))); } diff --git a/src/engine/LV2Plugin.cpp b/src/engine/LV2Plugin.cpp index 76c2290d..a49818f5 100644 --- a/src/engine/LV2Plugin.cpp +++ b/src/engine/LV2Plugin.cpp @@ -32,12 +32,11 @@ namespace Ingen { LV2Plugin::LV2Plugin(SharedPtr lv2_info, const std::string& uri) - : PluginImpl(Plugin::LV2, uri) + : PluginImpl(*lv2_info->world().uris().get(), Plugin::LV2, uri) , _slv2_plugin(NULL) , _lv2_info(lv2_info) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - set_property(uris.rdf_type, uris.lv2_Plugin); + set_property(_uris.rdf_type, _uris.lv2_Plugin); } @@ -73,7 +72,7 @@ LV2Plugin::instantiate(BufferFactory& bufs, load(); // FIXME: unload at some point - Glib::Mutex::Lock lock(engine.world()->rdf_world->mutex()); + Glib::Mutex::Lock lock(engine.world()->rdf_world()->mutex()); LV2Node* n = new LV2Node(this, name, polyphonic, parent, srate); if ( ! n->instantiate(bufs) ) { diff --git a/src/engine/MessageContext.cpp b/src/engine/MessageContext.cpp index ec0fedbf..2e37f69a 100644 --- a/src/engine/MessageContext.cpp +++ b/src/engine/MessageContext.cpp @@ -37,17 +37,17 @@ namespace Ingen { void MessageContext::run(PortImpl* port, FrameTime time) { - if (ThreadManager::current_thread_id() == THREAD_PRE_PROCESS) { + if (ThreadManager::thread_is(THREAD_PRE_PROCESS)) { assert(port); Glib::Mutex::Lock lock(_mutex); _non_rt_request = Request(time, port); _sem.post(); _cond.wait(_mutex); - } else if (ThreadManager::current_thread_id() == THREAD_PROCESS) { + } else if (ThreadManager::thread_is(THREAD_PROCESS)) { Request r(time, port); _requests.write(sizeof(Request), &r); // signal() will be called at the end of this process cycle - } else if (ThreadManager::current_thread_id() == THREAD_MESSAGE) { + } else if (ThreadManager::thread_is(THREAD_MESSAGE)) { warn << "Message context recursion at " << port->path() << endl; } else { error << "Run requested from unknown thread" << endl; diff --git a/src/engine/NodeFactory.cpp b/src/engine/NodeFactory.cpp index 5ff21c04..c20afed8 100644 --- a/src/engine/NodeFactory.cpp +++ b/src/engine/NodeFactory.cpp @@ -66,8 +66,7 @@ NodeFactory::NodeFactory(Ingen::Shared::World* world) NodeFactory::~NodeFactory() { for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) - if (i->second->type() != Shared::Plugin::Internal) - delete i->second; + delete i->second; _plugins.clear(); } @@ -111,7 +110,7 @@ NodeFactory::load_plugins() { ThreadManager::assert_thread(THREAD_PRE_PROCESS); - _world->rdf_world->mutex().lock(); + _world->rdf_world()->mutex().lock(); // 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 @@ -132,24 +131,25 @@ NodeFactory::load_plugins() _has_loaded = true; } - _world->rdf_world->mutex().unlock(); + _world->rdf_world()->mutex().unlock(); } void NodeFactory::load_internal_plugins() { - InternalPlugin& controller_plug = ControllerNode::internal_plugin(); - _plugins.insert(make_pair(controller_plug.uri(), &controller_plug)); + Shared::LV2URIMap& uris = *_world->uris().get(); + InternalPlugin* controller_plug = ControllerNode::internal_plugin(uris); + _plugins.insert(make_pair(controller_plug->uri(), controller_plug)); - InternalPlugin& delay_plug = DelayNode::internal_plugin(); - _plugins.insert(make_pair(delay_plug.uri(), &delay_plug)); + InternalPlugin* delay_plug = DelayNode::internal_plugin(uris); + _plugins.insert(make_pair(delay_plug->uri(), delay_plug)); - InternalPlugin& note_plug = NoteNode::internal_plugin(); - _plugins.insert(make_pair(note_plug.uri(), ¬e_plug)); + InternalPlugin* note_plug = NoteNode::internal_plugin(uris); + _plugins.insert(make_pair(note_plug->uri(), note_plug)); - InternalPlugin& trigger_plug = TriggerNode::internal_plugin(); - _plugins.insert(make_pair(trigger_plug.uri(), &trigger_plug)); + InternalPlugin* trigger_plug = TriggerNode::internal_plugin(uris); + _plugins.insert(make_pair(trigger_plug->uri(), trigger_plug)); } @@ -159,7 +159,7 @@ NodeFactory::load_internal_plugins() void NodeFactory::load_lv2_plugins() { - SLV2Plugins plugins = slv2_world_get_all_plugins(_world->slv2_world); + SLV2Plugins plugins = slv2_world_get_all_plugins(_world->slv2_world()); for (unsigned i=0; i < slv2_plugins_size(plugins); ++i) { @@ -177,7 +177,7 @@ NodeFactory::load_lv2_plugins() _plugins.insert(make_pair(uri, plugin)); } - slv2_plugins_free(_world->slv2_world, plugins); + slv2_plugins_free(_world->slv2_world(), plugins); } #endif // HAVE_SLV2 @@ -254,10 +254,11 @@ NodeFactory::load_ladspa_plugins() const Plugins::const_iterator i = _plugins.find(uri); if (i == _plugins.end()) { - LADSPAPlugin* plugin = new LADSPAPlugin(lib_path, uri, - descriptor->UniqueID, - descriptor->Label, - descriptor->Name); + LADSPAPlugin* plugin = new LADSPAPlugin(*_world->uris().get(), + lib_path, uri, + descriptor->UniqueID, + descriptor->Label, + descriptor->Name); _plugins.insert(make_pair(uri, plugin)); diff --git a/src/engine/NodeImpl.cpp b/src/engine/NodeImpl.cpp index 332b69b2..d3639634 100644 --- a/src/engine/NodeImpl.cpp +++ b/src/engine/NodeImpl.cpp @@ -36,7 +36,7 @@ namespace Ingen { NodeImpl::NodeImpl(PluginImpl* plugin, const Raul::Symbol& symbol, bool polyphonic, PatchImpl* parent, SampleRate srate) - : GraphObjectImpl(parent, symbol) + : GraphObjectImpl(plugin->uris(), parent, symbol) , _plugin(plugin) , _polyphonic(polyphonic) , _polyphony((polyphonic && parent) ? parent->internal_poly() : 1) diff --git a/src/engine/ObjectSender.cpp b/src/engine/ObjectSender.cpp index 0055dff1..d2f00bba 100644 --- a/src/engine/ObjectSender.cpp +++ b/src/engine/ObjectSender.cpp @@ -136,13 +136,11 @@ ObjectSender::send_port(ClientInterface* client, const PortImpl* port, bool bund if (graph_parent) client->put(port->meta_uri(), port->meta().properties()); - const Shared::LV2URIMap& map = Shared::LV2URIMap::instance(); - client->put(port->path(), port->properties()); // Send control value if (port->is_a(PortType::CONTROL)) - client->set_property(port->path(), map.ingen_value, port->value()); + client->set_property(port->path(), port->bufs().uris().ingen_value, port->value()); if (bundle) client->bundle_end(); diff --git a/src/engine/OutputPort.cpp b/src/engine/OutputPort.cpp index 5509b655..8faefb3e 100644 --- a/src/engine/OutputPort.cpp +++ b/src/engine/OutputPort.cpp @@ -39,10 +39,8 @@ OutputPort::OutputPort(BufferFactory& bufs, size_t buffer_size) : PortImpl(bufs, parent, symbol, index, poly, type, value, buffer_size) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - if (!dynamic_cast(parent)) - add_property(uris.rdf_type, uris.lv2_OutputPort); + add_property(bufs.uris().rdf_type, bufs.uris().lv2_OutputPort); if (type == PortType::CONTROL) _broadcast = true; diff --git a/src/engine/PatchImpl.cpp b/src/engine/PatchImpl.cpp index 5d3b07a5..bce74b6b 100644 --- a/src/engine/PatchImpl.cpp +++ b/src/engine/PatchImpl.cpp @@ -18,6 +18,8 @@ #include #include #include "raul/log.hpp" +#include "module/World.hpp" +#include "shared/LV2URIMap.hpp" #include "ThreadManager.hpp" #include "NodeImpl.hpp" #include "PatchImpl.hpp" @@ -39,7 +41,8 @@ using namespace Shared; PatchImpl::PatchImpl(Engine& engine, const Raul::Symbol& symbol, uint32_t poly, PatchImpl* parent, SampleRate srate, uint32_t internal_poly) - : NodeImpl(new PatchPlugin("http://example.org/FIXME", "patch", "Ingen Patch"), + : NodeImpl(new PatchPlugin(*engine.world()->uris().get(), + engine.world()->uris()->ingen_Patch.c_str(), "patch", "Ingen Patch"), symbol, poly, parent, srate) , _engine(engine) , _internal_poly(internal_poly) @@ -338,9 +341,7 @@ PatchImpl::has_connection(const PortImpl* src_port, const PortImpl* dst_port) co uint32_t PatchImpl::num_ports() const { - ThreadID context = ThreadManager::current_thread_id(); - - if (context == THREAD_PROCESS) + if (ThreadManager::thread_is(THREAD_PROCESS)) return NodeImpl::num_ports(); else return _input_ports.size() + _output_ports.size(); diff --git a/src/engine/PatchPlugin.hpp b/src/engine/PatchPlugin.hpp index e4feb992..7f0ebe82 100644 --- a/src/engine/PatchPlugin.hpp +++ b/src/engine/PatchPlugin.hpp @@ -35,10 +35,12 @@ class NodeImpl; class PatchPlugin : public PluginImpl { public: - PatchPlugin(const std::string& uri, - const std::string& symbol, - const std::string& name) - : PluginImpl(Plugin::Patch, uri) + PatchPlugin( + Shared::LV2URIMap& uris, + const std::string& uri, + const std::string& symbol, + const std::string& name) + : PluginImpl(uris, Plugin::Patch, uri) {} NodeImpl* instantiate(BufferFactory& bufs, diff --git a/src/engine/PluginImpl.hpp b/src/engine/PluginImpl.hpp index 5aea4f68..ee33eff7 100644 --- a/src/engine/PluginImpl.hpp +++ b/src/engine/PluginImpl.hpp @@ -28,6 +28,8 @@ namespace Ingen { +namespace Shared { class LV2URIMap; } + class PatchImpl; class NodeImpl; class Engine; @@ -43,8 +45,9 @@ class PluginImpl : public Ingen::Shared::Plugin , public boost::noncopyable { public: - PluginImpl(Type type, const std::string& uri, const std::string library_path="") - : ResourceImpl(uri) + PluginImpl(Shared::LV2URIMap& uris, + Type type, const std::string& uri, const std::string library_path="") + : ResourceImpl(uris, uri) , _type(type) , _library_path(library_path) , _module(NULL) diff --git a/src/engine/PortImpl.cpp b/src/engine/PortImpl.cpp index 7abfb90d..0a8de1de 100644 --- a/src/engine/PortImpl.cpp +++ b/src/engine/PortImpl.cpp @@ -48,7 +48,7 @@ PortImpl::PortImpl(BufferFactory& bufs, PortType type, const Atom& value, size_t buffer_size) - : GraphObjectImpl(node, name) + : GraphObjectImpl(bufs.uris(), node, name) , _bufs(bufs) , _index(index) , _poly(poly) @@ -69,7 +69,7 @@ PortImpl::PortImpl(BufferFactory& bufs, if (_buffer_size == 0) _buffer_size = bufs.default_buffer_size(type); - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); add_property(uris.rdf_type, type.uri()); set_property(uris.lv2_index, Atom((int32_t)index)); set_context(_context); @@ -88,7 +88,7 @@ PortImpl::~PortImpl() bool PortImpl::supports(const Raul::URI& value_type) const { - return has_property(Shared::LV2URIMap::instance().obj_supports, value_type); + return has_property(_bufs.uris().obj_supports, value_type); } @@ -227,7 +227,7 @@ PortImpl::broadcast_value(Context& context, bool force) break; case PortType::VALUE: case PortType::MESSAGE: - LV2Object::to_atom(((ObjectBuffer*)buffer(0).get())->object(), val); + LV2Object::to_atom(_bufs.uris(), ((ObjectBuffer*)buffer(0).get())->object(), val); break; } @@ -242,11 +242,11 @@ PortImpl::broadcast_value(Context& context, bool force) void PortImpl::set_context(Context::ID c) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = _bufs.uris(); _context = c; switch (c) { case Context::AUDIO: - set_property(uris.ctx_context, uris.ctx_AudioContext); + remove_property(uris.ctx_context, uris.wildcard); break; case Context::MESSAGE: set_property(uris.ctx_context, uris.ctx_MessageContext); diff --git a/src/engine/PortImpl.hpp b/src/engine/PortImpl.hpp index cb458d01..efc5e92d 100644 --- a/src/engine/PortImpl.hpp +++ b/src/engine/PortImpl.hpp @@ -136,6 +136,8 @@ public: Context::ID context() const { return _context; } void set_context(Context::ID c); + BufferFactory& bufs() const { return _bufs; } + protected: PortImpl(BufferFactory& bufs, NodeImpl* node, diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp index d07bfe10..53bec047 100644 --- a/src/engine/QueuedEngineInterface.cpp +++ b/src/engine/QueuedEngineInterface.cpp @@ -225,7 +225,7 @@ QueuedEngineInterface::set_property(const URI& uri, bool meta = (hash != string::npos); Path path = meta ? (string("/") + path.chop_start("/")) : uri.str(); Resource::Properties remove; - remove.insert(make_pair(predicate, Shared::LV2URIMap::instance().wildcard)); + remove.insert(make_pair(predicate, _engine.world()->uris()->wildcard)); Resource::Properties add; add.insert(make_pair(predicate, value)); push_queued(new Events::SetMetadata(_engine, _request, now(), false, meta, path, add, remove)); diff --git a/src/engine/ThreadManager.hpp b/src/engine/ThreadManager.hpp index 3f86ba83..2dc7d4d5 100644 --- a/src/engine/ThreadManager.hpp +++ b/src/engine/ThreadManager.hpp @@ -34,16 +34,16 @@ enum ThreadID { class ThreadManager { public: - inline static ThreadID current_thread_id() { - return (ThreadID)Raul::Thread::get().context(); + inline static bool thread_is(ThreadID id) { + return Raul::Thread::get().is_context(id); } inline static void assert_thread(ThreadID id) { - assert(single_threaded || current_thread_id() == id); + assert(single_threaded || Raul::Thread::get().is_context(id)); } inline static void assert_not_thread(ThreadID id) { - assert(single_threaded || current_thread_id() != id); + assert(single_threaded || !Raul::Thread::get().is_context(id)); } /** Set to true during initialisation so ensure_thread doesn't fail. diff --git a/src/engine/events/CreateNode.cpp b/src/engine/events/CreateNode.cpp index dc3f4469..1e428fdc 100644 --- a/src/engine/events/CreateNode.cpp +++ b/src/engine/events/CreateNode.cpp @@ -81,8 +81,8 @@ CreateNode::CreateNode( _plugin_label = uri; } - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - const Resource::Properties::const_iterator p = properties.find(uris.ingen_polyphonic); + const Resource::Properties::const_iterator p = properties.find( + engine.world()->uris()->ingen_polyphonic); if (p != properties.end() && p->second.type() == Raul::Atom::BOOL && p->second.get_bool()) _polyphonic = true; diff --git a/src/engine/events/CreatePatch.cpp b/src/engine/events/CreatePatch.cpp index 5f87d605..17a27d11 100644 --- a/src/engine/events/CreatePatch.cpp +++ b/src/engine/events/CreatePatch.cpp @@ -83,7 +83,7 @@ CreatePatch::pre_process() if (_parent != NULL && _poly > 1 && _poly == static_cast(_parent->internal_poly())) poly = _poly; - const LV2URIMap& uris = *_engine.world()->uris.get(); + const LV2URIMap& uris = *_engine.world()->uris().get(); _patch = new PatchImpl(_engine, path.symbol(), poly, _parent, _engine.driver()->sample_rate(), _poly); diff --git a/src/engine/events/CreatePort.cpp b/src/engine/events/CreatePort.cpp index 33477400..cb76e9a2 100644 --- a/src/engine/events/CreatePort.cpp +++ b/src/engine/events/CreatePort.cpp @@ -84,7 +84,7 @@ CreatePort::pre_process() _patch = _engine.engine_store()->find_patch(_path.parent()); - const LV2URIMap& uris = *_engine.world()->uris.get(); + const LV2URIMap& uris = *_engine.world()->uris().get(); if (_patch != NULL) { assert(_patch->path() == _path.parent()); diff --git a/src/engine/events/Delete.cpp b/src/engine/events/Delete.cpp index 9e4548ac..45c54260 100644 --- a/src/engine/events/Delete.cpp +++ b/src/engine/events/Delete.cpp @@ -42,6 +42,7 @@ Delete::Delete(Engine& engine, SharedPtr request, FrameTime time, const : QueuedEvent(engine, request, time, true) , _path(path) , _store_iterator(engine.engine_store()->end()) + , _garbage(NULL) , _driver_port(NULL) , _patch_node_listnode(NULL) , _patch_port_listnode(NULL) @@ -153,9 +154,8 @@ Delete::execute(ProcessContext& context) _engine.maid()->push(_port->parent_patch()->external_ports()); _port->parent_patch()->external_ports(_ports_array); - if ( ! _port->parent_patch()->parent()) { - _driver_port = _engine.driver()->remove_port(_port->path()); - } + if ( ! _port->parent_patch()->parent()) + _garbage = _engine.driver()->remove_port(_port->path(), &_driver_port); } if (parent_patch) { @@ -201,10 +201,10 @@ Delete::post_process() _request->respond_error("Unable to delete object " + _path.chop_scheme()); } - if (_driver_port) { - _driver_port->elem()->destroy(); - _engine.maid()->push(_driver_port); - } + if (_driver_port) + _driver_port->destroy(); + + _engine.maid()->push(_garbage); } diff --git a/src/engine/events/Delete.hpp b/src/engine/events/Delete.hpp index be786c56..54a02d9f 100644 --- a/src/engine/events/Delete.hpp +++ b/src/engine/events/Delete.hpp @@ -75,7 +75,8 @@ private: EngineStore::iterator _store_iterator; SharedPtr _node; ///< Non-NULL iff a node SharedPtr _port; ///< Non-NULL iff a port - Raul::List::Node* _driver_port; + Raul::Deletable* _garbage; + DriverPort* _driver_port; PatchImpl::Nodes::Node* _patch_node_listnode; Raul::List::Node* _patch_port_listnode; Raul::Array* _ports_array; ///< New (external) ports for Patch diff --git a/src/engine/events/RequestMetadata.cpp b/src/engine/events/RequestMetadata.cpp index 69c5b271..5efc7072 100644 --- a/src/engine/events/RequestMetadata.cpp +++ b/src/engine/events/RequestMetadata.cpp @@ -74,7 +74,7 @@ RequestMetadata::pre_process() GraphObjectImpl* obj = dynamic_cast(_resource); if (obj) { - if (_key == _engine.world()->uris->ingen_value) + if (_key == _engine.world()->uris()->ingen_value) _special_type = PORT_VALUE; else if (_is_meta) _value = obj->meta().get_property(_key); @@ -101,7 +101,7 @@ RequestMetadata::execute(ProcessContext& context) } else { IntrusivePtr obuf = PtrCast(port->buffer(0)); if (obuf) { - LV2Object::to_atom(obuf->object(), _value); + LV2Object::to_atom(*_engine.world()->uris().get(), obuf->object(), _value); } } } else { @@ -119,7 +119,7 @@ RequestMetadata::post_process() if (_resource) { _request->respond_ok(); _request->client()->set_property(_uri.str(), - _engine.world()->uris->ingen_value, _value); + _engine.world()->uris()->ingen_value, _value); } else { const string msg = "Get value for non-port " + _uri.str(); _request->respond_error(msg); diff --git a/src/engine/events/SendBinding.cpp b/src/engine/events/SendBinding.cpp index c3c83ea4..82736f53 100644 --- a/src/engine/events/SendBinding.cpp +++ b/src/engine/events/SendBinding.cpp @@ -31,7 +31,7 @@ namespace Events { void SendBinding::post_process() { - const LV2URIMap& uris = *_engine.world()->uris.get(); + const LV2URIMap& uris = *_engine.world()->uris().get(); Raul::Atom::DictValue dict; if (_type == ControlBindings::MIDI_CC) { dict[uris.rdf_type] = uris.midi_Controller; diff --git a/src/engine/events/SendPortValue.cpp b/src/engine/events/SendPortValue.cpp index e6bf7ad9..394decad 100644 --- a/src/engine/events/SendPortValue.cpp +++ b/src/engine/events/SendPortValue.cpp @@ -33,7 +33,7 @@ SendPortValue::post_process() { _engine.broadcaster()->set_property( _port->path(), - _engine.world()->uris->ingen_value, _value); + _engine.world()->uris()->ingen_value, _value); } diff --git a/src/engine/events/SetMetadata.cpp b/src/engine/events/SetMetadata.cpp index 6b0e5832..8066a4e9 100644 --- a/src/engine/events/SetMetadata.cpp +++ b/src/engine/events/SetMetadata.cpp @@ -111,13 +111,13 @@ SetMetadata::pre_process() return; } - const LV2URIMap& uris = *_engine.world()->uris.get(); + const LV2URIMap& uris = *_engine.world()->uris().get(); if (is_graph_object && !_object) { Path path(_subject.str()); bool is_patch = false, is_node = false, is_port = false, is_output = false; PortType data_type(PortType::UNKNOWN); - ResourceImpl::type(_properties, is_patch, is_node, is_port, is_output, data_type); + ResourceImpl::type(uris, _properties, is_patch, is_node, is_port, is_output, data_type); // Create a separate request without a source so EventSource isn't unblocked twice SharedPtr sub_request(new Request(NULL, _request->client(), _request->id())); diff --git a/src/engine/events/SetPortValue.cpp b/src/engine/events/SetPortValue.cpp index b93783c2..1a41938d 100644 --- a/src/engine/events/SetPortValue.cpp +++ b/src/engine/events/SetPortValue.cpp @@ -102,7 +102,7 @@ SetPortValue::pre_process() if (_port) { _port->set_value(_value); - _port->set_property(_engine.world()->uris->ingen_value, _value); + _port->set_property(_engine.world()->uris()->ingen_value, _value); } QueuedEvent::pre_process(); @@ -151,7 +151,7 @@ SetPortValue::apply(Context& context) return; } - SharedPtr uris = _engine.world()->uris; + LV2URIMap& uris = *_engine.world()->uris().get(); EventBuffer* const ebuf = dynamic_cast(buf); if (ebuf) { @@ -159,14 +159,14 @@ SetPortValue::apply(Context& context) // Size 0 event, pass it along to the plugin as a typed but empty event if (_value.data_size() == 0) { - const uint32_t type_id = uris->uri_to_id(NULL, _value.get_blob_type()); + const uint32_t type_id = uris.uri_to_id(NULL, _value.get_blob_type()); ebuf->append(frames, 0, type_id, 0, NULL); _port->raise_set_by_user_flag(); return; } else if (!strcmp(_value.get_blob_type(), "http://lv2plug.in/ns/ext/midi#MidiEvent")) { ebuf->prepare_write(context); - ebuf->append(frames, 0, uris->midi_event.id, _value.data_size(), + ebuf->append(frames, 0, uris.midi_event.id, _value.data_size(), (const uint8_t*)_value.get_blob()); _port->raise_set_by_user_flag(); return; @@ -176,7 +176,7 @@ SetPortValue::apply(Context& context) ObjectBuffer* const obuf = dynamic_cast(buf); if (obuf) { obuf->object()->size = obuf->size() - sizeof(LV2_Object); - if (LV2Object::from_atom(_value, obuf->object())) { + if (LV2Object::from_atom(uris, _value, obuf->object())) { debug << "Converted atom " << _value << " :: " << obuf->object()->type << " * " << obuf->object()->size << " @ " << obuf->object() << endl; return; @@ -200,7 +200,7 @@ SetPortValue::post_process() assert(_port != NULL); _request->respond_ok(); _engine.broadcaster()->set_property(_port_path, - _engine.world()->uris->ingen_value, _value); + _engine.world()->uris()->ingen_value, _value); break; case TYPE_MISMATCH: ss << "Illegal value type " << _value.type() diff --git a/src/engine/ingen_engine.cpp b/src/engine/ingen_engine.cpp index b2f626c7..d25bcf46 100644 --- a/src/engine/ingen_engine.cpp +++ b/src/engine/ingen_engine.cpp @@ -25,13 +25,15 @@ using namespace Ingen; struct IngenEngineModule : public Ingen::Shared::Module { - void load(Ingen::Shared::World* world) { + virtual void load(Ingen::Shared::World* world) { set_denormal_flags(); - world->local_engine = SharedPtr(new Engine(world)); + SharedPtr engine(new Ingen::Engine(world)); + world->set_local_engine(engine); SharedPtr interface( - new Ingen::QueuedEngineInterface(*world->local_engine, event_queue_size)); - world->engine = interface; - world->local_engine->add_event_source(interface); + new Ingen::QueuedEngineInterface(*engine.get(), event_queue_size)); + world->set_engine(interface); + engine->add_event_source(interface); + assert(world->local_engine() == engine); } }; diff --git a/src/engine/ingen_http.cpp b/src/engine/ingen_http.cpp index 86ac481a..ffd26f2a 100644 --- a/src/engine/ingen_http.cpp +++ b/src/engine/ingen_http.cpp @@ -27,9 +27,9 @@ using namespace Ingen; struct IngenHTTPModule : public Ingen::Shared::Module { void load(Ingen::Shared::World* world) { SharedPtr interface( - new Ingen::HTTPEngineReceiver(*world->local_engine.get(), - world->conf->option("engine-port").get_int32())); - world->local_engine->add_event_source(interface); + new Ingen::HTTPEngineReceiver(*world->local_engine().get(), + world->conf()->option("engine-port").get_int32())); + world->local_engine()->add_event_source(interface); } }; diff --git a/src/engine/ingen_jack.cpp b/src/engine/ingen_jack.cpp index cdf9199e..cb4aff89 100644 --- a/src/engine/ingen_jack.cpp +++ b/src/engine/ingen_jack.cpp @@ -25,10 +25,10 @@ using namespace Ingen; struct IngenJackModule : public Ingen::Shared::Module { void load(Ingen::Shared::World* world) { - Ingen::JackDriver* driver = new Ingen::JackDriver(*world->local_engine.get()); - driver->attach(world->conf->option("jack-server").get_string(), - world->conf->option("jack-client").get_string(), NULL); - world->local_engine->set_driver(SharedPtr(driver)); + Ingen::JackDriver* driver = new Ingen::JackDriver(*world->local_engine().get()); + driver->attach(world->conf()->option("jack-server").get_string(), + world->conf()->option("jack-client").get_string(), NULL); + world->local_engine()->set_driver(SharedPtr(driver)); } }; diff --git a/src/engine/ingen_lv2.cpp b/src/engine/ingen_lv2.cpp index 424df46c..8d14cba7 100644 --- a/src/engine/ingen_lv2.cpp +++ b/src/engine/ingen_lv2.cpp @@ -16,55 +16,177 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef PLUGIN_URI -#error "This file requires PLUGIN_URI to be defined" -#endif - #include +#include +#include +#include #include "lv2.h" +#include "ingen-config.h" +#include "raul/log.hpp" +#include "raul/Thread.hpp" +#include "raul/SharedPtr.hpp" +#include "engine/AudioBuffer.hpp" #include "engine/Engine.hpp" +#include "engine/ThreadManager.hpp" #include "engine/Driver.hpp" #include "engine/ProcessContext.hpp" #include "engine/PatchImpl.hpp" +#include "engine/QueuedEngineInterface.hpp" #include "module/World.hpp" - -extern "C" { +#include "module/ingen_module.hpp" +#include "shared/runtime_paths.hpp" +#include "shared/Configuration.hpp" +#include "serialisation/Parser.hpp" +#include "interface/EngineInterface.hpp" using namespace Ingen; -/* Plugin */ +namespace Ingen { +namespace LV2 { + +/** Record of a patch found in this LV2 bundle */ +struct LV2Patch { + LV2Patch(const std::string& u, const std::string& f); + + const std::string uri; + const std::string filename; + LV2_Descriptor descriptor; +}; + + +/* Static library data */ +typedef std::vector< SharedPtr > LV2Patches; +static bool initialised = false; +static LV2Patches patches; +static Configuration conf; +static int argc = 0; +static char** argv = NULL; +static Shared::World* world = NULL; + + +struct LV2Driver; + +class LV2Port : public DriverPort +{ +public: + LV2Port(LV2Driver* driver, DuplexPort* patch_port) + : DriverPort(patch_port) + , _driver(driver) + , _buffer(NULL) + {} + + // TODO: LV2 dynamic ports + void create() {} + void destroy() {} + void move(const Raul::Path& path) {} + + void pre_process(ProcessContext& context) { + if (!is_input() || !_buffer) + return; + + if (_patch_port->buffer_type() == PortType::AUDIO) { + AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); + patch_buf->copy((Sample*)_buffer, 0, context.nframes() - 1); + } else if (_patch_port->buffer_type() == PortType::EVENTS) { + //Raul::warn << "TODO: LV2 event I/O" << std::endl; + } + } + + void post_process(ProcessContext& context) { + if (is_input() || !_buffer) + return; -struct IngenLV2Driver : public Ingen::Driver { - IngenLV2Driver(Engine& engine, SampleCount buffer_size, SampleCount sample_rate) + if (_patch_port->buffer_type() == PortType::AUDIO) { + AudioBuffer* patch_buf = (AudioBuffer*)_patch_port->buffer(0).get(); + memcpy((Sample*)_buffer, patch_buf->data(), context.nframes() * sizeof(Sample)); + } else if (_patch_port->buffer_type() == PortType::EVENTS) { + //Raul::warn << "TODO: LV2 event I/O" << std::endl; + } + } + + void* buffer() const { return _buffer; } + void set_buffer(void* buf) { _buffer = buf; } + +private: + LV2Driver* _driver; + void* _buffer; +}; + + +struct LV2Driver : public Driver { +private: + typedef std::vector Ports; + +public: + LV2Driver(Engine& engine, SampleCount buffer_size, SampleCount sample_rate) : _context(engine) + , _root_patch(NULL) , _buffer_size(buffer_size) , _sample_rate(sample_rate) , _frame_time(0) - , _root_patch(NULL) {} - void activate() {} - void deactivate() {} - bool is_activated() const { return true; } - void run(uint32_t nframes) { _context.locate(_frame_time, nframes, 0); + + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) + (*i)->pre_process(_context); + if (_root_patch) _root_patch->process(_context); + + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) + (*i)->post_process(_context); + _frame_time += nframes; } - virtual void set_root_patch(PatchImpl* patch) {} - virtual PatchImpl* root_patch() { return NULL; } + virtual void set_root_patch(PatchImpl* patch) { _root_patch = patch; } + virtual PatchImpl* root_patch() { return _root_patch; } + + virtual void add_port(DriverPort* port) { + // Note this doesn't have to be realtime safe since there's no dynamic LV2 ports + ThreadManager::assert_thread(THREAD_PROCESS); + assert(dynamic_cast(port)); + assert(port->patch_port()->index() == _ports.size()); + _ports.push_back((LV2Port*)port); + } + + virtual Raul::Deletable* remove_port(const Raul::Path& path, Ingen::DriverPort** port=NULL) { + // Note this doesn't have to be realtime safe since there's no dynamic LV2 ports + ThreadManager::assert_thread(THREAD_PROCESS); + + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) { + if ((*i)->patch_port()->path() == path) { + _ports.erase(i); + return NULL; + } + } + + Raul::warn << "Unable to find port " << path << std::endl; + return NULL; + } + + + virtual bool supports(Shared::PortType port_type, Shared::EventType event_type) { + return true; + } + + virtual DriverPort* create_port(DuplexPort* patch_port) { + return new LV2Port(this, patch_port); + } - virtual void add_port(DriverPort* port) {} - virtual DriverPort* remove_port(const Raul::Path& path) { return NULL; } + virtual DriverPort* driver_port(const Raul::Path& path) { + ThreadManager::assert_thread(THREAD_PROCESS); - virtual DriverPort* create_port(DuplexPort* patch_port) { return NULL; } + for (Ports::iterator i = _ports.begin(); i != _ports.end(); ++i) + if ((*i)->patch_port()->path() == path) + return (*i); - virtual DriverPort* driver_port(const Raul::Path& path) { return NULL; } + return NULL; + } - virtual SampleCount buffer_size() const { return _buffer_size; } + virtual SampleCount block_length() const { return _buffer_size; } virtual SampleCount sample_rate() const { return _sample_rate; } virtual SampleCount frame_time() const { return _frame_time;} @@ -77,30 +199,84 @@ private: SampleCount _buffer_size; SampleCount _sample_rate; SampleCount _frame_time; + Ports _ports; }; +} // namespace LV2 +} // namespace Ingen + + +/* LV2 Plugin Interface */ + +extern "C" { + struct IngenPlugin { - Ingen::Shared::World* world; - SharedPtr engine; + Ingen::Shared::World* world; }; -static void -ingen_activate(LV2_Handle instance) +static LV2_Handle +ingen_instantiate(const LV2_Descriptor* descriptor, + double rate, + const char* bundle_path, + const LV2_Feature*const* features) { - IngenPlugin* plugin = (IngenPlugin*)instance; - plugin->engine->activate(1); -} + Shared::set_bundle_path(bundle_path); + using namespace LV2; -static void -ingen_cleanup(LV2_Handle instance) -{ - IngenPlugin* plugin = (IngenPlugin*)instance; - plugin->engine.reset(); - ingen_destroy_world(); - free(instance); + const LV2Patch* patch = NULL; + for (LV2Patches::iterator i = patches.begin(); i != patches.end(); ++i) { + if (&(*i)->descriptor == descriptor) { + patch = (*i).get(); + break; + } + } + + if (!patch) { + Raul::error << "Could not find patch " << descriptor->URI << std::endl; + return NULL; + } + + IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); + //plugin->world = ingen_world_new(&conf, argc, argv); + plugin->world = LV2::world; + + SharedPtr engine(new Engine(plugin->world)); + plugin->world->set_local_engine(engine); + + SharedPtr interface( + new Ingen::QueuedEngineInterface(*plugin->world->local_engine(), event_queue_size)); + plugin->world->set_engine(interface); + plugin->world->local_engine()->add_event_source(interface); + + Raul::Thread::get().set_context(THREAD_PRE_PROCESS); + ThreadManager::single_threaded = true; + + ProcessContext context(*engine.get()); + + // FIXME: fixed (or at least maximum) buffer size + engine->set_driver(SharedPtr(new LV2Driver(*engine.get(), rate, 4096))); + + engine->activate(); + ThreadManager::single_threaded = true; + + // FIXME: don't load all plugins, only necessary ones + plugin->world->engine()->load_plugins(); + engine->process_events(context); + + plugin->world->parser()->parse_document(plugin->world, + plugin->world->engine().get(), patch->filename); + engine->process_events(context); + + engine->deactivate(); + + // Activate and deactivate to create root patch, allocate buffers, etc + //engine->activate(); + //engine->deactivate(); + + return (LV2_Handle)plugin; } @@ -110,33 +286,40 @@ ingen_connect_port(LV2_Handle instance, uint32_t port, void* data) } -static LV2_Handle -ingen_instantiate(const LV2_Descriptor* descriptor, - double rate, - const char* bundle_path, - const LV2_Feature*const* features) +static void +ingen_activate(LV2_Handle instance) { - IngenPlugin* plugin = (IngenPlugin*)malloc(sizeof(IngenPlugin)); + IngenPlugin* me = (IngenPlugin*)instance; + me->world->local_engine()->activate(); +} - Shared::bundle_path = bundle_path; - plugin->world = ingen_get_world(); - plugin->engine = SharedPtr(new Engine(plugin->world)); - plugin->world->local_engine = plugin->engine; +static void +ingen_run(LV2_Handle instance, uint32_t sample_count) +{ + IngenPlugin* me = (IngenPlugin*)instance; + // FIXME: don't do this every call + Raul::Thread::get().set_context(THREAD_PROCESS); + ((LV2::LV2Driver*)me->world->local_engine()->driver())->run(sample_count); +} - // FIXME: fixed buffer size - plugin->engine->set_driver(PortType::AUDIO, - SharedPtr(new IngenLV2Driver(*plugin->engine, rate, 4096))); - return (LV2_Handle)plugin; +static void +ingen_deactivate(LV2_Handle instance) +{ + IngenPlugin* me = (IngenPlugin*)instance; + me->world->local_engine()->deactivate(); } static void -ingen_run(LV2_Handle instance, uint32_t sample_count) +ingen_cleanup(LV2_Handle instance) { - IngenPlugin* plugin = (IngenPlugin*)instance; - ((IngenLV2Driver*)plugin->engine->driver())->run(sample_count); + IngenPlugin* me = (IngenPlugin*)instance; + me->world->set_local_engine(SharedPtr()); + me->world->set_engine(SharedPtr()); + //ingen_world_free(me->world); + free(instance); } @@ -147,47 +330,79 @@ ingen_extension_data(const char* uri) } -static void -ingen_deactivate(LV2_Handle instance) +/* Library Code */ + +namespace Ingen { +namespace LV2 { + +LV2Patch::LV2Patch(const std::string& u, const std::string& f) + : uri(u), filename(f) { - IngenPlugin* plugin = (IngenPlugin*)instance; - plugin->engine->deactivate(); + descriptor.URI = uri.c_str(); + descriptor.instantiate = ingen_instantiate; + descriptor.connect_port = ingen_connect_port; + descriptor.activate = ingen_activate; + descriptor.run = ingen_run; + descriptor.deactivate = ingen_deactivate; + descriptor.cleanup = ingen_cleanup; + descriptor.extension_data = ingen_extension_data; } +} // namespace LV2 +} // namespace Ingen -/* Library */ - -static LV2_Descriptor *ingen_descriptor = NULL; static void -init_descriptor() +init() { - ingen_descriptor = (LV2_Descriptor*)malloc(sizeof(LV2_Descriptor)); - - ingen_descriptor->URI = PLUGIN_URI; - ingen_descriptor->instantiate = ingen_instantiate; - ingen_descriptor->connect_port = ingen_connect_port; - ingen_descriptor->activate = ingen_activate; - ingen_descriptor->run = ingen_run; - ingen_descriptor->deactivate = ingen_deactivate; - ingen_descriptor->cleanup = ingen_cleanup; - ingen_descriptor->extension_data = ingen_extension_data; + Shared::set_bundle_path_from_code((void*)&init); + + using namespace LV2; + + //Shared::World* world = ingen_world_new(&conf, argc, argv); + + world = ingen_world_new(&conf, argc, argv); + if (!world->load("ingen_serialisation")) { + Raul::error << "Unable to load serialisation module" << std::endl; + //ingen_world_free(world); + return; + } + + + Serialisation::Parser::PatchRecords records( + world->parser()->find_patches(world, + Glib::filename_to_uri(Shared::bundle_file_path("manifest.ttl")))); + + for (Serialisation::Parser::PatchRecords::iterator i = records.begin(); + i != records.end(); ++i) { + patches.push_back(SharedPtr( + new LV2Patch(i->uri.str(), i->filename))); + } + + + //ingen_world_free(world); + + initialised = true; } +/* LV2 Library Interface */ + +extern "C" { + LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor(uint32_t index) { - if (!ingen_descriptor) - init_descriptor(); + if (!LV2::initialised) + init(); - switch (index) { - case 0: - return ingen_descriptor; - default: + if (index >= LV2::patches.size()) return NULL; - } + else + return &LV2::patches[index]->descriptor; +} + } diff --git a/src/engine/ingen_osc.cpp b/src/engine/ingen_osc.cpp index 69c8b279..b4549080 100644 --- a/src/engine/ingen_osc.cpp +++ b/src/engine/ingen_osc.cpp @@ -27,10 +27,10 @@ using namespace Ingen; struct IngenOSCModule : public Ingen::Shared::Module { void load(Ingen::Shared::World* world) { SharedPtr interface( - new Ingen::OSCEngineReceiver(*world->local_engine.get(), + new Ingen::OSCEngineReceiver(*world->local_engine().get(), event_queue_size, - world->conf->option("engine-port").get_int32())); - world->local_engine->add_event_source(interface); + world->conf()->option("engine-port").get_int32())); + world->local_engine()->add_event_source(interface); } }; diff --git a/src/engine/internals/Controller.cpp b/src/engine/internals/Controller.cpp index aeeb1cd1..b65b80d5 100644 --- a/src/engine/internals/Controller.cpp +++ b/src/engine/internals/Controller.cpp @@ -36,19 +36,20 @@ namespace Internals { using namespace Shared; -static InternalPlugin controller_plugin(NS_INTERNALS "Controller", "controller"); - -InternalPlugin& ControllerNode::internal_plugin() { return controller_plugin; } +InternalPlugin* ControllerNode::internal_plugin(Shared::LV2URIMap& uris) { + return new InternalPlugin(uris, NS_INTERNALS "Controller", "controller"); +} -ControllerNode::ControllerNode(BufferFactory& bufs, - const string& path, - bool polyphonic, - PatchImpl* parent, - SampleRate srate) - : NodeImpl(&controller_plugin, path, false, parent, srate) +ControllerNode::ControllerNode(InternalPlugin* plugin, + BufferFactory& bufs, + const string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate) + : NodeImpl(plugin, path, false, parent, srate) , _learning(false) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); _ports = new Raul::Array(6); _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); diff --git a/src/engine/internals/Controller.hpp b/src/engine/internals/Controller.hpp index b3363665..a8c90a2a 100644 --- a/src/engine/internals/Controller.hpp +++ b/src/engine/internals/Controller.hpp @@ -40,7 +40,13 @@ namespace Internals { class ControllerNode : public NodeImpl { public: - ControllerNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); + ControllerNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate); void process(ProcessContext& context); @@ -48,7 +54,7 @@ public: void learn() { _learning = true; } - static InternalPlugin& internal_plugin(); + static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); private: bool _learning; diff --git a/src/engine/internals/Delay.cpp b/src/engine/internals/Delay.cpp index 7910713f..1316c567 100644 --- a/src/engine/internals/Delay.cpp +++ b/src/engine/internals/Delay.cpp @@ -49,18 +49,24 @@ using namespace Shared; static const float MAX_DELAY_SECONDS = 8.0f; -static InternalPlugin note_plugin(NS_INTERNALS "Delay", "delay"); - -InternalPlugin& DelayNode::internal_plugin() { return note_plugin; } +InternalPlugin* DelayNode::internal_plugin(Shared::LV2URIMap& uris) { + return new InternalPlugin(uris, NS_INTERNALS "Delay", "delay"); +} -DelayNode::DelayNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(¬e_plugin, path, polyphonic, parent, srate) +DelayNode::DelayNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate) + : NodeImpl(plugin, path, polyphonic, parent, srate) , _buffer(0) , _buffer_length(0) , _buffer_mask(0) , _write_phase(0) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); _ports = new Raul::Array(3); const float default_delay = 1.0f; diff --git a/src/engine/internals/Delay.hpp b/src/engine/internals/Delay.hpp index 758d32e7..f07a3f4c 100644 --- a/src/engine/internals/Delay.hpp +++ b/src/engine/internals/Delay.hpp @@ -44,14 +44,21 @@ namespace Internals { class DelayNode : public NodeImpl { public: - DelayNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); + DelayNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate); + ~DelayNode(); void activate(BufferFactory& bufs); void process(ProcessContext& context); - static InternalPlugin& internal_plugin(); + static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); float delay_samples() const { return _delay_samples; } diff --git a/src/engine/internals/Note.cpp b/src/engine/internals/Note.cpp index 298af84a..7bdcd6ec 100644 --- a/src/engine/internals/Note.cpp +++ b/src/engine/internals/Note.cpp @@ -43,19 +43,28 @@ namespace Internals { using namespace Shared; -static InternalPlugin note_plugin(NS_INTERNALS "Note", "note"); - -InternalPlugin& NoteNode::internal_plugin() { return note_plugin; } +InternalPlugin* NoteNode::internal_plugin(Shared::LV2URIMap& uris) { + return new InternalPlugin(uris, NS_INTERNALS "Note", "note"); +} -NoteNode::NoteNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(¬e_plugin, path, polyphonic, parent, srate) +NoteNode::NoteNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate) + : NodeImpl(plugin, path, polyphonic, parent, srate) , _voices(new Raul::Array(_polyphony)) , _prepared_voices(NULL) , _sustain(false) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); _ports = new Raul::Array(5); + + std::cout << "NEW NOTE NODE" << std::endl; + _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); _midi_in_port->set_property(uris.lv2_name, "Input"); _ports->at(0) = _midi_in_port; diff --git a/src/engine/internals/Note.hpp b/src/engine/internals/Note.hpp index 2866fb01..58b83782 100644 --- a/src/engine/internals/Note.hpp +++ b/src/engine/internals/Note.hpp @@ -40,7 +40,14 @@ namespace Internals { class NoteNode : public NodeImpl { public: - NoteNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); + NoteNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate); + ~NoteNode(); bool prepare_poly(BufferFactory& bufs, uint32_t poly); @@ -55,7 +62,7 @@ public: void sustain_on(ProcessContext& context, FrameTime time); void sustain_off(ProcessContext& context, FrameTime time); - static InternalPlugin& internal_plugin(); + static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); private: /** Key, one for each key on the keyboard */ diff --git a/src/engine/internals/Trigger.cpp b/src/engine/internals/Trigger.cpp index ed3b2d90..5fa78774 100644 --- a/src/engine/internals/Trigger.cpp +++ b/src/engine/internals/Trigger.cpp @@ -39,15 +39,21 @@ namespace Internals { using namespace Shared; -static InternalPlugin trigger_plugin(NS_INTERNALS "Trigger", "trigger"); - -InternalPlugin& TriggerNode::internal_plugin() { return trigger_plugin; } +InternalPlugin* TriggerNode::internal_plugin(Shared::LV2URIMap& uris) { + return new InternalPlugin(uris, NS_INTERNALS "Trigger", "trigger"); +} -TriggerNode::TriggerNode(BufferFactory& bufs, const string& path, bool polyphonic, PatchImpl* parent, SampleRate srate) - : NodeImpl(&trigger_plugin, path, false, parent, srate) +TriggerNode::TriggerNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate) + : NodeImpl(plugin, path, false, parent, srate) , _learning(false) { - const LV2URIMap& uris = LV2URIMap::instance(); + const LV2URIMap& uris = bufs.uris(); _ports = new Raul::Array(5); _midi_in_port = new InputPort(bufs, this, "input", 0, 1, PortType::EVENTS, Raul::Atom()); diff --git a/src/engine/internals/Trigger.hpp b/src/engine/internals/Trigger.hpp index 5513f6d8..a9c55deb 100644 --- a/src/engine/internals/Trigger.hpp +++ b/src/engine/internals/Trigger.hpp @@ -43,7 +43,13 @@ namespace Internals { class TriggerNode : public NodeImpl { public: - TriggerNode(BufferFactory& bufs, const std::string& path, bool polyphonic, PatchImpl* parent, SampleRate srate); + TriggerNode( + InternalPlugin* plugin, + BufferFactory& bufs, + const std::string& path, + bool polyphonic, + PatchImpl* parent, + SampleRate srate); void process(ProcessContext& context); @@ -52,7 +58,7 @@ public: void learn() { _learning = true; } - static InternalPlugin& internal_plugin(); + static InternalPlugin* internal_plugin(Shared::LV2URIMap& uris); private: bool _learning; diff --git a/src/engine/wscript b/src/engine/wscript index 6e7e72d0..25270a7d 100644 --- a/src/engine/wscript +++ b/src/engine/wscript @@ -58,13 +58,14 @@ def build(bld): internals/Note.cpp internals/Trigger.cpp ''' - - obj = bld.new_task_gen('cxx', 'shlib') - obj.source = core_source + if bld.env['HAVE_LADSPA_H'] == 1: - obj.source += ' LADSPAPlugin.cpp LADSPANode.cpp ' + core_source += ' LADSPAPlugin.cpp LADSPANode.cpp ' if bld.env['HAVE_SLV2'] == 1: - obj.source += ' LV2Info.cpp LV2Plugin.cpp LV2Node.cpp ' + core_source += ' LV2Info.cpp LV2Plugin.cpp LV2Node.cpp ' + + obj = bld.new_task_gen('cxx', 'shlib') + obj.source = core_source obj.export_incdirs = ['.'] obj.includes = ['.', '..', '../..', '../common'] obj.name = 'libingen_engine' @@ -115,19 +116,14 @@ def build(bld): obj.install_path = '${LIBDIR}/ingen' autowaf.use_lib(bld, obj, core_libs + ' JACK') - # Lightweight ingen/lv2 wrapper - #obj = bld.new_task_gen('cxx', 'shlib') - #obj.source = core_source - #if bld.env['HAVE_LADSPA_H'] == 1: - # obj.source += ' LADSPAPlugin.cpp LADSPANode.cpp ' - #if bld.env['HAVE_SLV2'] == 1: - # obj.source += ' LV2Plugin.cpp LV2Node.cpp ' - #obj.export_incdirs = ['.'] - #obj.includes = ['.', '..', '../common', './events'] - #obj.name = 'ingen_lv2' - #obj.target = 'ingen.lv2/ingen_lv2' - #obj.install_path = '' - #core_libs = 'GLIBMM GTHREAD LV2CORE SLV2 RAUL REDLANDMM' - #autowaf.use_lib(bld, obj, core_libs) - - + # Ingen LV2 wrapper + obj = bld.new_task_gen('cxx', 'shlib') + obj.source = ' ingen_lv2.cpp ' + obj.export_incdirs = ['.'] + obj.includes = ['.', '..', '../..', '../common'] + obj.name = 'libingen_lv2' + obj.target = 'ingen_lv2' + obj.install_path = '${LIBDIR}/ingen' + obj.uselib_local = 'libingen_shared libingen_module' + obj.add_objects = 'libingen_engine' + autowaf.use_lib(bld, obj, core_libs) diff --git a/src/gui/App.cpp b/src/gui/App.cpp index be15d4cb..ca59852a 100644 --- a/src/gui/App.cpp +++ b/src/gui/App.cpp @@ -90,10 +90,10 @@ App::App(Ingen::Shared::World* world) _about_dialog->property_program_name() = "Ingen"; _about_dialog->property_logo_icon_name() = "ingen"; - PluginModel::set_rdf_world(*world->rdf_world); + PluginModel::set_rdf_world(*world->rdf_world()); #ifdef HAVE_SLV2 - PluginModel::set_slv2_world(world->slv2_world); + PluginModel::set_slv2_world(world->slv2_world()); #endif } @@ -109,7 +109,7 @@ void App::init(Ingen::Shared::World* world) { Gnome::Canvas::init(); - _main = new Gtk::Main(world->argc, world->argv); + _main = new Gtk::Main(&world->argc(), &world->argv()); if (!_instance) _instance = new App(world); @@ -169,12 +169,12 @@ App::attach(SharedPtr client, assert( ! _store); assert( ! _loader); - _world->engine->register_client(client.get()); + _world->engine()->register_client(client.get()); _client = client; _handle = handle; - _store = SharedPtr(new ClientStore(_world->engine, client)); - _loader = SharedPtr(new ThreadedLoader(_world->engine)); + _store = SharedPtr(new ClientStore(_world->uris(), _world->engine(), client)); + _loader = SharedPtr(new ThreadedLoader(_world->uris(), _world->engine())); _patch_tree_window->init(*_store); @@ -186,7 +186,7 @@ App::attach(SharedPtr client, void App::detach() { - if (_world->engine) { + if (_world->engine()) { _window_factory->clear(); _store->clear(); @@ -194,18 +194,18 @@ App::detach() _store.reset(); _client.reset(); _handle.reset(); - _world->engine.reset(); + _world->set_engine(SharedPtr()); } } -const SharedPtr& +SharedPtr App::serialiser() { - if (!_world->serialiser) + if (!_world->serialiser()) _world->load("ingen_serialisation"); - return _world->serialiser; + return _world->serialiser(); } @@ -299,8 +299,8 @@ App::gtk_main_iteration() if (!_client) return false; - if (_world->local_engine) { - _world->local_engine->main_iteration(); + if (_world->local_engine()) { + _world->local_engine()->main_iteration(); } else { _enable_signal = false; _client->emit_signals(); @@ -326,7 +326,7 @@ bool App::quit(Gtk::Window& dialog_parent) { bool quit = true; - if (App::instance().world()->local_engine) { + if (App::instance().world()->local_engine()) { Gtk::MessageDialog d(dialog_parent, "The engine is running in this process. Quitting will terminate Ingen." "\n\n" "Are you sure you want to quit?", diff --git a/src/gui/App.hpp b/src/gui/App.hpp index 3ac881f6..a793b968 100644 --- a/src/gui/App.hpp +++ b/src/gui/App.hpp @@ -105,12 +105,12 @@ public: Glib::RefPtr icon_from_path(const std::string& path, int size); - const SharedPtr& engine() const { return _world->engine; } - const SharedPtr& client() const { return _client; } - const SharedPtr& store() const { return _store; } - const SharedPtr& loader() const { return _loader; } + SharedPtr engine() const { return _world->engine(); } + SharedPtr client() const { return _client; } + SharedPtr store() const { return _store; } + SharedPtr loader() const { return _loader; } - const SharedPtr& serialiser(); + SharedPtr serialiser(); static inline App& instance() { assert(_instance); return *_instance; } @@ -118,7 +118,7 @@ public: static void run(); inline Ingen::Shared::World* world() const { return _world; } - inline Ingen::Shared::LV2URIMap& uris() const { return *_world->uris; } + inline Ingen::Shared::LV2URIMap& uris() const { return *_world->uris(); } protected: diff --git a/src/gui/ConnectWindow.cpp b/src/gui/ConnectWindow.cpp index aae826e4..ec440501 100644 --- a/src/gui/ConnectWindow.cpp +++ b/src/gui/ConnectWindow.cpp @@ -74,13 +74,13 @@ ConnectWindow::ConnectWindow(BaseObjectType* cobject, const Glib::RefPtrlocal_engine) { + if (world->local_engine()) { _mode = INTERNAL; if (_widgets_loaded) _internal_radio->set_active(true); } - set_connected_to(world->engine); + set_connected_to(world->engine()); connect(true); } @@ -89,7 +89,7 @@ ConnectWindow::start(Ingen::Shared::World* world) void ConnectWindow::set_connected_to(SharedPtr engine) { - App::instance().world()->engine = engine; + App::instance().world()->set_engine(engine); if (!_widgets_loaded) return; @@ -111,7 +111,7 @@ ConnectWindow::set_connected_to(SharedPtr engine) _connect_button->set_sensitive(true); _disconnect_button->set_sensitive(false); - if (App::instance().world()->local_engine) + if (App::instance().world()->local_engine()) _internal_radio->set_sensitive(true); else _internal_radio->set_sensitive(false); @@ -178,7 +178,7 @@ ConnectWindow::connect(bool existing) } if (existing) - uri = world->engine->uri().str(); + uri = world->engine()->uri().str(); // Create client-side listener SharedPtr tsci(new ThreadedSigClientInterface(1024)); @@ -198,14 +198,14 @@ ConnectWindow::connect(bool existing) if (!existing) { #ifdef HAVE_LIBLO if (scheme == "osc.udp" || scheme == "osc.tcp") - world->engine = SharedPtr(new OSCEngineSender(uri)); + world->set_engine(SharedPtr(new OSCEngineSender(uri))); #endif #ifdef HAVE_SOUP if (scheme == "http") - world->engine = SharedPtr(new HTTPEngineSender(world, uri)); + world->set_engine(SharedPtr(new HTTPEngineSender(world, uri))); #endif } else { - uri = world->engine->uri().str(); + uri = world->engine()->uri().str(); scheme = uri.substr(0, uri.find(":")); } @@ -223,8 +223,8 @@ ConnectWindow::connect(bool existing) const string cmd = string("ingen -e --engine-port=").append(port_str); if (Raul::Process::launch(cmd)) { - world->engine = SharedPtr( - new OSCEngineSender(string("osc.udp://localhost:").append(port_str))); + world->set_engine(SharedPtr( + new OSCEngineSender(string("osc.udp://localhost:").append(port_str)))); // FIXME: static args SharedPtr tsci(new ThreadedSigClientInterface(1024)); @@ -246,15 +246,15 @@ ConnectWindow::connect(bool existing) } else #endif // defined(HAVE_LIBLO) || defined(HAVE_SOUP) if (_mode == INTERNAL) { - if (!world->local_engine) + if (!world->local_engine()) world->load("ingen_engine"); SharedPtr client(new SigClientInterface()); - if (!world->local_engine->driver()) + if (!world->local_engine()->driver()) world->load("ingen_jack"); - world->local_engine->activate(); + world->local_engine()->activate(); App::instance().attach(client); App::instance().register_callbacks(); diff --git a/src/gui/LoadRemotePatchWindow.cpp b/src/gui/LoadRemotePatchWindow.cpp index 0359b34c..a7725571 100644 --- a/src/gui/LoadRemotePatchWindow.cpp +++ b/src/gui/LoadRemotePatchWindow.cpp @@ -66,17 +66,17 @@ LoadRemotePatchWindow::present(SharedPtr patch, GraphObject::Propert set_patch(patch); _initial_data = data; - Redland::Model model(*App::instance().world()->rdf_world, + Redland::Model model(*App::instance().world()->rdf_world(), "http://rdf.drobilla.net/ingen_patches/index.ttl", "http://rdf.drobilla.net/ingen_patches/"); - Redland::Query query(*App::instance().world()->rdf_world, Glib::ustring( + Redland::Query query(*App::instance().world()->rdf_world(), Glib::ustring( "SELECT DISTINCT ?name ?uri WHERE {" " ?uri a ingen:Patch ;" " doap:name ?name ." "}")); - Redland::Query::Results results = query.run(*App::instance().world()->rdf_world, model); + Redland::Query::Results results = query.run(*App::instance().world()->rdf_world(), model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { Gtk::TreeModel::iterator iter = _liststore->append(); diff --git a/src/gui/NodeModule.cpp b/src/gui/NodeModule.cpp index 30762f99..a2db6f83 100644 --- a/src/gui/NodeModule.cpp +++ b/src/gui/NodeModule.cpp @@ -120,7 +120,7 @@ NodeModule::show_human_names(bool b) const LV2URIMap& uris = App::instance().uris(); if (b && node()->plugin()) { - Glib::Mutex::Lock lock(App::instance().world()->rdf_world->mutex()); + Glib::Mutex::Lock lock(App::instance().world()->rdf_world()->mutex()); const Raul::Atom& name_property = node()->get_property(uris.lv2_name); if (name_property.type() == Atom::STRING) set_name(name_property.get_string()); diff --git a/src/gui/PatchCanvas.cpp b/src/gui/PatchCanvas.cpp index 4981bf6e..a1617993 100644 --- a/src/gui/PatchCanvas.cpp +++ b/src/gui/PatchCanvas.cpp @@ -661,11 +661,12 @@ PatchCanvas::paste() clear_selection(); ++_paste_count; - Builder builder(*App::instance().engine()); - ClientStore clipboard; + const LV2URIMap& uris = App::instance().uris(); + + Builder builder(App::instance().world()->uris(), *App::instance().engine()); + ClientStore clipboard(App::instance().world()->uris()); clipboard.set_plugins(App::instance().store()->plugins()); - const LV2URIMap& uris = App::instance().uris(); // mkdir -p string to_create = _patch->path().chop_scheme().substr(1); diff --git a/src/gui/Port.cpp b/src/gui/Port.cpp index 4e1a5460..0ef9f634 100644 --- a/src/gui/Port.cpp +++ b/src/gui/Port.cpp @@ -192,7 +192,7 @@ Port::set_control(float value, bool signal) App& app = App::instance(); Ingen::Shared::World* const world = app.world(); app.engine()->set_property(model()->path(), - world->uris->ingen_value, Atom(value)); + world->uris()->ingen_value, Atom(value)); PatchWindow* pw = app.window_factory()->patch_window( PtrCast(model()->parent())); if (!pw) @@ -241,8 +241,7 @@ Port::dash() if (!pm) return NULL; - const Raul::Atom& context = pm->get_property(uris.ctx_context); - if (!context.is_valid() || context.type() != Atom::URI || context == uris.ctx_AudioContext) + if (pm->has_context(uris.ctx_AudioContext)) return NULL; if (!_dash) { diff --git a/src/gui/PropertiesWindow.cpp b/src/gui/PropertiesWindow.cpp index 44c1c774..5f7e3d15 100644 --- a/src/gui/PropertiesWindow.cpp +++ b/src/gui/PropertiesWindow.cpp @@ -18,7 +18,6 @@ #include #include #include "raul/log.hpp" -#include "module/ingen_module.hpp" #include "module/World.hpp" #include "client/NodeModel.hpp" #include "client/PluginModel.hpp" @@ -89,7 +88,7 @@ PropertiesWindow::set_object(SharedPtr model) set_title(model->path().chop_scheme() + " Properties - Ingen"); - Shared::World* world = ingen_get_world(); + Shared::World* world = App::instance().world(); ostringstream ss; unsigned n_rows = 0; @@ -100,7 +99,7 @@ PropertiesWindow::set_object(SharedPtr model) const Raul::Atom& value = i->second; // Column 0: Property - Gtk::Label* lab = manage(new Gtk::Label(world->rdf_world->qualify(i->first.str()), 0.0, 0.5)); + Gtk::Label* lab = manage(new Gtk::Label(world->rdf_world()->qualify(i->first.str()), 0.0, 0.5)); _table->attach(*lab, 0, 1, n_rows, n_rows + 1, Gtk::FILL|Gtk::SHRINK, Gtk::SHRINK); // Column 1: Type diff --git a/src/gui/ThreadedLoader.cpp b/src/gui/ThreadedLoader.cpp index 9b991555..eae032f4 100644 --- a/src/gui/ThreadedLoader.cpp +++ b/src/gui/ThreadedLoader.cpp @@ -31,9 +31,9 @@ namespace Ingen { namespace GUI { -ThreadedLoader::ThreadedLoader(SharedPtr engine) +ThreadedLoader::ThreadedLoader(SharedPtr uris, SharedPtr engine) : _engine(engine) - , _deprecated_loader(engine) + , _deprecated_loader(uris, engine) { set_name("Loader"); @@ -47,12 +47,12 @@ ThreadedLoader::ThreadedLoader(SharedPtr engine) SharedPtr ThreadedLoader::parser() { - Ingen::Shared::World* world = ingen_get_world(); + Ingen::Shared::World* world = App::instance().world(); - if (!world->parser) + if (!world->parser()) world->load("ingen_serialisation"); - return world->parser; + return world->parser(); } @@ -79,7 +79,7 @@ ThreadedLoader::load_patch(bool merge, { _mutex.lock(); - Ingen::Shared::World* world = ingen_get_world(); + Ingen::Shared::World* world = App::instance().world(); Glib::ustring engine_base = ""; if (engine_parent) { @@ -101,9 +101,9 @@ ThreadedLoader::load_patch(bool merge, false))); } else { _events.push_back(sigc::hide_return(sigc::bind( - sigc::mem_fun(world->parser.get(), &Ingen::Serialisation::Parser::parse_document), + sigc::mem_fun(world->parser().get(), &Ingen::Serialisation::Parser::parse_document), App::instance().world(), - App::instance().world()->engine.get(), + App::instance().world()->engine().get(), document_uri, data_path, engine_parent, diff --git a/src/gui/ThreadedLoader.hpp b/src/gui/ThreadedLoader.hpp index f6b8d706..1c05ea22 100644 --- a/src/gui/ThreadedLoader.hpp +++ b/src/gui/ThreadedLoader.hpp @@ -55,7 +55,7 @@ namespace GUI { class ThreadedLoader : public Raul::Slave { public: - ThreadedLoader(SharedPtr engine); + ThreadedLoader(SharedPtr uris, SharedPtr engine); void load_patch(bool merge, const Glib::ustring& document_uri, diff --git a/src/ingen/main.cpp b/src/ingen/main.cpp index cd8ad999..e269ae89 100644 --- a/src/ingen/main.cpp +++ b/src/ingen/main.cpp @@ -30,6 +30,7 @@ #include "raul/SharedPtr.hpp" #include "redlandmm/World.hpp" #include "interface/EngineInterface.hpp" +#include "shared/Configuration.hpp" #include "shared/runtime_paths.hpp" #include "module/ingen_module.hpp" #include "module/Module.hpp" @@ -44,51 +45,30 @@ using namespace std; using namespace Raul; using namespace Ingen; -SharedPtr engine; +Ingen::Shared::World* world = NULL; void ingen_interrupt(int) { cout << "ingen: Interrupted" << endl; - engine->quit(); + if (world->local_engine()) + world->local_engine()->quit(); + ingen_world_free(world); + exit(1); } void ingen_abort(const char* msg) { cerr << "ingen: Error: " << msg << endl; - ingen_destroy_world(); + ingen_world_free(world); exit(1); } int main(int argc, char** argv) { - Raul::Configuration conf("A realtime modular audio processor.", - "Ingen is a flexible modular system that be used in various ways.\n" - "The engine can run as a stand-alone server controlled via a network protocol\n" - "(e.g. OSC), or internal to another process (e.g. the GUI). The GUI, or other\n" - "clients, can communicate with the engine via any supported protocol, or host the\n" - "engine in the same process. Many clients can connect to an engine at once.\n\n" - "Examples:\n" - " ingen -e # Run an engine, listen for OSC\n" - " ingen -g # Run a GUI, connect via OSC\n" - " ingen -eg # Run an engine and a GUI in one process\n" - " ingen -egl patch.ing.ttl # Run an engine and a GUI and load a patch file\n" - " ingen -egl patch.ing.lv2 # Run an engine and a GUI and load a patch bundle"); - - conf.add("client-port", 'C', "Client OSC port", Atom::INT, Atom()) - .add("connect", 'c', "Connect to engine URI", Atom::STRING, "osc.udp://localhost:16180") - .add("engine", 'e', "Run (JACK) engine", Atom::BOOL, false) - .add("engine-port", 'E', "Engine listen port", Atom::INT, 16180) - .add("gui", 'g', "Launch the GTK graphical interface", Atom::BOOL, false) - .add("help", 'h', "Print this help message", Atom::BOOL, false) - .add("jack-client", 'n', "JACK client name", Atom::STRING, "ingen") - .add("jack-server", 's', "JACK server name", Atom::STRING, "default") - .add("load", 'l', "Load patch", Atom::STRING, Atom()) - .add("parallelism", 'p', "Number of concurrent process threads", Atom::INT, 1) - .add("path", 'L', "Target path for loaded patch", Atom::STRING, Atom()) - .add("run", 'r', "Run script", Atom::STRING, Atom()); + Shared::Configuration conf; // Parse command line options try { @@ -107,8 +87,10 @@ main(int argc, char** argv) return EXIT_SUCCESS; } +#ifdef BUNDLE // Set bundle path from executable location so resources/modules can be found Shared::set_bundle_path_from_code((void*)&main); +#endif SharedPtr engine_interface; @@ -117,37 +99,19 @@ main(int argc, char** argv) g_type_init(); #endif - Ingen::Shared::World* world = ingen_get_world(); - - world->argc = argc; - world->argv = argv; - world->conf = &conf; - - // Set up RDF namespaces - world->rdf_world->add_prefix("dc", "http://purl.org/dc/elements/1.1/"); - world->rdf_world->add_prefix("doap", "http://usefulinc.com/ns/doap#"); - world->rdf_world->add_prefix("ingen", "http://drobilla.net/ns/ingen#"); - world->rdf_world->add_prefix("ingenui", "http://drobilla.net/ns/ingenuity#"); - world->rdf_world->add_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); - world->rdf_world->add_prefix("lv2ev", "http://lv2plug.in/ns/ext/event#"); - world->rdf_world->add_prefix("ctx", "http://lv2plug.in/ns/dev/contexts#"); - world->rdf_world->add_prefix("lv2midi", "http://lv2plug.in/ns/ext/midi#"); - world->rdf_world->add_prefix("midi", "http://drobilla.net/ns/dev/midi#"); - world->rdf_world->add_prefix("owl", "http://www.w3.org/2002/07/owl#"); - world->rdf_world->add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); - world->rdf_world->add_prefix("sp", "http://lv2plug.in/ns/dev/string-port#"); - world->rdf_world->add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); + Ingen::Shared::World* world = ingen_world_new(&conf, argc, argv); + + assert(!world->local_engine()); // Run engine if (conf.option("engine").get_bool()) { if (!world->load("ingen_engine")) ingen_abort("Unable to load engine module"); - if (!world->local_engine) + if (!world->local_engine()) ingen_abort("Unable to create engine"); - engine = world->local_engine; - engine_interface = world->engine; + engine_interface = world->engine(); // Not loading a GUI, load network engine interfaces if (!conf.option("gui").get_bool()) { @@ -175,14 +139,14 @@ main(int argc, char** argv) } // Activate the engine, if we have one - if (engine) { + if (world->local_engine()) { if (!world->load("ingen_jack")) ingen_abort("Unable to load jack module"); - engine->activate(); + world->local_engine()->activate(); } - world->engine = engine_interface; + world->set_engine(engine_interface); // Load a patch if (conf.option("load").is_valid() && engine_interface) { @@ -206,7 +170,7 @@ main(int argc, char** argv) if (!world->load("ingen_serialisation")) ingen_abort("Unable to load serialisation module"); - if (world->parser) { + if (world->parser()) { // Assumption: Containing ':' means URI, otherwise filename string uri = conf.option("load").get_string(); if (uri.find(':') == string::npos) { @@ -220,7 +184,7 @@ main(int argc, char** argv) engine_interface->load_plugins(); if (conf.option("gui").get_bool()) engine_interface->get("ingen:plugins"); - world->parser->parse_document( + world->parser()->parse_document( world, engine_interface.get(), uri, data_path, parent, symbol); } else { @@ -245,19 +209,17 @@ main(int argc, char** argv) #endif // Listen to OSC and run main loop - } else if (engine && !conf.option("gui").get_bool()) { + } else if (world->local_engine() && !conf.option("gui").get_bool()) { signal(SIGINT, ingen_interrupt); signal(SIGTERM, ingen_interrupt); - engine->main(); // Block here + world->local_engine()->main(); // Block here } // Shut down - if (engine) { - engine->deactivate(); - engine.reset(); - } + if (world->local_engine()) + world->local_engine()->deactivate(); - ingen_destroy_world(); + ingen_world_free(world); return 0; } diff --git a/src/module/World.cpp b/src/module/World.cpp index 43d89d6c..727e2dc8 100644 --- a/src/module/World.cpp +++ b/src/module/World.cpp @@ -15,12 +15,19 @@ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "ingen-config.h" +#include #include #include #include +#ifdef HAVE_SLV2 +#include "slv2/slv2.h" +#endif #include "raul/log.hpp" -#include "ingen-config.h" +#include "redlandmm/World.hpp" #include "shared/runtime_paths.hpp" +#include "shared/LV2Features.hpp" +#include "shared/LV2URIMap.hpp" #include "World.hpp" #define LOG(s) s << "[Module] " @@ -85,6 +92,124 @@ load_module(const string& name) } } + +struct WorldImpl : public boost::noncopyable { + WorldImpl(Raul::Configuration* conf, int& a_argc, char**& a_argv) + : argc(a_argc) + , argv(a_argv) + , conf(conf) + , lv2_features(NULL) + , rdf_world(new Redland::World()) + , uris(new Shared::LV2URIMap()) +#ifdef HAVE_SLV2 + , slv2_world(slv2_world_new_using_rdf_world(rdf_world->c_obj())) +#endif + { +#ifdef HAVE_SLV2 + lv2_features = new Ingen::Shared::LV2Features(); + lv2_features->add_feature(LV2_URI_MAP_URI, uris); + slv2_world_load_all(slv2_world); +#endif + + // Set up RDF namespaces + rdf_world->add_prefix("dc", "http://purl.org/dc/elements/1.1/"); + rdf_world->add_prefix("doap", "http://usefulinc.com/ns/doap#"); + rdf_world->add_prefix("ingen", "http://drobilla.net/ns/ingen#"); + rdf_world->add_prefix("ingenui", "http://drobilla.net/ns/ingenuity#"); + rdf_world->add_prefix("lv2", "http://lv2plug.in/ns/lv2core#"); + rdf_world->add_prefix("lv2ev", "http://lv2plug.in/ns/ext/event#"); + rdf_world->add_prefix("ctx", "http://lv2plug.in/ns/dev/contexts#"); + rdf_world->add_prefix("lv2midi", "http://lv2plug.in/ns/ext/midi#"); + rdf_world->add_prefix("midi", "http://drobilla.net/ns/dev/midi#"); + rdf_world->add_prefix("owl", "http://www.w3.org/2002/07/owl#"); + rdf_world->add_prefix("rdfs", "http://www.w3.org/2000/01/rdf-schema#"); + rdf_world->add_prefix("sp", "http://lv2plug.in/ns/dev/string-port#"); + rdf_world->add_prefix("xsd", "http://www.w3.org/2001/XMLSchema#"); + } + + virtual ~WorldImpl() + { + modules.clear(); + interface_factories.clear(); + script_runners.clear(); + + #ifdef HAVE_SLV2 + slv2_world_free(slv2_world); + slv2_world = NULL; + #endif + + delete rdf_world; + rdf_world = NULL; + + delete lv2_features; + lv2_features = NULL; + + uris.reset(); + } + + typedef std::map< const std::string, SharedPtr > Modules; + Modules modules; + + typedef std::map InterfaceFactories; + InterfaceFactories interface_factories; + + typedef bool (*ScriptRunner)(World* world, const char* filename); + typedef std::map ScriptRunners; + ScriptRunners script_runners; + + int& argc; + char**& argv; + Raul::Configuration* conf; + LV2Features* lv2_features; + Redland::World* rdf_world; + SharedPtr uris; + SharedPtr engine; + SharedPtr local_engine; + SharedPtr serialiser; + SharedPtr parser; + SharedPtr store; +#ifdef HAVE_SLV2 + SLV2World slv2_world; +#endif +}; + + +World::World(Raul::Configuration* conf, int& argc, char**& argv) + : _impl(new WorldImpl(conf, argc, argv)) +{ +} + + +World::~World() +{ + unload_all(); + delete _impl; +} + +void World::set_local_engine(SharedPtr e) { _impl->local_engine = e; } +void World::set_engine(SharedPtr e) { _impl->engine = e; } +void World::set_serialiser(SharedPtr s) { _impl->serialiser = s; } +void World::set_parser(SharedPtr p) { _impl->parser = p; } +void World::set_store(SharedPtr s) { _impl->store = s; } +void World::set_conf(Raul::Configuration* c) { _impl->conf = c; } + +int& World::argc() { return _impl->argc; } +char**& World::argv() { return _impl->argv; } +SharedPtr World::local_engine() { return _impl->local_engine; } +SharedPtr World::engine() { return _impl->engine; } +SharedPtr World::serialiser() { return _impl->serialiser; } +SharedPtr World::parser() { return _impl->parser; } +SharedPtr World::store() { return _impl->store; } +Raul::Configuration* World::conf() { return _impl->conf; } +LV2Features* World::lv2_features() { return _impl->lv2_features; } + +#ifdef HAVE_SLV2 +SLV2World World::slv2_world() { return _impl->slv2_world; } +#endif +Redland::World* World::rdf_world() { return _impl->rdf_world; } +SharedPtr World::uris() { return _impl->uris; } + + /** Load an Ingen module. * @return true on success, false on failure */ @@ -97,7 +222,7 @@ World::load(const char* name) Module* module = module_load(); module->library = lib; module->load(this); - modules.insert(make_pair(string(name), module)); + _impl->modules.insert(make_pair(string(name), module)); return true; } else { LOG(error) << "Failed to load module `" << name << "'" << endl; @@ -111,7 +236,7 @@ World::load(const char* name) void World::unload_all() { - modules.clear(); + _impl->modules.clear(); } @@ -121,8 +246,8 @@ SharedPtr World::interface(const std::string& url) { const string scheme = url.substr(0, url.find(":")); - const InterfaceFactories::const_iterator i = interface_factories.find(scheme); - if (i == interface_factories.end()) { + const WorldImpl::InterfaceFactories::const_iterator i = _impl->interface_factories.find(scheme); + if (i == _impl->interface_factories.end()) { warn << "Unknown URI scheme `" << scheme << "'" << endl; return SharedPtr(); } @@ -135,8 +260,8 @@ World::interface(const std::string& url) bool World::run(const std::string& mime_type, const std::string& filename) { - const ScriptRunners::const_iterator i = script_runners.find(mime_type); - if (i == script_runners.end()) { + const WorldImpl::ScriptRunners::const_iterator i = _impl->script_runners.find(mime_type); + if (i == _impl->script_runners.end()) { warn << "Unknown script MIME type `" << mime_type << "'" << endl; return false; } @@ -147,7 +272,7 @@ World::run(const std::string& mime_type, const std::string& filename) void World::add_interface_factory(const std::string& scheme, InterfaceFactory factory) { - interface_factories.insert(make_pair(scheme, factory)); + _impl->interface_factories.insert(make_pair(scheme, factory)); } diff --git a/src/module/World.hpp b/src/module/World.hpp index fcb48845..a84e2454 100644 --- a/src/module/World.hpp +++ b/src/module/World.hpp @@ -21,11 +21,17 @@ #include #include #include +#include #include +#include "ingen-config.h" #include "raul/Configuration.hpp" +#include "raul/SharedPtr.hpp" #include "Module.hpp" +#include "module/ingen_module.hpp" +#ifdef HAVE_SLV2 typedef struct _SLV2World* SLV2World; +#endif namespace Redland { class World; } @@ -41,6 +47,7 @@ class EngineInterface; class Store; class LV2Features; class LV2URIMap; +struct WorldImpl; /** The "world" all Ingen modules may share. @@ -52,46 +59,53 @@ class LV2URIMap; * using World::load, e.g. loading the "ingen_serialisation" module will * set World::serialiser and World::parser to valid objects. */ -struct World { - World() : argc(0), argv(0), conf(0), rdf_world(0), slv2_world(0), lv2_features(0) {} +class World : public boost::noncopyable { + friend Ingen::Shared::World* ::ingen_world_new(Raul::Configuration*, int&, char**&); + World(Raul::Configuration* conf, int& argc, char**& argv); - bool load(const char* name); - void unload_all(); + friend void ::ingen_world_free(Ingen::Shared::World* world); + virtual ~World(); + + WorldImpl* _impl; + +public: + virtual bool load(const char* name); + virtual void unload_all(); typedef SharedPtr (*InterfaceFactory)( World* world, const std::string& engine_url); - void add_interface_factory(const std::string& scheme, InterfaceFactory factory); - SharedPtr interface(const std::string& engine_url); + virtual void add_interface_factory(const std::string& scheme, InterfaceFactory factory); + virtual SharedPtr interface(const std::string& engine_url); - bool run(const std::string& mime_type, const std::string& filename); + virtual bool run(const std::string& mime_type, const std::string& filename); - int argc; - char** argv; - Raul::Configuration* conf; + virtual void set_local_engine(SharedPtr e); + virtual void set_engine(SharedPtr e); + virtual void set_serialiser(SharedPtr s); + virtual void set_parser(SharedPtr p); + virtual void set_store(SharedPtr s); - Redland::World* rdf_world; - SLV2World slv2_world; - LV2Features* lv2_features; + virtual SharedPtr local_engine(); + virtual SharedPtr engine(); + virtual SharedPtr serialiser(); + virtual SharedPtr parser(); + virtual SharedPtr store(); - boost::shared_ptr uris; + virtual Redland::World* rdf_world(); + virtual SharedPtr uris(); - boost::shared_ptr engine; - boost::shared_ptr local_engine; - boost::shared_ptr serialiser; - boost::shared_ptr parser; - boost::shared_ptr store; + virtual int& argc(); + virtual char**& argv(); -private: - typedef std::map< const std::string, boost::shared_ptr > Modules; - Modules modules; + virtual Raul::Configuration* conf(); + virtual void set_conf(Raul::Configuration* c); - typedef std::map InterfaceFactories; - InterfaceFactories interface_factories; + virtual LV2Features* lv2_features(); - typedef bool (*ScriptRunner)(World* world, const char* filename); - typedef std::map ScriptRunners; - ScriptRunners script_runners; +#ifdef HAVE_SLV2 + virtual SLV2World slv2_world(); +#endif }; diff --git a/src/module/ingen_module.cpp b/src/module/ingen_module.cpp index 167fd0f2..140aec2e 100644 --- a/src/module/ingen_module.cpp +++ b/src/module/ingen_module.cpp @@ -28,46 +28,16 @@ extern "C" { -static Ingen::Shared::World* world = NULL; - Ingen::Shared::World* -ingen_get_world() +ingen_world_new(Raul::Configuration* conf, int& argc, char**& argv) { - static Ingen::Shared::World* world = NULL; - - if (!world) { - world = new Ingen::Shared::World(); - world->rdf_world = new Redland::World(); -#ifdef HAVE_SLV2 - world->slv2_world = slv2_world_new_using_rdf_world(world->rdf_world->world()); - world->lv2_features = new Ingen::Shared::LV2Features(); - world->uris = PtrCast( - world->lv2_features->feature(LV2_URI_MAP_URI)); - slv2_world_load_all(world->slv2_world); -#else - world->uris = SharedPtr( - new Ingen::Shared::LV2URIMap()); -#endif - world->engine.reset(); - world->local_engine.reset(); - } - - return world; + return new Ingen::Shared::World(conf, argc, argv); } void -ingen_destroy_world() +ingen_world_free(Ingen::Shared::World* world) { - if (world) { - world->unload_all(); -#ifdef HAVE_SLV2 - slv2_world_free(world->slv2_world); - delete world->lv2_features; -#endif - delete world->rdf_world; - delete world; - world = NULL; - } + delete world; } } // extern "C" diff --git a/src/module/ingen_module.hpp b/src/module/ingen_module.hpp index bb2c3adb..0fd921f7 100644 --- a/src/module/ingen_module.hpp +++ b/src/module/ingen_module.hpp @@ -18,12 +18,14 @@ #ifndef INGEN_MODULE_HPP #define INGEN_MODULE_HPP +namespace Raul { class Configuration; } + namespace Ingen { namespace Shared { class World; } } extern "C" { -Ingen::Shared::World* ingen_get_world(); -void ingen_destroy_world(); +Ingen::Shared::World* ingen_world_new(Raul::Configuration* conf, int& argc, char**& argv); +void ingen_world_free(Ingen::Shared::World* world); } // extern "C" diff --git a/src/serialisation/Parser.cpp b/src/serialisation/Parser.cpp index 9fe1d036..720134e8 100644 --- a/src/serialisation/Parser.cpp +++ b/src/serialisation/Parser.cpp @@ -71,6 +71,31 @@ normalise_uri(Glib::ustring& uri) } +Parser::PatchRecords +Parser::find_patches( + Ingen::Shared::World* world, + const Glib::ustring& manifest_uri) +{ + Redland::Model model(*world->rdf_world(), manifest_uri, manifest_uri); + Redland::Query query(*world->rdf_world(), + "SELECT DISTINCT ?patch ?file WHERE {\n" + "?patch a ingen:Patch ;\n" + " rdfs:seeAlso ?file .\n" + "}"); + + std::list records; + + Redland::Query::Results results(query.run(*world->rdf_world(), model, manifest_uri)); + for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { + const Redland::Node& patch((*i)["patch"]); + const Redland::Node& file((*i)["file"]); + records.push_back(PatchRecord(patch.to_c_string(), file.to_c_string())); + } + + return records; +} + + /** Parse a patch from RDF into a CommonInterface (engine or client). * @return whether or not load was successful. */ @@ -96,7 +121,7 @@ Parser::parse_document( document_uri += "/" + basename + INGEN_PATCH_FILE_EXT; } - Redland::Model model(*world->rdf_world, document_uri, document_uri); + Redland::Model model(*world->rdf_world(), document_uri, document_uri); LOG(info) << "Parsing " << document_uri << endl; if (data_path) @@ -131,7 +156,7 @@ Parser::parse_string( boost::optional symbol, boost::optional data) { - Redland::Model model(*world->rdf_world, str.c_str(), str.length(), base_uri); + Redland::Model model(*world->rdf_world(), str.c_str(), str.length(), base_uri); LOG(info) << "Parsing " << (data_path ? data_path->str() : "*") << " from string"; if (!base_uri.empty()) @@ -139,7 +164,7 @@ Parser::parse_string( info << endl; bool ret = parse(world, target, model, base_uri, data_path, parent, symbol, data); - Redland::Resource subject(*world->rdf_world, base_uri); + Redland::Resource subject(*world->rdf_world(), base_uri); parse_connections(world, target, model, subject, parent ? *parent : "/"); return ret; @@ -157,14 +182,12 @@ Parser::parse_update( boost::optional symbol, boost::optional data) { - Redland::Model model(*world->rdf_world, str.c_str(), str.length(), base_uri); - - std::cout << "PARSE UPDATE " << str << endl; + Redland::Model model(*world->rdf_world(), str.c_str(), str.length(), base_uri); // Delete anything explicitly declared to not exist Glib::ustring query_str = Glib::ustring("SELECT DISTINCT ?o WHERE { ?o a owl:Nothing }"); - Redland::Query query(*world->rdf_world, query_str); - Redland::Query::Results results = query.run(*world->rdf_world, model, base_uri); + Redland::Query query(*world->rdf_world(), query_str); + Redland::Query::Results results = query.run(*world->rdf_world(), model, base_uri); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { const Redland::Node& object = (*i)["o"]; @@ -172,15 +195,15 @@ Parser::parse_update( } // Properties - query = Redland::Query(*world->rdf_world, + query = Redland::Query(*world->rdf_world(), "SELECT DISTINCT ?s ?p ?o WHERE {\n" "?s ?p ?o .\n" "}"); - results = Redland::Query::Results(query.run(*world->rdf_world, model, base_uri)); + results = Redland::Query::Results(query.run(*world->rdf_world(), model, base_uri)); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); string obj_uri((*i)["s"].to_string()); const string key((*i)["p"].to_string()); const Redland::Node& val_node((*i)["o"]); @@ -194,23 +217,23 @@ Parser::parse_update( // Connections - Redland::Resource subject(*world->rdf_world, base_uri); + Redland::Resource subject(*world->rdf_world(), base_uri); parse_connections(world, target, model, subject, "/"); // Port values - query = Redland::Query(*world->rdf_world, + query = Redland::Query(*world->rdf_world(), "SELECT DISTINCT ?path ?value WHERE {\n" "?path ingen:value ?value .\n" "}"); - results = Redland::Query::Results(query.run(*world->rdf_world, model, base_uri)); + results = Redland::Query::Results(query.run(*world->rdf_world(), model, base_uri)); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const string obj_path = (*i)["path"].to_string(); const Redland::Node& val_node = (*i)["value"]; const Atom a(AtomRDF::node_to_atom(model, val_node)); - target->set_property(obj_path, world->uris->ingen_value, a); + target->set_property(obj_path, world->uris()->ingen_value, a); } return parse(world, target, model, base_uri, data_path, parent, symbol, data); @@ -234,22 +257,22 @@ Parser::parse( ? Glib::ustring("SELECT DISTINCT ?t WHERE { <") + data_path->chop_start("/") + "> a ?t . }" : Glib::ustring("SELECT DISTINCT ?s ?t WHERE { ?s a ?t . }"); - Redland::Query query(*world->rdf_world, query_str); - Redland::Query::Results results(query.run(*world->rdf_world, model, document_uri)); + Redland::Query query(*world->rdf_world(), query_str); + Redland::Query::Results results(query.run(*world->rdf_world(), model, document_uri)); #define NS_INGEN "http://drobilla.net/ns/ingen#" #define NS_LV2 "http://lv2plug.in/ns/lv2core#" - const Redland::Node patch_class (*world->rdf_world, res, NS_INGEN "Patch"); - const Redland::Node node_class (*world->rdf_world, res, NS_INGEN "Node"); - const Redland::Node internal_class (*world->rdf_world, res, NS_INGEN "Internal"); - const Redland::Node ladspa_class (*world->rdf_world, res, NS_INGEN "LADSPAPlugin"); - const Redland::Node in_port_class (*world->rdf_world, res, NS_LV2 "InputPort"); - const Redland::Node out_port_class (*world->rdf_world, res, NS_LV2 "OutputPort"); - const Redland::Node lv2_class (*world->rdf_world, res, NS_LV2 "Plugin"); + const Redland::Node patch_class (*world->rdf_world(), res, NS_INGEN "Patch"); + const Redland::Node node_class (*world->rdf_world(), res, NS_INGEN "Node"); + const Redland::Node internal_class (*world->rdf_world(), res, NS_INGEN "Internal"); + const Redland::Node ladspa_class (*world->rdf_world(), res, NS_INGEN "LADSPAPlugin"); + const Redland::Node in_port_class (*world->rdf_world(), res, NS_LV2 "InputPort"); + const Redland::Node out_port_class (*world->rdf_world(), res, NS_LV2 "OutputPort"); + const Redland::Node lv2_class (*world->rdf_world(), res, NS_LV2 "Plugin"); const Redland::Node subject_node = (data_path && !data_path->is_root()) - ? Redland::Node(*world->rdf_world, res, data_path->chop_start("/")) + ? Redland::Node(*world->rdf_world(), res, data_path->chop_start("/")) : model.base_uri(); std::string path_str; @@ -298,6 +321,7 @@ Parser::parse( ret = parse_node(world, target, model, subject, path, data); } else if (rdf_class == in_port_class || rdf_class == out_port_class) { parse_properties(world, target, model, subject, path, data); + ret = path; } if (!ret) { @@ -333,7 +357,7 @@ Parser::parse_patch( boost::optional a_symbol, boost::optional data) { - const LV2URIMap& uris = *world->uris.get(); + const LV2URIMap& uris = *world->uris().get(); uint32_t patch_poly = 0; typedef Redland::Query::Results Results; @@ -349,10 +373,10 @@ Parser::parse_patch( /* Load polyphony from file if necessary */ if (patch_poly == 0) { - Redland::Query query(*world->rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?poly WHERE { ") + subject + " ingen:polyphony ?poly }"); - Results results = query.run(*world->rdf_world, model); + Results results = query.run(*world->rdf_world(), model); if (results.size() > 0) { const Redland::Node& poly_node = (*results.begin())["poly"]; if (poly_node.is_int()) @@ -395,14 +419,14 @@ Parser::parse_patch( /* Find patches in document */ - Redland::Query query(*world->rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?patch WHERE {\n") + "?patch a ingen:Patch .\n" "}"); set patches; - Results results = query.run(*world->rdf_world, model, base_uri); + Results results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); patches.insert((*i)["patch"].to_string()); } @@ -413,7 +437,7 @@ Parser::parse_patch( /* Find nodes on this patch */ - query = Redland::Query(*world->rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?node ?type WHERE {\n") + subject + " ingen:node ?node .\n" "?node rdf:instanceOf ?type .\n" @@ -422,9 +446,9 @@ Parser::parse_patch( Objects plugin_nodes; Resources resources; Types types; - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); Redland::Node& node = (*i)["node"]; Redland::Node& type = (*i)["type"]; if (node.type() == Redland::Node::RESOURCE && type.type() == Redland::Node::RESOURCE) { @@ -440,14 +464,14 @@ Parser::parse_patch( /* Load nodes on this patch */ - query = Redland::Query(*world->rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?node ?predicate ?object WHERE {\n") + subject + " ingen:node ?node .\n" "?node ?predicate ?object .\n" "}"); - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); Redland::Node& node = (*i)["node"]; Redland::Node& predicate = (*i)["predicate"]; Redland::Node& object = (*i)["object"]; @@ -478,7 +502,7 @@ Parser::parse_patch( if (res_i == resources.end()) continue; parse_patch(world, target, model, res_i->second, patch_path, Symbol(node_path.symbol())); - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); target->put(node_path, i->second); } @@ -497,16 +521,16 @@ Parser::parse_patch( /* Load node ports */ - query = Redland::Query(*world->rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?node ?port ?key ?val WHERE {\n") + subject + " ingen:node ?node .\n" "?node lv2:port ?port .\n" "?port ?key ?val .\n" "}"); Objects node_ports; - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const string node_uri = (*i)["node"].to_string(); const string port_uri = (*i)["port"].to_string(); if (port_uri.length() <= node_uri.length()) { @@ -531,15 +555,15 @@ Parser::parse_patch( /* Find ports on this patch */ - query = Redland::Query(*world->rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?port ?type WHERE {\n") + subject + " lv2:port ?port .\n" "?port rdf:instanceOf ?type .\n" "}"); Objects patch_ports; - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); Redland::Node& port = (*i)["port"]; Redland::Node& type = (*i)["type"]; if (port.type() == Redland::Node::RESOURCE && type.type() == Redland::Node::RESOURCE) { @@ -550,14 +574,14 @@ Parser::parse_patch( /* Load patch ports */ - query = Redland::Query(*world->rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?port ?key ?val WHERE {\n") + subject + " lv2:port ?port .\n" "?port ?key ?val .\n" "}"); - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const string port_uri = (*i)["port"].to_string(); const Path port_path = patch_path.child(relative_uri(base_uri, port_uri, false)); const string key = (*i)["key"].to_string(); @@ -603,7 +627,7 @@ Parser::parse_patch( for (uint32_t index = 0; index < patch_ports.size(); ++index) { Objects::iterator i = ports_by_index[index]; - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const Path port_path = patch_path.child(relative_uri(base_uri, i->first, false)); std::pair types_range = i->second.equal_range(uris.rdf_type); @@ -641,14 +665,14 @@ Parser::parse_patch( /* Enable */ - query = Redland::Query(*world->rdf_world, Glib::ustring( + query = Redland::Query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?enabled WHERE {\n") + subject + " ingen:enabled ?enabled .\n" "}"); - results = query.run(*world->rdf_world, model, base_uri); + results = query.run(*world->rdf_world(), model, base_uri); for (Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const Redland::Node& enabled_node = (*i)["enabled"]; if (enabled_node.is_bool() && enabled_node) { target->set_property(patch_path, uris.ingen_enabled, (bool)true); @@ -671,15 +695,15 @@ Parser::parse_node( const Raul::Path& path, boost::optional data) { - const LV2URIMap& uris = *world->uris.get(); + const LV2URIMap& uris = *world->uris().get(); /* Get plugin */ - Redland::Query query(*world->rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?plug WHERE {\n") + subject.to_turtle_token() + " rdf:instanceOf ?plug .\n" "}"); - Redland::Query::Results results = query.run(*world->rdf_world, model); + Redland::Query::Results results = query.run(*world->rdf_world(), model); if (results.size() == 0) { LOG(error) << "Node missing mandatory rdf:instanceOf property" << endl; @@ -692,7 +716,7 @@ Parser::parse_node( return boost::optional(); } - const string plugin_uri = world->rdf_world->expand_uri(plugin_node.to_c_string()); + const string plugin_uri = world->rdf_world()->expand_uri(plugin_node.to_c_string()); Resource::Properties props; props.insert(make_pair(uris.rdf_type, Raul::URI(uris.ingen_Node))); props.insert(make_pair(uris.rdf_instanceOf, Raul::Atom(Raul::Atom::URI, plugin_uri))); @@ -711,7 +735,7 @@ Parser::parse_connections( const Redland::Node& subject, const Raul::Path& parent) { - Redland::Query query(*world->rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?src ?dst WHERE {\n") + subject.to_turtle_token() + " ingen:connection ?connection .\n" "?connection ingen:source ?src ;\n" @@ -720,9 +744,9 @@ Parser::parse_connections( const Glib::ustring& base_uri = model.base_uri().to_string(); - Redland::Query::Results results = query.run(*world->rdf_world, model); + Redland::Query::Results results = query.run(*world->rdf_world(), model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const Path src_path(parent.child(relative_uri(base_uri, (*i)["src"].to_string(), false))); const Path dst_path(parent.child(relative_uri(base_uri, (*i)["dst"].to_string(), false))); target->connect(src_path, dst_path); @@ -743,15 +767,15 @@ Parser::parse_properties( { const Glib::ustring& subject = subject_node.to_turtle_token(); - Redland::Query query(*world->rdf_world, Glib::ustring( + Redland::Query query(*world->rdf_world(), Glib::ustring( "SELECT DISTINCT ?key ?val WHERE {\n") + subject + " ?key ?val .\n" "}"); Resource::Properties properties; - Redland::Query::Results results = query.run(*world->rdf_world, model); + Redland::Query::Results results = query.run(*world->rdf_world(), model); for (Redland::Query::Results::iterator i = results.begin(); i != results.end(); ++i) { - Glib::Mutex::Lock lock(world->rdf_world->mutex()); + Glib::Mutex::Lock lock(world->rdf_world()->mutex()); const string key = string((*i)["key"]); const Redland::Node& val = (*i)["val"]; if (skip_property((*i)["key"])) diff --git a/src/serialisation/Parser.hpp b/src/serialisation/Parser.hpp index cd96bd0b..aeda022f 100644 --- a/src/serialisation/Parser.hpp +++ b/src/serialisation/Parser.hpp @@ -19,6 +19,7 @@ #define INGEN_SERIALISATION_LOADER_HPP #include +#include #include #include #include "interface/GraphObject.hpp" @@ -69,6 +70,18 @@ public: boost::optional symbol=boost::optional(), boost::optional data=boost::optional()); + struct PatchRecord { + PatchRecord(const Raul::URI& u, const Glib::ustring& f) : uri(u), filename(f) {} + const Raul::URI uri; + const Glib::ustring filename; + }; + + typedef std::list PatchRecords; + + virtual PatchRecords find_patches( + Ingen::Shared::World* world, + const Glib::ustring& manifest_uri); + private: boost::optional parse( Ingen::Shared::World* world, diff --git a/src/serialisation/Serialiser.cpp b/src/serialisation/Serialiser.cpp index 735f9788..5f02d9cc 100644 --- a/src/serialisation/Serialiser.cpp +++ b/src/serialisation/Serialiser.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "raul/log.hpp" #include "raul/Atom.hpp" #include "raul/AtomRDF.hpp" @@ -101,19 +103,26 @@ void Serialiser::write_manifest(const std::string& bundle_uri, const Records& records) { - const string filename = Glib::filename_from_uri(bundle_uri) + "manifest.ttl"; + const string bundle_path(Glib::filename_from_uri(bundle_uri)); + const string filename(Glib::build_filename(bundle_path, "manifest.ttl")); start_to_filename(filename); _model->set_base_uri(bundle_uri); for (Records::const_iterator i = records.begin(); i != records.end(); ++i) { SharedPtr patch = PtrCast(i->object); if (patch) { - const Redland::Resource subject(_model->world(), uri_to_symbol(i->uri)); + const std::string filename = uri_to_symbol(i->uri) + INGEN_PATCH_FILE_EXT; + const Redland::Resource subject(_model->world(), filename); _model->add_statement(subject, "rdf:type", Redland::Resource(_model->world(), "ingen:Patch")); _model->add_statement(subject, "rdf:type", Redland::Resource(_model->world(), "lv2:Plugin")); _model->add_statement(subject, "rdfs:seeAlso", - Redland::Resource(_model->world(), i->uri)); + Redland::Resource(_model->world(), filename)); + _model->add_statement(subject, "lv2:binary", + Redland::Resource(_model->world(), + Glib::Module::build_path("", "ingen_lv2"))); + symlink(Glib::Module::build_path(INGEN_MODULE_DIR, "ingen_lv2").c_str(), + Glib::Module::build_path(bundle_path, "ingen_lv2").c_str()); } } finish(); @@ -178,7 +187,7 @@ Serialiser::start_to_filename(const string& filename) _base_uri = "file://" + filename; else _base_uri = filename; - _model = new Redland::Model(*_world.rdf_world); + _model = new Redland::Model(*_world.rdf_world()); _model->set_base_uri(_base_uri); _mode = TO_FILE; } @@ -201,7 +210,7 @@ Serialiser::start_to_string(const Raul::Path& root, const string& base_uri) _root_path = root; _base_uri = base_uri; - _model = new Redland::Model(*_world.rdf_world); + _model = new Redland::Model(*_world.rdf_world()); _model->set_base_uri(base_uri); _mode = TO_STRING; } @@ -310,19 +319,27 @@ Serialiser::serialise_patch(SharedPtr patch, const Redland::Node& _model->add_statement(patch_id, "rdf:type", Redland::Resource(_model->world(), "lv2:Plugin")); - GraphObject::Properties::const_iterator s = patch->properties().find("lv2:symbol"); - // If symbol is stored as a property, write that - if (s != patch->properties().end() && s->second.is_valid()) { - _model->add_statement(patch_id, "lv2:symbol", - Redland::Literal(_model->world(), s->second.get_string())); - // Otherwise take the one from our path (if possible) - } else if (!patch->path().is_root()) { - _model->add_statement(patch_id, "lv2:symbol", - Redland::Literal(_model->world(), patch->path().symbol())); + const LV2URIMap& uris = *_world.uris().get(); + + // Always write a symbol (required by Ingen) + string symbol; + GraphObject::Properties::const_iterator s = patch->properties().find(uris.lv2_symbol); + if (s == patch->properties().end() + || !s->second.type() == Atom::STRING + || !Symbol::is_valid(s->second.get_string())) { + symbol = Glib::path_get_basename(Glib::filename_from_uri(_model->base_uri().to_c_string())); + symbol = Symbol::symbolify(symbol.substr(0, symbol.find('.'))); + _model->add_statement(patch_id, uris.lv2_symbol.c_str(), + Redland::Literal(_model->world(), symbol)); } else { - LOG(warn) << "Patch has no lv2:symbol" << endl; + symbol = s->second.get_string(); } + // If the patch has no doap:name (required by LV2), use the symbol + if (patch->meta().properties().find(uris.doap_name) == patch->meta().properties().end()) + _model->add_statement(patch_id, uris.doap_name.c_str(), + Redland::Literal(_model->world(), symbol)); + serialise_properties(patch_id, NULL, patch->meta().properties()); for (Store::const_iterator n = _store->children_begin(patch); @@ -427,6 +444,9 @@ Serialiser::serialise_port(const Port* port, const Redland::Node& port_id) _model->add_statement(port_id, "rdf:instanceOf", class_rdf_node(port->path())); + _model->add_statement(port_id, "lv2:symbol", + Redland::Literal(_model->world(), port->path().symbol())); + serialise_properties(port_id, &port->meta(), port->properties()); } @@ -450,6 +470,9 @@ Serialiser::serialise_port_meta(const Port* port, const Redland::Node& port_id) _model->add_statement(port_id, "lv2:index", AtomRDF::atom_to_node(*_model, Atom((int)port->index()))); + _model->add_statement(port_id, "lv2:symbol", + Redland::Literal(_model->world(), port->path().symbol())); + if (!port->get_property("http://lv2plug.in/ns/lv2core#default").is_valid()) { if (port->is_input()) { if (port->value().is_valid()) { @@ -480,7 +503,7 @@ Serialiser::serialise_connection(SharedPtr parent, ? instance_rdf_node(connection->dst_port_path()) : class_rdf_node(connection->dst_port_path()); - const Redland::Node connection_node = _world.rdf_world->blank_id(); + const Redland::Node connection_node = _world.rdf_world()->blank_id(); _model->add_statement(connection_node, "ingen:source", src_node); _model->add_statement(connection_node, "ingen:destination", dst_node); if (parent) { diff --git a/src/serialisation/serialisation.cpp b/src/serialisation/serialisation.cpp index a453f000..b9a21670 100644 --- a/src/serialisation/serialisation.cpp +++ b/src/serialisation/serialisation.cpp @@ -25,10 +25,10 @@ using namespace Ingen; struct IngenModule : public Shared::Module { void load(Shared::World* world) { - world->parser = SharedPtr( - new Serialisation::Parser()); - world->serialiser = SharedPtr( - new Serialisation::Serialiser(*world, world->store)); + world->set_parser(SharedPtr( + new Serialisation::Parser())); + world->set_serialiser(SharedPtr( + new Serialisation::Serialiser(*world, world->store()))); } }; diff --git a/src/shared/Builder.cpp b/src/shared/Builder.cpp index 0cc4e980..72e90ad1 100644 --- a/src/shared/Builder.cpp +++ b/src/shared/Builder.cpp @@ -32,8 +32,9 @@ namespace Ingen { namespace Shared { -Builder::Builder(CommonInterface& interface) - : _interface(interface) +Builder::Builder(SharedPtr uris, CommonInterface& interface) + : _uris(uris) + , _interface(interface) { } @@ -41,7 +42,7 @@ Builder::Builder(CommonInterface& interface) void Builder::build(SharedPtr object) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); + const LV2URIMap& uris = *_uris.get(); SharedPtr patch = PtrCast(object); if (patch) { if (!object->path().is_root()) { diff --git a/src/shared/Builder.hpp b/src/shared/Builder.hpp index ec953d41..b77201dd 100644 --- a/src/shared/Builder.hpp +++ b/src/shared/Builder.hpp @@ -25,8 +25,9 @@ namespace Raul { class Path; } namespace Ingen { namespace Shared { -class GraphObject; class CommonInterface; +class GraphObject; +class LV2URIMap; /** Wrapper for CommonInterface to create existing objects/models. @@ -36,7 +37,7 @@ class CommonInterface; class Builder { public: - Builder(CommonInterface& interface); + Builder(SharedPtr uris, CommonInterface& interface); virtual ~Builder() {} void build(SharedPtr object); @@ -45,7 +46,8 @@ public: private: void build_object(SharedPtr object); - CommonInterface& _interface; + SharedPtr _uris; + CommonInterface& _interface; }; diff --git a/src/shared/LV2Features.cpp b/src/shared/LV2Features.cpp index 5088d6e0..21d6039e 100644 --- a/src/shared/LV2Features.cpp +++ b/src/shared/LV2Features.cpp @@ -28,7 +28,6 @@ namespace Shared { LV2Features::LV2Features() { - add_feature(LV2_URI_MAP_URI, SharedPtr(new LV2URIMap())); } diff --git a/src/shared/LV2Object.cpp b/src/shared/LV2Object.cpp index 252972ff..4388ede8 100644 --- a/src/shared/LV2Object.cpp +++ b/src/shared/LV2Object.cpp @@ -32,10 +32,8 @@ namespace LV2Object { bool -to_atom(const LV2_Object* object, Raul::Atom& atom) +to_atom(const Shared::LV2URIMap& uris, const LV2_Object* object, Raul::Atom& atom) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - if (object->type == uris.object_class_string.id) { atom = Raul::Atom((char*)(object + 1)); return true; @@ -57,10 +55,8 @@ to_atom(const LV2_Object* object, Raul::Atom& atom) * object->size should be the capacity of the object (not including header) */ bool -from_atom(const Raul::Atom& atom, LV2_Object* object) +from_atom(const Shared::LV2URIMap& uris, const Raul::Atom& atom, LV2_Object* object) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - char* str; switch (atom.type()) { case Raul::Atom::FLOAT: diff --git a/src/shared/LV2Object.hpp b/src/shared/LV2Object.hpp index 794422a0..bec2ff89 100644 --- a/src/shared/LV2Object.hpp +++ b/src/shared/LV2Object.hpp @@ -25,11 +25,12 @@ namespace Ingen { namespace Shared { class World; +class LV2URIMap; namespace LV2Object { - bool to_atom(const LV2_Object* object, Raul::Atom& atom); - bool from_atom(const Raul::Atom& atom, LV2_Object* object); + bool to_atom(const Shared::LV2URIMap& uris, const LV2_Object* object, Raul::Atom& atom); + bool from_atom(const Shared::LV2URIMap& uris, const Raul::Atom& atom, LV2_Object* object); } // namespace LV2Object diff --git a/src/shared/LV2URIMap.cpp b/src/shared/LV2URIMap.cpp index d8114014..e069a644 100644 --- a/src/shared/LV2URIMap.cpp +++ b/src/shared/LV2URIMap.cpp @@ -19,11 +19,10 @@ #include #include #include +#include #include "raul/log.hpp" #include "object.lv2/object.h" #include "LV2URIMap.hpp" -#include "module/ingen_module.hpp" -#include "module/World.hpp" using namespace std; using namespace Raul; @@ -38,6 +37,12 @@ LV2URIMap::Quark::Quark(const char* c_str) { } +const char* +LV2URIMap::Quark::c_str() const +{ + return g_quark_to_string(id); +} + #define NS_CTX "http://lv2plug.in/ns/dev/contexts#" #define NS_INGEN "http://drobilla.net/ns/ingen#" #define NS_INGENUI "http://drobilla.net/ns/ingenuity#" @@ -114,23 +119,14 @@ LV2URIMap::LV2URIMap() } -const LV2URIMap& -LV2URIMap::instance() -{ - return *ingen_get_world()->uris; -} +struct null_deleter { void operator()(void const *) const {} }; uint32_t LV2URIMap::uri_to_id(const char* map, const char* uri) { - const uint32_t ret = static_cast(g_quark_from_string(uri)); - debug << "[LV2URIMap] "; - if (map) - debug << map << " : "; - debug << uri << " => " << ret << endl; - return ret; + return static_cast(g_quark_from_string(uri)); } diff --git a/src/shared/LV2URIMap.hpp b/src/shared/LV2URIMap.hpp index 2c5bdef2..30203de7 100644 --- a/src/shared/LV2URIMap.hpp +++ b/src/shared/LV2URIMap.hpp @@ -38,9 +38,7 @@ public: return SharedPtr(&uri_map_feature, NullDeleter); } - uint32_t uri_to_id(const char* map, const char* uri); - - static const LV2URIMap& instance(); + virtual uint32_t uri_to_id(const char* map, const char* uri); private: static uint32_t uri_map_uri_to_id(LV2_URI_Map_Callback_Data callback_data, @@ -53,6 +51,7 @@ private: public: struct Quark : public Raul::URI { Quark(const char* str); + const char* c_str() const; uint32_t id; }; diff --git a/src/shared/ResourceImpl.cpp b/src/shared/ResourceImpl.cpp index b542ff2d..db44f0f7 100644 --- a/src/shared/ResourceImpl.cpp +++ b/src/shared/ResourceImpl.cpp @@ -67,8 +67,7 @@ ResourceImpl::set_property(const Raul::URI& uri, const Raul::Atom& value) void ResourceImpl::remove_property(const Raul::URI& uri, const Raul::Atom& value) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); - if (value == uris.wildcard) { + if (value == _uris.wildcard) { _properties.erase(uri); } else { Properties::iterator i = _properties.find(uri); @@ -113,13 +112,13 @@ ResourceImpl::get_property(const Raul::URI& uri) const bool ResourceImpl::type( + const LV2URIMap& uris, const Properties& properties, bool& patch, bool& node, bool& port, bool& is_output, PortType& data_type) { typedef Resource::Properties::const_iterator iterator; - const LV2URIMap& uris = Shared::LV2URIMap::instance(); const std::pair types_range = properties.equal_range(uris.rdf_type); patch = node = port = is_output = false; @@ -198,10 +197,9 @@ ResourceImpl::add_properties(const Properties& p) void ResourceImpl::remove_properties(const Properties& p) { - const LV2URIMap& uris = Shared::LV2URIMap::instance(); typedef Resource::Properties::const_iterator iterator; for (iterator i = p.begin(); i != p.end(); ++i) { - if (i->second == uris.wildcard) { + if (i->second == _uris.wildcard) { _properties.erase(i->first); } else { for (Properties::iterator j = _properties.find(i->first); diff --git a/src/shared/ResourceImpl.hpp b/src/shared/ResourceImpl.hpp index 8e827df8..7b77d669 100644 --- a/src/shared/ResourceImpl.hpp +++ b/src/shared/ResourceImpl.hpp @@ -21,16 +21,22 @@ #include #include #include "raul/URI.hpp" +#include "raul/SharedPtr.hpp" #include "interface/Resource.hpp" #include "interface/PortType.hpp" namespace Ingen { namespace Shared { +class LV2URIMap; + class ResourceImpl : virtual public Resource { public: - ResourceImpl(const Raul::URI& uri) : _uri(uri) {} + ResourceImpl(LV2URIMap& uris, const Raul::URI& uri) + : _uris(uris), _uri(uri) {} + + LV2URIMap& uris() const { return _uris; } virtual void set_uri(const Raul::URI& uri) { _uri = uri; } virtual const Raul::URI& uri() const { return _uri; } @@ -56,6 +62,7 @@ public: * output parameter set to true. Otherwise false is returned. */ static bool type( + const LV2URIMap& uris, const Properties& properties, bool& patch, bool& node, @@ -67,6 +74,8 @@ public: protected: Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value) const; + LV2URIMap& _uris; + private: Raul::URI _uri; mutable Properties _properties; diff --git a/src/shared/runtime_paths.cpp b/src/shared/runtime_paths.cpp index f823c4e2..832c3472 100644 --- a/src/shared/runtime_paths.cpp +++ b/src/shared/runtime_paths.cpp @@ -41,29 +41,44 @@ set_bundle_path_from_code(void* function) Dl_info dli; dladdr(function, &dli); +#ifdef BUNDLE char bin_loc[PATH_MAX]; realpath(dli.dli_fname, bin_loc); +#else + const char* bin_loc = dli.dli_fname; +#endif -#ifdef BUNDLE string bundle = bin_loc; bundle = bundle.substr(0, bundle.find_last_of(G_DIR_SEPARATOR)); bundle_path = bundle; -#endif } +void +set_bundle_path(const char* path) +{ + bundle_path = path; +} + + +/** Return the absolute path of a file in an Ingen LV2 bundle + */ +std::string +bundle_file_path(const std::string& name) +{ + return Glib::build_filename(bundle_path, name); +} + /** Return the absolute path of a 'resource' file. */ std::string data_file_path(const std::string& name) { - std::string ret; #ifdef BUNDLE - ret = Glib::build_filename(bundle_path, Glib::build_path(INGEN_DATA_DIR, name)); + return Glib::build_filename(bundle_path, Glib::build_path(INGEN_DATA_DIR, name)); #else - ret = Glib::build_filename(INGEN_DATA_DIR, name); + return Glib::build_filename(INGEN_DATA_DIR, name); #endif - return ret; } @@ -72,13 +87,11 @@ data_file_path(const std::string& name) std::string module_path(const std::string& name) { - std::string ret; #ifdef BUNDLE - ret = Glib::Module::build_path(Glib::build_path(bundle_path, INGEN_MODULE_DIR), name); + return Glib::Module::build_path(Glib::build_path(bundle_path, INGEN_MODULE_DIR), name); #else - ret = Glib::Module::build_path(INGEN_MODULE_DIR, name); + return Glib::Module::build_path(INGEN_MODULE_DIR, name); #endif - return ret; } diff --git a/src/shared/runtime_paths.hpp b/src/shared/runtime_paths.hpp index e93e2343..0e8e2b85 100644 --- a/src/shared/runtime_paths.hpp +++ b/src/shared/runtime_paths.hpp @@ -27,8 +27,10 @@ namespace Ingen { namespace Shared { +void set_bundle_path(const char* path); void set_bundle_path_from_code(void* function); +std::string bundle_file_path(const std::string& name); std::string data_file_path(const std::string& name); std::string module_path(const std::string& name); diff --git a/src/shared/wscript b/src/shared/wscript index 540d4e83..6626f55a 100644 --- a/src/shared/wscript +++ b/src/shared/wscript @@ -9,6 +9,7 @@ def build(bld): obj.source = ''' Builder.cpp ClashAvoider.cpp + Configuration.cpp LV2Features.cpp LV2Object.cpp LV2URIMap.cpp -- cgit v1.2.1