From 2fe35cd17f96a1d393fda203ccaa234b0aa69b16 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 30 Oct 2015 00:37:40 +0000 Subject: 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 --- ingen/URIs.hpp | 1 + ingen/ingen.h | 1 + src/URIs.cpp | 1 + src/server/events/Delta.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++- src/server/events/Delta.hpp | 3 ++- 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()); + } 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()); + } + } + 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 + * ] . + * + * # Replace /old.lv2 with /new.lv2 + * [] + * a patch:Patch ; + * patch:subject ; + * patch:remove [ + * ingen:loadedBundle + * ]; + * patch:add [ + * ingen:loadedBundle + * ] . + * @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(_engine.store()->get(Node::uri_to_path(_subject))) : static_cast(_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()); + } 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 SetEvents; -- cgit v1.2.1