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 --- src/server/events/Delta.cpp | 65 ++++++++++++++++++++++++++++++++++++++++++++- src/server/events/Delta.hpp | 3 ++- 2 files changed, 66 insertions(+), 2 deletions(-) (limited to 'src/server/events') 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