summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-10-25 05:10:37 +0000
committerDavid Robillard <d@drobilla.net>2015-10-25 05:10:37 +0000
commit94d2f7cfc7e573c6fdd7487b1ab207d01e9fdbcf (patch)
tree0d2c95c194d95e6e5925c66bbd4c709173421bfd
parentcbd64a410c165972f13d18e4260bb63b770b3c1f (diff)
downloadingen-94d2f7cfc7e573c6fdd7487b1ab207d01e9fdbcf.tar.gz
ingen-94d2f7cfc7e573c6fdd7487b1ab207d01e9fdbcf.tar.bz2
ingen-94d2f7cfc7e573c6fdd7487b1ab207d01e9fdbcf.zip
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
-rw-r--r--ingen/Resource.hpp25
-rw-r--r--src/server/CompiledGraph.hpp18
-rw-r--r--src/server/Engine.cpp108
-rw-r--r--src/server/GraphImpl.cpp10
-rw-r--r--src/server/events/CreateGraph.cpp92
-rw-r--r--src/server/events/CreateGraph.hpp17
-rw-r--r--src/server/events/CreatePort.cpp12
-rw-r--r--src/server/events/CreatePort.hpp10
-rw-r--r--src/server/events/Delta.cpp2
9 files changed, 162 insertions, 132 deletions
diff --git a/ingen/Resource.hpp b/ingen/Resource.hpp
index d798b009..31d23dac 100644
--- a/ingen/Resource.hpp
+++ b/ingen/Resource.hpp
@@ -99,7 +99,30 @@ public:
virtual ~Resource() {}
- typedef std::multimap<Raul::URI, Property> Properties;
+ class Properties : public std::multimap<Raul::URI, Property> {
+ public:
+ Properties() {}
+
+ Properties(const Properties& copy)
+ : std::multimap<Raul::URI, Property>(copy)
+ {}
+
+ Properties(std::initializer_list<value_type> l)
+ : std::multimap<Raul::URI, Property>(l)
+ {}
+
+ void put(const Raul::URI& key,
+ const Atom& value,
+ Graph ctx = Graph::DEFAULT) {
+ insert(std::make_pair(key, Property(value, ctx)));
+ }
+
+ void put(const Raul::URI& key,
+ const URIs::Quark& value,
+ Graph ctx = Graph::DEFAULT) {
+ insert(std::make_pair(key, Property(value, ctx)));
+ }
+ };
/** Get a single property value.
*
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<BlockImpl*>& 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<BlockImpl*>& dependants() const { return _dependants; }
+ BlockImpl* block() const { return _block; }
private:
- BlockImpl* _block;
- std::vector<BlockImpl*> _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<Interface>(), -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<Interface> 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<Events::CreatePort>(
+ 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<Events::CreatePort>(
+ 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<GraphImpl*>(_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<GraphImpl*>(_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<Event> 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<Event> 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<Event> 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<Event> > _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 <boost/optional.hpp>
+
#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> _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()) {