summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-03 16:21:13 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-03 16:21:13 (GMT)
commitcb30bd1f44fcc3a0642a362afd4eaea0d8a7d199 (patch)
tree8cfcf2ceca801c5d506e03d0e187f440094d1674 /apps
parent9caf9ade8ff87a1cb94fb612df4abd96fb5ed239 (diff)
downloaduscxml-cb30bd1f44fcc3a0642a362afd4eaea0d8a7d199.zip
uscxml-cb30bd1f44fcc3a0642a362afd4eaea0d8a7d199.tar.gz
uscxml-cb30bd1f44fcc3a0642a362afd4eaea0d8a7d199.tar.bz2
First signs of WebSockets and some changes to miles
Diffstat (limited to 'apps')
-rwxr-xr-xapps/samples/miles/emptyface.jpgbin0 -> 1603 bytes
-rw-r--r--apps/samples/miles/miles.html26
-rw-r--r--apps/samples/miles/miles.js369
-rw-r--r--apps/samples/miles/miles.scxml155
-rw-r--r--apps/samples/miles/test1.jpegbin10996 -> 7350 bytes
-rw-r--r--apps/samples/miles/test2.jpegbin40332 -> 7871 bytes
-rw-r--r--apps/samples/miles/test3.jpegbin0 -> 7939 bytes
-rw-r--r--apps/samples/miles/test4.jpegbin0 -> 7780 bytes
-rw-r--r--apps/samples/websockets/websockets.html77
-rw-r--r--apps/samples/websockets/websockets.scxml16
10 files changed, 571 insertions, 72 deletions
diff --git a/apps/samples/miles/emptyface.jpg b/apps/samples/miles/emptyface.jpg
new file mode 100755
index 0000000..a1b2f32
--- /dev/null
+++ b/apps/samples/miles/emptyface.jpg
Binary files differ
diff --git a/apps/samples/miles/miles.html b/apps/samples/miles/miles.html
index 9cee058..08cfeca 100644
--- a/apps/samples/miles/miles.html
+++ b/apps/samples/miles/miles.html
@@ -15,13 +15,31 @@
<script type="text/javascript">
require(["dojo/domReady!"], function(dom) {
- var milesSession = new Miles("miles1");
+ var milesSession1 = new Miles("miles1");
+ var milesSession2 = new Miles("miles2");
+ var milesSession3 = new Miles("miles3");
+ var milesSession4 = new Miles("miles4");
});
</script>
</head>
<body class="tundra">
- <div style="width: 600px; height: 400px">
- <div id="miles1"></div>
- </div>
+ <table>
+ <tr>
+ <td>
+ <div id="miles1"></div>
+ </td>
+ <td>
+ <div id="miles2"></div>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <div id="miles3"></div>
+ </td>
+ <td>
+ <div id="miles4"></div>
+ </td>
+ </tr>
+ </table>
</body>
</html>
diff --git a/apps/samples/miles/miles.js b/apps/samples/miles/miles.js
index 1b2d0b6..a1d4422 100644
--- a/apps/samples/miles/miles.js
+++ b/apps/samples/miles/miles.js
@@ -12,11 +12,45 @@ function Miles(element, params) {
this.connected = false;
this.imageIteration = 0;
+ this.width = 300;
+ this.height = 200;
+
// private attributes
var scxmlURL = "localhost:8080"
- var reflectorIp = "localhost"
- var email = "me@somehost.de";
- var problemName = "some really hard problem";
+ var reflectorIp = "88.131.107.12"
+ var email = "user@smartvortex.eu";
+ var problemName = "webconfero";
+ var remoteEmail = "other@smartvortex.eu";
+
+ var participants = []; // empty array
+ var videoCompressions = [
+ { value: 'jpeg', label: "JPEG" },
+ { value: 'h263', label: "H.263" },
+ { value: 'h264', label: "H.264" },
+ ];
+ var videoCompression = "";
+
+ var audioEncodings = [
+ { value: 'pcm', label: "PCM" },
+ { value: 'ulaw', label: "uLaw" },
+ { value: 'ogg', label: "Ogg Theora" },
+ ];
+ var audioEncoding = "";
+
+ var repollInterval = {
+ image: 50,
+ chat: 500,
+ participants: 1000
+ };
+
+ var showVideo = true;
+ var enableAudio = true;
+ var stopChatScrolling = false;
+ var activateCamera = true;
+ var openMicrophone = true;
+ var videoFramerate = 25;
+ var videoHeight = self.height;
+ var videoWidth = self.width;
// override with parameters if given
this.params = params;
@@ -27,68 +61,140 @@ function Miles(element, params) {
// called when dojo loaded all requirements below
this.connect = function() {
- self.xhr.post({
+ var query = "";
+ query += "?reflector=" + encodeURIComponent(reflectorIp);
+ query += "&userid=" + encodeURIComponent(email);
+ query += "&session=" + encodeURIComponent(problemName);
+
+ self.xhr.get({
// The URL to request
- url: "http://" + scxmlURL + "/miles/connect",
+ url: "http://" + scxmlURL + "/miles/start" + query,
// handleAs:"text",
- contentType: 'application/json',
- postData: dojo.toJson({
- reflectorIp: reflectorIp,
- email: email,
- problemName: problemName
- }),
- headers:{
- "X-Requested-With": null,
- },
error: function(err) {
console.log(err);
},
load: function(result) {
- // we expect nothing in return
self.connected = true;
- // trigger continuously loading the image
+
+ // toggle connect button to disconnect
+ self.connectDropDown.dropDown.onCancel(true);
+ self.controlElem.replaceChild(self.controlDropDown.domNode, self.connectDropDown.domNode);
+
+ // trigger continuous updates
refreshImage();
+ getChatText();
+ getParticipants();
}
});
}
+ this.disconnect = function() {
+ self.connected = false;
+ self.controlDropDown.dropDown.onCancel(true);
+ self.controlElem.replaceChild(self.connectDropDown.domNode, self.controlDropDown.domNode);
+ }
+
+ var getParticipants = function() {
+ var query = "";
+ self.xhr.get({
+ // The URL to request
+ url: "http://" + scxmlURL + "/miles/participants" + query,
+ handleAs:"json",
+ error: function(err) {
+ console.log(err);
+ if (self.connected) {
+ setTimeout(getParticipants, repollInterval.participants);
+ }
+ },
+ load: function(result) {
+ if (result.participants) {
+ participants = result.participants;
+ }
+ if (self.connected) {
+ console.log(participants);
+ setTimeout(getParticipants, repollInterval.participants);
+ }
+ }
+ });
+ }
+
// fetch a base64 encoded image and set it as the src attribute
var refreshImage = function() {
+ var query = "";
+ query += "?userid=" + encodeURIComponent(email);
self.xhr.get({
// The URL to request
- url: "http://" + scxmlURL + "/miles/image",
+ url: "http://" + scxmlURL + "/miles/thumbnail" + query,
+ handleAs:"text",
headers:{
- "X-Requested-With":null
+ "X-Content-Encoding": "base64"
},
error: function(err) {
console.log(err);
if (self.connected) {
- self.messageElem.innerHTML = self.imageIteration++;
- refreshImage();
+ setTimeout(refreshImage, repollInterval.image);
}
},
load: function(result) {
self.pictureElem.src = "data:image/jpeg;base64," + result;
if (self.connected) {
self.messageElem.innerHTML = self.imageIteration++;
- refreshImage();
+ setTimeout(refreshImage, repollInterval.image);
}
}
});
-
};
+ var getChatText = function() {
+ self.xhr.get({
+ // The URL to request
+ url: "http://" + scxmlURL + "/miles/gettext",
+ handleAs:"json",
+ error: function(err) {
+ console.log(err);
+ if (self.connected) {
+ setTimeout(getChatText, repollInterval.chat);
+ }
+ },
+ load: function(result) {
+ if (result.message) {
+ self.chatOutputElem.innerHTML += stopChatScrolling + " " + Math.random() + ": " + result.message + '<br />';
+ if (!stopChatScrolling)
+ self.chatOutputElem.scrollTop = self.chatOutputElem.scrollHeight;
+ }
+ if (self.connected) {
+ setTimeout(getChatText, repollInterval.chat);
+ }
+ }
+ });
+ };
+
+
require(["dojo/dom-construct",
"dojo/_base/xhr",
"dojo/dom",
+ "dojo/on",
+ "dojo/_base/unload",
"dijit/form/DropDownButton",
"dijit/TooltipDialog",
+ "dijit/form/TextBox",
+ "dijit/form/Button",
+ "dijit/form/CheckBox",
+ "dijit/form/Select",
+ "dijit/form/NumberSpinner",
"dojo/ready"],
function(domConst,
xhr,
dom,
+ on,
+ baseUnload,
DropDownButton,
TooltipDialog,
+ TextBox,
+ Button,
+ CheckBox,
+ Select,
+ NumberSpinner,
ready) {
ready(function() {
self.xhr = xhr;
@@ -97,14 +203,19 @@ function Miles(element, params) {
if (typeof(element) === 'string') {
element = dom.byId(element);
}
+ element.style.width = self.width + "px";
+
+ baseUnload.addOnWindowUnload(function(){
+// alert("unloading...");
+ });
// dynamically assemble the DOM we need
element.appendChild(domConst.toDom('\
<table>\
<tr>\
- <td valign="top">\
+ <td valign="top" colspan="2" >\
<div style="position: relative; padding: 0px">\
- <img class="picture" src="test1.jpeg"></img>\
+ <img class="picture" src="emptyface.jpg"></img>\
<div style="position: absolute; left: 10px; top: 10px">\
<table></tr>\
<td class="control" style="vertical-align: middle"></td>\
@@ -113,9 +224,18 @@ function Miles(element, params) {
</div>\
</td>\
</tr>\
+ <tr><td valign="top" colspan="2" >\
+ <div class="chatOutput" style="max-height:120px; overflow: auto">\
+ </td></tr>\
+ <tr>\
+ <td valign="top" style="vertical-align: middle">\
+ <div class="chatInput">\
+ </td>\
+ <td valign="top"><div class="chatSendButton"></td>\
+ </tr>\
<tr>\
- <td valign="top">\
- <div class="messages" style="position: relative; padding: 0px">\
+ <td valign="top" colspan="2" >\
+ <div class="messages">\
</td>\
</tr>\
</table>\
@@ -123,19 +243,202 @@ function Miles(element, params) {
// from the above DOM, fetch some nodes to put dojo widgets in
self.pictureElem = dojo.query("img.picture", element)[0];
+ self.pictureElem.width = self.width;
+ self.pictureElem.height = self.height;
self.controlElem = dojo.query("td.control", element)[0];
self.messageElem = dojo.query("div.messages", element)[0];
+ self.chatOutputElem = dojo.query("div.chatOutput", element)[0];
+ self.chatOutputElem.style.fontSize = "0.8em";
+ on(self.chatOutputElem, "mouseover", function(evt) {
+ stopChatScrolling = true;
+ });
+ on(self.chatOutputElem, "mouseout", function(evt) {
+ stopChatScrolling = false;
+ });
+
+ self.chatInputElem = dojo.query("div.chatInput", element)[0];
+
+ self.chatSendButton = new Button({
+ label: "Send",
+ onClick: function(){
+ self.xhr.post({
+ // The URL to request
+ url: "http://" + scxmlURL + "/miles/chat",
+ contentType: 'text/plain',
+ postData: dojo.toJson({
+ message: chatInputElem.value
+ }),
+ error: function(err) {
+ console.log(err);
+ },
+ load: function(result) {}
+ });
+
+ }
+ }, dojo.query("div.chatSendButton", element)[0]);
+
+ // the chat interface
+ self.chatInput = new TextBox({
+ name: "chatInput",
+ style: "width: 100%",
+ }, self.chatInputElem);
- // the control dropdown button
- self.controlDropDownContent = domConst.toDom('<div />');
+
+ // the connect dropdown button
+ self.connectDropDownContent = domConst.toDom('\
+ <div>\
+ <table>\
+ <tr><td>Problem Name:</td><td><div class="problemName" /></td></tr>\
+ <tr><td>Your Email:</td><td><div class="email" /></td></tr>\
+ <!-- tr><td>Other Email:</td><td><div class="remoteEmail" /></td></tr -->\
+ <tr><td>Reflector Host:</td><td><div class="reflectorIp" /></td></tr>\
+ <tr><td>Video Server:</td><td><div class="scxmlURL" /></td></tr>\
+ <tr><td></td><td align="right"><div class="connectButton" /></td></tr>\
+ </div>\
+ ');
+ self.connectToolTip = new TooltipDialog({ content:self.connectDropDownContent, style:"max-height:320px"});
+ self.connectDropDown = new DropDownButton({ label: "Connect", dropDown: self.connectToolTip });
+
+ // Connect parameters
+ self.problemNameBox = new TextBox({
+ name: "problemName",
+ value: problemName,
+ style: "width: 100%",
+ });
+ dojo.query("div.problemName", self.connectToolTip.domNode)[0].appendChild(self.problemNameBox.domNode);
+
+ self.emailBox = new TextBox({
+ name: "email",
+ value: email,
+ style: "width: 100%",
+ });
+ dojo.query("div.email", self.connectToolTip.domNode)[0].appendChild(self.emailBox.domNode);
+
+ // self.remoteEmailBox = new TextBox({
+ // name: "remoteEmail",
+ // value: remoteEmail,
+ // style: "width: 100%",
+ // });
+ // dojo.query("div.remoteEmail", self.connectToolTip.domNode)[0].appendChild(self.remoteEmailBox.domNode);
+
+ self.reflectorIpBox = new TextBox({
+ name: "reflectorIp",
+ value: reflectorIp,
+ style: "width: 100%",
+ });
+ dojo.query("div.reflectorIp", self.connectToolTip.domNode)[0].appendChild(self.reflectorIpBox.domNode);
+
+ self.scxmlURLBox = new TextBox({
+ name: "scxmlURL",
+ value: scxmlURL,
+ style: "width: 100%",
+ });
+ dojo.query("div.scxmlURL", self.connectToolTip.domNode)[0].appendChild(self.scxmlURLBox.domNode);
+
+ self.connectButton = new Button({
+ label: "Connect",
+ onClick: function(){
+ self.connect();
+ }
+ });
+ dojo.query("div.connectButton", self.connectToolTip.domNode)[0].appendChild(self.connectButton.domNode);
+
+ // Control parameters
+ self.controlDropDownContent = domConst.toDom('\
+ <div>\
+ <table>\
+ <tr><td>Activate Camera:</td><td><div class="activateCamera" /></td></tr>\
+ <tr><td style="padding-left: 1em">Compression:</td><td><div class="videoCompression" /></td></tr>\
+ <tr><td style="padding-left: 1em">Framerate:</td><td><div class="videoFramerate" /></td></tr>\
+ <tr><td style="padding-left: 1em">Width:</td><td><div class="videoWidth" /></td></tr>\
+ <tr><td style="padding-left: 1em">Height:</td><td><div class="videoHeight" /></td></tr>\
+ <tr><td>Open Microphone:</td><td><div class="openMicrophone" /></td></tr>\
+ <tr><td style="padding-left: 1em">Encoding:</td><td><div class="audioEncoding" /></td></tr>\
+ <tr><td colspan="2"><hr /></td></tr>\
+ <tr><td>Enable Audio:</td><td><div class="enableAudio" /></td></tr>\
+ <tr><td>Show Video:</td><td><div class="showVideo" /></td></tr>\
+ <tr><td colspan="2"><hr /></td></tr>\
+ <tr><td></td><td align="right"><div class="disconnectButton" /></td></tr>\
+ </div>\
+ ');
self.controlToolTip = new TooltipDialog({ content:self.controlDropDownContent, style:"max-height:320px"});
- self.controlDropDown = new DropDownButton({ label: "Connect", dropDown: self.controlToolTip });
- self.controlElem.appendChild(self.controlDropDown.domNode);
+ self.controlDropDown = new DropDownButton({ label: "Session", dropDown: self.controlToolTip });
- // many more control widgets to be instantiated here
+ // Control parameters
+ self.activateCameraCheckbox = new CheckBox({
+ name: "activateCamera",
+ value: activateCamera,
+ checked: activateCamera,
+ });
+ dojo.query("div.activateCamera", self.controlToolTip.domNode)[0].appendChild(self.activateCameraCheckbox.domNode);
- // connect and start to fetch images from the server
- self.connect();
+ self.videoCompressionSelect = new Select({
+ name: "videoCompression",
+ value: videoCompression,
+ options: videoCompressions,
+ });
+ dojo.query("div.videoCompression", self.controlToolTip.domNode)[0].appendChild(self.videoCompressionSelect.domNode);
+
+ self.videoFramerateSpinner = new NumberSpinner({
+ name: "videoFramerate",
+ value: videoFramerate,
+ style: "width: 50px"
+ });
+ dojo.query("div.videoFramerate", self.controlToolTip.domNode)[0].appendChild(self.videoFramerateSpinner.domNode);
+
+ self.videoWidthSpinner = new NumberSpinner({
+ name: "videoWidth",
+ value: videoWidth,
+ style: "width: 50px"
+ });
+ dojo.query("div.videoWidth", self.controlToolTip.domNode)[0].appendChild(self.videoWidthSpinner.domNode);
+
+ self.videoHeightSpinner = new NumberSpinner({
+ name: "videoHeight",
+ value: videoHeight,
+ style: "width: 50px"
+ });
+ dojo.query("div.videoHeight", self.controlToolTip.domNode)[0].appendChild(self.videoHeightSpinner.domNode);
+
+ self.openMicrophoneCheckbox = new CheckBox({
+ name: "openMicrophone",
+ value: openMicrophone,
+ checked: openMicrophone,
+ });
+ dojo.query("div.openMicrophone", self.controlToolTip.domNode)[0].appendChild(self.openMicrophoneCheckbox.domNode);
+
+ self.audioEncodingSelect = new Select({
+ name: "audioEncoding",
+ value: audioEncoding,
+ options: audioEncodings,
+ });
+ dojo.query("div.audioEncoding", self.controlToolTip.domNode)[0].appendChild(self.audioEncodingSelect.domNode);
+
+ // session scoped parameters
+ self.enableAudioCheckbox = new CheckBox({
+ name: "enableAudio",
+ value: enableAudio,
+ checked: enableAudio,
+ });
+ dojo.query("div.enableAudio", self.controlToolTip.domNode)[0].appendChild(self.enableAudioCheckbox.domNode);
+
+ self.showVideo = new CheckBox({
+ name: "showVideo",
+ value: showVideo,
+ checked: showVideo,
+ });
+ dojo.query("div.showVideo", self.controlToolTip.domNode)[0].appendChild(self.showVideo.domNode);
+
+ self.disconnectButton = new Button({
+ label: "Disconnect",
+ onClick: function(){
+ self.disconnect();
+ }
+ });
+ dojo.query("div.disconnectButton", self.controlToolTip.domNode)[0].appendChild(self.disconnectButton.domNode);
+
+ // intially append the connect dropdown
+ self.controlElem.appendChild(self.connectDropDown.domNode);
})
});
diff --git a/apps/samples/miles/miles.scxml b/apps/samples/miles/miles.scxml
index 0ecca05..9b1426a 100644
--- a/apps/samples/miles/miles.scxml
+++ b/apps/samples/miles/miles.scxml
@@ -2,16 +2,25 @@
<script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" />
<state id="main">
<invoke type="miles" id="miles">
- <param name="foo" expr="'asdf'" />
<finalize>
+ <script>//dump(_event);</script>
<if cond="_event.data.origin">
<!-- <log label="Reply-length" expr="_event.data.base64.length" /> -->
- <respond status="200" to="_event.data.origin">
- <header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload -->
- <header name="Content-Type" value="text/plain" />
- <header name="Access-Control-Allow-Origin" value="*" />
- <content expr="_event.data.base64" />
- </respond>
+ <if cond="_event.name === 'thumbnail.reply'">
+ <respond status="200" to="_event.data.origin">
+ <header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload -->
+ <header name="Content-Type" value="text/plain" />
+ <content expr="_event.data.image.base64()" />
+ </respond>
+ <else />
+ <respond status="200" to="_event.data.origin">
+ <header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload -->
+ <!-- respond element will add content-type header -->
+ <content expr="_event.data" />
+ </respond>
+ </if>
+ <else />
+ <log label="Error" expr="'Event returned from invoker did not specify its origin for a reply'" />
</if>
</finalize>
</invoke>
@@ -19,49 +28,125 @@
<state id="idle">
<!-- XHR CORS preflight respond -->
<transition event="http.options" target="idle">
- <script>//dump(_event);</script>
<respond status="200" to="_event.origin">
- <header name="Access-Control-Allow-Origin" value="*" />
- <header name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" />
- <header name="Access-Control-Allow-Headers" value="X-Requested-With, Content-Type" />
+ <header name="Access-Control-Allow-Origin" value="*" /> <!-- request origins we allow -->
+ <header name="Access-Control-Allow-Methods" value="POST, GET, OPTIONS" /> <!-- http methods we allow -->
+ <header name="Access-Control-Allow-Headers"
+ value="X-Requested-With, X-Content-Encoding, Content-Type" /> <!-- headers we allow -->
</respond>
</transition>
- <transition event="http.*" target="idle">
+ <transition event="http.get" target="idle">
<script>//dump(_event);</script>
- <if cond="_event.data.pathComponent[1] === 'session'">
- <respond status="200" to="_event.origin" />
-
- <elseif cond="_event.data.pathComponent[1] === 'connect'" />
- <script>dump(_event);</script>
- <send target="#_miles" event="connect">
- <param name="reflectorIp" expr="_event.data.content.reflectorIp" />
- <param name="email" expr="_event.data.content.email" />
- <param name="problemName" expr="_event.data.content.problemName" />
+ <if cond="false">
+
+ <!-- START ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'start'" />
+ <send target="#_miles" event="start">
+ <param name="origin" expr="_event.origin" />
+ <param name="reflector" expr="_event.data.query.reflector" />
+ <param name="userId" expr="_event.data.query.userid" />
+ <param name="session" expr="_event.data.query.session" />
</send>
- <respond status="200" to="_event.origin">
- <header name="Connection" value="close" />
- <header name="Content-Type" value="application/json" />
- <header name="Access-Control-Allow-Origin" value="*" />
- </respond>
-
- <elseif cond="_event.data.pathComponent[1] === 'disconnect'" />
- <send target="#_miles" event="disconnect">
- <param name="reflectorIp" expr="_event.data.content.reflectorIp" />
- <param name="problemName" expr="_event.data.content.problemName" />
+
+ <!-- PARTICIPANTS ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'participants'" />
+ <send target="#_miles" event="participants">
+ <param name="origin" expr="_event.origin" />
+ </send>
+
+ <!-- THUMBNAIL ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'thumbnail'" />
+ <send target="#_miles" event="thumbnail">
+ <param name="origin" expr="_event.origin" />
+ <param name="userId" expr="_event.data.query.userid" />
+ </send>
+
+ <!-- VIDEO ON ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'videoon'" />
+ <send target="#_miles" event="videoon">
+ <param name="origin" expr="_event.origin" />
+ <param name="userid" expr="_event.data.query.userid" />
+ </send>
+
+ <!-- VIDEO OFF ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'videooff'" />
+ <send target="#_miles" event="videooff">
+ <param name="origin" expr="_event.origin" />
+ <param name="userid" expr="_event.data.query.userid" />
+ </send>
+
+ <!-- AUDIO ON ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'audioon'" />
+ <send target="#_miles" event="audioon">
+ <param name="origin" expr="_event.origin" />
+ <param name="userid" expr="_event.data.query.userid" />
+ </send>
+
+ <!-- AUDIO OFF ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'videooff'" />
+ <send target="#_miles" event="audiooff">
+ <param name="origin" expr="_event.origin" />
+ <param name="userid" expr="_event.data.query.userid" />
</send>
- <respond status="200" to="_event.origin" />
- <elseif cond="_event.data.pathComponent[1] === 'image'" />
- <send target="#_miles" event="image">
+ <!-- SEND VIDEO ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'sendvideo'" />
+ <send target="#_miles" event="sendvideo">
<param name="origin" expr="_event.origin" />
+ <param name="width" expr="_event.data.query.width" />
+ <param name="height" expr="_event.data.query.height" />
+ <param name="framerate" expr="_event.data.query.framerate" />
+ <param name="compression" expr="_event.data.query.compression" />
+ </send>
+
+ <!-- SEND VIDEO OFF ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'sendvideooff'" />
+ <send target="#_miles" event="sendvideooff">
+ <param name="origin" expr="_event.origin" />
+ </send>
+
+ <!-- SEND AUDIO ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'sendaudio'" />
+ <send target="#_miles" event="sendaudio">
+ <param name="origin" expr="_event.origin" />
+ <param name="encoding" expr="_event.data.query.encoding" />
+ </send>
+
+ <!-- SEND AUDIO OFF ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'sendaudiooff'" />
+ <send target="#_miles" event="sendaudiooff">
+ </send>
+
+ <!-- GET TEXT ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'gettext'" />
+ <send target="#_miles" event="gettext">
+ <param name="origin" expr="_event.origin" />
+ </send>
+
+ <else />
+ <respond status="404" to="_event.origin" />
+ </if>
+ </transition>
+
+ <transition event="http.post" target="idle">
+ <script>//dump(_event);</script>
+ <if cond="false">
+
+ <!-- POST TEXT ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'text'" />
+ <send target="#_miles" event="posttext">
+ <param name="origin" expr="_event.origin" />
+ <param name="userid" expr="_event.data.query.userid" />
+ <param name="message" expr="_event.data.content" />
</send>
<else />
<respond status="404" to="_event.origin" />
-
</if>
+
</transition>
+
</state>
</state>
</scxml> \ No newline at end of file
diff --git a/apps/samples/miles/test1.jpeg b/apps/samples/miles/test1.jpeg
index e174f89..18c9517 100644
--- a/apps/samples/miles/test1.jpeg
+++ b/apps/samples/miles/test1.jpeg
Binary files differ
diff --git a/apps/samples/miles/test2.jpeg b/apps/samples/miles/test2.jpeg
index aca2300..7fb9cc0 100644
--- a/apps/samples/miles/test2.jpeg
+++ b/apps/samples/miles/test2.jpeg
Binary files differ
diff --git a/apps/samples/miles/test3.jpeg b/apps/samples/miles/test3.jpeg
new file mode 100644
index 0000000..6ed85b0
--- /dev/null
+++ b/apps/samples/miles/test3.jpeg
Binary files differ
diff --git a/apps/samples/miles/test4.jpeg b/apps/samples/miles/test4.jpeg
new file mode 100644
index 0000000..8a623f0
--- /dev/null
+++ b/apps/samples/miles/test4.jpeg
Binary files differ
diff --git a/apps/samples/websockets/websockets.html b/apps/samples/websockets/websockets.html
new file mode 100644
index 0000000..9a21f46
--- /dev/null
+++ b/apps/samples/websockets/websockets.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+
+ <style type="text/css">
+ </style>
+
+ <script type="text/javascript">
+ </script>
+
+ <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.9.1/dojo/dojo.js"></script>
+
+ <script type="text/javascript">
+ require([
+ "dojo/domReady!",
+ "dojox/socket",
+ ], function(
+ dom,
+ Socket
+ ) {
+ var socket = new Socket("ws://localhost:8080/websockets");
+
+ function send(data){
+ return socket.send(json.stringify(data));
+ }
+
+ socket.on("connect", function(){
+ // send a handshake
+ send([
+ {
+ "channel": "/meta/handshake",
+ "version": "1.0",
+ "minimumVersion": "1.0beta",
+ "supportedConnectionTypes": ["long-polling"] // or ["callback-polling"] for x-domain
+ }
+ ])
+ socket.on("message", function(data){
+ // wait for the response so we can connect with the provided client id
+ data = json.parse(data);
+ if(data.error){
+ throw new Error(error);
+ }
+ // get the client id for all future messages
+ clientId = data.clientId;
+ // send a connect message
+ send([
+ {
+ "channel": "/meta/connect",
+ "clientId": clientId,
+ "connectionType": "long-polling"
+ },
+ { // also send a subscription message
+ "channel": "/meta/subscribe",
+ "clientId": clientId,
+ "subscription": "/foo/**"
+ }
+ ]);
+ socket.on("message", function(data){
+ console.log(data);
+ });
+ });
+ });
+ });
+ </script>
+ </head>
+ <body class="tundra">
+ <table>
+ <tr>
+ <td>
+ <div id="websockets"></div>
+ </td>
+ <td>
+ </tr>
+ </table>
+ </body>
+</html>
diff --git a/apps/samples/websockets/websockets.scxml b/apps/samples/websockets/websockets.scxml
new file mode 100644
index 0000000..0050091
--- /dev/null
+++ b/apps/samples/websockets/websockets.scxml
@@ -0,0 +1,16 @@
+<scxml datamodel="ecmascript" name="websockets">
+ <script src="http://uscxml.tk.informatik.tu-darmstadt.de/scripts/dump.js" />
+ <state id="main">
+ <transition target="main" event="http.get" cond="_event.data.header['Upgrade'] === 'websocket'">
+ <respond status="101">
+
+ </respond>
+ </transition>
+
+ <transition target="main" event="*">
+ <script>
+ dump(_event);
+ </script>
+ </transition>
+ </state>
+</scxml> \ No newline at end of file