summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-08-12 04:46:29 +0000
committerDavid Robillard <d@drobilla.net>2015-08-12 04:46:29 +0000
commitdd79e76e41446833088482588456afed37231bff (patch)
treec0f3c5c2fc74b286d529df69ad2206e2fddd96f9 /src/server
parent44af7b7b66e2083819103c760ab3bf4980469f86 (diff)
downloadingen-dd79e76e41446833088482588456afed37231bff.tar.gz
ingen-dd79e76e41446833088482588456afed37231bff.tar.bz2
ingen-dd79e76e41446833088482588456afed37231bff.zip
Server-side presets.
git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5703 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/server')
-rw-r--r--src/server/BlockImpl.cpp8
-rw-r--r--src/server/BlockImpl.hpp16
-rw-r--r--src/server/ControlBindings.cpp2
-rw-r--r--src/server/DuplexPort.cpp19
-rw-r--r--src/server/EventWriter.cpp8
-rw-r--r--src/server/GraphPlugin.hpp2
-rw-r--r--src/server/InputPort.cpp2
-rw-r--r--src/server/InternalPlugin.cpp2
-rw-r--r--src/server/LV2Block.cpp71
-rw-r--r--src/server/LV2Block.hpp3
-rw-r--r--src/server/LV2Plugin.cpp44
-rw-r--r--src/server/LV2Plugin.hpp2
-rw-r--r--src/server/NodeImpl.cpp2
-rw-r--r--src/server/NodeImpl.hpp2
-rw-r--r--src/server/PluginImpl.hpp30
-rw-r--r--src/server/events/Delta.cpp54
-rw-r--r--src/server/events/Delta.hpp5
-rw-r--r--src/server/events/Get.cpp38
-rw-r--r--src/server/events/Get.hpp7
19 files changed, 268 insertions, 49 deletions
diff --git a/src/server/BlockImpl.cpp b/src/server/BlockImpl.cpp
index ecc73090..103747fe 100644
--- a/src/server/BlockImpl.cpp
+++ b/src/server/BlockImpl.cpp
@@ -71,12 +71,18 @@ BlockImpl::port(uint32_t index) const
return (*_ports)[index];
}
-const Plugin*
+const Resource*
BlockImpl::plugin() const
{
return _plugin;
}
+const PluginImpl*
+BlockImpl::plugin_impl() const
+{
+ return _plugin;
+}
+
void
BlockImpl::activate(BufferFactory& bufs)
{
diff --git a/src/server/BlockImpl.hpp b/src/server/BlockImpl.hpp
index 44271cc3..2dcc4762 100644
--- a/src/server/BlockImpl.hpp
+++ b/src/server/BlockImpl.hpp
@@ -20,6 +20,7 @@
#include <list>
#include <boost/intrusive/slist.hpp>
+#include <boost/optional.hpp>
#include "lilv/lilv.h"
@@ -28,6 +29,7 @@
#include "BufferRef.hpp"
#include "Context.hpp"
#include "NodeImpl.hpp"
+#include "PluginImpl.hpp"
#include "PortType.hpp"
#include "types.hpp"
@@ -36,9 +38,6 @@ class Maid;
}
namespace Ingen {
-
-class Plugin;
-
namespace Server {
class Buffer;
@@ -106,6 +105,11 @@ public:
/** Restore `state`. */
virtual void apply_state(LilvState* state) {}
+ /** Save current state as preset. */
+ virtual boost::optional<Resource>
+ save_preset(const Raul::URI& bundle,
+ const Properties& props) { return boost::optional<Resource>(); }
+
/** Learn the next incoming MIDI event (for internals) */
virtual void learn() {}
@@ -152,14 +156,14 @@ public:
ProcessContext& context, Raul::Maid& maid, uint32_t poly);
/** Information about the Plugin this Block is an instance of.
- * Not the best name - not all blocks come from plugins (e.g. Graph)
+ * Not the best name - not all blocks come from plugins (ie Graph)
*/
- virtual PluginImpl* plugin_impl() const { return _plugin; }
+ virtual const Resource* plugin() const;
/** Information about the Plugin this Block is an instance of.
* Not the best name - not all blocks come from plugins (ie Graph)
*/
- virtual const Plugin* plugin() const;
+ virtual const PluginImpl* plugin_impl() const;
virtual void plugin(PluginImpl* pi) { _plugin = pi; }
diff --git a/src/server/ControlBindings.cpp b/src/server/ControlBindings.cpp
index 40255fff..c4a95476 100644
--- a/src/server/ControlBindings.cpp
+++ b/src/server/ControlBindings.cpp
@@ -180,7 +180,7 @@ ControlBindings::port_value_changed(ProcessContext& context,
break;
}
if (size > 0) {
- _feedback->append_event(0, size, uris.midi_MidiEvent.id, buf);
+ _feedback->append_event(0, size, (LV2_URID)uris.midi_MidiEvent, buf);
}
}
}
diff --git a/src/server/DuplexPort.cpp b/src/server/DuplexPort.cpp
index 0a928a3f..f681e250 100644
--- a/src/server/DuplexPort.cpp
+++ b/src/server/DuplexPort.cpp
@@ -91,28 +91,25 @@ DuplexPort::inherit_neighbour(const PortImpl* port,
Resource::Properties& remove,
Resource::Properties& add)
{
+ const URIs& uris = _bufs.uris();
+
/* TODO: This needs to become more sophisticated, and correct the situation
if the port is disconnected. */
if (_type == PortType::CONTROL || _type == PortType::CV) {
if (port->minimum().get<float>() < _min.get<float>()) {
_min = port->minimum();
- remove.insert(std::make_pair(_bufs.uris().lv2_minimum,
- Property(_bufs.uris().patch_wildcard)));
- add.insert(std::make_pair(_bufs.uris().lv2_minimum,
- port->minimum()));
+ remove.emplace(uris.lv2_minimum, uris.patch_wildcard);
+ add.emplace(uris.lv2_minimum, port->minimum());
}
if (port->maximum().get<float>() > _max.get<float>()) {
_max = port->maximum();
- remove.insert(std::make_pair(_bufs.uris().lv2_maximum,
- Property(_bufs.uris().patch_wildcard)));
- add.insert(std::make_pair(_bufs.uris().lv2_maximum,
- port->maximum()));
+ remove.emplace(uris.lv2_maximum, uris.patch_wildcard);
+ add.emplace(uris.lv2_maximum, port->maximum());
}
} else if (_type == PortType::ATOM) {
for (Resource::Properties::const_iterator i = port->properties().find(
- _bufs.uris().atom_supports);
- i != port->properties().end() &&
- i->first == _bufs.uris().atom_supports;
+ uris.atom_supports);
+ i != port->properties().end() && i->first == uris.atom_supports;
++i) {
set_property(i->first, i->second);
add.insert(*i);
diff --git a/src/server/EventWriter.cpp b/src/server/EventWriter.cpp
index 1ec5e1a7..6c04c73d 100644
--- a/src/server/EventWriter.cpp
+++ b/src/server/EventWriter.cpp
@@ -127,11 +127,11 @@ EventWriter::set_property(const Raul::URI& uri,
const Atom& value)
{
Resource::Properties remove;
- remove.insert(
- make_pair(predicate,
- Resource::Property(_engine.world()->uris().patch_wildcard)));
+ remove.emplace(predicate,
+ _engine.world()->uris().patch_wildcard.urid);
+
Resource::Properties add;
- add.insert(make_pair(predicate, value));
+ add.emplace(predicate, value);
_engine.enqueue_event(
new Events::Delta(_engine, _respondee, _request_id, now(),
Events::Delta::Type::SET, Resource::Graph::DEFAULT,
diff --git a/src/server/GraphPlugin.hpp b/src/server/GraphPlugin.hpp
index 8cd08c1b..e18e173a 100644
--- a/src/server/GraphPlugin.hpp
+++ b/src/server/GraphPlugin.hpp
@@ -36,7 +36,7 @@ public:
const Raul::URI& uri,
const Raul::Symbol& symbol,
const std::string& name)
- : PluginImpl(uris, Plugin::Graph, uri)
+ : PluginImpl(uris, uris.ingen_Graph, uri)
{}
BlockImpl* instantiate(BufferFactory& bufs,
diff --git a/src/server/InputPort.cpp b/src/server/InputPort.cpp
index 974fe3ab..f2aacea1 100644
--- a/src/server/InputPort.cpp
+++ b/src/server/InputPort.cpp
@@ -51,7 +51,7 @@ InputPort::InputPort(BufferFactory& bufs,
const Ingen::URIs& uris = bufs.uris();
if (parent->graph_type() != Node::GraphType::GRAPH) {
- add_property(uris.rdf_type, uris.lv2_InputPort);
+ add_property(uris.rdf_type, uris.lv2_InputPort.urid);
}
}
diff --git a/src/server/InternalPlugin.cpp b/src/server/InternalPlugin.cpp
index f1ee9024..647823f7 100644
--- a/src/server/InternalPlugin.cpp
+++ b/src/server/InternalPlugin.cpp
@@ -35,7 +35,7 @@ using namespace Internals;
InternalPlugin::InternalPlugin(URIs& uris,
const Raul::URI& uri,
const Raul::Symbol& symbol)
- : PluginImpl(uris, Plugin::Internal, uri)
+ : PluginImpl(uris, uris.ingen_Internal, uri)
, _symbol(symbol)
{
set_property(uris.rdf_type, uris.ingen_Internal);
diff --git a/src/server/LV2Block.cpp b/src/server/LV2Block.cpp
index 30d1f090..6b644e5c 100644
--- a/src/server/LV2Block.cpp
+++ b/src/server/LV2Block.cpp
@@ -19,6 +19,9 @@
#include <cassert>
#include <cmath>
+#include <glibmm/miscutils.h>
+#include <glibmm/convert.h>
+
#include "lv2/lv2plug.in/ns/ext/morph/morph.h"
#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
#include "lv2/lv2plug.in/ns/ext/options/options.h"
@@ -577,6 +580,74 @@ LV2Block::apply_state(LilvState* state)
}
}
+static const void*
+get_port_value(const char* port_symbol,
+ void* user_data,
+ uint32_t* size,
+ uint32_t* type)
+{
+ LV2Block* const block = (LV2Block*)user_data;
+ PortImpl* const port = block->port_by_symbol(port_symbol);
+
+ if (port && port->is_input() && port->value().is_valid()) {
+ *size = port->value().size();
+ *type = port->value().type();
+ return port->value().get_body();
+ }
+
+ return NULL;
+}
+
+boost::optional<Resource>
+LV2Block::save_preset(const Raul::URI& uri,
+ const Properties& props)
+{
+ World* world = parent_graph()->engine().world();
+ LilvWorld* lworld = _lv2_plugin->lv2_info()->lv2_world();
+ LV2_URID_Map* lmap = &world->uri_map().urid_map_feature()->urid_map;
+ LV2_URID_Unmap* lunmap = &world->uri_map().urid_unmap_feature()->urid_unmap;
+
+ const std::string path = Glib::filename_from_uri(uri);
+ const std::string dirname = Glib::path_get_dirname(path);
+ const std::string basename = Glib::path_get_basename(path);
+
+ LilvState* state = lilv_state_new_from_instance(
+ _lv2_plugin->lilv_plugin(), instance(0), lmap,
+ NULL, NULL, NULL, path.c_str(),
+ get_port_value, this, LV2_STATE_IS_NATIVE, NULL);
+
+ if (state) {
+ const Properties::const_iterator l = props.find(_uris.rdfs_label);
+ if (l != props.end() && l->second.type() == _uris.atom_String) {
+ lilv_state_set_label(state, l->second.ptr<char>());
+ }
+
+ lilv_state_save(lworld, lmap, lunmap, state, NULL,
+ dirname.c_str(), basename.c_str());
+
+ const Raul::URI uri(lilv_node_as_uri(lilv_state_get_uri(state)));
+ const std::string label(lilv_state_get_label(state)
+ ? lilv_state_get_label(state)
+ : basename);
+ lilv_state_free(state);
+
+ Resource preset(_uris, uri);
+ preset.set_property(_uris.rdf_type, _uris.pset_Preset);
+ preset.set_property(_uris.rdfs_label, world->forge().alloc(label));
+ preset.set_property(_uris.lv2_appliesTo,
+ world->forge().make_urid(_lv2_plugin->uri()));
+
+ LilvNode* lbundle = lilv_new_uri(
+ lworld, Glib::filename_to_uri(dirname + "/").c_str());
+ lilv_world_load_bundle(lworld, lbundle);
+ lilv_node_free(lbundle);
+
+ return preset;
+ }
+
+ return boost::optional<Resource>();
+}
+
void
LV2Block::set_port_buffer(uint32_t voice,
uint32_t port_num,
diff --git a/src/server/LV2Block.hpp b/src/server/LV2Block.hpp
index f07f845f..ffb86d0a 100644
--- a/src/server/LV2Block.hpp
+++ b/src/server/LV2Block.hpp
@@ -67,6 +67,9 @@ public:
void apply_state(LilvState* state);
+ boost::optional<Resource> save_preset(const Raul::URI& bundle,
+ const Properties& props);
+
void set_port_buffer(uint32_t voice,
uint32_t port_num,
BufferRef buf,
diff --git a/src/server/LV2Plugin.cpp b/src/server/LV2Plugin.cpp
index 58491f4c..d88689ca 100644
--- a/src/server/LV2Plugin.cpp
+++ b/src/server/LV2Plugin.cpp
@@ -16,7 +16,9 @@
#include <string>
+#include "ingen/Log.hpp"
#include "ingen/URIs.hpp"
+#include "lv2/lv2plug.in/ns/ext/presets/presets.h"
#include "Driver.hpp"
#include "Engine.hpp"
@@ -29,7 +31,9 @@ namespace Ingen {
namespace Server {
LV2Plugin::LV2Plugin(SPtr<LV2Info> lv2_info, const Raul::URI& uri)
- : PluginImpl(lv2_info->world().uris(), Plugin::LV2, uri)
+ : PluginImpl(lv2_info->world().uris(),
+ lv2_info->world().uris().lv2_Plugin,
+ uri)
, _lilv_plugin(NULL)
, _lv2_info(lv2_info)
{
@@ -80,5 +84,43 @@ LV2Plugin::lilv_plugin(const LilvPlugin* p)
_lilv_plugin = p;
}
+void
+LV2Plugin::load_presets()
+{
+ LilvWorld* lworld = _lv2_info->world().lilv_world();
+ LilvNode* pset_Preset = lilv_new_uri(lworld, LV2_PRESETS__Preset);
+ LilvNode* rdfs_label = lilv_new_uri(lworld, LILV_NS_RDFS "label");
+ LilvNodes* presets = lilv_plugin_get_related(_lilv_plugin, pset_Preset);
+
+ if (presets) {
+ LILV_FOREACH(nodes, i, presets) {
+ const LilvNode* preset = lilv_nodes_get(presets, i);
+ lilv_world_load_resource(lworld, preset);
+
+ LilvNodes* labels = lilv_world_find_nodes(
+ lworld, preset, rdfs_label, NULL);
+ if (labels) {
+ const LilvNode* label = lilv_nodes_get_first(labels);
+
+ _presets.emplace(Raul::URI(lilv_node_as_uri(preset)),
+ lilv_node_as_string(label));
+
+ lilv_nodes_free(labels);
+ } else {
+ _lv2_info->world().log().error(
+ fmt("Preset <%1%> has no rdfs:label\n")
+ % lilv_node_as_string(lilv_nodes_get(presets, i)));
+ }
+ }
+
+ lilv_nodes_free(presets);
+ }
+
+ lilv_node_free(rdfs_label);
+ lilv_node_free(pset_Preset);
+
+ PluginImpl::load_presets();
+}
+
} // namespace Server
} // namespace Ingen
diff --git a/src/server/LV2Plugin.hpp b/src/server/LV2Plugin.hpp
index 0dde120c..63946071 100644
--- a/src/server/LV2Plugin.hpp
+++ b/src/server/LV2Plugin.hpp
@@ -52,6 +52,8 @@ public:
const LilvPlugin* lilv_plugin() const { return _lilv_plugin; }
void lilv_plugin(const LilvPlugin* p);
+ void load_presets();
+
private:
const LilvPlugin* _lilv_plugin;
SPtr<LV2Info> _lv2_info;
diff --git a/src/server/NodeImpl.cpp b/src/server/NodeImpl.cpp
index 27d1ba4e..c95f3c5e 100644
--- a/src/server/NodeImpl.cpp
+++ b/src/server/NodeImpl.cpp
@@ -23,7 +23,7 @@ using namespace std;
namespace Ingen {
namespace Server {
-NodeImpl::NodeImpl(Ingen::URIs& uris,
+NodeImpl::NodeImpl(const Ingen::URIs& uris,
NodeImpl* parent,
const Raul::Symbol& symbol)
: Node(uris, parent ? parent->path().child(symbol) : Raul::Path("/"))
diff --git a/src/server/NodeImpl.hpp b/src/server/NodeImpl.hpp
index 17238a74..457834f2 100644
--- a/src/server/NodeImpl.hpp
+++ b/src/server/NodeImpl.hpp
@@ -92,7 +92,7 @@ public:
ProcessContext& context, Raul::Maid& maid, uint32_t poly) = 0;
protected:
- NodeImpl(Ingen::URIs& uris,
+ NodeImpl(const Ingen::URIs& uris,
NodeImpl* parent,
const Raul::Symbol& symbol);
diff --git a/src/server/PluginImpl.hpp b/src/server/PluginImpl.hpp
index 92338b70..414bd1f1 100644
--- a/src/server/PluginImpl.hpp
+++ b/src/server/PluginImpl.hpp
@@ -21,7 +21,6 @@
#include <boost/utility.hpp>
-#include "ingen/Plugin.hpp"
#include "ingen/Resource.hpp"
#include "raul/Symbol.hpp"
#include "raul/URI.hpp"
@@ -41,17 +40,19 @@ class GraphImpl;
*
* Conceptually, a Block is an instance of this.
*/
-class PluginImpl : public Plugin
+class PluginImpl : public Resource
, public boost::noncopyable
{
public:
PluginImpl(Ingen::URIs& uris,
- Type type,
+ const Atom& type,
const Raul::URI& uri)
- : Plugin(uris, uri)
+ : Resource(uris, uri)
, _type(type)
{}
+ virtual ~PluginImpl() {}
+
virtual BlockImpl* instantiate(BufferFactory& bufs,
const Raul::Symbol& symbol,
bool polyphonic,
@@ -60,11 +61,26 @@ public:
virtual const Raul::Symbol symbol() const = 0;
- Plugin::Type type() const { return _type; }
- void type(Plugin::Type t) { _type = t; }
+ const Atom& type() const { return _type; }
+ void set_type(const Atom& t) { _type = t; }
+
+ typedef std::pair<Raul::URI, std::string> Preset;
+ typedef std::map<Raul::URI, std::string> Presets;
+
+ const Presets& presets(bool force_reload=false) {
+ if (!_presets_loaded || force_reload) {
+ load_presets();
+ }
+
+ return _presets;
+ }
+
+ virtual void load_presets() { _presets_loaded = true; }
protected:
- Plugin::Type _type;
+ Atom _type;
+ Presets _presets;
+ bool _presets_loaded;
};
} // namespace Server
diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp
index 7d2f896d..dc6759b0 100644
--- a/src/server/events/Delta.cpp
+++ b/src/server/events/Delta.cpp
@@ -34,6 +34,7 @@
#include "PortImpl.hpp"
#include "PortType.hpp"
#include "SetPortValue.hpp"
+#include "events/Get.hpp"
// #define DUMP 1
// #include "ingen/URIMap.hpp"
@@ -134,10 +135,45 @@ s_add_set_event(const char* port_symbol,
bool
Delta::pre_process()
{
+ const Ingen::URIs& uris = _engine.world()->uris();
+
const bool is_graph_object = Node::uri_is_path(_subject);
const bool is_client = (_subject == "ingen:/clients/this");
+ const bool is_file = (_subject.substr(0, 5) == "file:");
bool poly_changed = false;
+ if (_type == Type::PUT && is_file) {
+ // Ensure type is Preset, the only supported file put
+ const auto t = _properties.find(uris.rdf_type);
+ if (t == _properties.end() || t->second != uris.pset_Preset) {
+ return Event::pre_process_done(Status::BAD_REQUEST, _subject);
+ }
+
+ // Get "prototype" for preset (node to save state for)
+ const auto p = _properties.find(uris.lv2_prototype);
+ if (p == _properties.end()) {
+ return Event::pre_process_done(Status::BAD_REQUEST, _subject);
+ }
+
+ const Raul::URI prot(_engine.world()->forge().str(p->second, false));
+
+ Node* node = _engine.store()->get(Node::uri_to_path(Raul::URI(prot)));
+ if (!node) {
+ return Event::pre_process_done(Status::NOT_FOUND, prot);
+ }
+
+ BlockImpl* block = dynamic_cast<BlockImpl*>(node);
+ if (!block) {
+ return Event::pre_process_done(Status::BAD_OBJECT_TYPE, prot);
+ }
+
+ if ((_preset = block->save_preset(_subject, _properties))) {
+ return Event::pre_process_done(Status::SUCCESS);
+ } else {
+ return Event::pre_process_done(Status::FAILURE);
+ }
+ }
+
// Take a writer lock while we modify the store
std::unique_lock<std::mutex> lock(_engine.store()->mutex());
@@ -149,8 +185,6 @@ Delta::pre_process()
return Event::pre_process_done(Status::NOT_FOUND, _subject);
}
- const Ingen::URIs& uris = _engine.world()->uris();
-
if (is_graph_object && !_object) {
Raul::Path path(Node::uri_to_path(_subject));
bool is_graph = false, is_block = false, is_port = false, is_output = false;
@@ -258,6 +292,8 @@ Delta::pre_process()
if ((_state = block->load_preset(Raul::URI(str)))) {
lilv_state_emit_port_values(
_state, s_add_set_event, this);
+ } else {
+ _engine.log().warn(fmt("Failed to load preset <%1%>\n") % str);
}
} else {
_status = Status::BAD_VALUE;
@@ -341,7 +377,7 @@ Delta::pre_process()
void
Delta::execute(ProcessContext& context)
{
- if (_status != Status::SUCCESS) {
+ if (_status != Status::SUCCESS || _preset) {
return;
}
@@ -406,7 +442,7 @@ Delta::execute(ProcessContext& context)
if (port) {
_engine.control_bindings()->port_binding_changed(context, port, value);
} else if (block) {
- if (block->plugin_impl()->type() == Plugin::Internal) {
+ if (uris.ingen_Internal == block->plugin_impl()->type()) {
block->learn();
}
}
@@ -472,7 +508,15 @@ Delta::post_process()
_engine.broadcaster()->clear_ignore_client();
break;
case Type::PUT:
- _engine.broadcaster()->put(_subject, _properties, _context);
+ if (_type == Type::PUT && _subject.substr(0, 5) == "file:") {
+ // Preset save
+ Get::Response response;
+ response.put(_preset->uri(), _preset->properties());
+ response.send(_engine.broadcaster());
+ } else {
+ // Graph object put
+ _engine.broadcaster()->put(_subject, _properties, _context);
+ }
break;
case Type::PATCH:
_engine.broadcaster()->delta(_subject, _remove, _properties);
diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp
index 0b5934ac..7c303fc2 100644
--- a/src/server/events/Delta.hpp
+++ b/src/server/events/Delta.hpp
@@ -19,10 +19,13 @@
#include <vector>
+#include <boost/optional.hpp>
+
#include "lilv/lilv.h"
#include "raul/URI.hpp"
+#include "PluginImpl.hpp"
#include "ControlBindings.hpp"
#include "Event.hpp"
@@ -128,6 +131,8 @@ private:
SPtr<ControlBindings::Bindings> _old_bindings;
+ boost::optional<Resource> _preset;
+
std::unique_lock<std::mutex> _poly_lock; ///< Long-term lock for poly changes
};
diff --git a/src/server/events/Get.cpp b/src/server/events/Get.cpp
index bba95485..185f275a 100644
--- a/src/server/events/Get.cpp
+++ b/src/server/events/Get.cpp
@@ -60,8 +60,10 @@ Get::Response::put_port(const PortImpl* port)
void
Get::Response::put_block(const BlockImpl* block)
{
- PluginImpl* const plugin = block->plugin_impl();
- if (plugin->type() == Plugin::Graph) {
+ const PluginImpl* const plugin = block->plugin_impl();
+ const URIs& uris = plugin->uris();
+
+ if (uris.ingen_Graph == plugin->type()) {
put_graph((const GraphImpl*)block);
} else {
put(block->uri(), block->properties());
@@ -82,7 +84,7 @@ Get::Response::put_graph(const GraphImpl* graph)
graph->properties(Resource::Graph::EXTERNAL),
Resource::Graph::EXTERNAL);
- // Enqueue locks
+ // Enqueue blocks
for (const auto& b : graph->blocks()) {
put_block(&b);
}
@@ -100,6 +102,29 @@ Get::Response::put_graph(const GraphImpl* graph)
}
}
+void
+Get::Response::put_plugin(PluginImpl* plugin)
+{
+ put(plugin->uri(), plugin->properties());
+
+ for (const auto& p : plugin->presets()) {
+ put_preset(plugin->uris(), plugin->uri(), p.first, p.second);
+ }
+}
+
+void
+Get::Response::put_preset(const URIs& uris,
+ const Raul::URI& plugin,
+ const Raul::URI& preset,
+ const std::string& label)
+{
+ Resource::Properties props;
+ props.emplace(uris.rdf_type, uris.pset_Preset.urid);
+ props.emplace(uris.rdfs_label, uris.forge.alloc(label));
+ props.emplace(uris.lv2_appliesTo, uris.forge.make_urid(plugin));
+ put(preset, props);
+}
+
/** Returns true if a is closer to the root than b. */
static inline bool
put_higher_than(const Get::Response::Put& a, const Get::Response::Put& b)
@@ -159,11 +184,10 @@ Get::pre_process()
return Event::pre_process_done(Status::SUCCESS);
}
return Event::pre_process_done(Status::NOT_FOUND, _uri);
+ } else if ((_plugin = _engine.block_factory()->plugin(_uri))) {
+ _response.put_plugin(_plugin);
+ return Event::pre_process_done(Status::SUCCESS);
} else {
- if ((_plugin = _engine.block_factory()->plugin(_uri))) {
- _response.put(_uri, _plugin->properties());
- return Event::pre_process_done(Status::SUCCESS);
- }
return Event::pre_process_done(Status::NOT_FOUND, _uri);
}
}
diff --git a/src/server/events/Get.hpp b/src/server/events/Get.hpp
index 5a4bde23..f24e42e0 100644
--- a/src/server/events/Get.hpp
+++ b/src/server/events/Get.hpp
@@ -67,6 +67,11 @@ public:
void put_port(const PortImpl* port);
void put_block(const BlockImpl* block);
void put_graph(const GraphImpl* graph);
+ void put_plugin(PluginImpl* plugin);
+ void put_preset(const URIs& uris,
+ const Raul::URI& plugin,
+ const Raul::URI& preset,
+ const std::string& label);
void send(Interface* dest);
@@ -88,7 +93,7 @@ public:
private:
const Raul::URI _uri;
const Node* _object;
- const PluginImpl* _plugin;
+ PluginImpl* _plugin;
BlockFactory::Plugins _plugins;
Response _response;
};