summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-10-19 04:07:02 +0000
committerDavid Robillard <d@drobilla.net>2009-10-19 04:07:02 +0000
commita0108c19c4704316a02c85676af349acdda29d72 (patch)
treec971fe3fa385bd3abfb3d450f7f2b4e1a718ed60
parent78ebb57ba3268da3560aa596dfe14c515f617890 (diff)
downloadingen-a0108c19c4704316a02c85676af349acdda29d72.tar.gz
ingen-a0108c19c4704316a02c85676af349acdda29d72.tar.bz2
ingen-a0108c19c4704316a02c85676af349acdda29d72.zip
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
-rw-r--r--src/common/interface/Resource.hpp3
-rw-r--r--src/engine/QueuedEngineInterface.cpp4
-rw-r--r--src/engine/events/SetMetadata.cpp42
-rw-r--r--src/engine/events/SetMetadata.hpp9
-rw-r--r--src/engine/events/SetPortValue.cpp34
-rw-r--r--src/engine/events/SetPortValue.hpp6
-rw-r--r--src/shared/ResourceImpl.cpp4
7 files changed, 83 insertions, 19 deletions
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> 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<GraphObjectImpl*>(_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<GraphObjectImpl*>(_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<PatchImpl*>(_object);
@@ -150,6 +167,15 @@ SetMetadata::pre_process()
_error = BAD_TYPE;
}
}
+ } else if (key.str() == "ingen:value") {
+ PortImpl* port = dynamic_cast<PortImpl*>(_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<SpecialType>::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> 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<SetPortValue*> SetEvents;
+
QueuedEvent* _create_event;
+ SetEvents _set_events;
std::vector<SpecialType> _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> 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> 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);
}
@@ -146,8 +146,6 @@ 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);
}