From 94d2f7cfc7e573c6fdd7487b1ab207d01e9fdbcf Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 25 Oct 2015 05:10:37 +0000 Subject: Create all graphs the same way This ensures that subgraphs always have the standard control ports, so they are valid Ingen graphs on their own.. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5783 a436a847-0d15-0410-975c-d299462d15a1 --- src/server/CompiledGraph.hpp | 18 ++----- src/server/Engine.cpp | 108 +++++++------------------------------- src/server/GraphImpl.cpp | 10 ++-- src/server/events/CreateGraph.cpp | 92 ++++++++++++++++++++++++++++---- src/server/events/CreateGraph.hpp | 17 +++--- src/server/events/CreatePort.cpp | 12 +++-- src/server/events/CreatePort.hpp | 10 +++- src/server/events/Delta.cpp | 2 +- 8 files changed, 138 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/server/CompiledGraph.hpp b/src/server/CompiledGraph.hpp index 8ef9bac3..9f4071a5 100644 --- a/src/server/CompiledGraph.hpp +++ b/src/server/CompiledGraph.hpp @@ -26,30 +26,18 @@ namespace Ingen { namespace Server { -class EdgeImpl; class BlockImpl; /** All information required about a block to execute it in an audio thread. */ class CompiledBlock { public: - CompiledBlock(BlockImpl* b, size_t np, const std::list& deps) - : _block(b) - { - // Copy to a vector for maximum iteration speed and cache optimization - // (Need to take a copy anyway) + CompiledBlock(BlockImpl* b) : _block(b) {} - _dependants.reserve(deps.size()); - for (const auto& d : deps) - _dependants.push_back(d); - } - - BlockImpl* block() const { return _block; } - const std::vector& dependants() const { return _dependants; } + BlockImpl* block() const { return _block; } private: - BlockImpl* _block; - std::vector _dependants; ///< Blocks this one's output ports are connected to + BlockImpl* _block; }; /** A graph ``compiled'' into a flat structure with the correct order so diff --git a/src/server/Engine.cpp b/src/server/Engine.cpp index a84a2423..90a2c200 100644 --- a/src/server/Engine.cpp +++ b/src/server/Engine.cpp @@ -22,7 +22,7 @@ #include "lv2/lv2plug.in/ns/ext/buf-size/buf-size.h" -#include "events/CreatePort.hpp" +#include "events/CreateGraph.hpp" #include "ingen/Configuration.hpp" #include "ingen/Log.hpp" #include "ingen/Store.hpp" @@ -201,19 +201,6 @@ Engine::event_time() return start + _driver->block_length(); } -static void -execute_and_delete_event(ProcessContext& context, Event* ev) -{ - ev->pre_process(); - if (ev->time() < context.start()) { - // Didn't get around to executing in time, oh well... - ev->set_time(context.start()); - } - ev->execute(context); - ev->post_process(); - delete ev; -} - void Engine::init(double sample_rate, uint32_t block_length, size_t seq_size) { @@ -235,86 +222,29 @@ Engine::activate() driver()->block_length(), buffer_factory()->default_size(_world->uris().atom_Sequence)); - const Ingen::URIs& uris = world()->uris(); - Forge& forge = world()->forge(); + const Ingen::URIs& uris = world()->uris(); - // Create root graph if (!_root_graph) { - _root_graph = new GraphImpl( - *this, Raul::Symbol("root"), 1, NULL, _driver->sample_rate(), 1); - _root_graph->set_property( - uris.rdf_type, - Resource::Property(uris.ingen_Graph, Resource::Graph::INTERNAL)); - _root_graph->set_property( - uris.ingen_polyphony, - Resource::Property(_world->forge().make(int32_t(1)), - Resource::Graph::INTERNAL)); - _root_graph->activate(*_buffer_factory); - _world->store()->add(_root_graph); - _root_graph->set_compiled_graph(_root_graph->compile()); + // Create root graph + Resource::Properties graph_properties; + graph_properties.insert( + make_pair(uris.rdf_type, + Resource::Property(uris.ingen_Graph))); + graph_properties.insert( + make_pair(uris.ingen_polyphony, + Resource::Property(_world->forge().make(1), + Resource::Graph::INTERNAL))); + Events::CreateGraph ev( + *this, SPtr(), -1, 0, Raul::Path("/"), graph_properties); + + // Execute in "fake" process context (we are single threaded) ProcessContext context(*this); + ev.pre_process(); + ev.execute(context); + ev.post_process(); - Resource::Properties control_properties; - control_properties.insert( - make_pair(uris.lv2_name, forge.alloc("Control"))); - control_properties.insert( - make_pair(uris.rdf_type, - Resource::Property(uris.atom_AtomPort))); - control_properties.insert( - make_pair(uris.atom_bufferType, - Resource::Property(uris.atom_Sequence))); - control_properties.insert( - make_pair(uris.rsz_minimumSize, - // forge.make(int32_t(driver()->seq_size())))); - forge.make(4096))); - - // Add control input - Resource::Properties in_properties(control_properties); - in_properties.insert( - make_pair(uris.rdf_type, - Resource::Property(uris.lv2_InputPort))); - in_properties.insert(make_pair(uris.lv2_index, forge.make(0))); - in_properties.insert( - make_pair(uris.lv2_portProperty, - Resource::Property(uris.lv2_connectionOptional))); - in_properties.insert( - make_pair(uris.ingen_canvasX, - Resource::Property(forge.make(32.0f), - Resource::Graph::EXTERNAL))); - in_properties.insert( - make_pair(uris.ingen_canvasY, - Resource::Property(forge.make(32.0f), - Resource::Graph::EXTERNAL))); - - SPtr respondee; - execute_and_delete_event( - context, new Events::CreatePort( - *this, respondee, -1, 0, Raul::Path("/control_in"), - false, in_properties)); - - // Add control out - Resource::Properties out_properties(control_properties); - out_properties.insert( - make_pair(uris.rdf_type, - Resource::Property(uris.lv2_OutputPort))); - out_properties.insert(make_pair(uris.lv2_index, forge.make(1))); - in_properties.insert( - make_pair(uris.lv2_portProperty, - Resource::Property(uris.lv2_connectionOptional))); - out_properties.insert( - make_pair(uris.ingen_canvasX, - Resource::Property(forge.make(128.0f), - Resource::Graph::EXTERNAL))); - out_properties.insert( - make_pair(uris.ingen_canvasY, - Resource::Property(forge.make(32.0f), - Resource::Graph::EXTERNAL))); - - execute_and_delete_event( - context, new Events::CreatePort( - *this, respondee, -1, 0, Raul::Path("/control_out"), - true, out_properties)); + _root_graph = ev.graph(); } _driver->activate(); diff --git a/src/server/GraphImpl.cpp b/src/server/GraphImpl.cpp index 535269a6..ef7f6a22 100644 --- a/src/server/GraphImpl.cpp +++ b/src/server/GraphImpl.cpp @@ -249,8 +249,12 @@ GraphImpl::set_buffer_size(Context& context, { BlockImpl::set_buffer_size(context, bufs, type, size); - for (size_t i = 0; i < _compiled_graph->size(); ++i) - (*_compiled_graph)[i].block()->set_buffer_size(context, bufs, type, size); + if (_compiled_graph) { + for (size_t i = 0; i < _compiled_graph->size(); ++i) { + const CompiledBlock& block = (*_compiled_graph)[i]; + block.block()->set_buffer_size(context, bufs, type, size); + } + } } void @@ -362,7 +366,7 @@ compile_recursive(BlockImpl* n, CompiledGraph* output) if (!p->traversed()) compile_recursive(p, output); - output->push_back(CompiledBlock(n, n->providers().size(), n->dependants())); + output->push_back(CompiledBlock(n)); } CompiledGraph* diff --git a/src/server/events/CreateGraph.cpp b/src/server/events/CreateGraph.cpp index 7c4b1940..e6ad0cb4 100644 --- a/src/server/events/CreateGraph.cpp +++ b/src/server/events/CreateGraph.cpp @@ -24,6 +24,7 @@ #include "Engine.hpp" #include "GraphImpl.hpp" #include "events/CreateGraph.hpp" +#include "events/CreatePort.hpp" namespace Ingen { namespace Server { @@ -43,16 +44,63 @@ CreateGraph::CreateGraph(Engine& engine, , _compiled_graph(NULL) {} +void +CreateGraph::build_child_events() +{ + const Ingen::URIs& uris = _engine.world()->uris(); + + // Properties common to both ports + Resource::Properties control_properties; + control_properties.put(uris.lv2_name, uris.forge.alloc("Control")); + control_properties.put(uris.rdf_type, uris.atom_AtomPort); + control_properties.put(uris.atom_bufferType, uris.atom_Sequence); + control_properties.put(uris.rsz_minimumSize, uris.forge.make(4096)); + control_properties.put(uris.lv2_portProperty, uris.lv2_connectionOptional); + + // Add control input + Resource::Properties in_properties(control_properties); + in_properties.put(uris.rdf_type, uris.lv2_InputPort); + in_properties.put(uris.lv2_index, uris.forge.make(0)); + in_properties.put(uris.ingen_canvasX, uris.forge.make(32.0f), + Resource::Graph::EXTERNAL); + in_properties.put(uris.ingen_canvasY, uris.forge.make(32.0f), + Resource::Graph::EXTERNAL); + + _child_events.push_back( + SPtr( + new Events::CreatePort( + _engine, _request_client, -1, _time, + _path.child(Raul::Symbol("control_in")), + in_properties))); + + // Add control out + Resource::Properties out_properties(control_properties); + out_properties.put(uris.rdf_type, uris.lv2_OutputPort); + out_properties.put(uris.lv2_index, uris.forge.make(1)); + out_properties.put(uris.ingen_canvasX, uris.forge.make(128.0f), + Resource::Graph::EXTERNAL); + out_properties.put(uris.ingen_canvasY, uris.forge.make(32.0f), + Resource::Graph::EXTERNAL); + + _child_events.push_back( + SPtr( + new Events::CreatePort(_engine, _request_client, -1, _time, + _path.child(Raul::Symbol("control_out")), + out_properties))); +} + bool CreateGraph::pre_process() { - if (_path.is_root() || _engine.store()->get(_path)) { + if (_engine.store()->get(_path)) { return Event::pre_process_done(Status::EXISTS, _path); } - _parent = dynamic_cast(_engine.store()->get(_path.parent())); - if (!_parent) { - return Event::pre_process_done(Status::PARENT_NOT_FOUND, _path.parent()); + if (!_path.is_root()) { + const Raul::Path up(_path.parent()); + if (!(_parent = dynamic_cast(_engine.store()->get(up)))) { + return Event::pre_process_done(Status::PARENT_NOT_FOUND, up); + } } const Ingen::URIs& uris = _engine.world()->uris(); @@ -70,11 +118,11 @@ CreateGraph::pre_process() return Event::pre_process_done(Status::INVALID_POLY, _path); } - if (int_poly == _parent->internal_poly()) { + if (!_parent || int_poly == _parent->internal_poly()) { ext_poly = int_poly; } - const Raul::Symbol symbol((_path.is_root()) ? "root" : _path.symbol()); + const Raul::Symbol symbol(_path.is_root() ? "graph" : _path.symbol()); // Get graph prototype iterator t = _properties.find(uris.lv2_prototype); @@ -108,10 +156,13 @@ CreateGraph::pre_process() _graph->set_properties(_properties); - _parent->add_block(*_graph); - if (_parent->enabled()) { - _graph->enable(); - _compiled_graph = _parent->compile(); + if (_parent) { + // Add graph to parent + _parent->add_block(*_graph); + if (_parent->enabled()) { + _graph->enable(); + _compiled_graph = _parent->compile(); + } } _graph->activate(*_engine.buffer_factory()); @@ -123,6 +174,12 @@ CreateGraph::pre_process() _engine.store()->add(&block); } + // Build and pre-process child events to create standard ports + build_child_events(); + for (SPtr ev : _child_events) { + ev->pre_process(); + } + return Event::pre_process_done(Status::SUCCESS); } @@ -130,7 +187,13 @@ void CreateGraph::execute(ProcessContext& context) { if (_graph) { - _parent->set_compiled_graph(_compiled_graph); + if (_parent) { + _parent->set_compiled_graph(_compiled_graph); + } + + for (SPtr ev : _child_events) { + ev->execute(context); + } } } @@ -141,6 +204,13 @@ CreateGraph::post_process() if (respond() == Status::SUCCESS) { _update.send(_engine.broadcaster()); } + + if (_graph) { + for (SPtr ev : _child_events) { + ev->post_process(); + } + } + _child_events.clear(); } } // namespace Events diff --git a/src/server/events/CreateGraph.hpp b/src/server/events/CreateGraph.hpp index e7a5e7af..bcb857ae 100644 --- a/src/server/events/CreateGraph.hpp +++ b/src/server/events/CreateGraph.hpp @@ -48,13 +48,18 @@ public: void execute(ProcessContext& context); void post_process(); + GraphImpl* graph() { return _graph; } + private: - const Raul::Path _path; - Resource::Properties _properties; - Events::Get::Response _update; - GraphImpl* _graph; - GraphImpl* _parent; - CompiledGraph* _compiled_graph; + void build_child_events(); + + const Raul::Path _path; + Resource::Properties _properties; + Events::Get::Response _update; + GraphImpl* _graph; + GraphImpl* _parent; + CompiledGraph* _compiled_graph; + std::list< SPtr > _child_events; }; } // namespace Events diff --git a/src/server/events/CreatePort.cpp b/src/server/events/CreatePort.cpp index 4988c480..0f711f4f 100644 --- a/src/server/events/CreatePort.cpp +++ b/src/server/events/CreatePort.cpp @@ -41,7 +41,6 @@ CreatePort::CreatePort(Engine& engine, int32_t id, SampleCount timestamp, const Raul::Path& path, - bool is_output, const Resource::Properties& properties) : Event(engine, client, id, timestamp) , _path(path) @@ -53,7 +52,6 @@ CreatePort::CreatePort(Engine& engine, , _old_ports_array(NULL) , _engine_port(NULL) , _properties(properties) - , _is_output(is_output) { const Ingen::URIs& uris = _engine.world()->uris(); @@ -71,6 +69,10 @@ CreatePort::CreatePort(Engine& engine, _port_type = PortType::CV; } else if (type == uris.atom_AtomPort) { _port_type = PortType::ATOM; + } else if (type == uris.lv2_InputPort) { + _flow = Flow::INPUT; + } else if (type == uris.lv2_OutputPort) { + _flow = Flow::OUTPUT; } } @@ -88,6 +90,8 @@ CreatePort::pre_process() { if (_port_type == PortType::UNKNOWN) { return Event::pre_process_done(Status::UNKNOWN_TYPE, _path); + } else if (!_flow) { + return Event::pre_process_done(Status::UNKNOWN_TYPE, _path); } else if (_path.is_root()) { return Event::pre_process_done(Status::BAD_URI, _path); } else if (_engine.store()->get(_path)) { @@ -136,12 +140,12 @@ CreatePort::pre_process() _graph->num_ports_non_rt(), polyphonic, _port_type, _buf_type, buf_size, - value, _is_output); + value, _flow == Flow::OUTPUT); _graph_port->properties().insert(_properties.begin(), _properties.end()); _engine.store()->add(_graph_port); - if (_is_output) { + if (_flow == Flow::OUTPUT) { _graph->add_output(*_graph_port); } else { _graph->add_input(*_graph_port); diff --git a/src/server/events/CreatePort.hpp b/src/server/events/CreatePort.hpp index f9f1b6fa..a2dd55ce 100644 --- a/src/server/events/CreatePort.hpp +++ b/src/server/events/CreatePort.hpp @@ -17,6 +17,8 @@ #ifndef INGEN_EVENTS_CREATEPORT_HPP #define INGEN_EVENTS_CREATEPORT_HPP +#include + #include "ingen/Resource.hpp" #include "lv2/lv2plug.in/ns/ext/urid/urid.h" #include "raul/Array.hpp" @@ -47,7 +49,6 @@ public: int32_t id, SampleCount timestamp, const Raul::Path& path, - bool is_output, const Resource::Properties& properties); bool pre_process(); @@ -55,6 +56,11 @@ public: void post_process(); private: + enum class Flow { + INPUT, + OUTPUT + }; + Raul::Path _path; PortType _port_type; LV2_URID _buf_type; @@ -65,7 +71,7 @@ private: EnginePort* _engine_port; ///< Driver port if on the root Resource::Properties _properties; Resource::Properties _update; - bool _is_output; + boost::optional _flow; }; } // namespace Events diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index a85c8253..f6932075 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -201,7 +201,7 @@ Delta::pre_process() } else if (is_port) { _create_event = new CreatePort( _engine, _request_client, _request_id, _time, - path, is_output, _properties); + path, _properties); } if (_create_event) { if (_create_event->pre_process()) { -- cgit v1.2.1