summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-07 22:28:39 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-11-07 22:28:39 (GMT)
commit63907d01004264445645453cb8ae6eeba7ab540a (patch)
tree3d20a8e9db6e020536abfa09e21c2a8196608c58
parentbc769f1abae57cd277c31c7f0ecc0576758e83ac (diff)
parentc57b32ea2fa6b80ec35e43d190f251958665a256 (diff)
downloaduscxml-63907d01004264445645453cb8ae6eeba7ab540a.zip
uscxml-63907d01004264445645453cb8ae6eeba7ab540a.tar.gz
uscxml-63907d01004264445645453cb8ae6eeba7ab540a.tar.bz2
Merge branch 'master' of https://github.com/tklab-tud/uscxml
-rw-r--r--apps/samples/miles/miles.html6
-rw-r--r--apps/samples/miles/miles.js32
-rw-r--r--apps/samples/miles/miles.scxml25
-rw-r--r--src/uscxml/plugins/invoker/miles/.MilesSessionInvoker.cpp.swpbin0 -> 16384 bytes
-rw-r--r--src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp293
-rw-r--r--src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h12
6 files changed, 299 insertions, 69 deletions
diff --git a/apps/samples/miles/miles.html b/apps/samples/miles/miles.html
index 08cfeca..5028621 100644
--- a/apps/samples/miles/miles.html
+++ b/apps/samples/miles/miles.html
@@ -16,9 +16,9 @@
<script type="text/javascript">
require(["dojo/domReady!"], function(dom) {
var milesSession1 = new Miles("miles1");
- var milesSession2 = new Miles("miles2");
- var milesSession3 = new Miles("miles3");
- var milesSession4 = new Miles("miles4");
+ var milesSession2 = new Miles("miles2", {"scxmlURL": "localhost:8080", "reflectorIp": "88.131.107.12", "email": "user@smartvortex.eu", "problemName": "webconfero", "remoteEmail": "yetanother@smartvortex.eu"});
+ var milesSession3 = new Miles("miles3", {"scxmlURL": "localhost:8080", "reflectorIp": "88.131.107.12", "email": "user@smartvortex.eu", "problemName": "webconfero", "remoteEmail": "stillanother@smartvortex.eu"});
+ var milesSession4 = new Miles("miles4", {"scxmlURL": "localhost:8080", "reflectorIp": "88.131.107.12", "email": "user@smartvortex.eu", "problemName": "webconfero", "remoteEmail": "last@smartvortex.eu"});
});
</script>
</head>
diff --git a/apps/samples/miles/miles.js b/apps/samples/miles/miles.js
index f979266..d1efb0d 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"
@@ -60,6 +60,7 @@ function Miles(element, params) {
if (params && params.reflectorIp) reflectorIp = params.reflectorIp;
if (params && params.email) email = params.email;
if (params && params.problemName) problemName = params.problemName;
+ if (params && params.remoteEmail) remoteEmail = params.remoteEmail;
// called when dojo loaded all requirements below
this.connect = function() {
@@ -93,10 +94,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 +192,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 +299,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..c1c6c69 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">
@@ -49,7 +51,16 @@
<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="userid" expr="_event.data.query.userid" />
+ <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>
@@ -63,7 +74,7 @@
<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" />
+ <param name="userid" expr="_event.data.query.userid" />
</send>
<!-- VIDEO ON ############### -->
@@ -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..b36935c 100644
--- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
+++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.cpp
@@ -41,13 +41,11 @@ bool pluginConnect(pluma::Host& host) {
#endif
MilesSessionInvoker::MilesSessionInvoker() {
- /* Initalize Miles */
+ /* Initialize Miles */
miles_init();
- /* media buffers */
- init_media_buffers();
-
_isRunning = false;
+ num_connected = 0;
}
MilesSessionInvoker::~MilesSessionInvoker() {
@@ -75,6 +73,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 +103,74 @@ 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;
+}
+
+void MilesSessionInvoker::free_video_buffers() {
+ if(video_out_buf)
+ free(video_out_buf);
+ video_out_buf = NULL;
+ if(encoded_out_img)
+ free(encoded_out_img);
+ encoded_out_img = NULL;
+ if(render_img)
+ free(render_img);
+ render_img = NULL;
+ render_img_size = 0;
+ if(video_data)
+ free(video_data);
+ video_data = NULL;
+}
+
+void MilesSessionInvoker::free_audio_buffers() {
+ if(audio_in_buf)
+ free(audio_in_buf);
+ audio_in_buf = NULL;
+ if(audio_data)
+ free(audio_data);
+ audio_data = NULL;
+ video_data = NULL;
+ if(encoded_out_audio)
+ free(encoded_out_audio);
+ encoded_out_audio = NULL;
+ if(audio_read_buf)
+ free(audio_read_buf);
+ audio_read_buf = NULL;
+}
+
+void MilesSessionInvoker::free_text_buffers() {
+ 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 +269,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";
+ if(num_connected>0) {
+ num_connected++;
+ ev.name = "start.reply";
+ returnEvent(ev);
return;
}
@@ -213,17 +285,21 @@ 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";
+ /* set up media buffers */
+ init_media_buffers();
+
/* Set up audio and video RTP sockets */
video_rtp_in_socket = miles_net_setup_udp_socket((char*)reflector.c_str(), video_port, video_port, 10, 16000);
audio_rtp_in_socket = miles_net_setup_udp_socket((char*)reflector.c_str(), audio_port, audio_port, 10, 16000);
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 +317,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,7 +343,15 @@ 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;
+ num_connected=1;
_reflector = reflector;
_userId = userid;
_session = session;
@@ -271,29 +359,55 @@ 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(num_connected==0) {
+ LOG(ERROR) << "not connected";
+ ev.name = "stop.error";
+ returnEvent(ev);
+ return;
+ }
+ num_connected--;
+ if(num_connected>0) {
+ ev.name = "stop.reply";
+ 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();
+ /* Unregister RTCP APP handler for text messages */
+ rv = miles_rtp_unregister_rtcp_app_handler("text");
+ if(rv==0) {
+ LOG(ERROR) << "Error registering text message callback";
+ }
_isRunning = false;
- Event ev;
+ free_text_buffers();
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(num_connected==0) {
+ 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,47 +417,51 @@ 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(num_connected==0) {
+ 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 thumb_entry *use_thumb = NULL;
struct miles_rtp_in_stream *rtps;
struct miles_list *p;
struct thumb_entry *te;
_mutex.lock();
- if(video_session->instreams) {
- rtps = video_session->instreams->stream;
- if(rtps) {
- p = thumb_list;
- while(p) {
- te = (struct thumb_entry *)p->item;
- if(te->ssrc == rtps->ssrc) {
- break;
- }
- p = p->next;
- }
- if(p) {
- has_thumb = 1;
- ev.data.compound["image"] = Data(te->img_buf, te->img_size, "image/jpeg");
- }
+ // Find thumbnail of user
+ p = thumb_list;
+ while(p) {
+ te = (struct thumb_entry *)p->item;
+ if(te->userid && strcmp(te->userid, userid.c_str()) == 0) {
+ use_thumb = te;
+ break;
}
- }
- if(!has_thumb) {
- // Return empty face image
- ev.data.compound["image"] = Data(imageContent.data(), imageContent.size(), "image/jpeg");
+ if(te->userid==NULL && use_thumb == NULL) {
+ use_thumb = te;
+ }
+ p = p->next;
+ }
+ if(!p && use_thumb)
+ use_thumb->userid = strdup(userid.c_str());
+ if(use_thumb) {
+ ev.data.compound["image"] = Data(use_thumb->img_buf, use_thumb->img_size, "image/jpeg");
+ } else {
+ // Return empty face image
+ ev.data.compound["image"] = Data(imageContent.data(), imageContent.size(), "image/jpeg");
}
_mutex.unlock();
@@ -378,6 +496,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,33 +504,67 @@ 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;
+ if(num_connected==0) {
+ LOG(ERROR) << "not connected";
+ ev.name = "posttext.error";
+ returnEvent(ev);
+ return;
+ }
+ ev.name = "posttext.reply";
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(num_connected==0) {
+ LOG(ERROR) << "not connected";
+ ev.name = "gettext.error";
+ returnEvent(ev);
+ return;
+ }
- 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.name = "gettext.reply";
+ 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;
}
returnEvent(ev);
@@ -428,19 +581,57 @@ 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);
}
+ /* done, clean up */
+ if(video_grabber_available) {
+ miles_rtp_destroy_out_stream(out_rtp_video_stream);
+ miles_video_grabber_destroy(video_grabber);
+ miles_video_codec_destroy_encoder(video_encoder);
+ video_grabber_available = 0;
+ sendvideo_enabled = 0;
+ }
+ miles_rtp_destroy_session(video_session);
+ miles_list_destroy(thumb_list);
+ thumb_list = NULL;
+ miles_net_socket_close(video_rtp_in_socket);
+ miles_net_socket_close(video_rtcp_in_socket);
+
+ free_video_buffers();
}
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);
}
+ /* done, clean up */
+ if(audio_available) {
+ miles_rtp_destroy_out_stream(out_rtp_audio_stream);
+ if(audio_dev_playback)
+ miles_audio_device_close(MILES_AUDIO_IO_OPENAL, audio_dev_playback, 0);
+ if(audio_dev)
+ miles_audio_device_close(MILES_AUDIO_IO_OPENAL, audio_dev_playback, 1);
+ miles_audio_codec_destroy_encoder(audio_encoder);
+ audio_available = 0;
+ sendaudio_enabled = 0;
+ }
+ miles_rtp_destroy_session(audio_session);
+ miles_net_socket_close(audio_rtp_in_socket);
+ miles_net_socket_close(audio_rtcp_in_socket);
+
+ free_video_buffers();
}
int MilesSessionInvoker::setup_audio() {
+ /* Check that we have OpeanAL audio */
+ if(!miles_audio_io_is_supported(MILES_AUDIO_IO_OPENAL)) {
+ fprintf(stderr, "OpenAL audio i/o not supported on this platform.\n");
+ return 0;
+ }
+
/* Initialize and configure audio encoder */
audio_encoder = miles_audio_codec_init_encoder();
audio_encoder->codec_id = miles_audio_codec_get_encoder_for_rtp_payload_type(MILES_RTP_PAYLOAD_TYPE_L16);
@@ -454,10 +645,9 @@ int MilesSessionInvoker::setup_audio() {
LOG(ERROR) << "Couldn't set up audio codec";
return 0;
}
- LOG(ERROR) << "audio enc set up";
/* Set up audio grabber */
- int n = miles_audio_device_get_supported_devices(MILES_AUDIO_DEVICE_OPENAL, &supported_audio_devices);
+ int n = miles_audio_device_get_supported_devices(MILES_AUDIO_IO_OPENAL, &supported_audio_devices);
if(n<=0) {
/* No audio device available */
LOG(ERROR) << "No audio device available";
@@ -465,7 +655,7 @@ int MilesSessionInvoker::setup_audio() {
}
/* Use first device that supports capture */
for(int i=0; i<n; i++) {
- audio_dev = miles_audio_device_open(MILES_AUDIO_DEVICE_OPENAL, supported_audio_devices[i].id, MILES_AUDIO_FORMAT_PCM, 16000, 2, 1, 640, 1);
+ audio_dev = miles_audio_device_open(MILES_AUDIO_IO_OPENAL, supported_audio_devices[i].id, MILES_AUDIO_FORMAT_PCM, 16000, 2, 1, 640, 1);
if(audio_dev)
break;
}
@@ -476,7 +666,7 @@ int MilesSessionInvoker::setup_audio() {
/* Find first audio device that supports playback */
for(int i=0; i<n; i++) {
- audio_dev_playback = miles_audio_device_open(MILES_AUDIO_DEVICE_OPENAL, supported_audio_devices[i].id, MILES_AUDIO_FORMAT_PCM, 16000, 2, 1, 640, 0);
+ audio_dev_playback = miles_audio_device_open(MILES_AUDIO_IO_OPENAL, supported_audio_devices[i].id, MILES_AUDIO_FORMAT_PCM, 16000, 2, 1, 640, 0);
if(audio_dev_playback) {
audio_dev_playback_id = supported_audio_devices[i].id;
break;
@@ -594,14 +784,14 @@ void MilesSessionInvoker::playback_audio(u_int32_t ssrc, char *buf, int sample_r
if(audio_dev_playback == NULL || audio_dev_playback->chunk_size != size || audio_dev_playback->sample_rate != sample_rate ||
audio_dev_playback->format != audio_format || audio_dev_playback->bytes_per_sample != bps) {
if(audio_dev_playback)
- miles_audio_device_close(MILES_AUDIO_DEVICE_OPENAL, audio_dev_playback, 0);
- audio_dev_playback = miles_audio_device_open(MILES_AUDIO_DEVICE_OPENAL, audio_dev_playback_id, audio_format, sample_rate, bps, 1, size, 0);
+ miles_audio_device_close(MILES_AUDIO_IO_OPENAL, audio_dev_playback, 0);
+ audio_dev_playback = miles_audio_device_open(MILES_AUDIO_IO_OPENAL, audio_dev_playback_id, audio_format, sample_rate, bps, 1, size, 0);
if(audio_dev_playback == NULL)
return;
}
/* play audio */
- miles_audio_device_write(MILES_AUDIO_DEVICE_OPENAL, audio_dev_playback, buf, size);
+ miles_audio_device_write(MILES_AUDIO_IO_OPENAL, audio_dev_playback, buf, size);
}
/**
@@ -655,6 +845,7 @@ int MilesSessionInvoker::video_receiver(struct miles_rtp_in_stream *rtp_stream,
p = miles_list_append(thumb_list, te);
te->ssrc = rtp_stream->ssrc;
te->window_ctx = NULL;
+ te->userid = NULL;
te->img_buf = (char *)malloc(bytes_read);
te->buf_size = bytes_read;
te->img_size = 0;
@@ -842,7 +1033,7 @@ int MilesSessionInvoker::audio_transmitter(struct miles_audio_device *dev, struc
/* Send RTCP packets, if due */
miles_rtp_send_rtcp(out_rtcp_audio_stream);
- n = miles_audio_device_read(MILES_AUDIO_DEVICE_OPENAL, dev, audio_read_buf, codec_ctx->chunk_size);
+ n = miles_audio_device_read(MILES_AUDIO_IO_OPENAL, dev, audio_read_buf, codec_ctx->chunk_size);
if(n <= 0)
return 0;
if(dev->format != codec_ctx->input_format) {
diff --git a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
index 32d4610..fec2243 100644
--- a/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
+++ b/src/uscxml/plugins/invoker/miles/MilesSessionInvoker.h
@@ -27,6 +27,7 @@ extern "C" {
#include "miles/network.h"
#include "miles/rtp.h"
#include "miles/audio_codec.h"
+#include "miles/audio_io.h"
#include "miles/audio_device.h"
#include "miles/video_codec.h"
#include "miles/video_grabber.h"
@@ -50,6 +51,7 @@ struct thumb_entry {
int img_format; // JPEG or PNG image
char *decode_buf;
u_int32_t ssrc;
+ char *userid; // The user id assigned to the video stream
void *window_ctx; // The context of the window popped up when the thumbnail is clicked.
};
@@ -120,10 +122,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);
@@ -134,6 +141,10 @@ protected:
void init_media_buffers();
void free_media_buffers();
+ void free_video_buffers();
+ void free_audio_buffers();
+ void free_text_buffers();
+
void render_video_image(char *img, int width, int height, int img_format);
void playback_audio(u_int32_t ssrc, char *buf, int sample_rate, int bps, int audio_format, int size);
int video_receiver(struct miles_rtp_in_stream *rtp_stream, char *data, int bytes_read);
@@ -145,6 +156,7 @@ protected:
bool _isRunning;
+ int num_connected;
std::string _userId, _reflector, _session;
tthread::thread* _videoThread;
tthread::thread* _audioThread;