diff options
author | David Robillard <d@drobilla.net> | 2017-03-19 13:26:38 +0100 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2017-03-20 02:58:56 +0100 |
commit | f1c793f7e2148b10610a09a459d9e89b39d2d87b (patch) | |
tree | b898407dce08af0f2f978d59a85d4887d8555b54 | |
parent | efc0fe0a973db706d9409b345ad6fae585f4388c (diff) | |
download | ingen-f1c793f7e2148b10610a09a459d9e89b39d2d87b.tar.gz ingen-f1c793f7e2148b10610a09a459d9e89b39d2d87b.tar.bz2 ingen-f1c793f7e2148b10610a09a459d9e89b39d2d87b.zip |
Fix round-trip preservation of property contexts
-rw-r--r-- | bundles/ingen.lv2/ingen.ttl | 10 | ||||
-rw-r--r-- | ingen/AtomReader.hpp | 1 | ||||
-rw-r--r-- | ingen/AtomWriter.hpp | 7 | ||||
-rw-r--r-- | ingen/Interface.hpp | 6 | ||||
-rw-r--r-- | ingen/Properties.hpp | 6 | ||||
-rw-r--r-- | ingen/Resource.hpp | 16 | ||||
-rw-r--r-- | ingen/Tee.hpp | 12 | ||||
-rw-r--r-- | ingen/URIs.hpp | 3 | ||||
-rw-r--r-- | ingen/client/ClientStore.hpp | 6 | ||||
-rw-r--r-- | ingen/client/PluginUI.hpp | 3 | ||||
-rw-r--r-- | ingen/client/SigClientInterface.hpp | 16 | ||||
-rw-r--r-- | ingen/client/ThreadedSigClientInterface.hpp | 36 | ||||
-rw-r--r-- | ingen/ingen.h | 68 | ||||
-rw-r--r-- | src/AtomReader.cpp | 69 | ||||
-rw-r--r-- | src/AtomWriter.cpp | 25 | ||||
-rw-r--r-- | src/Parser.cpp | 9 | ||||
-rw-r--r-- | src/URIs.cpp | 3 | ||||
-rw-r--r-- | src/client/ClientStore.cpp | 8 | ||||
-rw-r--r-- | src/client/PluginUI.cpp | 13 | ||||
-rw-r--r-- | src/gui/App.cpp | 10 | ||||
-rw-r--r-- | src/gui/App.hpp | 6 | ||||
-rw-r--r-- | src/gui/SubgraphModule.cpp | 8 | ||||
-rw-r--r-- | src/server/Broadcaster.hpp | 12 | ||||
-rw-r--r-- | src/server/EventWriter.cpp | 19 | ||||
-rw-r--r-- | src/server/EventWriter.hpp | 6 | ||||
-rw-r--r-- | src/server/events/Delta.cpp | 16 | ||||
-rw-r--r-- | tests/TestClient.hpp | 6 | ||||
-rw-r--r-- | wscript | 2 |
28 files changed, 249 insertions, 153 deletions
diff --git a/bundles/ingen.lv2/ingen.ttl b/bundles/ingen.lv2/ingen.ttl index 90c47c82..9cf5e8c2 100644 --- a/bundles/ingen.lv2/ingen.ttl +++ b/bundles/ingen.lv2/ingen.ttl @@ -272,3 +272,13 @@ ingen:numThreads rdfs:label "number of threads" ; ingen:shortSwitch "p" ; ingen:longSwitch "threads" . + +ingen:externalContext + a rdfs:Resource ; + rdfs:label "external context" ; + rdfs:comment """The context for externally visible Graph properties, that is, properties which apply to the Graph when viewed as a Block within its parent Graph and should be saved in the parent's description.""" . + +ingen:internalContext + a rdfs:Resource ; + rdfs:label "internal context" ; + rdfs:comment """The context for internally visible Graph properties, that is, properties which are only relevant inside the graph and should be saved in the Graph's description.""" . diff --git a/ingen/AtomReader.hpp b/ingen/AtomReader.hpp index 8a1a80aa..bcfe9ab5 100644 --- a/ingen/AtomReader.hpp +++ b/ingen/AtomReader.hpp @@ -51,6 +51,7 @@ private: boost::optional<Raul::URI> atom_to_uri(const LV2_Atom* atom); boost::optional<Raul::Path> atom_to_path(const LV2_Atom* atom); + Resource::Graph atom_to_context(const LV2_Atom* atom); void get_props(const LV2_Atom_Object* obj, Ingen::Properties& props); diff --git a/ingen/AtomWriter.hpp b/ingen/AtomWriter.hpp index 35db84a4..e7a02049 100644 --- a/ingen/AtomWriter.hpp +++ b/ingen/AtomWriter.hpp @@ -52,7 +52,8 @@ public: void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add); + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT); void copy(const Raul::URI& old_uri, const Raul::URI& new_uri); @@ -73,7 +74,8 @@ public: void set_property(const Raul::URI& subject, const Raul::URI& predicate, - const Atom& value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT); void undo(); @@ -92,6 +94,7 @@ private: void forge_properties(const Properties& properties); void forge_arc(const Raul::Path& tail, const Raul::Path& head); void forge_request(LV2_Atom_Forge_Frame* frame, LV2_URID type); + void forge_context(Resource::Graph ctx); void finish_msg(); diff --git a/ingen/Interface.hpp b/ingen/Interface.hpp index e37888f9..e396872e 100644 --- a/ingen/Interface.hpp +++ b/ingen/Interface.hpp @@ -70,7 +70,8 @@ public: virtual void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) = 0; + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT) = 0; virtual void copy(const Raul::URI& old_uri, const Raul::URI& new_uri) = 0; @@ -91,7 +92,8 @@ public: virtual void set_property(const Raul::URI& subject, const Raul::URI& predicate, - const Atom& value) = 0; + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT) = 0; virtual void undo() = 0; diff --git a/ingen/Properties.hpp b/ingen/Properties.hpp index ef608574..437db874 100644 --- a/ingen/Properties.hpp +++ b/ingen/Properties.hpp @@ -29,9 +29,9 @@ namespace Ingen { class Property : public Atom { public: enum class Graph { - DEFAULT, - EXTERNAL, - INTERNAL + DEFAULT, ///< Default context for "universal" properties + EXTERNAL, ///< Externally visible graph properties + INTERNAL ///< Internally visible graph properties }; Property(const Atom& atom, Graph ctx=Graph::DEFAULT) diff --git a/ingen/Resource.hpp b/ingen/Resource.hpp index 3eb1349f..fe3d94fa 100644 --- a/ingen/Resource.hpp +++ b/ingen/Resource.hpp @@ -57,25 +57,19 @@ public: static Raul::URI graph_to_uri(Graph g) { switch (g) { - case Graph::DEFAULT: return Raul::URI(INGEN_NS "defaultContext"); case Graph::EXTERNAL: return Raul::URI(INGEN_NS "externalContext"); case Graph::INTERNAL: return Raul::URI(INGEN_NS "internalContext"); + default: return Raul::URI(INGEN_NS "defaultContext"); } } - static Graph uri_to_graph(const char* uri) { - const char* suffix = uri + sizeof(INGEN_NS) - 1; - if (strncmp(uri, INGEN_NS, sizeof(INGEN_NS) - 1)) { - return Graph::DEFAULT; - } else if (!strcmp(suffix, "defaultContext")) { - return Graph::DEFAULT; - } else if (!strcmp(suffix, "externalContext")) { + static Graph uri_to_graph(const Raul::URI& uri) { + if (uri == INGEN_NS "externalContext") { return Graph::EXTERNAL; - } else if (!strcmp(suffix, "internalContext")) { + } else if (uri == INGEN_NS "internalContext") { return Graph::INTERNAL; - } else { - return Graph::DEFAULT; } + return Graph::DEFAULT; } virtual ~Resource() {} diff --git a/ingen/Tee.hpp b/ingen/Tee.hpp index 2cbd84d6..02596e03 100644 --- a/ingen/Tee.hpp +++ b/ingen/Tee.hpp @@ -66,13 +66,14 @@ public: void put(const Raul::URI& uri, const Properties& properties, Resource::Graph ctx = Resource::Graph::DEFAULT) { - BROADCAST(put, uri, properties); + BROADCAST(put, uri, properties, ctx); } void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) { - BROADCAST(delta, uri, remove, add); + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT) { + BROADCAST(delta, uri, remove, add, ctx); } void copy(const Raul::URI& old_uri, @@ -104,8 +105,9 @@ public: void set_property(const Raul::URI& subject, const Raul::URI& predicate, - const Atom& value) { - BROADCAST(set_property, subject, predicate, value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT) { + BROADCAST(set_property, subject, predicate, value, ctx); } void undo() { BROADCAST(undo); } diff --git a/ingen/URIs.hpp b/ingen/URIs.hpp index 9bc21592..b05f6270 100644 --- a/ingen/URIs.hpp +++ b/ingen/URIs.hpp @@ -114,9 +114,11 @@ public: const Quark ingen_canvasX; const Quark ingen_canvasY; const Quark ingen_enabled; + const Quark ingen_externalContext; const Quark ingen_file; const Quark ingen_head; const Quark ingen_incidentTo; + const Quark ingen_internalContext; const Quark ingen_loadedBundle; const Quark ingen_maxRunLoad; const Quark ingen_meanRunLoad; @@ -186,6 +188,7 @@ public: const Quark patch_Set; const Quark patch_add; const Quark patch_body; + const Quark patch_context; const Quark patch_destination; const Quark patch_property; const Quark patch_remove; diff --git a/ingen/client/ClientStore.hpp b/ingen/client/ClientStore.hpp index 84a95b7b..1887bed3 100644 --- a/ingen/client/ClientStore.hpp +++ b/ingen/client/ClientStore.hpp @@ -79,7 +79,8 @@ public: void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add); + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT); void copy(const Raul::URI& old_uri, const Raul::URI& new_uri); @@ -89,7 +90,8 @@ public: void set_property(const Raul::URI& subject_path, const Raul::URI& predicate, - const Atom& value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT); void connect(const Raul::Path& tail, const Raul::Path& head); diff --git a/ingen/client/PluginUI.hpp b/ingen/client/PluginUI.hpp index d4d47e3b..c44cad82 100644 --- a/ingen/client/PluginUI.hpp +++ b/ingen/client/PluginUI.hpp @@ -78,7 +78,8 @@ public: INGEN_SIGNAL(property_changed, void, const Raul::URI&, // Subject const Raul::URI&, // Predicate - const Atom&); // Object + const Atom&, // Object + Resource::Graph); // Context Ingen::World* world() const { return _world; } SPtr<const BlockModel> block() const { return _block; } diff --git a/ingen/client/SigClientInterface.hpp b/ingen/client/SigClientInterface.hpp index a65806f4..7e903fab 100644 --- a/ingen/client/SigClientInterface.hpp +++ b/ingen/client/SigClientInterface.hpp @@ -53,14 +53,14 @@ public: INGEN_SIGNAL(bundle_end, void) INGEN_SIGNAL(error, void, std::string) INGEN_SIGNAL(put, void, Raul::URI, Properties, Resource::Graph) - INGEN_SIGNAL(delta, void, Raul::URI, Properties, Properties) + INGEN_SIGNAL(delta, void, Raul::URI, Properties, Properties, Resource::Graph) INGEN_SIGNAL(object_copied, void, Raul::URI, Raul::URI) INGEN_SIGNAL(object_moved, void, Raul::Path, Raul::Path) INGEN_SIGNAL(object_deleted, void, Raul::URI) INGEN_SIGNAL(connection, void, Raul::Path, Raul::Path) INGEN_SIGNAL(disconnection, void, Raul::Path, Raul::Path) INGEN_SIGNAL(disconnect_all, void, Raul::Path, Raul::Path) - INGEN_SIGNAL(property_change, void, Raul::URI, Raul::URI, Atom) + INGEN_SIGNAL(property_change, void, Raul::URI, Raul::URI, Atom, Resource::Graph) /** Fire pending signals. Only does anything on derived classes (that may queue) */ virtual bool emit_signals() { return false; } @@ -90,8 +90,9 @@ protected: void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) - { EMIT(delta, uri, remove, add); } + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT) + { EMIT(delta, uri, remove, add, ctx); } void connect(const Raul::Path& tail, const Raul::Path& head) { EMIT(connection, tail, head); } @@ -111,8 +112,11 @@ protected: void disconnect_all(const Raul::Path& graph, const Raul::Path& path) { EMIT(disconnect_all, graph, path); } - void set_property(const Raul::URI& subject, const Raul::URI& key, const Atom& value) - { EMIT(property_change, subject, key, value); } + void set_property(const Raul::URI& subject, + const Raul::URI& key, + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT) + { EMIT(property_change, subject, key, value, ctx); } void undo() {} void redo() {} diff --git a/ingen/client/ThreadedSigClientInterface.hpp b/ingen/client/ThreadedSigClientInterface.hpp index db3aad44..219fd8d1 100644 --- a/ingen/client/ThreadedSigClientInterface.hpp +++ b/ingen/client/ThreadedSigClientInterface.hpp @@ -87,8 +87,9 @@ public: void delta(const Raul::URI& path, const Properties& remove, - const Properties& add) - { push_sig(sigc::bind(delta_slot, path, remove, add)); } + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT) + { push_sig(sigc::bind(delta_slot, path, remove, add, ctx)); } void connect(const Raul::Path& tail, const Raul::Path& head) { push_sig(sigc::bind(connection_slot, tail, head)); } @@ -108,8 +109,11 @@ public: void disconnect_all(const Raul::Path& graph, const Raul::Path& path) { push_sig(sigc::bind(disconnect_all_slot, graph, path)); } - void set_property(const Raul::URI& subject, const Raul::URI& key, const Atom& value) - { push_sig(sigc::bind(property_change_slot, subject, key, value)); } + void set_property(const Raul::URI& subject, + const Raul::URI& key, + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT) + { push_sig(sigc::bind(property_change_slot, subject, key, value, ctx)); } /** Process all queued events - Called from GTK thread to emit signals. */ bool emit_signals() { @@ -149,22 +153,24 @@ private: Raul::SRSWQueue<Closure> _sigs; - typedef Resource::Graph Graph; + using Graph = Resource::Graph; + using Path = Raul::Path; + using URI = Raul::URI; sigc::slot<void> bundle_begin_slot; sigc::slot<void> bundle_end_slot; sigc::slot<void, int32_t, Status, std::string> response_slot; sigc::slot<void, std::string> error_slot; - sigc::slot<void, Raul::URI, Raul::URI, Raul::Symbol> new_plugin_slot; - sigc::slot<void, Raul::URI, Properties, Graph> put_slot; - sigc::slot<void, Raul::URI, Properties, Properties> delta_slot; - sigc::slot<void, Raul::Path, Raul::Path> connection_slot; - sigc::slot<void, Raul::URI> object_deleted_slot; - sigc::slot<void, Raul::Path, Raul::Path> object_moved_slot; - sigc::slot<void, Raul::URI, Raul::URI> object_copied_slot; - sigc::slot<void, Raul::Path, Raul::Path> disconnection_slot; - sigc::slot<void, Raul::Path, Raul::Path> disconnect_all_slot; - sigc::slot<void, Raul::URI, Raul::URI, Atom> property_change_slot; + sigc::slot<void, URI, URI, Raul::Symbol> new_plugin_slot; + sigc::slot<void, URI, Properties, Graph> put_slot; + sigc::slot<void, URI, Properties, Properties, Graph> delta_slot; + sigc::slot<void, Path, Path> connection_slot; + sigc::slot<void, URI> object_deleted_slot; + sigc::slot<void, Path, Path> object_moved_slot; + sigc::slot<void, URI, URI> object_copied_slot; + sigc::slot<void, Path, Path> disconnection_slot; + sigc::slot<void, Path, Path> disconnect_all_slot; + sigc::slot<void, URI, URI, Atom, Graph> property_change_slot; }; } // namespace Client diff --git a/ingen/ingen.h b/ingen/ingen.h index e3313e28..05b9e7b2 100644 --- a/ingen/ingen.h +++ b/ingen/ingen.h @@ -36,38 +36,40 @@ #define INGEN_NS "http://drobilla.net/ns/ingen#" -#define INGEN__Arc INGEN_NS "Arc" -#define INGEN__Block INGEN_NS "Block" -#define INGEN__BundleEnd INGEN_NS "BundleEnd" -#define INGEN__BundleStart INGEN_NS "BundleStart" -#define INGEN__Graph INGEN_NS "Graph" -#define INGEN__GraphPrototype INGEN_NS "GraphPrototype" -#define INGEN__Internal INGEN_NS "Internal" -#define INGEN__Node INGEN_NS "Node" -#define INGEN__Plugin INGEN_NS "Plugin" -#define INGEN__Redo INGEN_NS "Redo" -#define INGEN__Undo INGEN_NS "Undo" -#define INGEN__activity INGEN_NS "activity" -#define INGEN__arc INGEN_NS "arc" -#define INGEN__block INGEN_NS "block" -#define INGEN__broadcast INGEN_NS "broadcast" -#define INGEN__canvasX INGEN_NS "canvasX" -#define INGEN__canvasY INGEN_NS "canvasY" -#define INGEN__enabled INGEN_NS "enabled" -#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__maxRunLoad INGEN_NS "maxRunLoad" -#define INGEN__meanRunLoad INGEN_NS "meanRunLoad" -#define INGEN__minRunLoad INGEN_NS "minRunLoad" -#define INGEN__numThreads INGEN_NS "numThreads" -#define INGEN__polyphonic INGEN_NS "polyphonic" -#define INGEN__polyphony INGEN_NS "polyphony" -#define INGEN__prototype INGEN_NS "prototype" -#define INGEN__sprungLayout INGEN_NS "sprungLayout" -#define INGEN__tail INGEN_NS "tail" -#define INGEN__uiEmbedded INGEN_NS "uiEmbedded" -#define INGEN__value INGEN_NS "value" +#define INGEN__Arc INGEN_NS "Arc" +#define INGEN__Block INGEN_NS "Block" +#define INGEN__BundleEnd INGEN_NS "BundleEnd" +#define INGEN__BundleStart INGEN_NS "BundleStart" +#define INGEN__Graph INGEN_NS "Graph" +#define INGEN__GraphPrototype INGEN_NS "GraphPrototype" +#define INGEN__Internal INGEN_NS "Internal" +#define INGEN__Node INGEN_NS "Node" +#define INGEN__Plugin INGEN_NS "Plugin" +#define INGEN__Redo INGEN_NS "Redo" +#define INGEN__Undo INGEN_NS "Undo" +#define INGEN__activity INGEN_NS "activity" +#define INGEN__arc INGEN_NS "arc" +#define INGEN__block INGEN_NS "block" +#define INGEN__broadcast INGEN_NS "broadcast" +#define INGEN__canvasX INGEN_NS "canvasX" +#define INGEN__canvasY INGEN_NS "canvasY" +#define INGEN__enabled INGEN_NS "enabled" +#define INGEN__externalContext INGEN_NS "externalContext" +#define INGEN__file INGEN_NS "file" +#define INGEN__head INGEN_NS "head" +#define INGEN__incidentTo INGEN_NS "incidentTo" +#define INGEN__internalContext INGEN_NS "internalContext" +#define INGEN__loadedBundle INGEN_NS "loadedBundle" +#define INGEN__maxRunLoad INGEN_NS "maxRunLoad" +#define INGEN__meanRunLoad INGEN_NS "meanRunLoad" +#define INGEN__minRunLoad INGEN_NS "minRunLoad" +#define INGEN__numThreads INGEN_NS "numThreads" +#define INGEN__polyphonic INGEN_NS "polyphonic" +#define INGEN__polyphony INGEN_NS "polyphony" +#define INGEN__prototype INGEN_NS "prototype" +#define INGEN__sprungLayout INGEN_NS "sprungLayout" +#define INGEN__tail INGEN_NS "tail" +#define INGEN__uiEmbedded INGEN_NS "uiEmbedded" +#define INGEN__value INGEN_NS "value" #endif // INGEN_H diff --git a/src/AtomReader.cpp b/src/AtomReader.cpp index 57aa09bb..18b5877c 100644 --- a/src/AtomReader.cpp +++ b/src/AtomReader.cpp @@ -106,6 +106,21 @@ AtomReader::atom_to_path(const LV2_Atom* atom) return boost::optional<Raul::Path>(); } +Resource::Graph +AtomReader::atom_to_context(const LV2_Atom* atom) +{ + Resource::Graph ctx = Resource::Graph::DEFAULT; + if (atom) { + boost::optional<Raul::URI> maybe_uri = atom_to_uri(atom); + if (maybe_uri) { + ctx = Resource::uri_to_graph(*maybe_uri); + } else { + _log.warn("Message has invalid context\n"); + } + } + return ctx; +} + bool AtomReader::is_message(const URIs& uris, const LV2_Atom* msg) { @@ -168,8 +183,8 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) const LV2_Atom* head = NULL; const LV2_Atom* incidentTo = NULL; lv2_atom_object_get(body, - (LV2_URID)_uris.ingen_tail, &tail, - (LV2_URID)_uris.ingen_head, &head, + (LV2_URID)_uris.ingen_tail, &tail, + (LV2_URID)_uris.ingen_head, &head, (LV2_URID)_uris.ingen_incidentTo, &incidentTo, NULL); @@ -187,8 +202,12 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) } } } else if (obj->body.otype == _uris.patch_Put) { - const LV2_Atom_Object* body = NULL; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_body, &body, 0); + const LV2_Atom_Object* body = NULL; + const LV2_Atom* context = NULL; + lv2_atom_object_get(obj, + (LV2_URID)_uris.patch_body, &body, + (LV2_URID)_uris.patch_context, &context, + 0); if (!body) { _log.warn("Put message has no body\n"); return false; @@ -219,7 +238,7 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) } else { Ingen::Properties props; get_props(body, props); - _iface.put(*subject_uri, props); + _iface.put(*subject_uri, props, atom_to_context(context)); } } else if (obj->body.otype == _uris.patch_Set) { if (!subject_uri) { @@ -227,16 +246,18 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) return false; } - const LV2_Atom_URID* prop = NULL; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_property, &prop, 0); + const LV2_Atom_URID* prop = NULL; + const LV2_Atom* value = NULL; + const LV2_Atom* context = NULL; + lv2_atom_object_get(obj, + (LV2_URID)_uris.patch_property, &prop, + (LV2_URID)_uris.patch_value, &value, + (LV2_URID)_uris.patch_context, &context, + 0); if (!prop || ((const LV2_Atom*)prop)->type != _uris.atom_URID) { _log.warn("Set message missing property\n"); return false; - } - - const LV2_Atom* value = NULL; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_value, &value, 0); - if (!value) { + } else if (!value) { _log.warn("Set message missing value\n"); return false; } @@ -245,23 +266,26 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) get_atom(value, atom); _iface.set_property(*subject_uri, Raul::URI(_map.unmap_uri(prop->body)), - atom); + atom, + atom_to_context(context)); } else if (obj->body.otype == _uris.patch_Patch) { if (!subject_uri) { _log.warn("Patch message has no subject\n"); return false; } - const LV2_Atom_Object* remove = NULL; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_remove, &remove, 0); + const LV2_Atom_Object* remove = NULL; + const LV2_Atom_Object* add = NULL; + const LV2_Atom* context = NULL; + lv2_atom_object_get(obj, + (LV2_URID)_uris.patch_remove, &remove, + (LV2_URID)_uris.patch_add, &add, + (LV2_URID)_uris.patch_context, &context, + 0); if (!remove) { _log.warn("Patch message has no remove\n"); return false; - } - - const LV2_Atom_Object* add = NULL; - lv2_atom_object_get(obj, (LV2_URID)_uris.patch_add, &add, 0); - if (!add) { + } else if (!add) { _log.warn("Patch message has no add\n"); return false; } @@ -272,7 +296,8 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) Ingen::Properties remove_props; get_props(remove, remove_props); - _iface.delta(*subject_uri, remove_props, add_props); + _iface.delta(*subject_uri, remove_props, add_props, + atom_to_context(context)); } else if (obj->body.otype == _uris.patch_Copy) { if (!subject) { _log.warn("Copy message has no subject\n"); @@ -330,7 +355,7 @@ AtomReader::write(const LV2_Atom* msg, int32_t default_id) const LV2_Atom* body = NULL; lv2_atom_object_get(obj, (LV2_URID)_uris.patch_sequenceNumber, &seq, - (LV2_URID)_uris.patch_body, &body, + (LV2_URID)_uris.patch_body, &body, 0); if (!seq || seq->type != _uris.atom_Int) { _log.warn("Response message has no sequence number\n"); diff --git a/src/AtomWriter.cpp b/src/AtomWriter.cpp index 2fc3ee18..54dcd0a2 100644 --- a/src/AtomWriter.cpp +++ b/src/AtomWriter.cpp @@ -165,6 +165,22 @@ AtomWriter::forge_request(LV2_Atom_Forge_Frame* frame, LV2_URID type) } } +void +AtomWriter::forge_context(Resource::Graph ctx) +{ + switch (ctx) { + case Resource::Graph::EXTERNAL: + lv2_atom_forge_key(&_forge, _uris.patch_context); + forge_uri(_uris.ingen_externalContext); + break; + case Resource::Graph::INTERNAL: + lv2_atom_forge_key(&_forge, _uris.patch_context); + forge_uri(_uris.ingen_internalContext); + break; + default: break; + } +} + /** @page protocol * @section methods Methods * @subsection Put @@ -196,6 +212,7 @@ AtomWriter::put(const Raul::URI& uri, { LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Put); + forge_context(ctx); lv2_atom_forge_key(&_forge, _uris.patch_subject); forge_uri(uri); lv2_atom_forge_key(&_forge, _uris.patch_body); @@ -238,10 +255,12 @@ AtomWriter::put(const Raul::URI& uri, void AtomWriter::delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) + const Properties& add, + Resource::Graph ctx) { LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Patch); + forge_context(ctx); lv2_atom_forge_key(&_forge, _uris.patch_subject); forge_uri(uri); @@ -371,10 +390,12 @@ AtomWriter::del(const Raul::URI& uri) void AtomWriter::set_property(const Raul::URI& subject, const Raul::URI& predicate, - const Atom& value) + const Atom& value, + Resource::Graph ctx) { LV2_Atom_Forge_Frame msg; forge_request(&msg, _uris.patch_Set); + forge_context(ctx); lv2_atom_forge_key(&_forge, _uris.patch_subject); forge_uri(subject); lv2_atom_forge_key(&_forge, _uris.patch_property); diff --git a/src/Parser.cpp b/src/Parser.cpp index c26553a9..c3d6eaaf 100644 --- a/src/Parser.cpp +++ b/src/Parser.cpp @@ -351,9 +351,8 @@ parse_graph(Ingen::World* world, { const URIs& uris = world->uris(); - const Sord::URI ingen_block(*world->rdf_world(), uris.ingen_block); - const Sord::URI ingen_polyphony(*world->rdf_world(), uris.ingen_polyphony); - const Sord::URI lv2_port(*world->rdf_world(), LV2_CORE__port); + const Sord::URI ingen_block(*world->rdf_world(), uris.ingen_block); + const Sord::URI lv2_port(*world->rdf_world(), LV2_CORE__port); const Sord::Node& graph = subject_node; const Sord::Node nil; @@ -542,11 +541,11 @@ parse_properties(Ingen::World* world, { Properties properties = get_properties(world, model, subject, ctx); - target->put(uri, properties); + target->put(uri, properties, ctx); // Set passed properties last to override any loaded values if (data) - target->put(uri, data.get()); + target->put(uri, data.get(), ctx); return true; } diff --git a/src/URIs.cpp b/src/URIs.cpp index 47cf64c9..f5e0903d 100644 --- a/src/URIs.cpp +++ b/src/URIs.cpp @@ -97,9 +97,11 @@ URIs::URIs(Forge& f, URIMap* map, LilvWorld* lworld) , ingen_canvasX (forge, map, lworld, INGEN__canvasX) , ingen_canvasY (forge, map, lworld, INGEN__canvasY) , ingen_enabled (forge, map, lworld, INGEN__enabled) + , ingen_externalContext (forge, map, lworld, INGEN__externalContext) , ingen_file (forge, map, lworld, INGEN__file) , ingen_head (forge, map, lworld, INGEN__head) , ingen_incidentTo (forge, map, lworld, INGEN__incidentTo) + , ingen_internalContext (forge, map, lworld, INGEN__internalContext) , ingen_loadedBundle (forge, map, lworld, INGEN__loadedBundle) , ingen_maxRunLoad (forge, map, lworld, INGEN__maxRunLoad) , ingen_meanRunLoad (forge, map, lworld, INGEN__meanRunLoad) @@ -169,6 +171,7 @@ URIs::URIs(Forge& f, URIMap* map, LilvWorld* lworld) , patch_Set (forge, map, lworld, LV2_PATCH__Set) , patch_add (forge, map, lworld, LV2_PATCH__add) , patch_body (forge, map, lworld, LV2_PATCH__body) + , patch_context (forge, map, lworld, LV2_PATCH__context) , patch_destination (forge, map, lworld, LV2_PATCH__destination) , patch_property (forge, map, lworld, LV2_PATCH__property) , patch_remove (forge, map, lworld, LV2_PATCH__remove) diff --git a/src/client/ClientStore.cpp b/src/client/ClientStore.cpp index eac853f7..a622068c 100644 --- a/src/client/ClientStore.cpp +++ b/src/client/ClientStore.cpp @@ -342,7 +342,8 @@ ClientStore::put(const Raul::URI& uri, void ClientStore::delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) + const Properties& add, + Resource::Graph ctx) { if (uri == Raul::URI("ingen:/clients/this")) { // Client property, which we don't store (yet?) @@ -370,7 +371,8 @@ ClientStore::delta(const Raul::URI& uri, void ClientStore::set_property(const Raul::URI& subject_uri, const Raul::URI& predicate, - const Atom& value) + const Atom& value, + Resource::Graph ctx) { if (subject_uri == Raul::URI("ingen:/engine")) { _log.info(fmt("Engine property <%1%> = %2%\n") @@ -384,7 +386,7 @@ ClientStore::set_property(const Raul::URI& subject_uri, blinkenlights) but do not store the property. */ subject->on_property(predicate, value); } else { - subject->set_property(predicate, value); + subject->set_property(predicate, value, ctx); } } else { SPtr<PluginModel> plugin = _plugin(subject_uri); diff --git a/src/client/PluginUI.cpp b/src/client/PluginUI.cpp index b4631f0d..d4558ed4 100644 --- a/src/client/PluginUI.cpp +++ b/src/client/PluginUI.cpp @@ -73,7 +73,8 @@ lv2_ui_write(SuilController controller, ui->signal_property_changed()( port->uri(), uris.ingen_value, - ui->world()->forge().make(value)); + ui->world()->forge().make(value), + Resource::Graph::DEFAULT); } else if (format == uris.atom_eventTransfer.urid.get<LV2_URID>()) { const LV2_Atom* atom = (const LV2_Atom*)buffer; @@ -81,8 +82,8 @@ lv2_ui_write(SuilController controller, atom->size, atom->type, LV2_ATOM_BODY_CONST(atom)); ui->signal_property_changed()(port->uri(), uris.ingen_activity, - val); - + val, + Resource::Graph::DEFAULT); } else { ui->world()->log().warn( fmt("Unknown value format %1% from LV2 UI\n") @@ -119,7 +120,8 @@ lv2_ui_subscribe(SuilController controller, ui->signal_property_changed()( ui->block()->ports()[port_index]->uri(), ui->world()->uris().ingen_broadcast, - ui->world()->forge().make(true)); + ui->world()->forge().make(true), + Resource::Graph::DEFAULT); return 0; } @@ -139,7 +141,8 @@ lv2_ui_unsubscribe(SuilController controller, ui->signal_property_changed()( ui->block()->ports()[port_index]->uri(), ui->world()->uris().ingen_broadcast, - ui->world()->forge().make(false)); + ui->world()->forge().make(false), + Resource::Graph::DEFAULT); return 0; } diff --git a/src/gui/App.cpp b/src/gui/App.cpp index d303348a..15bdc796 100644 --- a/src/gui/App.cpp +++ b/src/gui/App.cpp @@ -258,17 +258,18 @@ App::error_message(const string& str) void App::set_property(const Raul::URI& subject, const Raul::URI& key, - const Atom& value) + const Atom& value, + Resource::Graph ctx) { // Send message to server - interface()->set_property(subject, key, value); + interface()->set_property(subject, key, value, ctx); /* The server does not feed back set messages (kludge to prevent control feedback and bandwidth wastage, see Delta.cpp). So, assume everything went as planned here and fire the signal ourselves as if the server feedback came back immediately. */ if (key != uris().ingen_activity) { - _client->signal_property_change().emit(subject, key, value); + _client->signal_property_change().emit(subject, key, value, ctx); } } @@ -298,7 +299,8 @@ App::put(const Raul::URI& uri, void App::property_change(const Raul::URI& subject, const Raul::URI& key, - const Atom& value) + const Atom& value, + Resource::Graph ctx) { if (subject != Raul::URI("ingen:/engine")) { return; diff --git a/src/gui/App.hpp b/src/gui/App.hpp index 4967513c..6dcab171 100644 --- a/src/gui/App.hpp +++ b/src/gui/App.hpp @@ -101,7 +101,8 @@ public: void set_property(const Raul::URI& subject, const Raul::URI& key, - const Atom& value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT); /** Set the tooltip for a widget from its RDF documentation. */ void set_tooltip(Gtk::Widget* widget, const LilvNode* node); @@ -149,7 +150,8 @@ protected: void property_change(const Raul::URI& subject, const Raul::URI& key, - const Atom& value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT); static Gtk::Main* _main; diff --git a/src/gui/SubgraphModule.cpp b/src/gui/SubgraphModule.cpp index 5c05153f..c261ec36 100644 --- a/src/gui/SubgraphModule.cpp +++ b/src/gui/SubgraphModule.cpp @@ -70,10 +70,10 @@ SubgraphModule::store_location(double ax, double ay) if (x != _block->get_property(uris.ingen_canvasX) || y != _block->get_property(uris.ingen_canvasY)) { - app().interface()->put( - _graph->uri(), - {{uris.ingen_canvasX, Property(x, Resource::Graph::EXTERNAL)}, - {uris.ingen_canvasY, Property(y, Resource::Graph::EXTERNAL)}}); + app().interface()->put(_graph->uri(), + {{uris.ingen_canvasX, x}, + {uris.ingen_canvasY, y}}, + Resource::Graph::EXTERNAL); } } diff --git a/src/server/Broadcaster.hpp b/src/server/Broadcaster.hpp index 2d184559..fd8d3996 100644 --- a/src/server/Broadcaster.hpp +++ b/src/server/Broadcaster.hpp @@ -102,13 +102,14 @@ public: void put(const Raul::URI& uri, const Properties& properties, Resource::Graph ctx = Resource::Graph::DEFAULT) { - BROADCAST(put, uri, properties); + BROADCAST(put, uri, properties, ctx); } void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) { - BROADCAST(delta, uri, remove, add); + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT) { + BROADCAST(delta, uri, remove, add, ctx); } void copy(const Raul::URI& old_uri, @@ -142,8 +143,9 @@ public: void set_property(const Raul::URI& subject, const Raul::URI& predicate, - const Atom& value) { - BROADCAST(set_property, subject, predicate, value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT) { + BROADCAST(set_property, subject, predicate, value, ctx); } Raul::URI uri() const { return Raul::URI("ingen:/broadcaster"); } diff --git a/src/server/EventWriter.cpp b/src/server/EventWriter.cpp index 1cd573b2..28a8d319 100644 --- a/src/server/EventWriter.cpp +++ b/src/server/EventWriter.cpp @@ -78,14 +78,14 @@ EventWriter::put(const Raul::URI& uri, } void -EventWriter::delta(const Raul::URI& uri, - const Properties& remove, - const Properties& add) +EventWriter::delta(const Raul::URI& uri, + const Properties& remove, + const Properties& add, + const Resource::Graph ctx) { _engine.enqueue_event( new Events::Delta(_engine, _respondee, _request_id, now(), - Events::Delta::Type::PATCH, Resource::Graph::DEFAULT, - uri, add, remove), + Events::Delta::Type::PATCH, ctx, uri, add, remove), _event_mode); } @@ -149,13 +149,14 @@ EventWriter::disconnect_all(const Raul::Path& graph, } void -EventWriter::set_property(const Raul::URI& uri, - const Raul::URI& predicate, - const Atom& value) +EventWriter::set_property(const Raul::URI& uri, + const Raul::URI& predicate, + const Atom& value, + const Resource::Graph ctx) { _engine.enqueue_event( new Events::Delta(_engine, _respondee, _request_id, now(), - Events::Delta::Type::SET, Resource::Graph::DEFAULT, + Events::Delta::Type::SET, ctx, uri, {{predicate, value}}, {}), _event_mode); } diff --git a/src/server/EventWriter.hpp b/src/server/EventWriter.hpp index 32e3b249..18e98421 100644 --- a/src/server/EventWriter.hpp +++ b/src/server/EventWriter.hpp @@ -63,7 +63,8 @@ public: virtual void delta(const Raul::URI& path, const Properties& remove, - const Properties& add); + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT); virtual void copy(const Raul::URI& old_uri, const Raul::URI& new_uri); @@ -79,7 +80,8 @@ public: virtual void set_property(const Raul::URI& subject_path, const Raul::URI& predicate, - const Atom& value); + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT); virtual void del(const Raul::URI& uri); diff --git a/src/server/events/Delta.cpp b/src/server/events/Delta.cpp index 9f4c1da2..ecc1830a 100644 --- a/src/server/events/Delta.cpp +++ b/src/server/events/Delta.cpp @@ -364,7 +364,7 @@ Delta::pre_process(PreProcessContext& ctx) if (value.get<int32_t>() < 1 || value.get<int32_t>() > 128) { _status = Status::INVALID_POLY; } else { - op = SpecialType::POLYPHONY; + op = SpecialType::POLYPHONY; _graph->prepare_internal_poly( *_engine.buffer_factory(), value.get<int32_t>()); } @@ -585,7 +585,7 @@ Delta::post_process() } break; case Type::PATCH: - _engine.broadcaster()->delta(_subject, _remove, _properties); + _engine.broadcaster()->delta(_subject, _remove, _properties, _context); break; } } @@ -597,15 +597,17 @@ Delta::undo(Interface& target) if (_create_event) { _create_event->undo(target); } else if (_type == Type::PATCH) { - target.delta(_subject, _added, _removed); + target.delta(_subject, _added, _removed, _context); } else if (_type == Type::SET || _type == Type::PUT) { if (_removed.size() == 1) { - target.set_property( - _subject, _removed.begin()->first, _removed.begin()->second); + target.set_property(_subject, + _removed.begin()->first, + _removed.begin()->second, + _context); } else if (_removed.empty()) { - target.delta(_subject, _added, {}); + target.delta(_subject, _added, {}, _context); } else { - target.put(_subject, _removed); + target.put(_subject, _removed, _context); } } } diff --git a/tests/TestClient.hpp b/tests/TestClient.hpp index f1e0c5a7..968e4423 100644 --- a/tests/TestClient.hpp +++ b/tests/TestClient.hpp @@ -39,7 +39,8 @@ public: void delta(const Raul::URI& uri, const Properties& remove, - const Properties& add) {} + const Properties& add, + Resource::Graph ctx = Resource::Graph::DEFAULT) {} void copy(const Raul::URI& old_uri, const Raul::URI& new_uri) {} @@ -60,7 +61,8 @@ public: void set_property(const Raul::URI& subject, const Raul::URI& predicate, - const Atom& value) {} + const Atom& value, + Resource::Graph ctx = Resource::Graph::DEFAULT) {} void set_response_id(int32_t id) {} @@ -74,7 +74,7 @@ def configure(conf): define_name='INGEN_HAVE_THREAD_BUILTIN') autowaf.check_pkg(conf, 'lv2', uselib_store='LV2', - atleast_version='1.14.0', mandatory=True) + atleast_version='1.15.3', mandatory=True) autowaf.check_pkg(conf, 'glibmm-2.4', uselib_store='GLIBMM', atleast_version='2.14.0', mandatory=True) autowaf.check_pkg(conf, 'gthread-2.0', uselib_store='GTHREAD', |