From a0108c19c4704316a02c85676af349acdda29d72 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 19 Oct 2009 04:07:02 +0000 Subject: Fix set/PUT with multiple properties of the same predicate. Actually set port value when PUT of ingen:value occurs (fix ticket #410). git-svn-id: http://svn.drobilla.net/lad/trunk/ingen@2198 a436a847-0d15-0410-975c-d299462d15a1 --- src/common/interface/Resource.hpp | 3 +++ src/engine/QueuedEngineInterface.cpp | 4 ++-- src/engine/events/SetMetadata.cpp | 42 +++++++++++++++++++++++++++++++----- src/engine/events/SetMetadata.hpp | 9 ++++++++ src/engine/events/SetPortValue.cpp | 34 +++++++++++++++++++++-------- src/engine/events/SetPortValue.hpp | 6 ++++++ src/shared/ResourceImpl.cpp | 4 +--- 7 files changed, 83 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/common/interface/Resource.hpp b/src/common/interface/Resource.hpp index 194e99cf..99bd3ef6 100644 --- a/src/common/interface/Resource.hpp +++ b/src/common/interface/Resource.hpp @@ -39,6 +39,9 @@ public: virtual Raul::Atom& set_property(const Raul::URI& uri, const Raul::Atom& value) = 0; + virtual void add_property(const Raul::URI& uri, + const Raul::Atom& value) = 0; + virtual const Raul::Atom& get_property(const Raul::URI& uri) const = 0; }; diff --git a/src/engine/QueuedEngineInterface.cpp b/src/engine/QueuedEngineInterface.cpp index 949626e9..d2ff74df 100644 --- a/src/engine/QueuedEngineInterface.cpp +++ b/src/engine/QueuedEngineInterface.cpp @@ -164,7 +164,7 @@ QueuedEngineInterface::put(const URI& uri, cerr << "\t" << i->first << " = " << i->second << " :: " << i->second.type() << endl; cerr << "}" << endl;*/ - push_queued(new Events::SetMetadata(_engine, _responder, now(), this, meta, subject, properties)); + push_queued(new Events::SetMetadata(_engine, _responder, now(), this, true, meta, subject, properties)); } @@ -249,7 +249,7 @@ QueuedEngineInterface::set_property(const URI& uri, Path path = meta ? (string("/") + path.chop_start("/")) : uri.str(); Resource::Properties properties; properties.insert(make_pair(predicate, value)); - push_queued(new Events::SetMetadata(_engine, _responder, now(), this, meta, path, properties)); + push_queued(new Events::SetMetadata(_engine, _responder, now(), this, true, meta, path, properties)); } // Requests // diff --git a/src/engine/events/SetMetadata.cpp b/src/engine/events/SetMetadata.cpp index e991bcf5..3d62781d 100644 --- a/src/engine/events/SetMetadata.cpp +++ b/src/engine/events/SetMetadata.cpp @@ -31,6 +31,7 @@ #include "QueuedEventSource.hpp" #include "Responder.hpp" #include "SetMetadata.hpp" +#include "SetPortValue.hpp" using namespace std; using namespace Raul; @@ -47,6 +48,7 @@ SetMetadata::SetMetadata( SharedPtr responder, SampleCount timestamp, QueuedEventSource* source, + bool replace, bool meta, const URI& subject, const Properties& properties) @@ -58,12 +60,20 @@ SetMetadata::SetMetadata( , _object(NULL) , _patch(NULL) , _compiled_patch(NULL) + , _replace(replace) , _is_meta(meta) , _success(false) { } +SetMetadata::~SetMetadata() +{ + for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) + delete *i; +} + + void SetMetadata::pre_process() { @@ -112,16 +122,23 @@ SetMetadata::pre_process() _types.reserve(_properties.size()); + GraphObjectImpl* obj = dynamic_cast(_object); + + // If we're replacing (i.e. this is a PUT, not a POST), first remove all properties + // with keys we will later set. This must be done first so a PUT with several properties + // of the same predicate (e.g. rdf:type) retains the multiple values. Only previously + // existing properties should be replaced + if (_replace) + for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p) + obj->properties().erase(p->first); + for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p) { const Raul::URI& key = p->first; const Raul::Atom& value = p->second; - GraphObjectImpl* obj = dynamic_cast(_object); SpecialType op = NONE; if (obj) { - if (_is_meta) - obj->meta().set_property(key, value); - else - obj->set_property(key, value); + Resource& resource = _is_meta ? obj->meta() : *obj; + resource.add_property(key, value); _patch = dynamic_cast(_object); @@ -150,6 +167,15 @@ SetMetadata::pre_process() _error = BAD_TYPE; } } + } else if (key.str() == "ingen:value") { + PortImpl* port = dynamic_cast(_object); + if (port) { + SetPortValue* ev = new SetPortValue(_engine, _responder, _time, port, value); + ev->pre_process(); + _set_events.push_back(ev); + } else { + cerr << "WARNING: Set value for non-port " << _object->uri() << endl; + } } } @@ -179,6 +205,9 @@ SetMetadata::execute(ProcessContext& context) return; } + for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) + (*i)->execute(context); + std::vector::const_iterator t = _types.begin(); for (Properties::iterator p = _properties.begin(); p != _properties.end(); ++p, ++t) { const Raul::Atom& value = p->second; @@ -219,6 +248,9 @@ SetMetadata::execute(ProcessContext& context) void SetMetadata::post_process() { + for (SetEvents::iterator i = _set_events.begin(); i != _set_events.end(); ++i) + (*i)->post_process(); + switch (_error) { case NO_ERROR: _responder->respond_ok(); diff --git a/src/engine/events/SetMetadata.hpp b/src/engine/events/SetMetadata.hpp index 3fd3c904..cf33b5aa 100644 --- a/src/engine/events/SetMetadata.hpp +++ b/src/engine/events/SetMetadata.hpp @@ -57,6 +57,8 @@ namespace Events { * properties from the message. */ +class SetPortValue; + /** Set properties of a graph object. * \ingroup engine */ @@ -68,10 +70,13 @@ public: SharedPtr responder, SampleCount timestamp, QueuedEventSource* source, + bool replace, bool meta, const Raul::URI& subject, const Shared::Resource::Properties& properties); + ~SetMetadata(); + void pre_process(); void execute(ProcessContext& context); void post_process(); @@ -86,13 +91,17 @@ private: POLYPHONIC }; + typedef std::vector SetEvents; + QueuedEvent* _create_event; + SetEvents _set_events; std::vector _types; Raul::URI _subject; Shared::Resource::Properties _properties; Shared::ResourceImpl* _object; PatchImpl* _patch; CompiledPatch* _compiled_patch; + bool _replace; bool _is_meta; bool _success; }; diff --git a/src/engine/events/SetPortValue.cpp b/src/engine/events/SetPortValue.cpp index ba906705..eacf172b 100644 --- a/src/engine/events/SetPortValue.cpp +++ b/src/engine/events/SetPortValue.cpp @@ -20,17 +20,17 @@ #include "shared/LV2URIMap.hpp" #include "shared/LV2Features.hpp" #include "module/World.hpp" -#include "Responder.hpp" -#include "SetPortValue.hpp" -#include "Engine.hpp" -#include "PortImpl.hpp" +#include "AudioBuffer.hpp" #include "ClientBroadcaster.hpp" -#include "NodeImpl.hpp" +#include "Engine.hpp" #include "EngineStore.hpp" -#include "AudioBuffer.hpp" #include "EventBuffer.hpp" -#include "ProcessContext.hpp" #include "MessageContext.hpp" +#include "NodeImpl.hpp" +#include "PortImpl.hpp" +#include "ProcessContext.hpp" +#include "Responder.hpp" +#include "SetPortValue.hpp" using namespace std; using namespace Raul; @@ -53,7 +53,7 @@ SetPortValue::SetPortValue(Engine& engine, , _omni(true) , _voice_num(0) , _port_path(port_path) - , _value(value) + , _value(value) , _port(NULL) , _error(NO_ERROR) { @@ -73,12 +73,28 @@ SetPortValue::SetPortValue(Engine& engine, , _omni(false) , _voice_num(voice_num) , _port_path(port_path) - , _value(value) + , _value(value) , _port(NULL) , _error(NO_ERROR) { } +/** Internal */ +SetPortValue::SetPortValue(Engine& engine, + SharedPtr responder, + SampleCount timestamp, + PortImpl* port, + const Raul::Atom& value) + : QueuedEvent(engine, responder, timestamp) + , _queued(false) + , _omni(true) + , _voice_num(0) + , _port_path(port->path()) + , _value(value) + , _port(port) + , _error(NO_ERROR) +{ +} SetPortValue::~SetPortValue() { diff --git a/src/engine/events/SetPortValue.hpp b/src/engine/events/SetPortValue.hpp index 6d7c142b..87f4f6f6 100644 --- a/src/engine/events/SetPortValue.hpp +++ b/src/engine/events/SetPortValue.hpp @@ -56,6 +56,12 @@ public: const Raul::Path& port_path, const Raul::Atom& value); + SetPortValue(Engine& engine, + SharedPtr responder, + SampleCount timestamp, + PortImpl* port, + const Raul::Atom& value); + ~SetPortValue(); void pre_process(); diff --git a/src/shared/ResourceImpl.cpp b/src/shared/ResourceImpl.cpp index ac828f58..e35bb7ad 100644 --- a/src/shared/ResourceImpl.cpp +++ b/src/shared/ResourceImpl.cpp @@ -137,7 +137,7 @@ ResourceImpl::set_properties(const Properties& p) for (iterator i = p.begin(); i != p.end(); ++i) _properties.erase(i->first); for (iterator i = p.begin(); i != p.end(); ++i) - set_property(i->first, i->second); + add_property(i->first, i->second); } @@ -145,8 +145,6 @@ void ResourceImpl::add_properties(const Properties& p) { typedef Resource::Properties::const_iterator iterator; - for (iterator i = p.begin(); i != p.end(); ++i) - _properties.erase(i->first); for (iterator i = p.begin(); i != p.end(); ++i) add_property(i->first, i->second); } -- cgit v1.2.1