summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/samples/miles/miles.js31
-rw-r--r--apps/samples/miles/miles.scxml21
-rw-r--r--src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swpbin0 -> 16384 bytes
-rw-r--r--src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp129
-rw-r--r--src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h5
5 files changed, 160 insertions, 26 deletions
diff --git a/apps/samples/miles/miles.js b/apps/samples/miles/miles.js
index f979266..451306b 100644
--- a/apps/samples/miles/miles.js
+++ b/apps/samples/miles/miles.js
@@ -12,8 +12,8 @@ function Miles(element, params) {
this.connected = false;
this.imageIteration = 0;
- this.width = 300;
- this.height = 200;
+ this.width = 320;
+ this.height = 240;
// private attributes
var scxmlURL = "localhost:8080"
@@ -93,10 +93,25 @@ function Miles(element, params) {
}
this.disconnect = function() {
- self.connected = false;
- hideChat();
- self.controlDropDown.dropDown.onCancel(true);
- self.controlElem.replaceChild(self.connectDropDown.domNode, self.controlDropDown.domNode);
+ 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/stop" + query,
+ // handleAs:"text",
+ error: function(err) {
+ console.log(err);
+ },
+ load: function(result) {
+ self.connected = false;
+ hideChat();
+ self.controlDropDown.dropDown.onCancel(true);
+ self.controlElem.replaceChild(self.connectDropDown.domNode, self.controlDropDown.domNode);
+ }
+ });
}
var hideChat = function() {
@@ -176,7 +191,7 @@ function Miles(element, params) {
},
load: function(result) {
if (result.message) {
- self.chatOutputElem.innerHTML += stopChatScrolling + " " + Math.random() + ": " + result.message + '<br />';
+ self.chatOutputElem.innerHTML += result.message + '<br />';
if (!stopChatScrolling)
self.chatOutputElem.scrollTop = self.chatOutputElem.scrollHeight;
}
@@ -283,7 +298,7 @@ function Miles(element, params) {
self.chatSendButton = new Button({
label: "Send",
onClick: function(){
- alert(self.chatInput.value);
+ //alert(self.chatInput.value);
self.xhr.post({
// The URL to request
url: "http://" + scxmlURL + "/miles/text",
diff --git a/apps/samples/miles/miles.scxml b/apps/samples/miles/miles.scxml
index 650add8..2cad7ba 100644
--- a/apps/samples/miles/miles.scxml
+++ b/apps/samples/miles/miles.scxml
@@ -3,7 +3,7 @@
<state id="main">
<invoke type="miles" id="miles">
<finalize>
- <log label="out" expr="_event.name" />
+ <!-- <log label="out" expr="_event.name" /> -->
<script>//dump(_event);</script>
<if cond="_event.data.origin">
<!-- <log label="Reply-length" expr="_event.data.base64.length" /> -->
@@ -12,6 +12,7 @@
<header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload -->
<header name="Access-Control-Allow-Origin" value="*" />
<header name="Content-Type" value="text/plain" />
+ <header name="Access-Control-Allow-Origin" value="*" />
<content expr="_event.data.image.base64()" />
</respond>
<else />
@@ -19,6 +20,7 @@
<header name="Cache-Control" value="no-cache" /> <!-- force IE to actually reload -->
<header name="Access-Control-Allow-Origin" value="*" />
<!-- respond element will add content-type header -->
+ <header name="Access-Control-Allow-Origin" value="*" />
<content expr="_event.data" />
</respond>
</if>
@@ -40,7 +42,7 @@
</transition>
<transition event="http.get" target="idle">
- <log label="in" expr="_event.data.path" />
+ <!-- <log label="in" expr="_event.data.path" /> -->
<script>//dump(_event);</script>
<if cond="false">
@@ -53,6 +55,15 @@
<param name="session" expr="_event.data.query.session" />
</send>
+ <!-- STOP ############### -->
+ <elseif cond="_event.data.pathComponent[1] === 'stop'" />
+ <send target="#_miles" event="stop">
+ <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>
+
<!-- PARTICIPANTS ############### -->
<elseif cond="_event.data.pathComponent[1] === 'participants'" />
<send target="#_miles" event="participants">
@@ -135,8 +146,8 @@
</transition>
<transition event="http.post" target="idle">
- <log label="in" expr="_event.data.path" />
- <script>dump(_event);</script>
+ <!-- <log label="in" expr="_event.data.path" /> -->
+ <script>//dump(_event);</script>
<if cond="false">
<!-- POST TEXT ############### -->
@@ -155,4 +166,4 @@
</state>
</state>
-</scxml> \ No newline at end of file
+</scxml>
diff --git a/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp b/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp
new file mode 100644
index 0000000..368f327
--- /dev/null
+++ b/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp
Binary files differ
diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
index d4a709b..b45a324 100644
--- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
+++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
@@ -75,6 +75,8 @@ void MilesSessionInvoker::init_media_buffers() {
encoded_out_audio = NULL;
audio_read_buf = NULL;
video_data = (char *)malloc(1000000);
+ text_msg_buf = (char *)malloc(1000);
+ text_msg_available = 0;
}
void MilesSessionInvoker::free_media_buffers() {
@@ -103,6 +105,35 @@ void MilesSessionInvoker::free_media_buffers() {
if(audio_read_buf)
free(audio_read_buf);
audio_read_buf = NULL;
+ if(text_msg_buf)
+ free(text_msg_buf);
+ text_msg_buf = NULL;
+ text_msg_available = 0;
+}
+
+// Yes, sort of ugly...
+char confero_text_msg_buf[1000];
+int confero_text_msg_available = 0;
+
+int receive_text_message_callback(u_int32_t ssrc, char *pkt, int length) {
+ char cname[100];
+ int i=0, j;
+
+ while(pkt[i]) {
+ cname[i] = pkt[i];
+ i++;
+ }
+ cname[i++] = 0;
+ j = i;
+ while(pkt[j] && j<length) {
+ if(pkt[j]=='<' || pkt[j]=='>' || pkt[j]=='\r' || pkt[j]=='\n')
+ pkt[j] = ' ';
+ j++;
+ }
+ memcpy(confero_text_msg_buf, pkt+i, length-i);
+ //printf("RTCP app depacketizer called, cname = %s, msg = %s\n", cname, confero_text_msg_buf);
+ confero_text_msg_available = 1;
+ return length;
}
void MilesSessionInvoker::send(const SendRequest& req) {
@@ -201,9 +232,13 @@ void MilesSessionInvoker::send(const SendRequest& req) {
void MilesSessionInvoker::processEventStart(const std::string& origin, const std::string& userid, const std::string& reflector, const std::string& session) {
+ Event ev;
+ ev.data.compound["origin"] = origin;
//std::cout << req;
if(_isRunning) {
LOG(ERROR) << "already connected";
+ ev.name = "start.error";
+ returnEvent(ev);
return;
}
@@ -213,6 +248,8 @@ void MilesSessionInvoker::processEventStart(const std::string& origin, const std
rv = miles_connect_reflector_session((char*)reflector.c_str(), (char*)session.c_str());
if (!rv) {
LOG(ERROR) << "Could not setup reflector session";
+ ev.name = "start.error";
+ returnEvent(ev);
return;
}
LOG(ERROR) << "session set up";
@@ -223,7 +260,6 @@ void MilesSessionInvoker::processEventStart(const std::string& origin, const std
video_rtp_out_socket = video_rtp_in_socket;
audio_rtp_out_socket = audio_rtp_in_socket;
- LOG(ERROR) << "rtp sockets set up";
/* Set up audio and video RTCP sockets */
video_rtcp_in_socket = miles_net_setup_udp_socket((char*)reflector.c_str(), video_port+1, video_port+1, 10, 16000);
@@ -241,9 +277,13 @@ void MilesSessionInvoker::processEventStart(const std::string& origin, const std
/* Set up video capture */
video_grabber_available = setup_video_grabber();
+ if(video_grabber_available)
+ sendvideo_enabled = 1;
/* Set up audio capture/playback */
audio_available = setup_audio();
+ if(audio_available)
+ sendaudio_enabled = 1;
/* Set up outgoing RTP stream for video */
if(video_grabber_available) {
@@ -263,6 +303,13 @@ void MilesSessionInvoker::processEventStart(const std::string& origin, const std
out_rtcp_audio_stream = miles_rtp_setup_outgoing_rtcp_stream(audio_session->rtcp_session, audio_rtcp_out_socket, out_rtp_audio_stream->ssrc);
}
+ /* Register RTCP APP handler for text messages */
+ rv = miles_rtp_register_rtcp_app_handler("text", NULL, receive_text_message_callback, 0);
+ if(rv==0) {
+ LOG(ERROR) << "Error registering text message callback";
+ }
+ memset(confero_text_msg_buf, 0, 1000);
+
_isRunning = true;
_reflector = reflector;
_userId = userid;
@@ -271,29 +318,44 @@ void MilesSessionInvoker::processEventStart(const std::string& origin, const std
if(audio_available)
_audioThread = new tthread::thread(MilesSessionInvoker::runAudio, this);
_videoThread = new tthread::thread(MilesSessionInvoker::runVideo, this);
- Event ev;
ev.name = "start.reply";
- ev.data.compound["origin"] = origin;
returnEvent(ev);
}
void MilesSessionInvoker::processEventStop(const std::string& origin) {
+ Event ev;
+ ev.data.compound["origin"] = origin;
+
+ if(!_isRunning) {
+ LOG(ERROR) << "not connected";
+ ev.name = "stop.error";
+ returnEvent(ev);
+ return;
+ }
int rv = miles_disconnect_reflector_session((char*)_reflector.c_str(), (char*)_session.c_str());
if (!rv) {
LOG(ERROR) << "Could not disconnect from reflector session";
+ ev.name = "stop.error";
+ returnEvent(ev);
return;
}
free_media_buffers();
_isRunning = false;
- Event ev;
ev.name = "stop.reply";
- ev.data.compound["origin"] = origin;
returnEvent(ev);
+ LOG(ERROR) << "disconnected from reflector session";
}
void MilesSessionInvoker::processEventParticipants(const std::string& origin) {
Event ev;
+ ev.data.compound["origin"] = origin;
+ if(!_isRunning) {
+ LOG(ERROR) << "not connected";
+ ev.name = "participants.error";
+ returnEvent(ev);
+ return;
+ }
// create an array with objects inside
for (int i = 0; i < 5; i++) {
Data userInfo;
@@ -303,21 +365,25 @@ void MilesSessionInvoker::processEventParticipants(const std::string& origin) {
}
ev.name = "participants.reply";
- ev.data.compound["origin"] = origin;
returnEvent(ev);
-
}
+
void MilesSessionInvoker::processEventThumbnail(const std::string& origin, const std::string& userid) {
- LOG(ERROR) << "processEventThumbnail";
+ Event ev;
+ ev.data.compound["origin"] = origin;
+ if(!_isRunning) {
+ LOG(ERROR) << "not connected";
+ ev.name = "thumbnail.error";
+ returnEvent(ev);
+ return;
+ }
URL imageURL("emptyface.jpg");
imageURL.toAbsolute(_interpreter->getBaseURI());
std::stringstream ssImage;
ssImage << imageURL;
std::string imageContent = ssImage.str();
- Event ev;
ev.name = "thumbnail.reply";
- ev.data.compound["origin"] = origin;
int has_thumb = 0;
struct miles_rtp_in_stream *rtps;
@@ -378,6 +444,7 @@ void MilesSessionInvoker::processEventSendVideo(const std::string& origin, size_
Event ev;
ev.name = "sendvideo.reply";
ev.data.compound["origin"] = origin;
+ sendvideo_enabled = 1;
returnEvent(ev);
}
void MilesSessionInvoker::processEventSendVideoOff(const std::string& origin) {
@@ -385,34 +452,69 @@ void MilesSessionInvoker::processEventSendVideoOff(const std::string& origin) {
ev.name = "sendvideooff.reply";
ev.data.compound["origin"] = origin;
returnEvent(ev);
+ sendvideo_enabled = 0;
}
void MilesSessionInvoker::processEventSendAudio(const std::string& origin, const std::string& encoding) {
Event ev;
ev.name = "sendaudio.reply";
ev.data.compound["origin"] = origin;
returnEvent(ev);
+ sendaudio_enabled = 1;
}
void MilesSessionInvoker::processEventSendAudioOff(const std::string& origin) {
Event ev;
ev.name = "sendaudiooff.reply";
ev.data.compound["origin"] = origin;
returnEvent(ev);
+ sendaudio_enabled = 0;
}
void MilesSessionInvoker::processEventPostText(const std::string& origin, const std::string& userid, const std::string& message) {
+ char msgbuf[1000];
+ char pkt[1000];
+ char *cname = "user@all"; // for now
+ int n, length;
Event ev;
+
ev.name = "posttext.reply";
ev.data.compound["origin"] = origin;
returnEvent(ev);
+ if(out_rtcp_video_stream==NULL)
+ return;
+ //printf("sending message %s\n", message.c_str());
+ memcpy(msgbuf, cname, strlen(cname)+1);
+ sprintf(msgbuf+strlen(cname)+1, "<%s>: %s", userid.c_str(), message.c_str());
+ n = strlen(cname)+1 + userid.length() + 4 + message.length();
+ length = miles_rtp_make_rtcp_app(pkt, out_rtcp_video_stream->ssrc, "text", n, msgbuf);
+ if(length>0 && out_rtcp_video_stream)
+ out_rtcp_video_stream->send_packet(out_rtcp_video_stream->socket, pkt, length, 0);
}
+
void MilesSessionInvoker::processEventGetText(const std::string& origin) {
Event ev;
- ev.name = "gettext.reply";
ev.data.compound["origin"] = origin;
+ if(!_isRunning) {
+ LOG(ERROR) << "not connected";
+ ev.name = "gettext.error";
+ returnEvent(ev);
+ return;
+ }
+ ev.name = "gettext.reply";
+#if 0
if (rand() % 5 == 0) { // return some mocked up chat message
ev.data.compound["message"] = Data(".. and then she was all like: aren't we supposed to discuss work related stuff?", Data::VERBATIM);
ev.data.compound["user"] = Data("username1", Data::VERBATIM);
}
+#else
+ if(confero_text_msg_available) {
+ strcpy(text_msg_buf, confero_text_msg_buf);
+ ev.data.compound["message"] = Data(text_msg_buf, Data::VERBATIM);
+ //ev.data.compound["message"] = Data(base64_encode(text_msg_buf, strlen(text_msg_buf)), Data::VERBATIM);
+ ev.data.compound["user"] = Data("username1", Data::VERBATIM);
+ memset(confero_text_msg_buf, 0, 1000);
+ confero_text_msg_available = 0;
+ }
+#endif
returnEvent(ev);
}
@@ -428,7 +530,7 @@ void MilesSessionInvoker::runVideo(void* instance) {
void MilesSessionInvoker::processVideo() {
while(_isRunning) {
rtp_video_receiver(video_session);
- if(video_grabber_available)
+ if(video_grabber_available && sendvideo_enabled)
video_transmitter(video_grabber, video_encoder, out_rtp_video_stream, out_rtcp_video_stream);
}
}
@@ -436,7 +538,8 @@ void MilesSessionInvoker::processVideo() {
void MilesSessionInvoker::processAudio() {
while(_isRunning) {
rtp_audio_receiver(audio_session);
- audio_transmitter(audio_dev, audio_encoder, out_rtp_audio_stream, out_rtcp_audio_stream);
+ if(audio_available && sendaudio_enabled)
+ audio_transmitter(audio_dev, audio_encoder, out_rtp_audio_stream, out_rtcp_audio_stream);
}
}
diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
index 32d4610..eeb6e7c 100644
--- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
+++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
@@ -120,10 +120,15 @@ protected:
struct miles_list *thumb_list;
int save_image;
+ char *text_msg_buf;
+ int text_msg_available;
+
struct miles_audio_device *audio_dev_playback;
int audio_dev_playback_id;
int audio_available;
int video_grabber_available;
+ int sendvideo_enabled;
+ int sendaudio_enabled;
static void runAudio(void* instance);
static void runVideo(void* instance);