summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt28
-rw-r--r--README.md4
-rw-r--r--apps/samples/vrml/ffmpeg-server.invoked.scxml (renamed from apps/samples/vrml/ffmpeg-server.scxml)1
-rw-r--r--apps/samples/vrml/viewer.html5
-rw-r--r--apps/samples/vrml/viewer.js191
-rw-r--r--apps/samples/vrml/vrml-server.scxml20
-rw-r--r--apps/uscxml-browser.cpp17
-rw-r--r--config.h.in9
-rw-r--r--contrib/cmake/FindFFMPEG.cmake241
-rw-r--r--contrib/cmake/FindGLIB2.cmake237
-rw-r--r--contrib/cmake/FindLibPurple.cmake35
-rw-r--r--docs/Ubuntu-LTS.md46
-rw-r--r--src/uscxml/Factory.cpp11
-rw-r--r--src/uscxml/Interpreter.cpp2
-rw-r--r--src/uscxml/URL.cpp28
-rw-r--r--src/uscxml/URL.h4
-rw-r--r--src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp29
-rw-r--r--src/uscxml/concurrency/eventqueue/DelayedEventQueue.h8
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp39
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h2
-rw-r--r--src/uscxml/plugins/element/respond/RespondElement.cpp2
-rw-r--r--src/uscxml/plugins/invoker/CMakeLists.txt21
-rw-r--r--src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h3
-rw-r--r--src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp31
-rw-r--r--src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h2
-rw-r--r--src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp26
-rw-r--r--src/uscxml/plugins/invoker/im/IMInvoker.cpp361
-rw-r--r--src/uscxml/plugins/invoker/im/IMInvoker.h117
-rw-r--r--src/uscxml/plugins/invoker/sample/SampleInvoker.cpp1
-rw-r--r--src/uscxml/server/HTTPServer.cpp31
-rw-r--r--src/uscxml/server/HTTPServer.h1
-rw-r--r--test/CMakeLists.txt12
-rw-r--r--test/samples/uscxml/test-instant-messaging.scxml20
33 files changed, 1371 insertions, 214 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8a940d9..2921af0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,7 +11,7 @@ SET(BUILD_TYPE_HELP "Choose the type of build, options are: None(CMAKE_CXX_FLAGS
IF(DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING ${BUILD_TYPE_HELP})
ELSE()
- SET(CMAKE_BUILD_TYPE Debug CACHE STRING ${BUILD_TYPE_HELP})
+ SET(CMAKE_BUILD_TYPE Release CACHE STRING ${BUILD_TYPE_HELP})
ENDIF()
project(uscxml)
@@ -514,7 +514,7 @@ if (APPLE OR IOS)
endif()
-if (OFF AND APPLE OR IOS)
+if (APPLE OR IOS)
find_library(JSC_LIBRARY JavaScriptCore)
list (APPEND USCXML_OPT_LIBS ${JSC_LIBRARY})
set(JSC_FOUND ON)
@@ -566,6 +566,24 @@ if (LIBICAL_FOUND)
endif()
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_STATIC})
+set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SHARED})
+find_package(LibPurple)
+if (LIBPURPLE_FOUND)
+ find_package(ICONV)
+ find_package(GLIB2)
+ if (GLIB2_FOUND AND ICONV_FOUND)
+ include_directories (${LIBPURPLE_INCLUDE_DIR})
+ list (APPEND USCXML_OPT_LIBS ${LIBPURPLE_LIBRARY})
+ include_directories (${GLIB2_INCLUDE_DIRS})
+ list (APPEND USCXML_OPT_LIBS ${GLIB2_LIBRARIES})
+ include_directories (${ICONV_INCLUDE_DIR})
+ list (APPEND USCXML_OPT_LIBS ${ICONV_LIBRARIES})
+ else()
+ set(LIBPURPLE_FOUND OFF)
+ endif()
+endif()
+set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_STATIC})
+
if (WIN32)
find_package(UMUNDO COMPONENTS convenience)
@@ -770,6 +788,12 @@ else()
SET(PATH_SEPERATOR "/")
endif()
+if(CMAKE_BUILD_TYPE STREQUAL "Release")
+ set(CMAKE_BUILD_TYPE_RELEASE ON)
+elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ set(CMAKE_BUILD_TYPE_DEBUG ON)
+endif()
+
# enable config.h style compile time options and add as "uscxml/config.h"
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/uscxml/config.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/contrib/ctest/CTestCustom.ctest.in ${CMAKE_CURRENT_BINARY_DIR}/CTestCustom.ctest @ONCE)
diff --git a/README.md b/README.md
index c7557b6..71ef366 100644
--- a/README.md
+++ b/README.md
@@ -94,7 +94,7 @@ instructions](https://github.com/tklab-tud/uscxml/blob/master/docs/BUILDING.md).
In order to use the interpreter, you need to <tt>#include "uscxml/Interpreter.h"</tt> and instantiate
objects of <tt>uscxml::Interpreter</tt>.
-### Blocking Interpretation with SCXML from URL
+### Non-Blocking Interpretation with SCXML from URL
Interpreter scxml = Interpreter::fromURL("http://www.example.com/fancy.scxml");
scxml.start(); // non-blocking
@@ -108,7 +108,7 @@ This will perform a single iteration on the invoked components with a maximum of
or return immediately. You will have to call this method every now and then if you are using e.g. the
<tt>scenegraph</tt> invoker.
-### Non-Blocking Interpretation with inline SCXML
+### Blocking Interpretation with inline SCXML
Interpreter scxml = Interpreter::fromXML("<scxml><final id="exit"/></scxml>");
scxml.interpret(); // blocking
diff --git a/apps/samples/vrml/ffmpeg-server.scxml b/apps/samples/vrml/ffmpeg-server.invoked.scxml
index 1fd4038..bac0792 100644
--- a/apps/samples/vrml/ffmpeg-server.scxml
+++ b/apps/samples/vrml/ffmpeg-server.invoked.scxml
@@ -201,6 +201,7 @@
job.frames.push(frame);
}
}
+ job.totalFrames = job.frames.length;
requests[_event.origin] = {};
requests[_event.origin].job = job;
//]]>
diff --git a/apps/samples/vrml/viewer.html b/apps/samples/vrml/viewer.html
index 6e139e7..77bee0a 100644
--- a/apps/samples/vrml/viewer.html
+++ b/apps/samples/vrml/viewer.html
@@ -22,6 +22,11 @@
height:200px;
padding:7px;
}
+
+ .dijitMenuItemLabel {
+ font-size: 12px;
+ }
+
.tundra .dijitTooltipContainer {
background-color:rgba(200,200,200,0.5);
background:rgba(200,200,200,0.5);
diff --git a/apps/samples/vrml/viewer.js b/apps/samples/vrml/viewer.js
index 583f06f..a3f3b70 100644
--- a/apps/samples/vrml/viewer.js
+++ b/apps/samples/vrml/viewer.js
@@ -96,9 +96,10 @@ function VRMLViewer(element, params) {
codec !== "y41p" &&
codec !== "yuv4")
continue;
+ console.log(codec);
selectElem.options.push({ label: result.video[codec].longName, value: codec });
if (codec === "mpeg4")
- selectElem[selectElem.options.length - 1].selected = true;
+ selectElem.options[selectElem.options.length - 1].selected = true;
}
}
});
@@ -107,17 +108,26 @@ function VRMLViewer(element, params) {
this.refreshServer = function(server) {
self.serverURL = server;
self.localStorage.put("vrmlServer", self.serverURL, null);
-// self.progressElem.appendChild(self.progress.domNode);
-// self.progress.start();
+ if (self.fileStandby) { self.fileStandby.show(); }
self.xhr.get({
// The URL to request
url: server,
handleAs:"json",
headers:{"X-Requested-With":null},
+ error: function(result) {
+ if (self.browseButton) { self.browseButton.setAttribute('label', 'Browse'); }
+ if (self.fileStandby) { self.fileStandby.hide(); }
+ var allItems = self.fileStore.query();
+ for (var i = 0; i < allItems.total; i++) {
+ self.fileStore.remove(allItems[i].id);
+ }
+ },
load: function(result) {
-// self.progress.stop();
- for (id in self.fileStore.query) {
- self.fileStore.remove(id);
+ if (self.browseButton) { self.browseButton.setAttribute('label', 'Refresh'); }
+ if (self.fileStandby) { self.fileStandby.hide(); }
+ var allItems = self.fileStore.query();
+ for (var i = 0; i < allItems.total; i++) {
+ self.fileStore.remove(allItems[i].id);
}
(function fillstore(tree, parentId) {
for (key in tree) {
@@ -126,7 +136,7 @@ function VRMLViewer(element, params) {
} else {
self.fileStore.add({id:parentId+key, name:key, parent:parentId});
fillstore(tree[key], parentId+key);
- }
+ }
}
} (result.models, "root", ""));
}
@@ -172,7 +182,7 @@ function VRMLViewer(element, params) {
"dijit/Tree",
"dijit/form/TextBox",
"dijit/form/Button",
- "dojox/mobile/ProgressIndicator",
+ "dojox/widget/Standby",
"dijit/form/DropDownButton",
"dijit/TooltipDialog",
"dojo/dnd/Moveable",
@@ -192,7 +202,7 @@ function VRMLViewer(element, params) {
Tree,
TextBox,
Button,
- ProgressIndicator,
+ Standby,
DropDownButton,
TooltipDialog,
Moveable,
@@ -212,7 +222,6 @@ function VRMLViewer(element, params) {
self.element = element;
self.xhr = xhr;
- self.progress = new ProgressIndicator({size:40, center:false});
self.localStorage = dojox.storage.manager.getProvider();
self.localStorage.initialize();
@@ -286,9 +295,10 @@ function VRMLViewer(element, params) {
// fetch special dom nodes for content
self.messageBox = dojo.query("div.messages", element)[0];
self.imgElem = dojo.query("img.model", element)[0];
- self.filesDropDownElem = dojo.query("td.filesDropDown", element)[0];
- self.movieDropDownElem = dojo.query("div.movieDropDown", element)[0];
- self.movieAddButtonElem = dojo.query("button.movieAddButton", element)[0];
+
+ /**
+ * === POSE MANIPULATION AND RESET ====================
+ */
self.resetButtonElem = dojo.query("button.resetButton", element)[0];
self.progressElem = dojo.query("div.progress", element)[0];
@@ -407,6 +417,12 @@ function VRMLViewer(element, params) {
yLabel.innerHTML = 'Y:' + self.pose.y;
};
+ /**
+ * === FILES DROPDOWN ====================
+ */
+
+ self.filesDropDownElem = dojo.query("td.filesDropDown", element)[0];
+
self.createAvatar = function(item, mode) {
if (mode == 'avatar') {
// create your avatar if you want
@@ -480,6 +496,16 @@ function VRMLViewer(element, params) {
value: self.serverURL,
style: "width: 65%",
+ onKeyUp: function(e) {
+ if (self.browseButton) {
+ if (this.get("value") !== self.serverURL) {
+ self.browseButton.setAttribute('label', 'Browse');
+ } else {
+ self.browseButton.setAttribute('label', 'Refresh');
+ }
+ }
+ },
+
onKeyDown: function(e) {
var code = e.keyCode || e.which;
if( code === 13 ) {
@@ -506,15 +532,34 @@ function VRMLViewer(element, params) {
self.filesDropDown = new DropDownButton({ label: "Files", dropDown: self.filesToolTip });
self.filesDropDownElem.appendChild(self.filesDropDown.domNode);
- self.movieDropDownContent = domConst.toDom('<div style="overflow: auto; max-height: 420px;" />');
+ self.fileStandby = new Standby({target: self.filesDropDownContent });
+ self.filesDropDownContent.appendChild(self.fileStandby.domNode);
+ /**
+ * === MOVIE DROPDOWN ====================
+ */
+
+ self.movieDropDownElem = dojo.query("div.movieDropDown", element)[0];
+ self.movieAddButtonElem = dojo.query("button.movieAddButton", element)[0];
+
+ self.movieDropDownContent = domConst.toDom(
+ '<div style="overflow: auto; max-height: 420px;"> \
+ <table><tr class="movieFormatLengthRow" /></tr><tr class="movieWidthHeightLengthRow" /></table> \
+ <div class=\"dndArea\" /> \
+ </div>'
+ );
+
+ self.movieFormatLengthRowElem = dojo.query("tr.movieFormatLengthRow", self.movieDropDownContent)[0];
+ self.movieWidthHeightLengthRowElem = dojo.query("tr.movieWidthHeightLengthRow", self.movieDropDownContent)[0];
+ self.movieDnDArea = dojo.query("div.dndArea", self.movieDropDownContent)[0];
+
self.createMovieThumb = function(item, mode) {
if (mode == 'avatar') {
// when dragged
var avatar = dojo.create( 'div', { innerHTML: item.data });
var avatarPose = dojo.clone(self.pose);
- avatarPose.width=60;
- avatarPose.height=60;
+ avatarPose.width = 60;
+ avatarPose.height = 60;
var avatarImgUrl = urlSuffixForPose(avatarPose);
avatar.innerHTML = '<img src=' + self.imageURL + avatarImgUrl + ' /> ';
item.srcEcc = "VRMLViewer";
@@ -524,7 +569,6 @@ function VRMLViewer(element, params) {
item.pose = avatarPose;
return {node: avatar, data: item, type: item.type};
} else {
- // var thumb = dojo.create( 'div', { innerHTML: item.data });
// when added to list
var thumb = domConst.toDom("\
@@ -535,6 +579,7 @@ function VRMLViewer(element, params) {
</td><td align=\"left\">\
<table><tr>\
<td>Frame:</td><td><div class=\"relFrameLength\"/></td>\
+ <td><div class=\"fillInSeries\" \></td>\
</tr><tr>\
<td>Transition:</td><td><div class=\"relTransitionLength\"/></td>\
</tr></table>\
@@ -547,6 +592,23 @@ function VRMLViewer(element, params) {
var removeImgElem = dojo.query("img.removeThumb", thumb)[0];
var relFrameLengthElem = dojo.query("div.relFrameLength", thumb)[0];
var relTransitionLengthElem = dojo.query("div.relTransitionLength", thumb)[0];
+ var fillInSeriesElem = dojo.query("div.fillInSeries", thumb)[0];
+
+ item.getThisAndNeighborsFromDnD = function() {
+ var thisAndNeighbors = {};
+ self.addToMovieHandler.forInItems(function(obj, key, ctx) {
+ if (obj.data === item) {
+ thisAndNeighbors.this = { key: key, obj: obj };
+ } else {
+ thisAndNeighbors.before = { key: key, obj: obj };
+ }
+ if (thisAndNeighbors.this) {
+ thisAndNeighbors.after = { key: key, obj: obj };
+ return thisAndNeighbors;
+ }
+ });
+ return thisAndNeighbors;
+ };
item.relFrameLengthSlider = new HorizontalSlider({
value: 50,
@@ -555,21 +617,33 @@ function VRMLViewer(element, params) {
}, relFrameLengthElem);
item.relTransitionLengthSlider = new HorizontalSlider({
- value: 80,
+ value: 100,
title: "Relative Duration of Transition",
style: "width:150px;"
}, relTransitionLengthElem);
removeImgElem.onclick = function() {
- self.addToMovieHandler.forInItems(function(obj, key, ctx) {
- if (obj.data === item) {
- // haha - what a mess!
- self.addToMovieHandler.selectNone();
- self.addToMovieHandler.selection[key] = obj;
- self.addToMovieHandler.deleteSelectedNodes();
- }
- });
+ var thisItem = item.getThisAndNeighborsFromDnD();
+ if (thisItem.this) {
+ // haha - what a mess!
+ self.addToMovieHandler.selectNone();
+ self.addToMovieHandler.selection[thisItem.this.key] = thisItem.this.obj;
+ self.addToMovieHandler.deleteSelectedNodes();
+ }
+ // disable create button if this was the last one
+ if (!thisItem.after || !thisItem.before) {
+ self.movieCreateButton.setAttribute('disabled', true);
+ }
}
+
+ item.fillInSeriesButton = new Button({
+ label: "Insert Series",
+ style: "display: none;",
+ onClick: function(){
+ alert("foo");
+ }
+ }, fillInSeriesElem);
+
removeImgElem.src = self.resRoot + "img/close.png";
var thumbPose = dojo.clone(self.pose);
@@ -590,31 +664,18 @@ function VRMLViewer(element, params) {
}
};
- self.addToMovieHandler = new Source(self.movieDropDownContent, {copyOnly: true, creator: self.createMovieThumb});
+ self.addToMovieHandler = new Source(self.movieDnDArea, {copyOnly: true, creator: self.createMovieThumb});
self.movieFormatSelection = new Selector({
name: "movieFormat",
+ style: "width: 320px",
options: []
});
self.populateMovieCodecs(self.serverURL + '/movie/codecs', self.movieFormatSelection);
-
- self.movieDropDownContent.appendChild(dojo.create( 'div', {
- innerHTML: "Format: ",
- style: "margin-right: 1em; margin-left: 0.2em; display:inline;"
- }));
- self.movieDropDownContent.appendChild(self.movieFormatSelection.domNode);
- self.movieDurationSpinner = new NumberSpinner({
- value: 10,
- smallDelta: 1,
- style: "width: 40px",
- constraints: { min:0, places:0 },
- });
- self.movieDropDownContent.appendChild(self.movieDurationSpinner.domNode);
- self.movieDropDownContent.appendChild(dojo.create( 'div', {
- innerHTML: "sec ",
- style: "margin-right: 1em; margin-left: 0.2em; display:inline;"
- }));
+ self.movieFormatLengthRowElem.appendChild(dojo.create('td', { innerHTML: 'Format:'} ));
+ self.movieFormatLengthRowElem.appendChild(dojo.create('td', { colspan: "2"}));
+ self.movieFormatLengthRowElem.lastChild.appendChild(self.movieFormatSelection.domNode);
self.movieHeightSpinner = new NumberSpinner({
value: 400,
@@ -622,11 +683,6 @@ function VRMLViewer(element, params) {
style: "width: 60px",
constraints: { min:40, places:0 },
});
- self.movieDropDownContent.appendChild(self.movieHeightSpinner.domNode);
- self.movieDropDownContent.appendChild(dojo.create( 'div', {
- innerHTML: "x",
- style: "margin-right: 0.5em; margin-left: 0.5em; display:inline;"
- }));
self.movieWidthSpinner = new NumberSpinner({
value: 600,
@@ -634,11 +690,12 @@ function VRMLViewer(element, params) {
style: "width: 60px",
constraints: { min:40, places:0 },
});
- self.movieDropDownContent.appendChild(self.movieWidthSpinner.domNode);
self.movieCreateButton = new Button({
label: "Create",
+ disabled: true,
onClick: function(){
+
var form = document.createElement("form");
form.setAttribute("method", "post");
@@ -670,12 +727,39 @@ function VRMLViewer(element, params) {
form.appendChild(hiddenField);
+ // this will not save the returned binary file
+ // self.xhr.post({
+ // form: form,
+ // load: function(data){
+ // alert("asd");
+ // }
+ // });
+
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);
}
});
- self.movieDropDownContent.appendChild(self.movieCreateButton.domNode);
+
+ self.movieDurationSpinner = new NumberSpinner({
+ value: 10,
+ smallDelta: 1,
+ style: "width: 40px",
+ constraints: { min:0, places:0 },
+ });
+
+ // append format duration cell
+ self.movieWidthHeightLengthRowElem.appendChild(dojo.create('td', { innerHTML: 'Size:'} ));
+ var movieDimensionCell = dojo.create('td');
+ movieDimensionCell.appendChild(self.movieWidthSpinner.domNode);
+ movieDimensionCell.appendChild(dojo.create('span', { innerHTML: "x"} ));
+ movieDimensionCell.appendChild(self.movieHeightSpinner.domNode);
+ movieDimensionCell.appendChild(self.movieDurationSpinner.domNode);
+ movieDimensionCell.appendChild(dojo.create('span', { innerHTML: "sec"} ));
+ self.movieWidthHeightLengthRowElem.appendChild(movieDimensionCell);
+
+ self.movieWidthHeightLengthRowElem.appendChild(dojo.create('td', { align: "right"}));
+ self.movieWidthHeightLengthRowElem.lastChild.appendChild(self.movieCreateButton.domNode);
self.movieToolTip = new TooltipDialog({ content:self.movieDropDownContent });
@@ -689,8 +773,13 @@ function VRMLViewer(element, params) {
label: "+",
style: "margin-left: -10px; display: none;",
onClick: function(){
+ if (self.movieFormatSelection.options.length == 0) {
+ self.populateMovieCodecs(self.serverURL + '/movie/codecs', self.movieFormatSelection);
+ }
// we could pass item.data here to creator
self.addToMovieHandler.insertNodes(false, [ { } ]);
+ self.movieCreateButton.setAttribute('disabled', false);
+
}
}, self.movieAddButtonElem);
diff --git a/apps/samples/vrml/vrml-server.scxml b/apps/samples/vrml/vrml-server.scxml
index 20d63a6..5ee28dd 100644
--- a/apps/samples/vrml/vrml-server.scxml
+++ b/apps/samples/vrml/vrml-server.scxml
@@ -129,13 +129,12 @@
<!-- Called for every file we found -->
<finalize>
<script>
-
var key = keyForFile(_event.data.file);
// this is a binary 3D file converted from the wrls
if (_event.name === "file.deleted") {
delete models[key];
- print("Removed a vanished osgb file at " + _event.fileStruct.key + "\n");
+ print("Removed a vanished osgb file at " + key + "\n");
} else {
models[key] = _event.data.file;
models[key].group = '/' + _event.data.file.name.split(pathDelim).slice(0,-1).join('/');
@@ -155,14 +154,20 @@
_event.key = keyForFile(_event.data.file);
if (_event.name === "file.existing" || _event.name === "file.added") {
wrls[_event.key] = _event.data.file;
- print("Inserting wrl " + _event.data.file.path + " from " +_event.data.file.relDir + " at " + _event.key + "\n");
+ var dirMonFile = _event.data.file.relDir.substr(1) + _event.data.file.strippedName + ".osgb"
+ // we already procressed this file
+ if (_invokers['dirmon.processed'].file[dirMonFile]) {
+ models[_event.key] = _event.data.file;
+ }
+ print("Inserting wrl " + _event.data.file.path + " from " + _event.data.file.relDir + " at " + _event.key + "\n");
}
if (_event.name === "file.deleted") {
delete wrls[_event.key];
- print("Deleting wrl " + _event.data.file.path + " from " +_event.data.file.relDir + " at " + _event.key + "\n");
+ delete models[_event.key];
+ print("Deleting wrl " + _event.data.file.path + " from " + _event.data.file.relDir + " at " + _event.key + "\n");
}
</script>
- <if cond="models &amp;&amp;
+ <if cond="models &amp;&amp; _event.name !== 'file.deleted' &amp;&amp;
(!(_event.key in models) || wrls[_event.key].mtime > models[_event.key].mtime)">
<send target="#_osgvonvert.osgb">
<param name="source" expr="_event.data.file.path" />
@@ -186,6 +191,7 @@
<header name="Connection" value="close" />
<header name="Content-Type" value="application/json" />
<header name="Access-Control-Allow-Origin" value="*" />
+ <header name="Content-Type" valueexpr="_event.data.mimetype" />
<content expr="_event.data.content[_event.data.format]" />
</respond>
<else />
@@ -198,7 +204,7 @@
</invoke>
<!-- Start a nested SCXML interpreter to create movies from the images -->
- <invoke type="scxml" id="scxml.ffmpeg" src="ffmpeg-server.scxml" autoforward="true">
+ <invoke type="scxml" id="scxml.ffmpeg" src="ffmpeg-server.invoked.scxml" autoforward="true">
<param name="modelDir" expr="_x['args']['tmp-path']" />
</invoke>
@@ -209,12 +215,14 @@
_event.data.pathComponent[_event.data.pathComponent.length - 1].indexOf('.') !== -1">
<!-- request for a specific format http://host/vrml/relative/path/format?query=string -->
<script>
+ //dump(_invokers['dirmon.vrml']);
_event.fileStruct = reqToStruct(_event.data);
</script>
<if cond="_event.fileStruct.key in models &amp;&amp; isSupportedFormat(_event['fileStruct'].ext)">
<!-- There is such a file available as osgb -->
<send target="#_osgvonvert.osgb">
<param name="source" expr="models[_event['fileStruct'].key].path" />
+ <param name="format" expr="_event['fileStruct'].ext" />
<param name="pitch" expr="_event.fileStruct.pitch" />
<param name="roll" expr="_event.fileStruct.roll" />
<param name="yaw" expr="_event.fileStruct.yaw" />
diff --git a/apps/uscxml-browser.cpp b/apps/uscxml-browser.cpp
index 34cf47a..fa108f8 100644
--- a/apps/uscxml-browser.cpp
+++ b/apps/uscxml-browser.cpp
@@ -39,6 +39,7 @@ class VerboseMonitor : public uscxml::InterpreterMonitor {
}
};
+#ifdef CMAKE_BUILD_TYPE_DEBUG
#ifdef HAS_EXECINFO_H
void printBacktrace(void** array, int size) {
@@ -105,6 +106,7 @@ void customTerminate() {
#endif
abort();
}
+#endif
void printUsageAndExit() {
printf("uscxml-browser version " USCXML_VERSION " (" CMAKE_BUILD_TYPE " build - " CMAKE_COMPILER_STRING ")\n");
@@ -126,22 +128,25 @@ void printUsageAndExit() {
int main(int argc, char** argv) {
using namespace uscxml;
- std::set_terminate(customTerminate);
-
#if defined(HAS_SIGNAL_H) && !defined(WIN32)
signal(SIGPIPE, SIG_IGN);
#endif
+#ifdef CMAKE_BUILD_TYPE_DEBUG
+ std::set_terminate(customTerminate);
+#endif
+
if (argc < 2) {
printUsageAndExit();
}
bool verbose = false;
bool useDot = false;
+ bool glogIsInitialized = false;
size_t port = 8080;
- google::InitGoogleLogging(argv[0]);
+
google::LogToStderr();
-
+
#ifndef _WIN32
opterr = 0;
#endif
@@ -150,6 +155,7 @@ int main(int argc, char** argv) {
switch(option) {
case 'l':
google::InitGoogleLogging(optarg);
+ glogIsInitialized = true;
break;
case 'e':
uscxml::Factory::pluginPath = optarg;
@@ -171,6 +177,9 @@ int main(int argc, char** argv) {
}
}
+ if (!glogIsInitialized)
+ google::InitGoogleLogging(argv[0]);
+
// for (int i = 0; i < argc; i++)
// std::cout << argv[i] << std::endl;
// std::cout << optind << std::endl;
diff --git a/config.h.in b/config.h.in
index af772c6..93e4e4a 100644
--- a/config.h.in
+++ b/config.h.in
@@ -29,12 +29,6 @@
#cmakedefine PATH_SEPERATOR '@PATH_SEPERATOR@'
-/** Loglevels */
-#cmakedefine LOGLEVEL_COMMON @LOGLEVEL_COMMON@
-#cmakedefine LOGLEVEL_DISC @LOGLEVEL_DISC@
-#cmakedefine LOGLEVEL_NET @LOGLEVEL_NET@
-#cmakedefine LOGLEVEL_S11N @LOGLEVEL_S11N@
-
/** version */
#cmakedefine USCXML_VERSION_MAJOR "@USCXML_VERSION_MAJOR@"
#cmakedefine USCXML_VERSION_MINOR "@USCXML_VERSION_MINOR@"
@@ -43,6 +37,8 @@
/** build type */
#cmakedefine CMAKE_BUILD_TYPE "@CMAKE_BUILD_TYPE@"
+#cmakedefine CMAKE_BUILD_TYPE_DEBUG
+#cmakedefine CMAKE_BUILD_TYPE_RELEASE
#cmakedefine CMAKE_COMPILER_STRING "@CMAKE_COMPILER_STRING@"
/** miscellaneous */
@@ -69,6 +65,7 @@
#cmakedefine OPENSCENEGRAPH_FOUND
#cmakedefine PROTOBUF_FOUND
#cmakedefine CORELOCATION_FOUND
+#cmakedefine LIBPURPLE_FOUND
/** Header files we found */
#cmakedefine HAS_UNISTD_H
diff --git a/contrib/cmake/FindFFMPEG.cmake b/contrib/cmake/FindFFMPEG.cmake
index 397bcba..5f64790 100644
--- a/contrib/cmake/FindFFMPEG.cmake
+++ b/contrib/cmake/FindFFMPEG.cmake
@@ -1,93 +1,164 @@
-# - Try to find ffmpeg libraries (libavcodec, libavformat and libavutil)
-# Once done this will define
+# Locate ffmpeg
+# This module defines
+# FFMPEG_LIBRARIES
+# FFMPEG_FOUND, if false, do not try to link to ffmpeg
+# FFMPEG_INCLUDE_DIR, where to find the headers
#
-# FFMPEG_FOUND - system has ffmpeg or libav
-# FFMPEG_INCLUDE_DIR - the ffmpeg include directory
-# FFMPEG_LIBRARIES - Link these to use ffmpeg
-# FFMPEG_LIBAVCODEC
-# FFMPEG_LIBAVFORMAT
-# FFMPEG_LIBAVUTIL
-#
-# Copyright (c) 2008 Andreas Schneider <mail@cynapses.org>
-# Modified for other libraries by Lasse Kärkkäinen <tronic>
-# Modified for Hedgewars by Stepik777
-#
-# Redistribution and use is allowed according to the terms of the New
-# BSD license.
+# $FFMPEG_DIR is an environment variable that would
+# correspond to the ./configure --prefix=$FFMPEG_DIR
#
+# Created by Robert Osfield.
+
+
+#In ffmpeg code, old version use "#include <header.h>" and newer use "#include <libname/header.h>"
+#In OSG ffmpeg plugin, we used "#include <header.h>" for compatibility with old version of ffmpeg
+#With the new version of FFmpeg, a file named "time.h" was added that breaks compatability with the old version of ffmpeg.
+
+#We have to search the path which contain the header.h (usefull for old version)
+#and search the path which contain the libname/header.h (usefull for new version)
+
+#Then we need to include ${FFMPEG_libname_INCLUDE_DIRS} (in old version case, use by ffmpeg header and osg plugin code)
+# (in new version case, use by ffmpeg header)
+#and ${FFMPEG_libname_INCLUDE_DIRS/libname} (in new version case, use by osg plugin code)
+
+
+# Macro to find header and lib directories
+# example: FFMPEG_FIND(AVFORMAT avformat avformat.h)
+MACRO(FFMPEG_FIND varname shortname headername)
+ # old version of ffmpeg put header in $prefix/include/[ffmpeg]
+ # so try to find header in include directory
-if (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)
- # in cache already
- set(FFMPEG_FOUND TRUE)
-else (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)
- # use pkg-config to get the directories and then use these values
- # in the FIND_PATH() and FIND_LIBRARY() calls
- find_package(PkgConfig)
- if (PKG_CONFIG_FOUND)
- pkg_check_modules(_FFMPEG_AVCODEC libavcodec)
- pkg_check_modules(_FFMPEG_AVFORMAT libavformat)
- pkg_check_modules(_FFMPEG_AVUTIL libavutil)
- pkg_check_modules(_FFMPEG_SWSCALE libswscale)
-# pkg_check_modules(_FFMPEG_SWRESAMPLE libswresample)
- endif (PKG_CONFIG_FOUND)
-
- find_path(FFMPEG_AVCODEC_INCLUDE_DIR
- NAMES libavcodec/avcodec.h
- PATHS ${_FFMPEG_AVCODEC_INCLUDE_DIRS} /usr/include /usr/local/include /opt/local/include /sw/include
- PATH_SUFFIXES ffmpeg libav
- )
-
- find_library(FFMPEG_LIBAVCODEC
- NAMES avcodec
- PATHS ${_FFMPEG_AVCODEC_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib
- )
-
- find_library(FFMPEG_LIBAVFORMAT
- NAMES avformat
- PATHS ${_FFMPEG_AVFORMAT_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib
- )
-
- find_library(FFMPEG_LIBAVUTIL
- NAMES avutil
- PATHS ${_FFMPEG_AVUTIL_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib
- )
-
- find_library(FFMPEG_LIBSWSCALE
- NAMES swscale
- PATHS ${_FFMPEG_SWSCALE_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib
- )
-
- # find_library(FFMPEG_SWRESAMPLE
- # NAMES swresample
- # PATHS ${_FFMPEG_SWRESAMPLE_LIBRARY_DIRS} /usr/lib /usr/local/lib /opt/local/lib /sw/lib
- # )
-
- if (FFMPEG_LIBAVCODEC AND FFMPEG_LIBAVFORMAT)
- set(FFMPEG_FOUND TRUE)
- endif()
-
- if (FFMPEG_FOUND)
- set(FFMPEG_INCLUDE_DIR ${FFMPEG_AVCODEC_INCLUDE_DIR})
-
- set(FFMPEG_LIBRARIES
- ${FFMPEG_LIBAVCODEC}
- ${FFMPEG_LIBAVFORMAT}
- ${FFMPEG_LIBAVUTIL}
- ${FFMPEG_LIBSWSCALE}
-# ${FFMPEG_SWRESAMPLE}
+ FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS lib${shortname}/${headername}
+ PATHS
+ ${FFMPEG_ROOT}/include
+ $ENV{FFMPEG_DIR}/include
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local/include
+ /usr/include
+ /sw/include # Fink
+ /opt/local/include # DarwinPorts
+ /opt/csw/include # Blastwave
+ /opt/include
+ /usr/freeware/include
+ PATH_SUFFIXES ffmpeg
+ DOC "Location of FFMPEG Headers"
)
- endif (FFMPEG_FOUND)
+ FIND_PATH(FFMPEG_${varname}_INCLUDE_DIRS ${headername}
+ PATHS
+ ${FFMPEG_ROOT}/include
+ $ENV{FFMPEG_DIR}/include
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local/include
+ /usr/include
+ /sw/include # Fink
+ /opt/local/include # DarwinPorts
+ /opt/csw/include # Blastwave
+ /opt/include
+ /usr/freeware/include
+ PATH_SUFFIXES ffmpeg
+ DOC "Location of FFMPEG Headers"
+ )
+
+ FIND_LIBRARY(FFMPEG_${varname}_LIBRARIES
+ NAMES ${shortname}
+ PATHS
+ ${FFMPEG_ROOT}/lib
+ $ENV{FFMPEG_DIR}/lib
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local/lib
+ /usr/local/lib64
+ /usr/lib
+ /usr/lib64
+ /sw/lib
+ /opt/local/lib
+ /opt/csw/lib
+ /opt/lib
+ /usr/freeware/lib64
+ DOC "Location of FFMPEG Libraries"
+ )
+
+ IF (FFMPEG_${varname}_LIBRARIES AND FFMPEG_${varname}_INCLUDE_DIRS)
+ SET(FFMPEG_${varname}_FOUND 1)
+ ENDIF(FFMPEG_${varname}_LIBRARIES AND FFMPEG_${varname}_INCLUDE_DIRS)
+
+ENDMACRO(FFMPEG_FIND)
+
+SET(FFMPEG_ROOT "$ENV{FFMPEG_DIR}" CACHE PATH "Location of FFMPEG")
+
+# find stdint.h
+IF(WIN32)
+
+ FIND_PATH(FFMPEG_STDINT_INCLUDE_DIR stdint.h
+ PATHS
+ ${FFMPEG_ROOT}/include
+ $ENV{FFMPEG_DIR}/include
+ ~/Library/Frameworks
+ /Library/Frameworks
+ /usr/local/include
+ /usr/include
+ /sw/include # Fink
+ /opt/local/include # DarwinPorts
+ /opt/csw/include # Blastwave
+ /opt/include
+ /usr/freeware/include
+ PATH_SUFFIXES ffmpeg
+ DOC "Location of FFMPEG stdint.h Header"
+ )
+
+ IF (FFMPEG_STDINT_INCLUDE_DIR)
+ SET(STDINT_OK TRUE)
+ ENDIF()
+
+ELSE()
+
+ SET(STDINT_OK TRUE)
+
+ENDIF()
+
+FFMPEG_FIND(LIBAVFORMAT avformat avformat.h)
+FFMPEG_FIND(LIBAVDEVICE avdevice avdevice.h)
+FFMPEG_FIND(LIBAVCODEC avcodec avcodec.h)
+FFMPEG_FIND(LIBAVUTIL avutil avutil.h)
+FFMPEG_FIND(LIBSWSCALE swscale swscale.h) # not sure about the header to look for here.
+
+SET(FFMPEG_FOUND "NO")
+# Note we don't check FFMPEG_LIBSWSCALE_FOUND here, it's optional.
+IF (FFMPEG_LIBAVFORMAT_FOUND AND FFMPEG_LIBAVDEVICE_FOUND AND FFMPEG_LIBAVCODEC_FOUND AND FFMPEG_LIBAVUTIL_FOUND AND FFMPEG_LIBSWSCALE_FOUND AND STDINT_OK)
+
+ SET(FFMPEG_FOUND "YES")
+
+ SET(FFMPEG_INCLUDE_DIRS
+ ${FFMPEG_LIBAVFORMAT_INCLUDE_DIRS}
+ ${FFMPEG_LIBAVDEVICE_INCLUDE_DIRS}
+ ${FFMPEG_LIBAVCODEC_INCLUDE_DIRS}
+ ${FFMPEG_LIBAVUTIL_INCLUDE_DIRS}
+ )
+
+# Using the new include style for FFmpeg prevents issues with #include <time.h>
+ IF (FFMPEG_STDINT_INCLUDE_DIR)
+ SET(FFMPEG_INCLUDE_DIRS
+ ${FFMPEG_INCLUDE_DIRS}
+ ${FFMPEG_STDINT_INCLUDE_DIR}
+ )
+ ENDIF()
+
+
+ SET(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBAVFORMAT_LIBRARY_DIRS})
- if (FFMPEG_FOUND)
- if (NOT FFMPEG_FIND_QUIETLY)
- message(STATUS "Found FFMPEG or Libav: ${FFMPEG_LIBRARIES}, ${FFMPEG_INCLUDE_DIR}")
- endif (NOT FFMPEG_FIND_QUIETLY)
- else (FFMPEG_FOUND)
- if (FFMPEG_FIND_REQUIRED)
- message(FATAL_ERROR "Could not find libavcodec or libavformat or libavutil")
- endif (FFMPEG_FIND_REQUIRED)
- endif (FFMPEG_FOUND)
+ # Note we don't add FFMPEG_LIBSWSCALE_LIBRARIES here, it will be added if found later.
+ SET(FFMPEG_LIBRARIES
+ ${FFMPEG_LIBAVFORMAT_LIBRARIES}
+ ${FFMPEG_LIBSWSCALE_LIBRARIES}
+ ${FFMPEG_LIBAVDEVICE_LIBRARIES}
+ ${FFMPEG_LIBAVCODEC_LIBRARIES}
+ ${FFMPEG_LIBAVUTIL_LIBRARIES})
-endif (FFMPEG_LIBRARIES AND FFMPEG_INCLUDE_DIR)
+ENDIF()
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(FFMPEG DEFAULT_MSG FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
+MARK_AS_ADVANCED(FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIR)
diff --git a/contrib/cmake/FindGLIB2.cmake b/contrib/cmake/FindGLIB2.cmake
new file mode 100644
index 0000000..e62d843
--- /dev/null
+++ b/contrib/cmake/FindGLIB2.cmake
@@ -0,0 +1,237 @@
+# - Try to find GLib2
+# Once done this will define
+#
+# GLIB2_FOUND - system has GLib2
+# GLIB2_INCLUDE_DIRS - the GLib2 include directory
+# GLIB2_LIBRARIES - Link these to use GLib2
+#
+# HAVE_GLIB_GREGEX_H glib has gregex.h header and
+# supports g_regex_match_simple
+#
+# Copyright (c) 2006 Andreas Schneider <mail@cynapses.org>
+# Copyright (c) 2006 Philippe Bernery <philippe.bernery@gmail.com>
+# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
+# Copyright (c) 2007 Alban Browaeys <prahal@yahoo.com>
+# Copyright (c) 2008 Michael Bell <michael.bell@web.de>
+# Copyright (c) 2008-2009 Bjoern Ricks <bjoern.ricks@googlemail.com>
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+
+IF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
+ # in cache already
+ SET(GLIB2_FOUND TRUE)
+ELSE (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS )
+
+ if (NOT APPLE)
+ INCLUDE(FindPkgConfig)
+
+ ## Glib
+ IF ( GLIB2_FIND_REQUIRED )
+ SET( _pkgconfig_REQUIRED "REQUIRED" )
+ ELSE ( GLIB2_FIND_REQUIRED )
+ SET( _pkgconfig_REQUIRED "" )
+ ENDIF ( GLIB2_FIND_REQUIRED )
+
+ IF ( GLIB2_MIN_VERSION )
+ PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0>=${GLIB2_MIN_VERSION} )
+ ELSE ( GLIB2_MIN_VERSION )
+ PKG_SEARCH_MODULE( GLIB2 ${_pkgconfig_REQUIRED} glib-2.0 )
+ ENDIF ( GLIB2_MIN_VERSION )
+ IF ( PKG_CONFIG_FOUND )
+ IF ( GLIB2_FOUND )
+ SET ( GLIB2_CORE_FOUND TRUE )
+ ELSE ( GLIB2_FOUND )
+ SET ( GLIB2_CORE_FOUND FALSE )
+ ENDIF ( GLIB2_FOUND )
+ ENDIF ( PKG_CONFIG_FOUND )
+ endif()
+
+ # Look for glib2 include dir and libraries w/o pkgconfig
+ IF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND OR APPLE )
+ FIND_PATH(
+ _glibconfig_include_DIR
+ NAMES
+ glibconfig.h
+ PATHS
+ /opt/gnome/lib64
+ /opt/gnome/lib
+ /opt/lib/
+ /opt/local/lib
+ /sw/lib/
+ /usr/lib64
+ /usr/lib
+ /usr/local/include
+ ${CMAKE_LIBRARY_PATH}
+ PATH_SUFFIXES
+ glib-2.0/include
+ )
+
+ FIND_PATH(
+ _glib2_include_DIR
+ NAMES
+ glib.h
+ PATHS
+ /opt/gnome/include
+ /opt/local/include
+ /sw/include
+ /usr/include
+ /usr/local/include
+ PATH_SUFFIXES
+ glib-2.0
+ )
+
+ #MESSAGE(STATUS "Glib headers: ${_glib2_include_DIR}")
+
+ FIND_LIBRARY(
+ _glib2_link_DIR
+ NAMES
+ glib-2.0
+ glib
+ PATHS
+ /opt/gnome/lib
+ /opt/local/lib
+ /sw/lib
+ /usr/lib
+ /usr/local/lib
+ )
+ IF ( _glib2_include_DIR AND _glib2_link_DIR )
+ SET ( _glib2_FOUND TRUE )
+ ENDIF ( _glib2_include_DIR AND _glib2_link_DIR )
+
+
+ IF ( _glib2_FOUND )
+ SET ( GLIB2_INCLUDE_DIRS ${_glib2_include_DIR} ${_glibconfig_include_DIR} )
+ SET ( GLIB2_LIBRARIES ${_glib2_link_DIR} )
+ SET ( GLIB2_CORE_FOUND TRUE )
+ ELSE ( _glib2_FOUND )
+ SET ( GLIB2_CORE_FOUND FALSE )
+ ENDIF ( _glib2_FOUND )
+
+ # Handle dependencies
+ # libintl
+ IF ( NOT LIBINTL_FOUND )
+ FIND_PATH(LIBINTL_INCLUDE_DIR
+ NAMES
+ libintl.h
+ PATHS
+ /opt/gnome/include
+ /opt/local/include
+ /sw/include
+ /usr/include
+ /usr/local/include
+ )
+
+ FIND_LIBRARY(LIBINTL_LIBRARY
+ NAMES
+ intl
+ PATHS
+ /opt/gnome/lib
+ /opt/local/lib
+ /sw/lib
+ /usr/local/lib
+ /usr/lib
+ )
+
+ IF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
+ SET (LIBINTL_FOUND TRUE)
+ ENDIF (LIBINTL_LIBRARY AND LIBINTL_INCLUDE_DIR)
+ ENDIF ( NOT LIBINTL_FOUND )
+
+ # libiconv
+ IF ( NOT LIBICONV_FOUND )
+ FIND_PATH(LIBICONV_INCLUDE_DIR
+ NAMES
+ iconv.h
+ PATHS
+ /opt/gnome/include
+ /opt/local/include
+ /opt/local/include
+ /sw/include
+ /sw/include
+ /usr/local/include
+ /usr/include
+ PATH_SUFFIXES
+ glib-2.0
+ )
+
+ FIND_LIBRARY(LIBICONV_LIBRARY
+ NAMES
+ iconv
+ PATHS
+ /opt/gnome/lib
+ /opt/local/lib
+ /sw/lib
+ /usr/lib
+ /usr/local/lib
+ )
+
+ IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+ SET (LIBICONV_FOUND TRUE)
+ ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+ ENDIF ( NOT LIBICONV_FOUND )
+
+ IF (LIBINTL_FOUND)
+ SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBINTL_LIBRARY})
+ SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBINTL_INCLUDE_DIR})
+ ENDIF (LIBINTL_FOUND)
+
+ IF (LIBICONV_FOUND)
+ SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
+ SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
+ ENDIF (LIBICONV_FOUND)
+
+ ENDIF ( NOT GLIB2_FOUND AND NOT PKG_CONFIG_FOUND OR APPLE )
+ ##
+
+ IF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
+ SET (GLIB2_FOUND TRUE)
+ ENDIF (GLIB2_CORE_FOUND AND GLIB2_INCLUDE_DIRS AND GLIB2_LIBRARIES)
+
+ IF (GLIB2_FOUND)
+ IF (NOT GLIB2_FIND_QUIETLY)
+ MESSAGE (STATUS "Found GLib2: ${GLIB2_LIBRARIES} ${GLIB2_INCLUDE_DIRS}")
+ ENDIF (NOT GLIB2_FIND_QUIETLY)
+ ELSE (GLIB2_FOUND)
+ IF (GLIB2_FIND_REQUIRED)
+ MESSAGE (SEND_ERROR "Could not find GLib2")
+ ENDIF (GLIB2_FIND_REQUIRED)
+ ENDIF (GLIB2_FOUND)
+
+ # show the GLIB2_INCLUDE_DIRS and GLIB2_LIBRARIES variables only in the advanced view
+ MARK_AS_ADVANCED(GLIB2_INCLUDE_DIRS GLIB2_LIBRARIES)
+ MARK_AS_ADVANCED(LIBICONV_INCLUDE_DIR LIBICONV_LIBRARY)
+ MARK_AS_ADVANCED(LIBINTL_INCLUDE_DIR LIBINTL_LIBRARY)
+
+ENDIF (GLIB2_LIBRARIES AND GLIB2_INCLUDE_DIRS)
+
+IF ( WIN32 )
+ # include libiconv for win32
+ IF ( NOT LIBICONV_FOUND )
+ FIND_PATH(LIBICONV_INCLUDE_DIR iconv.h PATH_SUFFIXES glib-2.0)
+
+ FIND_LIBRARY(LIBICONV_LIBRARY NAMES iconv)
+
+ IF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+ SET (LIBICONV_FOUND TRUE)
+ ENDIF (LIBICONV_LIBRARY AND LIBICONV_INCLUDE_DIR)
+ ENDIF ( NOT LIBICONV_FOUND )
+ IF (LIBICONV_FOUND)
+ SET (GLIB2_LIBRARIES ${GLIB2_LIBRARIES} ${LIBICONV_LIBRARY})
+ SET (GLIB2_INCLUDE_DIRS ${GLIB2_INCLUDE_DIRS} ${LIBICONV_INCLUDE_DIR})
+ ENDIF (LIBICONV_FOUND)
+ENDIF ( WIN32 )
+
+IF ( GLIB2_FOUND )
+ # Check if system has a newer version of glib
+ # which supports g_regex_match_simple
+ INCLUDE( CheckIncludeFiles )
+ SET( CMAKE_REQUIRED_INCLUDES ${GLIB2_INCLUDE_DIRS} )
+ CHECK_INCLUDE_FILES ( glib/gregex.h HAVE_GLIB_GREGEX_H )
+ CHECK_INCLUDE_FILES ( glib/gchecksum.h HAVE_GLIB_GCHECKSUM_H )
+ # Reset CMAKE_REQUIRED_INCLUDES
+ SET( CMAKE_REQUIRED_INCLUDES "" )
+ENDIF( GLIB2_FOUND ) \ No newline at end of file
diff --git a/contrib/cmake/FindLibPurple.cmake b/contrib/cmake/FindLibPurple.cmake
new file mode 100644
index 0000000..fd9b3bc
--- /dev/null
+++ b/contrib/cmake/FindLibPurple.cmake
@@ -0,0 +1,35 @@
+FIND_PATH(LIBPURPLE_INCLUDE_DIR purple.h
+ PATH_SUFFIXES include/libpurple src/libpurple
+ PATHS
+ /usr/local
+ /usr
+ /sw # Fink
+ /opt/local # DarwinPorts
+ /opt/csw # Blastwave
+ /opt
+)
+
+FIND_LIBRARY(LIBPURPLE_LIBRARY_RELEASE
+ NAMES purple libpurple libpurple-static
+)
+if (LIBPURPLE_LIBRARY_RELEASE)
+ list(APPEND LIBPURPLE_LIBRARY optimized ${LIBPURPLE_LIBRARY_RELEASE})
+endif()
+
+FIND_LIBRARY(LIBPURPLE_LIBRARY_DEBUG
+ NAMES purple_d libpurple_d libpurple-static_d
+)
+if (LIBPURPLE_LIBRARY_DEBUG)
+ list(APPEND LIBPURPLE_LIBRARY debug ${LIBPURPLE_LIBRARY_DEBUG})
+else()
+ if (UNIX)
+ list(APPEND LIBPURPLE_LIBRARY debug ${LIBPURPLE_LIBRARY_RELEASE})
+ endif()
+endif()
+
+# message("LIBPURPLE_LIBRARY: ${LIBPURPLE_LIBRARY}")
+# message("LIBPURPLE_INCLUDE_DIR: ${LIBPURPLE_INCLUDE_DIR}")
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPURPLE DEFAULT_MSG LIBPURPLE_LIBRARY LIBPURPLE_INCLUDE_DIR)
+MARK_AS_ADVANCED(LIBPURPLE_LIBRARY LIBPURPLE_INCLUDE_DIR)
diff --git a/docs/Ubuntu-LTS.md b/docs/Ubuntu-LTS.md
new file mode 100644
index 0000000..15e58cc
--- /dev/null
+++ b/docs/Ubuntu-LTS.md
@@ -0,0 +1,46 @@
+Install Ubuntu LTS 12
+
+For core functionality without fancy plugins:
+
+$ sudo apt-get install cmake
+$ sudo apt-get install build-essential
+$ sudo apt-get install libxml2-dev
+$ sudo apt-get install libcurl4-openssl-dev
+
+For OpenSceneGraph invoker (version in repositories lacks vrml plugin):
+
+$ sudo apt-get install libpng12-dev
+$ sudo apt-get install libjpeg-dev
+$ sudo apt-get install libboost-all-dev
+$ sudo apt-get install libltdl-dev
+$ sudo apt-get install libopenscenegraph-dev # just for the dependencies
+$ sudo apt-get remove libopenscenegraph-dev
+
+$ wget http://sourceforge.net/projects/openvrml/files/latest/download
+$ tar xvjf openvrml*
+$ cd openvrml*
+$ ./configure --disable-render-text-node --disable-script-node-javascript --disable-script-node-java --disable-gl-renderer --disable-xembed --disable-player --disable-examples --disable-mozilla-plugin
+$ sudo make install
+$ cd ..
+
+$ sudo apt-get install git
+$ git clone https://github.com/openscenegraph/osg
+$ cd osg
+$ nano src/osgPlugins/vrml/IndexedFaceSet.cpp # Edit line 207 and remove the else block
+
+$ mkdir build && cd build
+$ cmake ..
+$ make -j4
+$ sudo make install
+
+For ffmpeg invoker:
+
+Follow http://ffmpeg.org/trac/ffmpeg/wiki/UbuntuCompilationGuide for a version of recent version of ffmpeg
+on ubuntu. The various libav* packages that come with the distribution are inadequate.
+
+Install uscxml:
+$ git clone https://github.com/tklab-tud/uscxml.git
+$ cd uscxml
+$ mkdir build && cd build
+$ cmake ..
+$ make \ No newline at end of file
diff --git a/src/uscxml/Factory.cpp b/src/uscxml/Factory.cpp
index 643c358..ae7af11 100644
--- a/src/uscxml/Factory.cpp
+++ b/src/uscxml/Factory.cpp
@@ -49,6 +49,10 @@
# include "uscxml/plugins/invoker/calendar/CalendarInvoker.h"
# endif
+# ifdef LIBPURPLE_FOUND
+# include "uscxml/plugins/invoker/im/IMInvoker.h"
+# endif
+
#ifdef OPENAL_FOUND
# include "uscxml/plugins/invoker/audio/OpenALInvoker.h"
#endif
@@ -168,6 +172,13 @@ Factory::Factory() {
}
#endif
+#ifdef LIBPURPLE_FOUND
+ {
+ IMInvoker* invoker = new IMInvoker();
+ registerInvoker(invoker);
+ }
+#endif
+
#if (defined OPENAL_FOUND && (defined LIBSNDFILE_FOUND || defined AUDIOTOOLBOX_FOUND))
{
OpenALInvoker* invoker = new OpenALInvoker();
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 3946bef..7e61ed7 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -905,7 +905,7 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) {
}
if (_dataModel) {
try {
- _dataModel.assign("_invokers['" + invokeReq.invokeid + "']", invoker.getDataModelVariables());
+// _dataModel.assign("_invokers['" + invokeReq.invokeid + "']", invoker.getDataModelVariables());
} catch(...) {
LOG(ERROR) << "Exception caught while assigning datamodel variables from invoker " << invokeReq.invokeid;
}
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp
index 1b15dee..8332c1d 100644
--- a/src/uscxml/URL.cpp
+++ b/src/uscxml/URL.cpp
@@ -56,6 +56,34 @@ std::string URL::tmpDir() {
return tmpDir;
}
+std::map<std::string, std::string> URL::mimeTypes;
+ std::string URL::getMimeType(const std::string extension, std::string magic) {
+ if (mimeTypes.empty()) {
+ mimeTypes["txt"] = "text/plain";
+ mimeTypes["c"] = "text/plain";
+ mimeTypes["h"] = "text/plain";
+ mimeTypes["html"] = "text/html";
+ mimeTypes["htm"] = "text/htm";
+ mimeTypes["css"] = "text/css";
+ mimeTypes["bmp"] = "image/bmp";
+ mimeTypes["gif"] = "image/gif";
+ mimeTypes["jpg"] = "image/jpeg";
+ mimeTypes["jpeg"] = "image/jpeg";
+ mimeTypes["mpg"] = "video/mpeg";
+ mimeTypes["mov"] = "video/quicktime";
+ mimeTypes["png"] = "image/png";
+ mimeTypes["pdf"] = "application/pdf";
+ mimeTypes["ps"] = "application/postscript";
+ mimeTypes["tif"] = "image/tiff";
+ mimeTypes["tiff"] = "image/tiff";
+ }
+
+ if (mimeTypes.find(extension) != mimeTypes.end()) {
+ return mimeTypes[extension];
+ }
+ return "";
+}
+
std::string URL::getTmpFilename(const std::string& suffix) {
std::string tmpFilename = tmpDir();
diff --git a/src/uscxml/URL.h b/src/uscxml/URL.h
index c00d24a..26b9437 100644
--- a/src/uscxml/URL.h
+++ b/src/uscxml/URL.h
@@ -246,7 +246,9 @@ public:
}
static std::string tmpDir();
-
+ static std::map<std::string, std::string> mimeTypes;
+ static std::string getMimeType(const std::string extension, std::string magic = "");
+
friend class URLFetcher;
friend std::ostream & operator<<(std::ostream &stream, const URL& p);
diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp
index 14028fa..cbb82eb 100644
--- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp
+++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.cpp
@@ -1,6 +1,7 @@
#include "DelayedEventQueue.h"
#include <assert.h>
#include <event2/event.h>
+#include <sstream>
namespace uscxml {
@@ -36,6 +37,27 @@ void DelayedEventQueue::run(void* instance) {
}
}
+void DelayedEventQueue::addEvent(std::string eventId, int fd, short opMask, void (*callback)(void*, const std::string eventId), void* userData, bool persist) {
+ if(_callbackData.find(eventId) != _callbackData.end()) {
+ cancelEvent(eventId);
+ }
+
+ if (persist)
+ opMask |= EV_PERSIST;
+
+ struct event* event = event_new(_eventLoop, fd, opMask, DelayedEventQueue::fileCallback, &_callbackData[eventId]);
+
+ _callbackData[eventId].eventId = eventId;
+ _callbackData[eventId].userData = userData;
+ _callbackData[eventId].eventQueue = this;
+ _callbackData[eventId].callback = callback;
+ _callbackData[eventId].event = event;
+ _callbackData[eventId].persist = false;
+
+ event_add(event, NULL);
+
+}
+
void DelayedEventQueue::addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData, bool persist) {
if(_callbackData.find(eventId) != _callbackData.end()) {
cancelEvent(eventId);
@@ -83,6 +105,13 @@ void DelayedEventQueue::stop() {
void DelayedEventQueue::dummyCallback(evutil_socket_t fd, short what, void *arg) {
}
+void DelayedEventQueue::fileCallback(evutil_socket_t fd, short what, void *arg) {
+ struct callbackData *data = (struct callbackData*)arg;
+ tthread::lock_guard<tthread::recursive_mutex> lock(data->eventQueue->_mutex);
+ std::string eventId = data->eventId; // copy eventId
+ data->callback(data->userData, eventId);
+}
+
void DelayedEventQueue::timerCallback(evutil_socket_t fd, short what, void *arg) {
struct callbackData *data = (struct callbackData*)arg;
tthread::lock_guard<tthread::recursive_mutex> lock(data->eventQueue->_mutex);
diff --git a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h
index 7ce766b..0b72719 100644
--- a/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h
+++ b/src/uscxml/concurrency/eventqueue/DelayedEventQueue.h
@@ -18,6 +18,12 @@ namespace uscxml {
class DelayedEventQueue {
public:
+ enum OpMask {
+ FD_READ = EV_READ,
+ FD_WRITE = EV_WRITE,
+ FD_SIGNAL = EV_SIGNAL
+ };
+
struct callbackData {
void *userData;
void (*callback)(void*, const std::string eventId);
@@ -30,6 +36,7 @@ public:
DelayedEventQueue();
virtual ~DelayedEventQueue();
+ void addEvent(std::string eventId, int fd, short opMask, void (*callback)(void*, const std::string eventId), void* userData, bool persist = true);
void addEvent(std::string eventId, void (*callback)(void*, const std::string eventId), uint32_t delayMs, void* userData, bool persist = false);
void cancelEvent(std::string eventId);
@@ -42,6 +49,7 @@ public:
}
static void timerCallback(evutil_socket_t fd, short what, void *arg);
+ static void fileCallback(evutil_socket_t fd, short what, void *arg);
static void dummyCallback(evutil_socket_t fd, short what, void *arg);
bool _isStarted;
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
index 0e72c67..d479a63 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.cpp
@@ -124,11 +124,14 @@ boost::shared_ptr<DataModelImpl> V8DataModel::create(InterpreterImpl* interprete
V8DataModel::getIOProcessors,
V8DataModel::setWithException,
v8::External::New(reinterpret_cast<void*>(dm.get())));
+ context->Global()->SetAccessor(v8::String::New("_invokers"),
+ V8DataModel::getInvokers,
+ V8DataModel::setWithException,
+ v8::External::New(reinterpret_cast<void*>(dm.get())));
dm->_contexts.push_back(context);
// instantiate objects - we have to have a context for that!
- dm->eval(Element<std::string>(), "_invokers = {};");
dm->eval(Element<std::string>(), "_x = {};");
return dm;
@@ -147,21 +150,35 @@ void V8DataModel::setWithException(v8::Local<v8::String> property, v8::Local<v8:
v8::Handle<v8::Value> V8DataModel::getIOProcessors(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
V8DataModel* dataModel = V8DOM::toClassPtr<V8DataModel>(info.Data());
- if (dataModel->_ioProcessors.IsEmpty()) {
- dataModel->_ioProcessors = v8::Persistent<v8::Object>::New(v8::Object::New());
- //v8::Handle<v8::Object> ioProcessorObj = v8::Object::New();
- std::map<std::string, IOProcessor> ioProcessors = dataModel->_interpreter->getIOProcessors();
- std::map<std::string, IOProcessor>::const_iterator ioProcIter = ioProcessors.begin();
- while(ioProcIter != ioProcessors.end()) {
+ dataModel->_ioProcessors = v8::Persistent<v8::Object>::New(v8::Object::New());
+ //v8::Handle<v8::Object> ioProcessorObj = v8::Object::New();
+ std::map<std::string, IOProcessor> ioProcessors = dataModel->_interpreter->getIOProcessors();
+ std::map<std::string, IOProcessor>::const_iterator ioProcIter = ioProcessors.begin();
+ while(ioProcIter != ioProcessors.end()) {
// std::cout << ioProcIter->first << std::endl;
- dataModel->_ioProcessors->Set(v8::String::New(ioProcIter->first.c_str()),
- dataModel->getDataAsValue(ioProcIter->second.getDataModelVariables()));
- ioProcIter++;
- }
+ dataModel->_ioProcessors->Set(v8::String::New(ioProcIter->first.c_str()),
+ dataModel->getDataAsValue(ioProcIter->second.getDataModelVariables()));
+ ioProcIter++;
}
return dataModel->_ioProcessors;
}
+v8::Handle<v8::Value> V8DataModel::getInvokers(v8::Local<v8::String> property, const v8::AccessorInfo& info) {
+ V8DataModel* dataModel = V8DOM::toClassPtr<V8DataModel>(info.Data());
+
+ dataModel->_invokers = v8::Persistent<v8::Object>::New(v8::Object::New());
+ //v8::Handle<v8::Object> ioProcessorObj = v8::Object::New();
+ std::map<std::string, Invoker> invokers = dataModel->_interpreter->getInvokers();
+ std::map<std::string, Invoker>::const_iterator invokerIter = invokers.begin();
+ while(invokerIter != invokers.end()) {
+ // std::cout << ioProcIter->first << std::endl;
+ dataModel->_invokers->Set(v8::String::New(invokerIter->first.c_str()),
+ dataModel->getDataAsValue(invokerIter->second.getDataModelVariables()));
+ invokerIter++;
+ }
+ return dataModel->_invokers;
+}
+
void V8DataModel::pushContext() {
_contexts.push_back(_contexts.back().New(_contexts.back()));
}
diff --git a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
index 0dffa27..1672919 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
+++ b/src/uscxml/plugins/datamodel/ecmascript/v8/V8DataModel.h
@@ -81,7 +81,9 @@ protected:
Arabica::DOM::V8DOM* _dom;
v8::Persistent<v8::Object> _ioProcessors;
+ v8::Persistent<v8::Object> _invokers;
static v8::Handle<v8::Value> getIOProcessors(v8::Local<v8::String> property, const v8::AccessorInfo& info);
+ static v8::Handle<v8::Value> getInvokers(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static v8::Handle<v8::Value> getAttribute(v8::Local<v8::String> property, const v8::AccessorInfo& info);
static void setWithException(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
diff --git a/src/uscxml/plugins/element/respond/RespondElement.cpp b/src/uscxml/plugins/element/respond/RespondElement.cpp
index ae81fed..9da3002 100644
--- a/src/uscxml/plugins/element/respond/RespondElement.cpp
+++ b/src/uscxml/plugins/element/respond/RespondElement.cpp
@@ -98,7 +98,7 @@ void RespondElement::enterElement(const Arabica::DOM::Node<std::string>& node) {
size_t lastDot;
if ((lastDot = file.path().find_last_of(".")) != std::string::npos) {
std::string extension = file.path().substr(lastDot + 1);
- std::string mimeType = HTTPServer::mimeTypeForExtension(extension);
+ std::string mimeType = URL::getMimeType(extension);
if (mimeType.length() > 0) {
httpReply.headers["Content-Type"] = mimeType;
}
diff --git a/src/uscxml/plugins/invoker/CMakeLists.txt b/src/uscxml/plugins/invoker/CMakeLists.txt
index db0d61f..5f767c9 100644
--- a/src/uscxml/plugins/invoker/CMakeLists.txt
+++ b/src/uscxml/plugins/invoker/CMakeLists.txt
@@ -131,6 +131,27 @@ if (FFMPEG_FOUND)
endif()
+# instant messaging invoker
+
+if (LIBPURPLE_FOUND)
+ set(USCXML_INVOKERS "im ${USCXML_INVOKERS}")
+ file(GLOB_RECURSE LIBPURPLE_INVOKER
+ im/*.cpp
+ im/*.h
+ )
+ source_group("Invoker\\im" FILES ${LIBPURPLE_INVOKER})
+ if (BUILD_AS_PLUGINS)
+ add_library(
+ invoker_im SHARED
+ ${LIBPURPLE_INVOKER})
+ target_link_libraries(invoker_im uscxml)
+ set_target_properties(invoker_im PROPERTIES FOLDER "Plugin Invoker")
+ else()
+ list (APPEND USCXML_FILES ${LIBPURPLE_INVOKER})
+ endif()
+endif()
+
+
# calendar invoker
if (LIBICAL_FOUND)
diff --git a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h
index e95b32e..ecce031 100644
--- a/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h
+++ b/src/uscxml/plugins/invoker/ffmpeg/FFMPEGInvoker.h
@@ -46,7 +46,8 @@ protected:
frame_count(0),
width(0),
height(0),
- sws_flags(SWS_BICUBIC) {}
+ sws_flags(SWS_BICUBIC),
+ sws_ctx(NULL) {}
virtual ~EncodingContext() {
if (sws_ctx)
diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp
index 1292e3a..559e441 100644
--- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp
+++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.cpp
@@ -49,7 +49,27 @@ boost::shared_ptr<InvokerImpl> DirMonInvoker::create(InterpreterImpl* interprete
}
Data DirMonInvoker::getDataModelVariables() {
+ tthread::lock_guard<tthread::recursive_mutex> lock(_mutex);
+
Data data;
+ data.compound["dir"] = Data(_dir, Data::VERBATIM);
+
+ std::set<std::string>::iterator suffixIter = _suffixes.begin();
+ while(suffixIter != _suffixes.end()) {
+ data.compound["suffixes"].array.push_back(Data(*suffixIter, Data::VERBATIM));
+ suffixIter++;
+ }
+
+ std::map<std::string, struct stat> entries = _watcher->getAllEntries();
+ std::map<std::string, struct stat>::iterator entryIter = entries.begin();
+ while(entryIter != entries.end()) {
+ data.compound["file"].compound[entryIter->first].compound["mtime"] = toStr(entryIter->second.st_mtime);
+ data.compound["file"].compound[entryIter->first].compound["ctime"] = toStr(entryIter->second.st_mtime);
+ data.compound["file"].compound[entryIter->first].compound["atime"] = toStr(entryIter->second.st_mtime);
+ data.compound["file"].compound[entryIter->first].compound["size"] = toStr(entryIter->second.st_mtime);
+ entryIter++;
+ }
+
return data;
}
@@ -115,7 +135,10 @@ void DirMonInvoker::invoke(const InvokeRequest& req) {
void DirMonInvoker::run(void* instance) {
while(((DirMonInvoker*)instance)->_isRunning) {
- ((DirMonInvoker*)instance)->_watcher->updateEntries();
+ {
+ tthread::lock_guard<tthread::recursive_mutex> lock(((DirMonInvoker*)instance)->_mutex);
+ ((DirMonInvoker*)instance)->_watcher->updateEntries();
+ }
tthread::this_thread::sleep_for(tthread::chrono::milliseconds(20));
}
}
@@ -233,7 +256,7 @@ DirectoryWatch::~DirectoryWatch() {
}
}
-
+
void DirectoryWatch::reportAsDeleted() {
std::map<std::string, struct stat>::iterator fileIter = _knownEntries.begin();
while(fileIter != _knownEntries.end()) {
@@ -248,8 +271,8 @@ void DirectoryWatch::reportAsDeleted() {
monIter++;
}
}
- _knownEntries.erase(fileIter->first);
- fileIter++;
+ _knownEntries.erase(fileIter++);
+// fileIter++;
}
assert(_knownDirs.size() == 0);
assert(_knownEntries.size() == 0);
diff --git a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h
index 59eee81..f5aa4bc 100644
--- a/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h
+++ b/src/uscxml/plugins/invoker/filesystem/dirmon/DirMonInvoker.h
@@ -44,7 +44,7 @@ public:
std::map<std::string, struct stat> dirEntries = dirIter->second->getAllEntries();
std::map<std::string, struct stat>::iterator dirEntryIter = dirEntries.begin();
while(dirEntryIter != dirEntries.end()) {
- entries[dirIter->first + PATH_SEPERATOR + dirEntryIter->first] = dirEntryIter->second;
+ entries[dirIter->first + '/' + dirEntryIter->first] = dirEntryIter->second;
dirEntryIter++;
}
dirIter++;
diff --git a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp
index 0e8430c..a6f303a 100644
--- a/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp
+++ b/src/uscxml/plugins/invoker/graphics/openscenegraph/converter/OSGConverter.cpp
@@ -247,7 +247,7 @@ void OSGConverter::process(const SendRequest& req) {
osgViewer::ScreenCaptureHandler* captureHandler = new osgViewer::ScreenCaptureHandler(cOp, -1);
{
-// tthread::lock_guard<tthread::recursive_mutex> lock(_viewerMutex);
+ tthread::lock_guard<tthread::recursive_mutex> lock(_viewerMutex);
osgViewer::Viewer viewer;
osg::ref_ptr<osg::GraphicsContext> gc;
@@ -259,7 +259,9 @@ void OSGConverter::process(const SendRequest& req) {
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits(ds);
traits->width = width;
traits->height = height;
+ // this fails with ubuntu in a VM in parallels
traits->pbuffer = true;
+
gc = osg::GraphicsContext::createGraphicsContext(traits.get());
if (!gc.valid()) {
@@ -267,6 +269,11 @@ void OSGConverter::process(const SendRequest& req) {
return;
}
+ if (!traits->width || !traits->height) {
+ LOG(ERROR) << "Traits returned with zero dimensions";
+ return;
+ }
+
GLenum pbuffer = gc->getTraits()->doubleBuffer ? GL_BACK : GL_FRONT;
viewer.setCameraManipulator(new osgGA::TrackballManipulator());
@@ -300,6 +307,11 @@ void OSGConverter::process(const SendRequest& req) {
void OSGConverter::reportSuccess(const SendRequest& req, const Data& content) {
Event event(req);
+
+ std::string format;
+ Event::getParam(req.params, "format", format);
+
+ event.data.compound["mimetype"] = Data(URL::getMimeType(format), Data::VERBATIM);
if (event.name.length() == 0)
event.name = "convert";
@@ -519,6 +531,10 @@ void OSGConverter::dumpMatrix(const osg::Matrix& m) {
void OSGConverter::NameRespectingWriteToFile::operator()(const osg::Image& image, const unsigned int context_id) {
+// std::cout << "NameRespectingWriteToFile" << std::endl;
+// std::cout << image.s() << std::endl;
+// std::cout << image.t() << std::endl;
+
// write to memory first
std::string format;
if (_req.params.find("format") != _req.params.end()) {
@@ -533,7 +549,9 @@ void OSGConverter::NameRespectingWriteToFile::operator()(const osg::Image& image
// osgDB got confused when we write to a stringstream
std::string tempFile = URL::getTmpFilename(format);
- osgDB::writeImageFile(image, tempFile, op);
+ if (!osgDB::writeImageFile(image, tempFile, op)) {
+ _converter->reportFailure(_req);
+ }
char* buffer = NULL;
size_t length = 0;
@@ -547,7 +565,9 @@ void OSGConverter::NameRespectingWriteToFile::operator()(const osg::Image& image
file.read(buffer, length);
}
- remove(tempFile.c_str());
+ std::cout << tempFile << std::endl;
+
+// remove(tempFile.c_str());
// osg::ref_ptr<osgDB::ReaderWriter> writerFormat = osgDB::Registry::instance()->getReaderWriterForExtension(format);
// if(!writerFormat.valid())
// _converter->reportFailure(_req);
diff --git a/src/uscxml/plugins/invoker/im/IMInvoker.cpp b/src/uscxml/plugins/invoker/im/IMInvoker.cpp
new file mode 100644
index 0000000..a7fd146
--- /dev/null
+++ b/src/uscxml/plugins/invoker/im/IMInvoker.cpp
@@ -0,0 +1,361 @@
+#include "IMInvoker.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 IMInvokerProvider() );
+ return true;
+}
+#endif
+
+Data IMInvoker::_pluginData;
+GHashTable* IMInvoker::_uiInfo = NULL;
+GRand* IMInvoker::_gRand = NULL;
+
+PurpleEventLoopUiOps IMInvoker::_uiEventLoopOps =
+{
+ purpleEventTimeoutAdd,
+ purpleEventTimeoutRemove,
+ purpleEventInputAdd,
+ purpleEventInputRemove,
+ purpleEventInputGetError,
+ purpleEventTimeoutAddSec,
+
+ /* padding */
+ NULL,
+ NULL,
+ NULL
+};
+
+PurpleAccountUiOps IMInvoker::_accountUIOps = {
+ accountNotifyAdded,
+ accountStatusChanged,
+ accountRequestAdd,
+ accountRequestAuthorize,
+ accountCloseRequest,
+ NULL,
+ NULL,
+ NULL
+};
+
+/*** Conversation uiops ***/
+static void
+null_write_conv(PurpleConversation *conv, const char *who, const char *alias,
+ const char *message, PurpleMessageFlags flags, time_t mtime)
+{
+ const char *name;
+ if (alias && *alias)
+ name = alias;
+ else if (who && *who)
+ name = who;
+ else
+ name = NULL;
+
+ printf("(%s) %s %s: %s\n", purple_conversation_get_name(conv),
+ purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
+ name, message);
+}
+
+static PurpleConversationUiOps null_conv_uiops =
+{
+ NULL, /* create_conversation */
+ NULL, /* destroy_conversation */
+ NULL, /* write_chat */
+ NULL, /* write_im */
+ null_write_conv, /* write_conv */
+ NULL, /* chat_add_users */
+ NULL, /* chat_rename_user */
+ NULL, /* chat_remove_users */
+ NULL, /* chat_update_user */
+ NULL, /* present */
+ NULL, /* has_focus */
+ NULL, /* custom_smiley_add */
+ NULL, /* custom_smiley_write */
+ NULL, /* custom_smiley_close */
+ NULL, /* send_confirm */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+static void
+null_ui_init(void)
+{
+ /**
+ * This should initialize the UI components for all the modules. Here we
+ * just initialize the UI for conversations.
+ */
+ purple_conversations_set_ui_ops(&null_conv_uiops);
+}
+
+static PurpleCoreUiOps null_core_uiops =
+{
+ NULL,
+ NULL,
+ null_ui_init,
+ NULL,
+
+ /* padding */
+ NULL,
+ NULL,
+ NULL,
+ NULL
+};
+
+DelayedEventQueue* IMInvoker::_eventQueue = NULL;
+
+void IMInvoker::initLibPurple(void *userdata, const std::string event) {
+ _uiInfo = g_hash_table_new(g_str_hash, g_str_equal);
+ _gRand = g_rand_new();
+
+ /* Set a custom user directory (optional) */
+ //purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);
+
+ /* We do not want any debugging for now to keep the noise to a minimum. */
+ purple_debug_set_enabled(false);
+
+ purple_core_set_ui_ops(&null_core_uiops);
+// purple_eventloop_set_ui_ops(&glib_eventloops);
+ purple_eventloop_set_ui_ops(&_uiEventLoopOps);
+
+ purple_plugins_add_search_path("/usr/local/lib/purple-3");
+ // purple_plugins_probe(G_MODULE_SUFFIX);
+
+ if (!purple_core_init("uscxml")) {
+ LOG(ERROR) << "libpurple initialization failed." << std::endl;
+ return;
+ }
+
+ /* Load the preferences. */
+ purple_prefs_load();
+ purple_plugins_load_saved("/purple/uscxml/plugins/saved");
+
+ GList *l;
+ PurplePlugin *plugin;
+
+ for (l = purple_plugins_get_all(); l != NULL; l = l->next) {
+ plugin = (PurplePlugin *)l->data;
+
+ Data pluginData;
+ if (plugin->info->id) pluginData.compound["id"] = Data(plugin->info->id, Data::VERBATIM);
+ if (plugin->info->homepage) pluginData.compound["homepage"] = Data(plugin->info->homepage, Data::VERBATIM);
+ if (plugin->info->author) pluginData.compound["author"] = Data(plugin->info->author, Data::VERBATIM);
+ if (plugin->info->description) pluginData.compound["description"] = Data(plugin->info->description, Data::VERBATIM);
+ if (plugin->info->name) pluginData.compound["name"] = Data(plugin->info->name, Data::VERBATIM);
+ if (plugin->info->summary) pluginData.compound["summary"] = Data(plugin->info->summary, Data::VERBATIM);
+ if (plugin->info->version) pluginData.compound["version"] = Data(plugin->info->version, Data::VERBATIM);
+ if (plugin->info->major_version) pluginData.compound["majorVersion"] = Data(toStr(plugin->info->major_version), Data::VERBATIM);
+ if (plugin->info->minor_version) pluginData.compound["minorVersion"] = Data(toStr(plugin->info->minor_version), Data::VERBATIM);
+
+ if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
+ _pluginData.compound["protocol"].compound[plugin->info->id] = pluginData;
+
+ }
+
+}
+
+void IMInvoker::send(void *userdata, const std::string event) {
+ EventContext* ctx = (EventContext*)userdata;
+ delete(ctx);
+}
+
+static void
+signed_on(PurpleConnection *gc, gpointer null)
+{
+ PurpleAccount *account = purple_connection_get_account(gc);
+ printf("Account connected: %s %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
+}
+
+void IMInvoker::invoke(void *userdata, const std::string event) {
+ EventContext* ctx = (EventContext*)userdata;
+ IMInvoker* instance = ctx->instance;
+
+ std::string username;
+ Event::getParam(ctx->invokeReq.params, "username", username);
+ std::string protocolId;
+ Event::getParam(ctx->invokeReq.params, "protocol", protocolId);
+ std::string password;
+ Event::getParam(ctx->invokeReq.params, "password", password);
+
+ instance->_account = purple_account_new(username.c_str(), protocolId.c_str());
+ purple_account_set_password(instance->_account, password.c_str(), NULL, NULL);
+
+ purple_accounts_set_ui_ops(&_accountUIOps);
+
+ purple_account_set_enabled(instance->_account, "uscxml", true);
+
+ PurpleSavedStatus* status = purple_savedstatus_new(NULL, PURPLE_STATUS_AVAILABLE);
+ purple_savedstatus_activate(status);
+
+ int handle;
+ purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
+ PURPLE_CALLBACK(signed_on), NULL);
+
+ delete(ctx);
+}
+
+IMInvoker::IMInvoker() {
+ _account = NULL;
+ if (!_eventQueue) {
+ _eventQueue = new DelayedEventQueue();
+ _eventQueue->addEvent("initLibPurple", IMInvoker::initLibPurple, 0, NULL);
+ _eventQueue->start();
+
+
+ }
+
+}
+
+IMInvoker::~IMInvoker() {
+ if (_account) {
+ purple_account_destroy(_account);
+ }
+};
+
+boost::shared_ptr<InvokerImpl> IMInvoker::create(InterpreterImpl* interpreter) {
+ boost::shared_ptr<IMInvoker> invoker = boost::shared_ptr<IMInvoker>(new IMInvoker());
+ return invoker;
+}
+
+Data IMInvoker::getDataModelVariables() {
+ return _pluginData;
+}
+
+void IMInvoker::send(const SendRequest& req) {
+ EventContext* ctx = new EventContext();
+ ctx->sendReq = req;
+ ctx->instance = this;
+ _eventQueue->addEvent(req.sendid, IMInvoker::invoke, 0, ctx);
+ return;
+}
+
+void IMInvoker::cancel(const std::string sendId) {
+}
+
+void IMInvoker::invoke(const InvokeRequest& req) {
+
+ EventContext* ctx = new EventContext();
+ ctx->invokeReq = req;
+ ctx->instance = this;
+ _eventQueue->addEvent(req.sendid, IMInvoker::invoke, 0, ctx);
+ return;
+}
+
+guint IMInvoker::purpleEventTimeoutAdd(guint interval, GSourceFunc function, gpointer data) {
+ PurpleEventContext* ctx = new PurpleEventContext();
+ ctx->function = function;
+ ctx->input = NULL;
+ ctx->data = data;
+ uintptr_t ptr = reinterpret_cast<uintptr_t>(ctx);
+
+ _eventQueue->addEvent(toStr(ptr), purpleCallback, interval, ctx);
+ return ptr;
+}
+
+gboolean IMInvoker::purpleEventTimeoutRemove(guint handle) {
+ _eventQueue->cancelEvent(toStr(handle));
+ return true;
+}
+
+guint IMInvoker::purpleEventTimeoutAddSec(guint interval, GSourceFunc function, gpointer data) {
+ return purpleEventTimeoutAdd(interval * 1000, function, data);
+}
+
+guint IMInvoker::purpleEventInputAdd(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer data) {
+ PurpleEventContext* ctx = new PurpleEventContext();
+ ctx->function = NULL;
+ ctx->input = func;
+ ctx->inputFD = fd;
+ ctx->cond = cond;
+ ctx->data = data;
+
+ short opMask = 0;
+ if (cond & PURPLE_INPUT_READ)
+ opMask |= DelayedEventQueue::FD_READ;
+ if (cond & PURPLE_INPUT_WRITE)
+ opMask |= DelayedEventQueue::FD_WRITE;
+
+ guint eventId = g_rand_int(_gRand);
+ _eventQueue->addEvent(toStr(eventId), fd, opMask, purpleCallback, ctx, true);
+ return eventId;
+}
+
+gboolean IMInvoker::purpleEventInputRemove(guint handle) {
+ _eventQueue->cancelEvent(toStr(handle));
+ return true;
+}
+
+int IMInvoker::purpleEventInputGetError(int fd, int *error) {
+ std::cout << "purpleEventInputGetError" << std::endl;
+ return 0;
+}
+
+void IMInvoker::purpleCallback(void *userdata, const std::string event) {
+ PurpleEventContext* ctx = (PurpleEventContext*)userdata;
+ if (ctx->function) {
+ ctx->function(ctx->data);
+ delete ctx;
+ } else if(ctx->input) {
+ ctx->input(ctx->data, ctx->inputFD, ctx->cond);
+ }
+}
+
+void IMInvoker::purplePrefsInit(void) {}
+void IMInvoker::purpleDebugInit(void) {}
+void IMInvoker::purpleUIInit(void) {}
+void IMInvoker::purpleQuit(void) {}
+
+GHashTable* IMInvoker::purpleGetUIInfo(void) {
+ return _uiInfo;
+}
+
+void IMInvoker::accountNotifyAdded(PurpleAccount *account,
+ const char *remote_user,
+ const char *id,
+ const char *alias,
+ const char *message) {
+ std::cout << "accountNotifyAdded" << std::endl;
+}
+
+void IMInvoker::accountStatusChanged(PurpleAccount *account,
+ PurpleStatus *status) {
+ std::cout << "accountStatusChanged" << std::endl;
+
+}
+
+void IMInvoker::accountRequestAdd(PurpleAccount *account,
+ const char *remote_user,
+ const char *id,
+ const char *alias,
+ const char *message) {
+ std::cout << "accountRequestAdd" << std::endl;
+}
+
+void* IMInvoker::accountRequestAuthorize(PurpleAccount *account,
+ const char *remote_user,
+ const char *id,
+ const char *alias,
+ const char *message,
+ gboolean on_list,
+ PurpleAccountRequestAuthorizationCb authorize_cb,
+ PurpleAccountRequestAuthorizationCb deny_cb,
+ void *user_data) {
+ // always accept all requests
+ authorize_cb(message, user_data);
+ return user_data;
+}
+
+void IMInvoker::accountCloseRequest(void *ui_handle) {
+ std::cout << "accountCloseRequest" << std::endl;
+}
+
+
+} \ No newline at end of file
diff --git a/src/uscxml/plugins/invoker/im/IMInvoker.h b/src/uscxml/plugins/invoker/im/IMInvoker.h
new file mode 100644
index 0000000..fb02e46
--- /dev/null
+++ b/src/uscxml/plugins/invoker/im/IMInvoker.h
@@ -0,0 +1,117 @@
+#ifndef IMINVOKER_H_FNWG0XCQ
+#define IMINVOKER_H_FNWG0XCQ
+
+#include <uscxml/Interpreter.h>
+
+//extern "C" {
+#include <libpurple/purple.h>
+//}
+
+#ifdef BUILD_AS_PLUGINS
+#include "uscxml/plugins/Plugins.h"
+#endif
+
+namespace uscxml {
+
+class IMInvoker : public InvokerImpl {
+public:
+ struct EventContext {
+ InvokeRequest invokeReq;
+ SendRequest sendReq;
+ IMInvoker* instance;
+ };
+
+ IMInvoker();
+ virtual ~IMInvoker();
+ virtual boost::shared_ptr<InvokerImpl> create(InterpreterImpl* interpreter);
+
+ virtual std::set<std::string> getNames() {
+ std::set<std::string> names;
+ names.insert("im");
+ names.insert("instant-messaging");
+ names.insert("http://uscxml.tk.informatik.tu-darmstadt.de/#instant-messaging");
+ 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:
+ static bool _libPurpleIsInitialized;
+ static Data _pluginData;
+ static PurpleAccountUiOps _accountUIOps;
+ static PurpleEventLoopUiOps _uiEventLoopOps;
+ static PurpleCoreUiOps _uiCoreOps;
+ static GHashTable* _uiInfo;
+ static GRand* _gRand;
+
+ static DelayedEventQueue* _eventQueue;
+
+ // these are only being called from the delayed queue's thread
+ static void initLibPurple(void *userdata, const std::string event);
+ static void send(void *userdata, const std::string event);
+ static void invoke(void *userdata, const std::string event);
+
+ // libpurple ui operations
+ static guint purpleEventTimeoutAdd(guint interval, GSourceFunc function, gpointer data);
+ static gboolean purpleEventTimeoutRemove(guint handle);
+ static guint purpleEventInputAdd(int fd, PurpleInputCondition cond, PurpleInputFunction func, gpointer user_data);
+ static gboolean purpleEventInputRemove(guint handle);
+ static int purpleEventInputGetError(int fd, int *error);
+ static guint purpleEventTimeoutAddSec(guint interval, GSourceFunc function, gpointer data);
+
+ // callback contexts
+ struct PurpleEventContext {
+ PurpleInputFunction input;
+ PurpleInputCondition cond;
+ int inputFD;
+ GSourceFunc function;
+ gpointer data;
+ };
+ static void purpleCallback(void *userdata, const std::string event);
+
+ // libpurple core operations
+ static void purplePrefsInit(void);
+ static void purpleDebugInit(void);
+ static void purpleUIInit(void);
+ static void purpleQuit(void);
+ static GHashTable* purpleGetUIInfo(void);
+
+ // account operations
+ static void accountNotifyAdded(PurpleAccount *account,
+ const char *remote_user,
+ const char *id,
+ const char *alias,
+ const char *message);
+ static void accountStatusChanged(PurpleAccount *account,
+ PurpleStatus *status);
+ static void accountRequestAdd(PurpleAccount *account,
+ const char *remote_user,
+ const char *id,
+ const char *alias,
+ const char *message);
+ static void* accountRequestAuthorize(PurpleAccount *account,
+ const char *remote_user,
+ const char *id,
+ const char *alias,
+ const char *message,
+ gboolean on_list,
+ PurpleAccountRequestAuthorizationCb authorize_cb,
+ PurpleAccountRequestAuthorizationCb deny_cb,
+ void *user_data);
+ static void accountCloseRequest(void *ui_handle);
+
+
+ PurpleAccount* _account;
+};
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_INHERIT_PROVIDER(IMInvoker, InvokerImpl);
+#endif
+
+}
+
+
+#endif /* end of include guard: IMINVOKER_H_FNWG0XCQ */
diff --git a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp
index 4d514ef..bb17370 100644
--- a/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp
+++ b/src/uscxml/plugins/invoker/sample/SampleInvoker.cpp
@@ -23,7 +23,6 @@ SampleInvoker::~SampleInvoker() {
boost::shared_ptr<InvokerImpl> SampleInvoker::create(InterpreterImpl* interpreter) {
boost::shared_ptr<SampleInvoker> invoker = boost::shared_ptr<SampleInvoker>(new SampleInvoker());
- invoker->_interpreter = interpreter;
return invoker;
}
diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp
index 0521d74..8799fc2 100644
--- a/src/uscxml/server/HTTPServer.cpp
+++ b/src/uscxml/server/HTTPServer.cpp
@@ -71,7 +71,6 @@ HTTPServer::~HTTPServer() {
HTTPServer* HTTPServer::_instance = NULL;
tthread::recursive_mutex HTTPServer::_instanceMutex;
-std::map<std::string, std::string> HTTPServer::mimeTypes;
HTTPServer* HTTPServer::getInstance(int port) {
// tthread::lock_guard<tthread::recursive_mutex> lock(_instanceMutex);
@@ -80,25 +79,6 @@ HTTPServer* HTTPServer::getInstance(int port) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
#endif
- // this is but a tiny list, supply a content-type <header> yourself
- mimeTypes["txt"] = "text/plain";
- mimeTypes["c"] = "text/plain";
- mimeTypes["h"] = "text/plain";
- mimeTypes["html"] = "text/html";
- mimeTypes["htm"] = "text/htm";
- mimeTypes["css"] = "text/css";
- mimeTypes["bmp"] = "image/bmp";
- mimeTypes["gif"] = "image/gif";
- mimeTypes["jpg"] = "image/jpeg";
- mimeTypes["jpeg"] = "image/jpeg";
- mimeTypes["mpg"] = "video/mpeg";
- mimeTypes["mov"] = "video/quicktime";
- mimeTypes["png"] = "image/png";
- mimeTypes["pdf"] = "application/pdf";
- mimeTypes["ps"] = "application/postscript";
- mimeTypes["tif"] = "image/tiff";
- mimeTypes["tiff"] = "image/tiff";
-
#ifndef _WIN32
evthread_use_pthreads();
#else
@@ -110,12 +90,6 @@ HTTPServer* HTTPServer::getInstance(int port) {
return _instance;
}
-std::string HTTPServer::mimeTypeForExtension(const std::string& ext) {
- if (mimeTypes.find(ext) != mimeTypes.end())
- return mimeTypes[ext];
- return "";
-}
-
/**
* This callback is registered for all HTTP requests
*/
@@ -165,7 +139,10 @@ void HTTPServer::httpRecvReqCallback(struct evhttp_request *req, void *callbackD
request.data.compound["httpMajor"] = Data(toStr((unsigned short)req->major), Data::VERBATIM);
request.data.compound["httpMinor"] = Data(toStr((unsigned short)req->minor), Data::VERBATIM);
request.data.compound["uri"] = Data(HTTPServer::getBaseURL() + req->uri, Data::VERBATIM);
- request.data.compound["path"] = Data(evhttp_uri_get_path(evhttp_request_get_evhttp_uri(req)), Data::VERBATIM);
+
+ char* pathCStr = evhttp_decode_uri(evhttp_uri_get_path(evhttp_request_get_evhttp_uri(req)));
+ request.data.compound["path"] = Data(pathCStr, Data::VERBATIM);
+ free(pathCStr);
raw << " " << request.data.compound["path"].atom;
const char* query = evhttp_uri_get_query(evhttp_request_get_evhttp_uri(req));
diff --git a/src/uscxml/server/HTTPServer.h b/src/uscxml/server/HTTPServer.h
index d216d5e..3e0d91c 100644
--- a/src/uscxml/server/HTTPServer.h
+++ b/src/uscxml/server/HTTPServer.h
@@ -45,7 +45,6 @@ public:
static std::string getBaseURL();
static void reply(const Reply& reply);
- static std::string mimeTypeForExtension(const std::string& ext);
static bool registerServlet(const std::string& path, HTTPServlet* servlet); ///< Register a servlet, returns false if path is already taken
static void unregisterServlet(HTTPServlet* servlet);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 5fcad93..de7fa70 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -18,12 +18,12 @@ if (SWI_FOUND)
add_test(test-prolog-swi ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uscxml-browser ${CMAKE_SOURCE_DIR}/test/samples/uscxml/test-prolog.scxml)
endif()
-if (FFMPEG_FOUND)
- add_executable(test-ffmpeg src/test-ffmpeg.cpp)
- target_link_libraries(test-ffmpeg uscxml)
- add_test(test-ffmpeg ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-ffmpeg)
- set_target_properties(test-ffmpeg PROPERTIES FOLDER "Tests")
-endif()
+# if (FFMPEG_FOUND)
+# add_executable(test-ffmpeg src/test-ffmpeg.cpp)
+# target_link_libraries(test-ffmpeg uscxml)
+# add_test(test-ffmpeg ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/test-ffmpeg)
+# set_target_properties(test-ffmpeg PROPERTIES FOLDER "Tests")
+# endif()
if (V8_FOUND)
add_test(test-ecmascript ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/uscxml-browser ${CMAKE_SOURCE_DIR}/test/samples/uscxml/test-ecmascript.scxml)
diff --git a/test/samples/uscxml/test-instant-messaging.scxml b/test/samples/uscxml/test-instant-messaging.scxml
new file mode 100644
index 0000000..569ec59
--- /dev/null
+++ b/test/samples/uscxml/test-instant-messaging.scxml
@@ -0,0 +1,20 @@
+<scxml datamodel="ecmascript">
+ <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" />
+ <state id="idle">
+ <onentry>
+ <send event="dump" delay="100ms" />
+ </onentry>
+
+ <invoke type="instant-messaging" id="im">
+ <param name="username" expr="'uscxml@localhost'" />
+ <param name="password" expr="'password'" />
+ <param name="protocol" expr="'prpl-jabber'" />
+ </invoke>
+
+ <state id="dump">
+ <transition event="dump" target="dump">
+ <script>dump(_invokers['im']);</script>
+ </transition>
+ </state>
+ </state>
+</scxml> \ No newline at end of file