diff options
author | Stefan Radomski <github@mintwerk.de> | 2013-11-07 00:00:47 (GMT) |
---|---|---|
committer | Stefan Radomski <github@mintwerk.de> | 2013-11-07 00:00:47 (GMT) |
commit | b2d7e26223288d0e555e8b72ef987be93d2d89ba (patch) | |
tree | fdd78fe7f47bfbbeaac32514d89fcafc1da45200 | |
parent | 62eed0a72b0a133bcec94131e7fd74415b87ba90 (diff) | |
parent | c3238c9a5c627491d26ad527f99a08ccfd218c29 (diff) | |
download | uscxml-b2d7e26223288d0e555e8b72ef987be93d2d89ba.zip uscxml-b2d7e26223288d0e555e8b72ef987be93d2d89ba.tar.gz uscxml-b2d7e26223288d0e555e8b72ef987be93d2d89ba.tar.bz2 |
Merge pull request #6 from mathiasjohanson/master
text messaging
-rw-r--r-- | apps/samples/miles/miles.js | 31 | ||||
-rw-r--r-- | apps/samples/miles/miles.scxml | 21 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp | bin | 0 -> 16384 bytes | |||
-rw-r--r-- | src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp | 129 | ||||
-rw-r--r-- | src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h | 5 |
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 Binary files differnew file mode 100644 index 0000000..368f327 --- /dev/null +++ b/src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swp 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); |