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/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 ++-- 64 files changed, 651 insertions(+), 352 deletions(-) (limited to 'src/engine') 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) -- cgit v1.2.1