summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--ingen/URIs.hpp1
-rw-r--r--ingen/ingen.h1
-rw-r--r--src/URIs.cpp1
-rw-r--r--src/server/events/Delta.cpp65
-rw-r--r--src/server/events/Delta.hpp3
5 files changed, 69 insertions, 2 deletions
diff --git a/ingen/URIs.hpp b/ingen/URIs.hpp
index 7f032cbc..00549593 100644
--- a/ingen/URIs.hpp
+++ b/ingen/URIs.hpp
@@ -113,6 +113,7 @@ public:
const Quark ingen_file;
const Quark ingen_head;
const Quark ingen_incidentTo;
+ const Quark ingen_loadedBundle;
const Quark ingen_polyphonic;
const Quark ingen_polyphony;
const Quark ingen_prototype;
diff --git a/ingen/ingen.h b/ingen/ingen.h
index 613541c5..d9091039 100644
--- a/ingen/ingen.h
+++ b/ingen/ingen.h
@@ -53,6 +53,7 @@
#define INGEN__file INGEN_NS "file"
#define INGEN__head INGEN_NS "head"
#define INGEN__incidentTo INGEN_NS "incidentTo"
+#define INGEN__loadedBundle INGEN_NS "loadedBundle"
#define INGEN__polyphonic INGEN_NS "polyphonic"
#define INGEN__polyphony INGEN_NS "polyphony"
#define INGEN__prototype INGEN_NS "prototype"
diff --git a/src/URIs.cpp b/src/URIs.cpp
index 0cea8445..2cc59aaa 100644
--- a/src/URIs.cpp
+++ b/src/URIs.cpp
@@ -95,6 +95,7 @@ URIs::URIs(Forge& f, URIMap* map, LilvWorld* lworld)
, ingen_file (forge, map, lworld, INGEN__file)
, ingen_head (forge, map, lworld, INGEN__head)
, ingen_incidentTo (forge, map, lworld, INGEN__incidentTo)
+ , ingen_loadedBundle (forge, map, lworld, INGEN__loadedBundle)
, ingen_polyphonic (forge, map, lworld, INGEN__polyphonic)
, ingen_polyphony (forge, map, lworld, INGEN__polyphony)
, ingen_prototype (forge, map, lworld, INGEN__prototype)
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;