diff options
-rw-r--r-- | ingen/URIs.hpp | 1 | ||||
-rw-r--r-- | ingen/ingen.h | 1 | ||||
-rw-r--r-- | src/URIs.cpp | 1 | ||||
-rw-r--r-- | src/server/events/Delta.cpp | 65 | ||||
-rw-r--r-- | 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<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; |