summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/uscxml/Factory.cpp56
-rw-r--r--src/uscxml/Factory.h12
-rw-r--r--src/uscxml/Interpreter.cpp12
-rw-r--r--src/uscxml/Message.h2
-rw-r--r--src/uscxml/NameSpacingParser.h7
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp102
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h5
-rw-r--r--src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp16
-rw-r--r--src/uscxml/plugins/invoker/CMakeLists.txt19
-rw-r--r--src/uscxml/plugins/invoker/location/LocationInvoker.cpp44
-rw-r--r--src/uscxml/plugins/invoker/location/LocationInvoker.h40
-rw-r--r--src/uscxml/plugins/invoker/miles/SpatialAudio.cpp43
-rw-r--r--src/uscxml/plugins/invoker/miles/SpatialAudio.h1
-rw-r--r--src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp14
-rw-r--r--src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp14
-rw-r--r--src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp63
16 files changed, 393 insertions, 57 deletions
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index b3ad09e..7ac3b98 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -392,6 +392,62 @@ boost::shared_ptr<ExecutableContentImpl> Factory::createExecutableContent(const
}
+size_t DataModelImpl::replaceExpressions(std::string& content) {
+ std::stringstream ss;
+ size_t replacements = 0;
+ size_t indent = 0;
+ size_t pos = 0;
+ size_t start = std::string::npos;
+ size_t end = 0;
+ while (true) {
+ // find any of ${}
+ pos = content.find_first_of("${}", pos);
+ if (pos == std::string::npos) {
+ ss << content.substr(end, content.length() - end);
+ break;
+ }
+ if (content[pos] == '$') {
+ if (content.size() > pos && content[pos+1] == '{') {
+ pos++;
+ start = pos + 1;
+ // copy everything in between
+ ss << content.substr(end, (start - 2) - end);
+ }
+ } else if (content[pos] == '{' && start != std::string::npos) {
+ indent++;
+ } else if (content[pos] == '}' && start != std::string::npos) {
+ if (!indent) {
+ end = pos;
+ // we found a token to substitute
+ std::string expr = content.substr(start, end - start);
+ end++;
+ try {
+ Data data = getStringAsData(expr);
+// if (data.type == Data::VERBATIM) {
+// ss << "\"" << data.atom << "\"";
+// } else {
+// ss << data.atom;
+// }
+ ss << Data::toJSON(data);
+ replacements++;
+ } catch (Event e) {
+ // insert unsubstituted
+ start -= 2;
+ ss << content.substr(start, end - start);
+ }
+ start = std::string::npos;
+ } else {
+ indent--;
+ }
+ }
+ pos++;
+ }
+ if (replacements)
+ content = ss.str();
+
+ return replacements;
+}
+
Factory* Factory::getInstance() {
if (_instance == NULL) {
diff --git a/src/uscxml/Factory.h b/src/uscxml/Factory.h
index 7b08982..2a0ec43 100644
--- a/src/uscxml/Factory.h
+++ b/src/uscxml/Factory.h
@@ -10,12 +10,14 @@
#include <string>
#include <set>
#include <boost/shared_ptr.hpp>
+#include <limits>
namespace uscxml {
// see http://stackoverflow.com/questions/228005/alternative-to-itoa-for-converting-integer-to-string-c
template <typename T> std::string toStr(T tmp) {
std::ostringstream out;
+ out.precision(std::numeric_limits<double>::digits10 + 1);
out << tmp;
return out.str();
}
@@ -28,9 +30,9 @@ template <typename T> T strTo(std::string tmp) {
}
inline bool isNumeric( const char* pszInput, int nNumberBase) {
- std::string base = "0123456789ABCDEF";
+ std::string base = ".0123456789ABCDEF";
std::string input = pszInput;
- return (input.find_first_not_of(base.substr(0, nNumberBase)) == std::string::npos);
+ return (input.find_first_not_of(base.substr(0, nNumberBase + 1)) == std::string::npos);
}
class InterpreterImpl;
@@ -252,6 +254,8 @@ public:
virtual void setEvent(const Event& event) = 0;
virtual Data getStringAsData(const std::string& content) = 0;
+ size_t replaceExpressions(std::string& content);
+
// foreach
virtual uint32_t getLength(const std::string& expr) = 0;
virtual void setForeach(const std::string& item,
@@ -363,6 +367,10 @@ public:
return _impl->isDeclared(expr);
}
+ size_t replaceExpressions(std::string& content) {
+ return _impl->replaceExpressions(content);
+ }
+
protected:
boost::shared_ptr<DataModelImpl> _impl;
};
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 158ea96..8c1b4a6 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -436,7 +436,7 @@ void InterpreterImpl::processContentElement(const Arabica::DOM::Node<std::string
std::string& expr) {
if (HAS_ATTR(content, "expr")) {
expr = ATTR(content, "expr");
- } else if (content.hasChildNodes()) {
+ } else if (content.hasChildNodes() || HAS_ATTR(content, "src") || HAS_ATTR(content, "srcexpr")) {
processDOMorText(content, dom, text);
} else {
LOG(ERROR) << "content element does not specify any content.";
@@ -455,7 +455,7 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no
LOG(ERROR) << LOCALNAME(node) << " element has relative src or srcexpr URI with no baseURI set.";
return;
}
- if (_cachedURLs.find(sourceURL.asString()) != _cachedURLs.end()) {
+ if (_cachedURLs.find(sourceURL.asString()) != _cachedURLs.end() && false) {
srcContent << _cachedURLs[sourceURL.asString()];
} else {
srcContent << sourceURL;
@@ -473,8 +473,12 @@ void InterpreterImpl::processDOMorText(const Arabica::DOM::Node<std::string>& no
std::auto_ptr<std::istream> ssPtr(ss);
Arabica::SAX::InputSource<std::string> inputSource;
inputSource.setByteStream(ssPtr);
+
+// parser.setFeature(Arabica::SAX::FeatureNames<std::string>().external_general, true);
+
if (parser.parse(inputSource) && parser.getDocument()) {
dom = parser.getDocument();
+ std::cout << dom;
Node<std::string> content = dom.getDocumentElement();
assert(content.getNodeType() == Node_base::ELEMENT_NODE);
Node<std::string> container = dom.createElement("container");
@@ -1106,7 +1110,7 @@ void InterpreterImpl::executeContent(const Arabica::DOM::Node<std::string>& cont
}
std::stringstream srcContent;
- if (_cachedURLs.find(scriptUrl.asString()) != _cachedURLs.end()) {
+ if (_cachedURLs.find(scriptUrl.asString()) != _cachedURLs.end() && false) {
srcContent << _cachedURLs[scriptUrl.asString()];
} else {
srcContent << scriptUrl;
@@ -1313,7 +1317,7 @@ Arabica::XPath::NodeSet<std::string> InterpreterImpl::getStates(const std::vecto
Arabica::DOM::Node<std::string> InterpreterImpl::getState(const std::string& stateId) {
- if (_cachedStates.find(stateId) != _cachedStates.end()) {
+ if (_cachedStates.find(stateId) != _cachedStates.end() && false) {
return _cachedStates[stateId];
}
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index dd62702..dda2279 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -26,7 +26,7 @@ public:
INTERPRETED
};
- Data() {}
+ Data() : type(INTERPRETED) {}
Data(const std::string& atom_, Type type_ = INTERPRETED) : atom(atom_), type(type_) {}
explicit Data(const Arabica::DOM::Node<std::string>& dom);
virtual ~Data() {}
diff --git a/src/uscxml/NameSpacingParser.h b/src/uscxml/NameSpacingParser.h
index fddf306..50cc260 100644
--- a/src/uscxml/NameSpacingParser.h
+++ b/src/uscxml/NameSpacingParser.h
@@ -6,6 +6,13 @@
namespace uscxml {
+class ScriptEntityResolver : public Arabica::SAX::EntityResolver<std::string> {
+ virtual InputSourceT resolveEntity(const std::string& publicId, const std::string& systemId) {
+ Arabica::SAX::InputSource<std::string> is;
+ return is;
+ }
+};
+
class NameSpacingParser : public Arabica::SAX2DOM::Parser<std::string> {
public:
NameSpacingParser();
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index 8feb73a..47ec21d 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -24,10 +24,37 @@ bool connect(pluma::Host& host) {
JSCDataModel::JSCDataModel() {
}
+#if 0
+typedef struct {
+ int version; /* current (and only) version is 0 */
+ JSClassAttributes attributes;
+
+ const char* className;
+ JSClassRef parentClass;
+
+ const JSStaticValue* staticValues;
+ const JSStaticFunction* staticFunctions;
+
+ JSObjectInitializeCallback initialize;
+ JSObjectFinalizeCallback finalize;
+ JSObjectHasPropertyCallback hasProperty;
+ JSObjectGetPropertyCallback getProperty;
+ JSObjectSetPropertyCallback setProperty;
+ JSObjectDeletePropertyCallback deleteProperty;
+ JSObjectGetPropertyNamesCallback getPropertyNames;
+ JSObjectCallAsFunctionCallback callAsFunction;
+ JSObjectCallAsConstructorCallback callAsConstructor;
+ JSObjectHasInstanceCallback hasInstance;
+ JSObjectConvertToTypeCallback convertToType;
+} JSClassDefinition;
+#endif
+
// functions need to be objects to hold private data in JSC
JSClassDefinition JSCDataModel::jsInClassDef = { 0, 0, "In", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsIn, 0, 0, 0 };
JSClassDefinition JSCDataModel::jsPrintClassDef = { 0, 0, "print", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, jsPrint, 0, 0, 0 };
+JSClassDefinition JSCDataModel::jsIOProcessorsClassDef = { 0, 0, "ioProcessors", 0, 0, 0, 0, 0, jsIOProcessorHasProp, jsIOProcessorGetProp, 0, 0, jsIOProcessorListProps, 0, 0, 0, 0 };
+
boost::shared_ptr<DataModelImpl> JSCDataModel::create(InterpreterImpl* interpreter) {
boost::shared_ptr<JSCDataModel> dm = boost::shared_ptr<JSCDataModel>(new JSCDataModel());
@@ -51,15 +78,33 @@ boost::shared_ptr<DataModelImpl> JSCDataModel::create(InterpreterImpl* interpret
JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), printName, jsPrint, kJSPropertyAttributeNone, NULL);
JSStringRelease(inName);
- dm->eval("_ioprocessors = {};");
+ JSClassRef jsIOProcClassRef = JSClassCreate(&jsIOProcessorsClassDef);
+ JSObjectRef jsIOProc = JSObjectMake(dm->_ctx, jsIOProcClassRef, dm.get());
+ JSStringRef ioProcName = JSStringCreateWithUTF8CString("_ioprocessors");
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), ioProcName, jsIOProc, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(ioProcName);
+
+ JSStringRef nameName = JSStringCreateWithUTF8CString("_name");
+ JSStringRef name = JSStringCreateWithUTF8CString(dm->_interpreter->getName().c_str());
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), nameName, JSValueMakeString(dm->_ctx, name), kJSPropertyAttributeNone, NULL);
+ JSStringRelease(nameName);
+ JSStringRelease(name);
+
+ JSStringRef sessionIdName = JSStringCreateWithUTF8CString("_sessionid");
+ JSStringRef sessionId = JSStringCreateWithUTF8CString(dm->_interpreter->getSessionId().c_str());
+ JSObjectSetProperty(dm->_ctx, JSContextGetGlobalObject(dm->_ctx), sessionIdName, JSValueMakeString(dm->_ctx, sessionId), kJSPropertyAttributeNone, NULL);
+ JSStringRelease(sessionIdName);
+ JSStringRelease(sessionId);
Arabica::DOM::JSCDocument::JSCDocumentPrivate* privData = new Arabica::DOM::JSCDocument::JSCDocumentPrivate();
- privData->nativeObj = new Arabica::DOM::Document<std::string>(interpreter->getDocument());
- privData->dom = dm->_dom;
+ if (interpreter) {
+ privData->nativeObj = new Arabica::DOM::Document<std::string>(interpreter->getDocument());
+ privData->dom = dm->_dom;
- JSObjectRef documentObject = JSObjectMake(dm->_ctx, Arabica::DOM::JSCDocument::getTmpl(), privData);
- JSObjectRef globalObject = JSContextGetGlobalObject(dm->_ctx);
- JSObjectSetProperty(dm->_ctx, globalObject, JSStringCreateWithUTF8CString("document"), documentObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
+ JSObjectRef documentObject = JSObjectMake(dm->_ctx, Arabica::DOM::JSCDocument::getTmpl(), privData);
+ JSObjectRef globalObject = JSContextGetGlobalObject(dm->_ctx);
+ JSObjectSetProperty(dm->_ctx, globalObject, JSStringCreateWithUTF8CString("document"), documentObject, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete, NULL);
+ }
dm->eval("_invokers = {};");
dm->eval("_x = {};");
@@ -202,10 +247,9 @@ Data JSCDataModel::getValueAsData(const JSValueRef value) {
JSValueRef exception = NULL;
switch(JSValueGetType(_ctx, value)) {
case kJSTypeUndefined:
- LOG(ERROR) << "IsUndefined is unimplemented";
- break;
case kJSTypeNull:
- LOG(ERROR) << "IsNull is unimplemented";
+ data.atom = "null";
+ data.type = Data::INTERPRETED;
break;
case kJSTypeBoolean:
data.atom = (JSValueToBoolean(_ctx, value) ? "true" : "false");
@@ -225,6 +269,7 @@ Data JSCDataModel::getValueAsData(const JSValueRef value) {
JSStringGetUTF8CString(stringValue, buf, maxSize);
data.atom = std::string(buf);
+ data.type = Data::VERBATIM;
JSStringRelease(stringValue);
free(buf);
break;
@@ -488,4 +533,43 @@ JSValueRef JSCDataModel::jsIn(JSContextRef ctx, JSObjectRef function, JSObjectRe
}
+bool JSCDataModel::jsIOProcessorHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) {
+ JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
+ std::map<std::string, IOProcessor> ioProcessors = INSTANCE->_interpreter->getIOProcessors();
+
+ size_t maxSize = JSStringGetMaximumUTF8CStringSize(propertyName);
+ char buffer[maxSize];
+ JSStringGetUTF8CString(propertyName, buffer, maxSize);
+ std::string prop(buffer);
+
+ return ioProcessors.find(prop) != ioProcessors.end();
+}
+
+JSValueRef JSCDataModel::jsIOProcessorGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
+ JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
+ std::map<std::string, IOProcessor> ioProcessors = INSTANCE->_interpreter->getIOProcessors();
+
+ size_t maxSize = JSStringGetMaximumUTF8CStringSize(propertyName);
+ char buffer[maxSize];
+ JSStringGetUTF8CString(propertyName, buffer, maxSize);
+ std::string prop(buffer);
+
+ if (ioProcessors.find(prop) != ioProcessors.end()) {
+ return INSTANCE->getDataAsValue(ioProcessors.find(prop)->second.getDataModelVariables());
+ }
+ return JSValueMakeUndefined(ctx);
+}
+
+void JSCDataModel::jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames) {
+ JSCDataModel* INSTANCE = (JSCDataModel*)JSObjectGetPrivate(object);
+ std::map<std::string, IOProcessor> ioProcessors = INSTANCE->_interpreter->getIOProcessors();
+
+ std::map<std::string, IOProcessor>::const_iterator ioProcIter = ioProcessors.begin();
+ while(ioProcIter != ioProcessors.end()) {
+ JSStringRef ioProcName = JSStringCreateWithUTF8CString(ioProcIter->first.c_str());
+ JSPropertyNameAccumulatorAddName(propertyNames, ioProcName);
+ ioProcIter++;
+ }
+}
+
} \ No newline at end of file
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
index 28a313e..36765c2 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.h
@@ -66,6 +66,11 @@ protected:
static JSClassDefinition jsPrintClassDef;
static JSValueRef jsPrint(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+ static JSClassDefinition jsIOProcessorsClassDef;
+ static bool jsIOProcessorHasProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName);
+ static JSValueRef jsIOProcessorGetProp(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+ static void jsIOProcessorListProps(JSContextRef ctx, JSObjectRef object, JSPropertyNameAccumulatorRef propertyNames);
+
JSValueRef getDocumentAsValue(const Arabica::DOM::Document<std::string>& doc);
JSValueRef getDataAsValue(const Data& data);
Data getValueAsData(const JSValueRef value);
diff --git a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
index c92274c..2e37b29 100644
--- a/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/prolog/swi/SWIDataModel.cpp
@@ -264,13 +264,17 @@ void SWIDataModel::eval(const std::string& expr) {
}
bool SWIDataModel::evalAsBool(const std::string& expr) {
- PlCompound compound(expr.c_str());
- PlTermv termv(compound.arity());
- for (int i = 0; i < compound.arity(); i++) {
- termv[i] = compound[i + 1];
+ try {
+ PlCompound compound(expr.c_str());
+ PlTermv termv(compound.arity());
+ for (int i = 0; i < compound.arity(); i++) {
+ termv[i] = compound[i + 1];
+ }
+ PlQuery query(compound.name(), termv);
+ return query.next_solution() > 0;
+ } catch(...) {
+ return false;
}
- PlQuery query(compound.name(), termv);
- return query.next_solution() > 0;
}
std::string SWIDataModel::evalAsString(const std::string& expr) {
diff --git a/src/uscxml/plugins/invoker/CMakeLists.txt b/src/uscxml/plugins/invoker/CMakeLists.txt
index 34d8918..e836275 100644
--- a/src/uscxml/plugins/invoker/CMakeLists.txt
+++ b/src/uscxml/plugins/invoker/CMakeLists.txt
@@ -32,6 +32,25 @@ else()
list (APPEND USCXML_FILES ${DIRMON_INVOKER})
endif()
+
+# Location invoker to watch for proximity to GPS coordinates
+
+file(GLOB_RECURSE LOCATION_INVOKER
+ location/*.cpp
+ location/*.h
+)
+source_group("Invoker\\location" FILES ${LOCATION_INVOKER})
+if (BUILD_AS_PLUGINS)
+ add_library(
+ invoker_location SHARED
+ ${LOCATION_INVOKER})
+ target_link_libraries(invoker_location uscxml)
+ set_target_properties(invoker_location PROPERTIES FOLDER "Plugin Invoker")
+else()
+ list (APPEND USCXML_FILES ${LOCATION_INVOKER})
+endif()
+
+
# System invoker to open a native command
file(GLOB_RECURSE XHTML_INVOKER
diff --git a/src/uscxml/plugins/invoker/location/LocationInvoker.cpp b/src/uscxml/plugins/invoker/location/LocationInvoker.cpp
new file mode 100644
index 0000000..9aeb6b4
--- /dev/null
+++ b/src/uscxml/plugins/invoker/location/LocationInvoker.cpp
@@ -0,0 +1,44 @@
+#include "LocationInvoker.h"
+#include <glog/logging.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include <Pluma/Connector.hpp>
+#endif
+
+namespace uscxml {
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_CONNECTOR
+bool connect(pluma::Host& host) {
+ host.add( new LocationInvokerProvider() );
+ return true;
+}
+#endif
+
+LocationInvoker::LocationInvoker() {
+}
+
+LocationInvoker::~LocationInvoker() {
+};
+
+boost::shared_ptr<InvokerImpl> LocationInvoker::create(InterpreterImpl* interpreter) {
+ boost::shared_ptr<LocationInvoker> invoker = boost::shared_ptr<LocationInvoker>(new LocationInvoker());
+ invoker->_interpreter = interpreter;
+ return invoker;
+}
+
+Data LocationInvoker::getDataModelVariables() {
+ Data data;
+ return data;
+}
+
+void LocationInvoker::send(const SendRequest& req) {
+}
+
+void LocationInvoker::cancel(const std::string sendId) {
+}
+
+void LocationInvoker::invoke(const InvokeRequest& req) {
+}
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/invoker/location/LocationInvoker.h b/src/uscxml/plugins/invoker/location/LocationInvoker.h
new file mode 100644
index 0000000..2eb4833
--- /dev/null
+++ b/src/uscxml/plugins/invoker/location/LocationInvoker.h
@@ -0,0 +1,40 @@
+#ifndef LOCATIONINVOKER_H_W09J90F0
+#define LOCATIONINVOKER_H_W09J90F0
+
+#include <uscxml/Interpreter.h>
+
+#ifdef BUILD_AS_PLUGINS
+#include "uscxml/plugins/Plugins.h"
+#endif
+
+namespace uscxml {
+
+class LocationInvoker : public InvokerImpl {
+public:
+ LocationInvoker();
+ virtual ~LocationInvoker();
+ virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter);
+
+ virtual std::set<std::string> getNames() {
+ std::set<std::string> names;
+ names.insert("location");
+ names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#location");
+ return names;
+ }
+
+ virtual Data getDataModelVariables();
+ virtual void send(const SendRequest& req);
+ virtual void cancel(const std::string sendId);
+ virtual void invoke(const InvokeRequest& req);
+
+protected:
+};
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_INHERIT_PROVIDER(LocationInvoker, InvokerImpl);
+#endif
+
+}
+
+
+#endif /* end of include guard: LOCATIONINVOKER_H_W09J90F0 */
diff --git a/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp b/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp
index 3826ebb..298b15f 100644
--- a/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp
+++ b/src/uscxml/plugins/invoker/miles/SpatialAudio.cpp
@@ -28,11 +28,11 @@ SpatialAudio::SpatialAudio() {
_pos[0] = _pos[1] = _pos[2] = 0.0;
_listener = new float[3];
_listener[0] = _listener[1] = _listener[2] = 0.0;
+ _maxPos = new float[3];
+ _maxPos[0] = _maxPos[1] = _maxPos[2] = 1.0;
miles_init();
-
}
-
SpatialAudio::~SpatialAudio() {
};
@@ -53,8 +53,8 @@ void SpatialAudio::send(const SendRequest& req) {
_audioDev = miles_audio_device_open(MILES_AUDIO_IO_OPENAL, _audioDevIndex, 0, 22050, 2, 1, 1024, false);
if (_audioDev != NULL) {
_audioDevOpen = true;
- float rolloffFactor = 0.2;
- miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_ROLLOFF_FACTOR, &rolloffFactor);
+// float rolloffFactor = 1.0;
+// miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_ROLLOFF_FACTOR, &rolloffFactor);
}
}
@@ -70,24 +70,30 @@ void SpatialAudio::send(const SendRequest& req) {
miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_POSITION, _pos);
+
char* buffer = (char*)malloc(_audioDev->chunk_size);
// skip wav header
_dataStream.seekg(44);
-
+
while(_dataStream.readsome(buffer, _audioDev->chunk_size) != 0) {
- miles_audio_device_write(MILES_AUDIO_IO_OPENAL, _audioDev, buffer, _audioDev->chunk_size);
+ int written = 0;
+ while(written < _audioDev->chunk_size) {
+ written += miles_audio_device_write(MILES_AUDIO_IO_OPENAL, _audioDev, buffer + written, _audioDev->chunk_size - written);
+ tthread::this_thread::sleep_for(tthread::chrono::milliseconds(10));
+ }
}
+ _dataStream.seekg(0);
free(buffer);
}
} else if (boost::iequals(req.name, "move.listener")) {
if (_audioDevOpen) {
getPosFromParams(req.params, _listener);
- std::cout << "Listener: ";
- for (int i = 0; i < 3; i++) {
- std::cout << _listener[i] << " ";
- }
- std::cout << std::endl;
+// std::cout << "Listener: ";
+// for (int i = 0; i < 3; i++) {
+// std::cout << _listener[i] << " ";
+// }
+// std::cout << std::endl;
miles_audio_device_control(MILES_AUDIO_IO_OPENAL, _audioDev, MILES_AUDIO_DEVICE_CTRL_SET_LISTENER_POS, _listener);
@@ -119,6 +125,17 @@ void SpatialAudio::invoke(const InvokeRequest& req) {
getPosFromParams(req.params, _pos);
+ std::multimap<std::string, std::string>::const_iterator paramIter = req.params.begin();
+ while(paramIter != req.params.end()) {
+ if (boost::iequals(paramIter->first, "maxX"))
+ _maxPos[0] = strTo<float>(paramIter->second);
+ if (boost::iequals(paramIter->first, "maxY"))
+ _maxPos[1] = strTo<float>(paramIter->second);
+ if (boost::iequals(paramIter->first, "maxZ"))
+ _maxPos[2] = strTo<float>(paramIter->second);
+ paramIter++;
+ }
+
struct miles_audio_device_description *devices;
int ndevs;
@@ -170,6 +187,10 @@ void SpatialAudio::getPosFromParams(const std::multimap<std::string, std::string
} catch (boost::bad_lexical_cast& e) {
LOG(ERROR) << "Cannot interpret circle as float value in params: " << e.what();
}
+
+ position[0] = position[0] / _maxPos[0];
+ position[1] = position[1] / _maxPos[1];
+ position[2] = position[2] / _maxPos[2];
// std::cout << _pos[0] << ":" << _pos[1] << ":" << _pos[2] << std::endl;
}
diff --git a/src/uscxml/plugins/invoker/miles/SpatialAudio.h b/src/uscxml/plugins/invoker/miles/SpatialAudio.h
index 082d796..59ecfdb 100644
--- a/src/uscxml/plugins/invoker/miles/SpatialAudio.h
+++ b/src/uscxml/plugins/invoker/miles/SpatialAudio.h
@@ -45,6 +45,7 @@ protected:
float* _pos;
float* _listener;
+ float* _maxPos;
bool _audioDevOpen;
int _audioDevIndex;
struct miles_audio_device* _audioDev;
diff --git a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
index 2b3377e..081842f 100644
--- a/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
+++ b/src/uscxml/plugins/invoker/umundo/UmundoInvoker.cpp
@@ -247,7 +247,11 @@ void UmundoInvoker::receive(void* object, umundo::Message* msg) {
// get meta fields into event
std::map<std::string, std::string>::const_iterator metaIter = msg->getMeta().begin();
while(metaIter != msg->getMeta().end()) {
- event.data.compound[metaIter->first] = Data(metaIter->second, Data::VERBATIM);
+ if (isNumeric(metaIter->second.c_str(), 10)) {
+ event.data.compound[metaIter->first] = Data(metaIter->second, Data::INTERPRETED);
+ } else {
+ event.data.compound[metaIter->first] = Data(metaIter->second, Data::VERBATIM);
+ }
metaIter++;
}
@@ -309,9 +313,13 @@ std::multimap<std::string, std::pair<std::string, boost::weak_ptr<umundo::Node>
boost::shared_ptr<umundo::Node> UmundoInvoker::getNode(InterpreterImpl* interpreter, const std::string& domain) {
std::pair<_nodes_t::iterator, _nodes_t::iterator> range = _nodes.equal_range(interpreter->getName());
for (_nodes_t::iterator it = range.first; it != range.second; it++) {
- if (it->second.first.compare(domain) == 0)
- return it->second.second.lock();
+ if (it->second.first.compare(domain) == 0) {
+ boost::shared_ptr<umundo::Node> node = it->second.second.lock();
+ if (node)
+ return node;
+ }
}
+ // create a new node
boost::shared_ptr<umundo::Node> node = boost::shared_ptr<umundo::Node>(new umundo::Node(domain));
std::pair<std::string, std::pair<std::string, boost::weak_ptr<umundo::Node> > > pair = std::make_pair(interpreter->getName(), std::make_pair(domain, node));
_nodes.insert(pair);
diff --git a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp
index a71d21a..a18be8e 100644
--- a/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/vxml/VoiceXMLInvoker.cpp
@@ -48,10 +48,20 @@ Data VoiceXMLInvoker::getDataModelVariables() {
void VoiceXMLInvoker::send(const SendRequest& req) {
StartRequest start;
std::stringstream domSS;
+// if (req.dom) {
+// // hack until jVoiceXML supports XML
+// std::cout << req.dom;
+// Arabica::DOM::NodeList<std::string> prompts = req.dom.getElementsByTagName("vxml:prompt");
+// for (int i = 0; i < prompts.getLength(); i++) {
+// if (prompts.item(i).hasChildNodes()) {
+// domSS << prompts.item(i).getFirstChild().getNodeValue() << ".";
+// }
+// }
+// }
domSS << req.getFirstDOMElement();
start.content = domSS.str();
-
- start.contentURL.href = "http://localhost/~sradomski/hello.vxml";
+ _interpreter->getDataModel().replaceExpressions(start.content);
+
start.requestId = "asdf";
start.source = "asdf";
start.target = "umundo://mmi/jvoicexml";
diff --git a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
index 0c7ef08..4e2c01a 100644
--- a/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
+++ b/src/uscxml/plugins/invoker/xhtml/XHTMLInvoker.cpp
@@ -7,9 +7,12 @@
#include <Pluma/Connector.hpp>
#endif
-#if defined(__APPLE__) and defined(TARGET_OS_MAC)
-#include <CoreFoundation/CFBundle.h>
-#include <ApplicationServices/ApplicationServices.h>
+#if __APPLE__
+# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+# else
+# include <CoreFoundation/CFBundle.h>
+# include <ApplicationServices/ApplicationServices.h>
+# endif
#endif
namespace uscxml {
@@ -41,6 +44,7 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
// these are the XHR requests
if (boost::iequals(req.data["header"]["X-Requested-With"].atom, "XMLHttpRequest")) {
if (boost::iequals(req.data["type"].atom, "get")) {
+ // the long-polling GET
if (_longPoll) {
evhttp_send_error(_longPoll.curlReq, 204, NULL);
_longPoll.curlReq = NULL;
@@ -52,9 +56,12 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
}
return true;
} else {
+ // a POST request
Event ev(req);
if (ev.data["header"]["X-SCXML-Name"]) {
ev.name = ev.data["header"]["X-SCXML-Name"].atom;
+ } else {
+ ev.name = req.data["type"].atom;
}
ev.origin = _invokeId;
ev.initContent(req.data["content"].atom);
@@ -62,6 +69,9 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
// content is already on ev.raw
ev.data.compound["Connection"].compound.erase("content");
+ HTTPServer::Reply reply(req);
+ HTTPServer::reply(reply);
+
returnEvent(ev);
return true;
}
@@ -70,17 +80,9 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
// initial request for a document
if (!req.data["query"] && // no query parameters
boost::iequals(req.data["type"].atom, "get") && // request type is GET
- (boost::icontains(req.data["header"]["Accept"].atom, "text/html") || // accepts html or
- boost::contains(req.data["header"]["User-Agent"].atom, "MSIE")) && // is the internet explorer
req.content.length() == 0) { // no content
HTTPServer::Reply reply(req);
- URL templateURL("templates/xhtml-invoker.html");
- templateURL.toAbsolute(_interpreter->getBaseURI());
- templateURL.download(true);
- std::string templateContent = templateURL.getInContent();
- boost::replace_all(templateContent, "${scxml.server}", _url);
- boost::replace_all(templateContent, "${scxml.invokeId}", _invokeId);
std::string content;
std::stringstream ss;
@@ -90,15 +92,25 @@ bool XHTMLInvoker::httpRecvRequest(const HTTPServer::Request& req) {
} else if(_invokeReq.data) {
ss << _invokeReq.data;
content = ss.str();
- } else {
+ } else if (_invokeReq.content.length() > 0){
content = _invokeReq.content;
+ } else {
+ URL templateURL("templates/xhtml-invoker.html");
+ templateURL.toAbsolute(_interpreter->getBaseURI());
+ templateURL.download(true);
+ content = templateURL.getInContent();
}
- boost::replace_all(templateContent, "${scxml.content}", content);
- reply.content = templateContent;
- reply.headers["Content-Type"] = "text/html";
+
+ _interpreter->getDataModel().replaceExpressions(content);
+ reply.content = content;
+
+ // application/xhtml+xml
+ reply.headers["Content-Type"] = "text/html; charset=utf-8";
+// reply.headers["Content-Type"] = "application/xhtml+xml; charset=utf-8";
// aggressive caching in IE will return all XHR get requests instantenously with the template otherwise
reply.headers["Cache-Control"] = "no-cache";
+// reply.headers["Cache-Control"] = "max-age=3600";
HTTPServer::reply(reply);
@@ -122,17 +134,27 @@ Data XHTMLInvoker::getDataModelVariables() {
void XHTMLInvoker::send(const SendRequest& req) {
tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+ SendRequest reqCopy(req);
+ _interpreter->getDataModel().replaceExpressions(reqCopy.content);
+ Data json = Data::fromJSON(reqCopy.content);
+ if (json) {
+ reqCopy.data = json;
+ }
+
if (!_longPoll) {
- _outQueue.push_back(req);
+ _outQueue.push_back(reqCopy);
return;
}
- reply(req, _longPoll);
+ reply(reqCopy, _longPoll);
_longPoll.curlReq = NULL;
}
void XHTMLInvoker::reply(const SendRequest& req, const HTTPServer::Request& longPoll) {
HTTPServer::Reply reply(longPoll);
+ // is there JSON in the content?
+ std::string content = req.content;
+
if (req.dom) {
std::stringstream ss;
Arabica::DOM::Node<std::string> content = req.dom.getDocumentElement();
@@ -164,8 +186,10 @@ void XHTMLInvoker::cancel(const std::string sendId) {
void XHTMLInvoker::invoke(const InvokeRequest& req) {
_invokeReq = req;
- HTTPServer::registerServlet(_interpreter->getName() + "/xhtml/" + req.invokeid, this);
-#if defined(__APPLE__) and defined(TARGET_OS_MAC)
+ HTTPServer::registerServlet(_interpreter->getName() + "/xhtml/" + req.invokeid + ".html", this);
+#if __APPLE__
+# if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+# else
// see http://stackoverflow.com/questions/4177744/c-osx-open-default-browser
CFURLRef url = CFURLCreateWithBytes (
NULL, // allocator
@@ -177,6 +201,7 @@ void XHTMLInvoker::invoke(const InvokeRequest& req) {
LSOpenCFURLRef(url,0);
CFRelease(url);
return;
+# endif
#endif
#ifdef _WIN32
// see http://support.microsoft.com/kb/224816