summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2015-10-30 00:37:40 +0000
committerDavid Robillard <d@drobilla.net>2015-10-30 00:37:40 +0000
commit2fe35cd17f96a1d393fda203ccaa234b0aa69b16 (patch)
tree94e1f42f334ec3be791b1bb97ee96b27557f2c49 /src/server
parentcc5ec7438bfc46fbbdcf980ba4f7f3d4a3e78e52 (diff)
downloadingen-2fe35cd17f96a1d393fda203ccaa234b0aa69b16.tar.gz
ingen-2fe35cd17f96a1d393fda203ccaa234b0aa69b16.tar.bz2
ingen-2fe35cd17f96a1d393fda203ccaa234b0aa69b16.zip
Add protocol for loading and unloading bundles
Currently this is only really useful for refreshing updated bundles. It will trigger the appropriate load and unload in the Lilv world, but the set of plugins and presets is not updated and clients will not be notified of any changes. git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@5807 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src/server')
-rw-r--r--src/server/events/Delta.cpp65
-rw-r--r--src/server/events/Delta.hpp3
2 files changed, 66 insertions, 2 deletions
diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp
index f6932075..9b990c2d 100644
--- a/src/server/events/Delta.cpp
+++ b/src/server/events/Delta.cpp
@@ -134,6 +134,48 @@ s_add_set_event(const char* port_symbol,
((Delta*)user_data)->add_set_event(port_symbol, value, size, type);
}
+static LilvNode*
+get_file_node(LilvWorld* lworld, const URIs& uris, const Atom& value)
+{
+ if (value.type() == uris.atom_Path) {
+ return lilv_new_file_uri(lworld, NULL, value.ptr<char>());
+ } else if (uris.forge.is_uri(value)) {
+ const std::string str = uris.forge.str(value, false);
+ if (str.substr(0, 5) == "file:") {
+ return lilv_new_uri(lworld, value.ptr<char>());
+ }
+ }
+ return NULL;
+}
+
+/** @page protocol
+ * @subsection loading Loading and Unloading Bundles
+ *
+ * The property ingen:loadedBundle on the engine can be used to load
+ * or unload bundles from Ingen's world. For example:
+ *
+ * @code{.ttl}
+ * # Load /old.lv2
+ * []
+ * a patch:Put ;
+ * patch:subject </> ;
+ * patch:body [
+ * ingen:loadedBundle <file:///old.lv2>
+ * ] .
+ *
+ * # Replace /old.lv2 with /new.lv2
+ * []
+ * a patch:Patch ;
+ * patch:subject </> ;
+ * patch:remove [
+ * ingen:loadedBundle <file:///old.lv2>
+ * ];
+ * patch:add [
+ * ingen:loadedBundle <file:///new.lv2>
+ * ] .
+ * @endcode
+ */
+
bool
Delta::pre_process()
{
@@ -141,6 +183,7 @@ Delta::pre_process()
const bool is_graph_object = Node::uri_is_path(_subject);
const bool is_client = (_subject == "ingen:/clients/this");
+ const bool is_engine = (_subject == "ingen:/");
const bool is_file = (_subject.substr(0, 5) == "file:");
bool poly_changed = false;
@@ -183,7 +226,8 @@ Delta::pre_process()
? static_cast<Ingen::Resource*>(_engine.store()->get(Node::uri_to_path(_subject)))
: static_cast<Ingen::Resource*>(_engine.block_factory()->plugin(_subject));
- if (!_object && !is_client && (!is_graph_object || _type != Type::PUT)) {
+ if (!_object && !is_client && !is_engine &&
+ (!is_graph_object || _type != Type::PUT)) {
return Event::pre_process_done(Status::NOT_FOUND, _subject);
}
@@ -229,6 +273,15 @@ Delta::pre_process()
}
if (_object) {
_object->remove_property(key, value);
+ } else if (is_engine && key == uris.ingen_loadedBundle) {
+ LilvWorld* lworld = _engine.world()->lilv_world();
+ LilvNode* bundle = get_file_node(lworld, uris, value);
+ if (bundle) {
+ lilv_world_unload_bundle(lworld, bundle);
+ lilv_node_free(bundle);
+ } else {
+ _status = Status::BAD_VALUE;
+ }
}
}
@@ -365,6 +418,15 @@ Delta::pre_process()
} else if (is_client && key == uris.ingen_broadcast) {
_engine.broadcaster()->set_broadcast(
_request_client, value.get<int32_t>());
+ } else if (is_engine && key == uris.ingen_loadedBundle) {
+ LilvWorld* lworld = _engine.world()->lilv_world();
+ LilvNode* bundle = get_file_node(lworld, uris, value);
+ if (bundle) {
+ lilv_world_load_bundle(lworld, bundle);
+ lilv_node_free(bundle);
+ } else {
+ _status = Status::BAD_VALUE;
+ }
}
if (_status != Status::NOT_PREPARED) {
@@ -468,6 +530,7 @@ Delta::execute(ProcessContext& context)
port->set_maximum(value);
}
}
+ case SpecialType::LOADED_BUNDLE:
break;
}
}
diff --git a/src/server/events/Delta.hpp b/src/server/events/Delta.hpp
index f9ca0eec..0782238c 100644
--- a/src/server/events/Delta.hpp
+++ b/src/server/events/Delta.hpp
@@ -85,7 +85,8 @@ private:
POLYPHONY,
POLYPHONIC,
CONTROL_BINDING,
- PRESET
+ PRESET,
+ LOADED_BUNDLE
};
typedef std::vector<SetPortValue*> SetEvents;