<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[Freeswitch-trunk][14166] </title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<div id="header">FreeSWITCH Subversion</div>
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=14166">14166</a></dd>
<dt>Author</dt> <dd>brian</dd>
<dt>Date</dt> <dd>2009-07-09 10:19:27 -0500 (Thu, 09 Jul 2009)</dd>
</dl>
<h3>Log Message</h3>
<pre>commit dbea6143d6b63765f2d0eba26728c3903d3d2606
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Wed Jul 8 17:37:24 2009 +0000
Added yet another buffer of media frames mpf_frame_buffer.
There are a number of similar buffers (mpf_jitter_buffer, mpf_buffer, mpf_frame_buffer). All of them produce mpf_frames as output, but input is somewhat dif
ferent. Input is RTP payload in case of mpf_jitter_buffer, synthesized chunks of voice in case of mpf_buffer, and mpf_frame in case of mpf_frame_buffer
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1043 f001bc3a-424a-0410-80a0-a715b8f413a8
commit 1bf7a66012180649bd1f01fd72e483a9e5de3495
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Wed Jul 8 16:33:36 2009 +0000
Fixed termination of client and server stacks (<a href="http://jira.freeswitch.org/browse/Issue-28">Issue-28</a>)
Network client/server stacks generated double TERMINATE_COMPLETE event, while mpf engine generated no TERMINATE_COMPLETE event.
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1042 f001bc3a-424a-0410-80a0-a715b8f413a8
commit 0327cf17779430b51290d22cc7d51130f997f2f2
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Sun Jul 5 19:22:31 2009 +0000
Enhanced flite plugin to
- support more than one SPEAK requests in a session (SPEAK -> STOP -> SPEAK or SPEAK-> SPEAK-COMPLETE->SPEAK), task is created upon channel creation and is
waiting for consecutive SPEAK requests to process
- properly handle race between STOP request and SPEAK-COMPLETE event
- respond with IN-PROGRESS, when all the required parameters are checked to be valid and synthesizing is due to start
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1037 f001bc3a-424a-0410-80a0-a715b8f413a8
commit e2f73f9279e54ef3a40cb637a38ab1ff485ea5d3
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Sun Jul 5 03:46:13 2009 +0000
Separated flite voices (unified voice register/unregister routine, select voice by name)
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1036 f001bc3a-424a-0410-80a0-a715b8f413a8
commit 694783a527cb795ca45982c2388895da06dd6009
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Sat Jul 4 05:06:17 2009 +0000
Checked content-type to be "text/plain" as flite doesn't support SSML yet.
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1035 f001bc3a-424a-0410-80a0-a715b8f413a8
commit aafdc6e30e77c40e5470cce844f48ec28a254786
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Fri Jul 3 14:55:10 2009 +0000
Enhanced float value generation to use the precision (digits after decimal sign) user provides by removing optional trailing 0s (if any)
<a href="http://jira.freeswitch.org/browse/Issue-35">Issue-35</a>
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1034 f001bc3a-424a-0410-80a0-a715b8f413a8
commit bcc2f137956f5c532c0256b064c8a3d1015a46d0
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date: Fri Jul 3 07:04:07 2009 +0000
Enhanced RTP port management (<a href="http://jira.freeswitch.org/browse/Issue-34">Issue-34</a>, Thanks cpsoares)
git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1033 f001bc3a-424a-0410-80a0-a715b8f413a8</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunklibsunimrcpupdate">freeswitch/trunk/libs/unimrcp/.update</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_text_streamh">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_net_client_taskc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_net_server_taskc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_text_streamc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfMakefileam">freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfmpfvcproj">freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_enginec">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_rtp_streamc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpfliteMakefileam">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpflitemrcpflitevcproj">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/mrcpflite.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpflitesrcmrcp_flitec">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_frame_bufferh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_frame_bufferc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c</a></li>
<li>freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/</li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpfliteincludeflite_voicesh">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpflitesrcflite_voicesc">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunklibsunimrcpupdate"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/.update (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/.update        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/.update        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -1 +1 @@
</span><del>-Wed Jul 1 19:53:07 CDT 2009
</del><ins>+Thu Jul 9 10:17:26 CDT 2009
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_text_streamh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -22,8 +22,6 @@
</span><span class="cx"> * @brief Text Stream Parse/Generate Routine
</span><span class="cx"> */
</span><span class="cx">
</span><del>-#include <stdlib.h>
-#include <stdio.h>
</del><span class="cx"> #include "apt_string.h"
</span><span class="cx"> #include "apt_pair.h"
</span><span class="cx">
</span><span class="lines">@@ -95,40 +93,17 @@
</span><span class="cx"> /** Generate boolean-value */
</span><span class="cx"> APT_DECLARE(apt_bool_t) apt_boolean_value_generate(apt_bool_t value, apt_text_stream_t *str);
</span><span class="cx">
</span><del>-
</del><span class="cx"> /** Parse size_t value */
</span><del>-static APR_INLINE apr_size_t apt_size_value_parse(const apt_str_t *str)
-{
-        return str->buf ? atol(str->buf) : 0;
-}
</del><ins>+APT_DECLARE(apr_size_t) apt_size_value_parse(const apt_str_t *str);
</ins><span class="cx">
</span><span class="cx"> /** Generate apr_size_t value */
</span><del>-static APR_INLINE apt_bool_t apt_size_value_generate(apr_size_t value, apt_text_stream_t *stream)
-{
-        int length = sprintf(stream->pos, "%"APR_SIZE_T_FMT, value);
-        if(length <= 0) {
-                return FALSE;
-        }
-        stream->pos += length;
-        return TRUE;
-}
</del><ins>+APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_text_stream_t *stream);
</ins><span class="cx">
</span><span class="cx"> /** Parse float value */
</span><del>-static APR_INLINE float apt_float_value_parse(const apt_str_t *str)
-{
-        return str->buf ? (float)atof(str->buf) : 0;
-}
</del><ins>+APT_DECLARE(float) apt_float_value_parse(const apt_str_t *str);
</ins><span class="cx">
</span><span class="cx"> /** Generate float value */
</span><del>-static APR_INLINE apt_bool_t apt_float_value_generate(float value, apt_text_stream_t *stream)
-{
-        int length = sprintf(stream->pos,"%.2f",value);
-        if(length <= 0) {
-                return FALSE;
-        }
-        stream->pos += length;
-        return TRUE;
-}
</del><ins>+APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_text_stream_t *stream);
</ins><span class="cx">
</span><span class="cx"> /** Generate string value */
</span><span class="cx"> static APR_INLINE apt_bool_t apt_string_value_generate(const apt_str_t *str, apt_text_stream_t *stream)
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_net_client_taskc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -300,8 +300,6 @@
</span><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         apt_net_client_task_pollset_destroy(task);
</span><del>-
-        apt_task_child_terminate(task->base);
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_net_server_taskc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -350,8 +350,6 @@
</span><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         apt_net_server_task_pollset_destroy(task);
</span><del>-
-        apt_task_child_terminate(task->base);
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_text_streamc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -14,6 +14,8 @@
</span><span class="cx"> * limitations under the License.
</span><span class="cx"> */
</span><span class="cx">
</span><ins>+#include <stdlib.h>
+#include <stdio.h>
</ins><span class="cx"> #include <apr_uuid.h>
</span><span class="cx"> #include "apt_text_stream.h"
</span><span class="cx">
</span><span class="lines">@@ -307,7 +309,46 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+/** Parse size_t value */
+APT_DECLARE(apr_size_t) apt_size_value_parse(const apt_str_t *str)
+{
+        return str->buf ? atol(str->buf) : 0;
+}
</ins><span class="cx">
</span><ins>+/** Generate apr_size_t value */
+APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_text_stream_t *stream)
+{
+        int length = sprintf(stream->pos, "%"APR_SIZE_T_FMT, value);
+        if(length <= 0) {
+                return FALSE;
+        }
+        stream->pos += length;
+        return TRUE;
+}
+
+/** Parse float value */
+APT_DECLARE(float) apt_float_value_parse(const apt_str_t *str)
+{
+        return str->buf ? (float)atof(str->buf) : 0;
+}
+
+/** Generate float value */
+APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_text_stream_t *stream)
+{
+        char *end;
+        int length = sprintf(stream->pos,"%f",value);
+        if(length <= 0) {
+                return FALSE;
+        }
+
+        /* remove trailing 0s (if any) */
+        end = stream->pos + length -1;
+        while(*end == 0x30 && end != stream->pos) end--;
+
+        stream->pos = end + 1;
+        return TRUE;
+}
+
</ins><span class="cx"> /** Generate value plus the length (number of digits) of the value itself. */
</span><span class="cx"> APT_DECLARE(apt_bool_t) apt_var_length_value_generate(apr_size_t *value, apr_size_t max_count, apt_str_t *str)
</span><span class="cx"> {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -20,6 +20,7 @@
</span><span class="cx"> include/mpf_context.h \
</span><span class="cx"> include/mpf_engine.h \
</span><span class="cx"> include/mpf_frame.h \
</span><ins>+ include/mpf_frame_buffer.h \
</ins><span class="cx"> include/mpf_message.h \
</span><span class="cx"> include/mpf_object.h \
</span><span class="cx"> include/mpf_stream.h \
</span><span class="lines">@@ -55,6 +56,7 @@
</span><span class="cx"> src/mpf_termination.c \
</span><span class="cx"> src/mpf_rtp_termination_factory.c \
</span><span class="cx"> src/mpf_file_termination_factory.c \
</span><ins>+ src/mpf_frame_buffer.c \
</ins><span class="cx"> src/mpf_timer.c \
</span><span class="cx"> src/mpf_encoder.c \
</span><span class="cx"> src/mpf_decoder.c \
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_frame_bufferh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h (0 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h         (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -0,0 +1,50 @@
</span><ins>+/*
+ * Copyright 2008 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MPF_FRAME_BUFFER_H__
+#define __MPF_FRAME_BUFFER_H__
+
+/**
+ * @file mpf_frame_buffer.h
+ * @brief Buffer of Media Frames
+ */
+
+#include "mpf_frame.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque frame buffer declaration */
+typedef struct mpf_frame_buffer_t mpf_frame_buffer_t;
+
+
+/** Create frame buffer */
+mpf_frame_buffer_t* mpf_frame_buffer_create(apr_size_t frame_size, apr_size_t frame_count, apr_pool_t *pool);
+
+/** Destroy frame buffer */
+void mpf_frame_buffer_destroy(mpf_frame_buffer_t *buffer);
+
+/** Restart frame buffer */
+apt_bool_t mpf_frame_buffer_restart(mpf_frame_buffer_t *buffer);
+
+/** Write frame to buffer */
+apt_bool_t mpf_frame_buffer_write(mpf_frame_buffer_t *buffer, const mpf_frame_t *frame);
+
+/** Read frame from buffer */
+apt_bool_t mpf_frame_buffer_read(mpf_frame_buffer_t *buffer, mpf_frame_t *frame);
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_FRAME_BUFFER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfmpfvcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -208,6 +208,10 @@
</span><span class="cx">                                 >
</span><span class="cx">                         </File>
</span><span class="cx">                         <File
</span><ins>+                                RelativePath=".\include\mpf_frame_buffer.h"
+                                >
+                        </File>
+                        <File
</ins><span class="cx">                                 RelativePath=".\include\mpf_jitter_buffer.h"
</span><span class="cx">                                 >
</span><span class="cx">                         </File>
</span><span class="lines">@@ -333,6 +337,10 @@
</span><span class="cx">                                 >
</span><span class="cx">                         </File>
</span><span class="cx">                         <File
</span><ins>+                                RelativePath=".\src\mpf_frame_buffer.c"
+                                >
+                        </File>
+                        <File
</ins><span class="cx">                                 RelativePath=".\src\mpf_jitter_buffer.c"
</span><span class="cx">                                 >
</span><span class="cx">                         </File>
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_enginec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -128,6 +128,7 @@
</span><span class="cx">
</span><span class="cx">         mpf_timer_stop(engine->timer);
</span><span class="cx">         mpf_engine_contexts_destroy(engine);
</span><ins>+        apt_task_child_terminate(task);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_frame_bufferc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c (0 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c         (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -0,0 +1,124 @@
</span><ins>+/*
+ * Copyright 2009 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mpf_frame_buffer.h"
+
+struct mpf_frame_buffer_t {
+        apr_byte_t *raw_data;
+        mpf_frame_t *frames;
+        apr_size_t frame_count;
+        apr_size_t frame_size;
+
+        apr_size_t write_pos;
+        apr_size_t read_pos;
+
+        apr_thread_mutex_t *guard;
+        apr_pool_t *pool;
+};
+
+
+mpf_frame_buffer_t* mpf_frame_buffer_create(apr_size_t frame_size, apr_size_t frame_count, apr_pool_t *pool)
+{
+        apr_size_t i;
+        mpf_frame_buffer_t *buffer = apr_palloc(pool,sizeof(mpf_frame_buffer_t));
+
+        buffer->frame_size = frame_size;
+        buffer->frame_count = frame_count;
+        buffer->raw_data = apr_palloc(pool,buffer->frame_size*buffer->frame_count);
+        buffer->frames = apr_palloc(pool,sizeof(mpf_frame_t)*buffer->frame_count);
+        for(i=0; i<buffer->frame_count; i++) {
+                buffer->frames[i].type = MEDIA_FRAME_TYPE_NONE;
+                buffer->frames[i].codec_frame.buffer = buffer->raw_data + i*buffer->frame_size;
+        }
+
+        buffer->write_pos = buffer->read_pos = 0;
+        apr_thread_mutex_create(&buffer->guard,APR_THREAD_MUTEX_UNNESTED,pool);
+        return buffer;
+}
+
+void mpf_frame_buffer_destroy(mpf_frame_buffer_t *buffer)
+{
+        if(buffer->guard) {
+                apr_thread_mutex_destroy(buffer->guard);
+                buffer->guard = NULL;
+        }
+}
+
+apt_bool_t mpf_frame_buffer_restart(mpf_frame_buffer_t *buffer)
+{
+        buffer->write_pos = buffer->read_pos;
+        return TRUE;
+}
+
+static APR_INLINE mpf_frame_t* mpf_frame_buffer_frame_get(mpf_frame_buffer_t *buffer, apr_size_t pos)
+{
+        apr_size_t index = pos % buffer->frame_count;
+        return &buffer->frames[index];
+}
+
+apt_bool_t mpf_frame_buffer_write(mpf_frame_buffer_t *buffer, const mpf_frame_t *frame)
+{
+        mpf_frame_t *write_frame;
+        void *data = frame->codec_frame.buffer;
+        apr_size_t size = frame->codec_frame.size;
+
+        apr_thread_mutex_lock(buffer->guard);
+        while(buffer->write_pos - buffer->read_pos < buffer->frame_count && size >= buffer->frame_size) {
+                write_frame = mpf_frame_buffer_frame_get(buffer,buffer->write_pos);
+                write_frame->type = frame->type;
+                write_frame->codec_frame.size = buffer->frame_size;
+                memcpy(
+                        write_frame->codec_frame.buffer,
+                        data,
+                        write_frame->codec_frame.size);
+
+                data = (char*)data + buffer->frame_size;
+                size -= buffer->frame_size;
+                buffer->write_pos ++;
+        }
+
+        apr_thread_mutex_unlock(buffer->guard);
+        /* if size != 0 => non frame alligned or buffer is full */
+        return size == 0 ? TRUE : FALSE;
+}
+
+apt_bool_t mpf_frame_buffer_read(mpf_frame_buffer_t *buffer, mpf_frame_t *media_frame)
+{
+        apr_thread_mutex_lock(buffer->guard);
+        if(buffer->write_pos > buffer->read_pos) {
+                /* normal read */
+                mpf_frame_t *src_media_frame = mpf_frame_buffer_frame_get(buffer,buffer->read_pos);
+                media_frame->type = src_media_frame->type;
+                if(media_frame->type & MEDIA_FRAME_TYPE_AUDIO) {
+                        media_frame->codec_frame.size = src_media_frame->codec_frame.size;
+                        memcpy(
+                                media_frame->codec_frame.buffer,
+                                src_media_frame->codec_frame.buffer,
+                                media_frame->codec_frame.size);
+                }
+                if(media_frame->type & MEDIA_FRAME_TYPE_EVENT) {
+                        media_frame->event_frame = src_media_frame->event_frame;
+                }
+                src_media_frame->type = MEDIA_FRAME_TYPE_NONE;
+                buffer->read_pos ++;
+        }
+        else {
+                /* underflow */
+                media_frame->type = MEDIA_FRAME_TYPE_NONE;
+        }
+        apr_thread_mutex_unlock(buffer->guard);
+        return TRUE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_rtp_streamc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -83,21 +83,6 @@
</span><span class="cx">         return rtp_stream->base;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static void mpf_rtp_stream_ip_port_set(mpf_rtp_media_descriptor_t *media, mpf_rtp_config_t *config)
-{
-        if(media->base.ip.length == 0) {
-                media->base.ip = config->ip;
-                media->base.ext_ip = config->ext_ip;
-        }
-        if(media->base.port == 0) {
-                media->base.port = config->rtp_port_cur;
-                config->rtp_port_cur += 2;
-                if(config->rtp_port_cur == config->rtp_port_max) {
-                        config->rtp_port_cur = config->rtp_port_min;
-                }
-        }
-}
-
</del><span class="cx"> static apt_bool_t mpf_rtp_stream_local_media_create(mpf_rtp_stream_t *rtp_stream, mpf_rtp_media_descriptor_t *local_media, mpf_rtp_media_descriptor_t *remote_media)
</span><span class="cx"> {
</span><span class="cx">         apt_bool_t status = TRUE;
</span><span class="lines">@@ -111,9 +96,31 @@
</span><span class="cx">         if(remote_media) {
</span><span class="cx">                 local_media->base.id = remote_media->base.id;
</span><span class="cx">         }
</span><ins>+        if(local_media->base.ip.length == 0) {
+                local_media->base.ip = rtp_stream->config->ip;
+                local_media->base.ext_ip = rtp_stream->config->ext_ip;
+        }
+        if(local_media->base.port == 0) {
+                /* RTP port management */
+                apr_port_t first_port_in_search = rtp_stream->config->rtp_port_cur;
+                apt_bool_t is_port_ok = FALSE;
</ins><span class="cx">
</span><del>-        mpf_rtp_stream_ip_port_set(local_media,rtp_stream->config);
-        if(mpf_rtp_socket_create(rtp_stream,local_media) == FALSE) {
</del><ins>+                do {
+                        local_media->base.port = rtp_stream->config->rtp_port_cur;
+                        rtp_stream->config->rtp_port_cur += 2;
+                        if(rtp_stream->config->rtp_port_cur == rtp_stream->config->rtp_port_max) {
+                                rtp_stream->config->rtp_port_cur = rtp_stream->config->rtp_port_min;
+                        }
+                        if(mpf_rtp_socket_create(rtp_stream,local_media) == TRUE) {
+                                is_port_ok = TRUE;
+                        }
+                } while((is_port_ok == FALSE) && (first_port_in_search != rtp_stream->config->rtp_port_cur));
+                if(is_port_ok == FALSE) {
+                        local_media->base.state = MPF_MEDIA_DISABLED;
+                        status = FALSE;
+                }
+        }
+        else if(mpf_rtp_socket_create(rtp_stream,local_media) == FALSE) {
</ins><span class="cx">                 local_media->base.state = MPF_MEDIA_DISABLED;
</span><span class="cx">                 status = FALSE;
</span><span class="cx">         }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpfliteMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/Makefile.am (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/Makefile.am        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/Makefile.am        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -14,6 +14,6 @@
</span><span class="cx">
</span><span class="cx"> plugin_LTLIBRARIES = mrcpflite.la
</span><span class="cx">
</span><del>-mrcpflite_la_SOURCES = src/mrcp_flite.c
</del><ins>+mrcpflite_la_SOURCES = src/mrcp_flite.c src/flite_voices.c
</ins><span class="cx"> mrcpflite_la_LDFLAGS = -module $(PLUGIN_LT_VERSION)
</span><span class="cx"> mrcpflite_la_LIBADD = $(UNIMRCP_FLITE_LIBS) -lm
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpfliteincludeflite_voicesh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h (0 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h         (rev 0)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+/*
+ * Copyright 2008 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __FLITE_VOICES_H__
+#define __FLITE_VOICES_H__
+
+/**
+ * @file flite_voices.h
+ * @brief Flite Voices
+ */
+
+#include <flite.h>
+#include <apr_hash.h>
+#include "mrcp_message.h"
+
+APT_BEGIN_EXTERN_C
+
+
+typedef struct flite_voices_t flite_voices_t;
+
+flite_voices_t* flite_voices_load(apr_pool_t *pool);
+void flite_voices_unload(flite_voices_t *voices);
+
+cst_voice* flite_voices_best_match_get(flite_voices_t *voices, mrcp_message_t *message);
+
+APT_END_EXTERN_C
+
+#endif /*__FLITE_VOICES_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpflitemrcpflitevcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/mrcpflite.vcproj (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/mrcpflite.vcproj        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/mrcpflite.vcproj        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -149,12 +149,20 @@
</span><span class="cx">                         Filter="h;hpp;hxx;hm;inl;inc;xsd"
</span><span class="cx">                         UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
</span><span class="cx">                         >
</span><ins>+                        <File
+                                RelativePath=".\include\flite_voices.h"
+                                >
+                        </File>
</ins><span class="cx">                 </Filter>
</span><span class="cx">                 <Filter
</span><span class="cx">                         Name="src"
</span><span class="cx">                         Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
</span><span class="cx">                         >
</span><span class="cx">                         <File
</span><ins>+                                RelativePath=".\src\flite_voices.c"
+                                >
+                        </File>
+                        <File
</ins><span class="cx">                                 RelativePath=".\src\mrcp_flite.c"
</span><span class="cx">                                 >
</span><span class="cx">                         </File>
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpflitesrcflite_voicesc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c (0 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c         (rev 0)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -0,0 +1,160 @@
</span><ins>+/*
+ * Copyright 2008 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "flite_voices.h"
+#include "mrcp_synth_header.h"
+
+typedef struct flite_voice_t flite_voice_t;
+
+/** Declaration of flite voice */
+struct flite_voice_t {
+        const char *name;
+        cst_voice *self;
+        cst_voice* (*register_voice)(void);
+        void (*unregister_voice)(cst_voice *);
+};
+
+struct flite_voices_t {
+        apr_hash_t *table;
+        apr_pool_t *pool;
+};
+
+
+/* declarations for flite voices */
+cst_voice *register_cmu_us_awb(void);
+cst_voice *register_cmu_us_kal(void);
+cst_voice *register_cmu_us_rms(void);
+cst_voice *register_cmu_us_slt(void);
+void unregister_cmu_us_awb(cst_voice * v);
+void unregister_cmu_us_kal(cst_voice * v);
+void unregister_cmu_us_rms(cst_voice * v);
+void unregister_cmu_us_slt(cst_voice * v);
+
+
+static apt_bool_t flite_voices_init(flite_voices_t *voices, apr_pool_t *pool)
+{
+        flite_voice_t *voice;
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice->name = "awb";
+        voice->self = NULL;
+        voice->register_voice = register_cmu_us_awb;
+        voice->unregister_voice = unregister_cmu_us_awb;
+        apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice->name = "kal";
+        voice->self = NULL;
+        voice->register_voice = register_cmu_us_kal;
+        voice->unregister_voice = unregister_cmu_us_kal;
+        apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice->name = "rms";
+        voice->self = NULL;
+        voice->register_voice = register_cmu_us_rms;
+        voice->unregister_voice = unregister_cmu_us_rms;
+        apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice->name = "slt";
+        voice->self = NULL;
+        voice->register_voice = register_cmu_us_slt;
+        voice->unregister_voice = unregister_cmu_us_slt;
+        apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
+
+        return TRUE;
+}
+
+
+flite_voices_t* flite_voices_load(apr_pool_t *pool)
+{
+        flite_voice_t *voice;
+        apr_hash_index_t *it;
+        void *val;
+
+        flite_voices_t *voices = apr_palloc(pool,sizeof(flite_voices_t));
+        voices->pool = pool;
+        voices->table = apr_hash_make(pool);
+
+        /* init voices */
+        flite_voices_init(voices,pool);
+
+        /* register voices */
+        it = apr_hash_first(pool,voices->table);
+        /* walk through the voices and register them */
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&val);
+                voice = val;
+                if(voice) {
+                        voice->self = voice->register_voice();
+                }
+        }
+
+        return voices;
+}
+
+void flite_voices_unload(flite_voices_t *voices)
+{
+        flite_voice_t *voice;
+        apr_hash_index_t *it;
+        void *val;
+
+        /* unregister voices */
+        it = apr_hash_first(voices->pool,voices->table);
+        /* walk through the voices and register them */
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&val);
+                voice = val;
+                if(voice && voice->self) {
+                        voice->unregister_voice(voice->self);
+                }
+        }
+}
+
+cst_voice* flite_voices_best_match_get(flite_voices_t *voices, mrcp_message_t *message)
+{
+        cst_voice *voice = NULL;
+        const char *voice_name = NULL;
+        mrcp_synth_header_t *synth_header = mrcp_resource_header_get(message);
+        if(synth_header) {
+                if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) {
+                        voice_name = synth_header->voice_param.name.buf;
+                }
+        }
+
+        if(voice_name) {
+                /* get voice by name */
+                flite_voice_t *flite_voice;
+                flite_voice = apr_hash_get(voices->table,voice_name,APR_HASH_KEY_STRING);
+                if(flite_voice) {
+                        voice = flite_voice->self;
+                }
+        }
+
+        if(!voice) {
+                /* still no voice found, get the default one */
+                flite_voice_t *flite_voice = NULL;
+                void *val;
+                apr_hash_index_t *it = apr_hash_first(voices->pool,voices->table);
+                apr_hash_this(it,NULL,NULL,&val);
+                if(val) {
+                        flite_voice = val;
+                        voice = flite_voice->self;
+                }
+        }
+        return voice;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpflitesrcmrcp_flitec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c (14165 => 14166)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c        2009-07-09 09:29:32 UTC (rev 14165)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c        2009-07-09 15:19:27 UTC (rev 14166)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> * 4. Methods (callbacks) of the MPF engine stream MUST not block.
</span><span class="cx"> */
</span><span class="cx">
</span><ins>+#include "flite_voices.h"
</ins><span class="cx"> #include "mrcp_resource_engine.h"
</span><span class="cx"> #include "mrcp_synth_resource.h"
</span><span class="cx"> #include "mrcp_synth_header.h"
</span><span class="lines">@@ -33,7 +34,6 @@
</span><span class="cx"> #include "apr_time.h"
</span><span class="cx"> #include "apt_consumer_task.h"
</span><span class="cx"> #include "apt_log.h"
</span><del>-#include "flite.h"
</del><span class="cx">
</span><span class="cx"> typedef struct flite_synth_engine_t flite_synth_engine_t;
</span><span class="cx"> typedef struct flite_synth_channel_t flite_synth_channel_t;
</span><span class="lines">@@ -57,8 +57,6 @@
</span><span class="cx"> static apt_bool_t flite_synth_channel_close(mrcp_engine_channel_t *channel);
</span><span class="cx"> static apt_bool_t flite_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
</span><span class="cx">
</span><del>-static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t *channel); // wait for speak thread
-
</del><span class="cx"> /** flite channel methods for processing MRCP channel request **/
</span><span class="cx"> static apt_bool_t flite_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
</span><span class="cx"> static apt_bool_t flite_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
</span><span class="lines">@@ -75,15 +73,12 @@
</span><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> /** Declaration of synthesizer audio stream methods */
</span><del>-static apt_bool_t flite_synth_stream_destroy(mpf_audio_stream_t *stream);
-static apt_bool_t flite_synth_stream_open(mpf_audio_stream_t *stream);
-static apt_bool_t flite_synth_stream_close(mpf_audio_stream_t *stream);
</del><span class="cx"> static apt_bool_t flite_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
</span><span class="cx">
</span><span class="cx"> static const mpf_audio_stream_vtable_t audio_stream_vtable = {
</span><del>-        flite_synth_stream_destroy,
-        flite_synth_stream_open,
-        flite_synth_stream_close,
</del><ins>+        NULL,
+        NULL,
+        NULL,
</ins><span class="cx">         flite_synth_stream_read,
</span><span class="cx">         NULL,
</span><span class="cx">         NULL,
</span><span class="lines">@@ -92,39 +87,25 @@
</span><span class="cx">
</span><span class="cx"> /** Declaration of flite synthesizer engine */
</span><span class="cx"> struct flite_synth_engine_t {
</span><del>-        int                                         iChannels;
-        struct {
-                cst_voice *awb;
-                cst_voice *kal;
-                cst_voice *rms;
-                cst_voice *slt;
-        } voices;
</del><ins>+        /** Table of flite voices */
+        flite_voices_t *voices;
+        int iChannels;
</ins><span class="cx"> };
</span><span class="cx">
</span><del>-/** declarations for flite voices **/
-cst_voice *register_cmu_us_awb(void);
-cst_voice *register_cmu_us_kal(void);
-cst_voice *register_cmu_us_rms(void);
-cst_voice *register_cmu_us_slt(void);
-void unregister_cmu_us_awb(cst_voice * v);
-void unregister_cmu_us_kal(cst_voice * v);
-void unregister_cmu_us_rms(cst_voice * v);
-void unregister_cmu_us_slt(cst_voice * v);
-
-
</del><span class="cx"> /** Declaration of flite synthesizer channel */
</span><span class="cx"> struct flite_synth_channel_t {
</span><del>-        flite_synth_engine_t *flite_engine;        // Back pointer to engine
-        mrcp_engine_channel_t        *channel;                // Engine channel base
-        mrcp_message_t                        *speak_request;        // Active (in-progress) speak request
-        mrcp_message_t                        *stop_response;        // Pending stop response
-        apt_bool_t                                 paused;                // Is paused
-        mpf_buffer_t                        *audio_buffer;        // Audio buffer
-        int                                                 iId;                        // Synth channel simultaneous reference count
-        cst_voice                                *voice;
-        apr_pool_t                                *pool;
-        apt_consumer_task_t *task;
-        apr_thread_mutex_t         *channel_guard;
</del><ins>+        flite_synth_engine_t *flite_engine; /* Back pointer to engine */
+        mrcp_engine_channel_t *channel;                 /* Engine channel base */
+        mrcp_message_t                 *speak_request; /* Active (in-progress) speak request */
+        mrcp_message_t                 *speak_response;/* Pending speak response */
+        mrcp_message_t *stop_response; /* Pending stop response */
+        apt_bool_t synthesizing; /* Is synthesizer task processing speak request */
+        apt_bool_t paused; /* Is paused */
+        mpf_buffer_t *audio_buffer; /* Audio buffer */
+        int iId; /* Synth channel simultaneous reference count */
+        apr_pool_t *pool;
+        apt_task_t *task;
+        apt_task_msg_pool_t *msg_pool;
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> /** Declaration of flite synthesizer task message */
</span><span class="lines">@@ -135,8 +116,8 @@
</span><span class="cx">
</span><span class="cx"> typedef struct flite_speak_msg_t flite_speak_msg_t;
</span><span class="cx">
</span><del>-// we have a special task for the actual synthesis -
-// the task is created when a mrcp speak message is received
</del><ins>+/* we have a special task for the actual synthesis -
+ the task is created when a mrcp speak message is received */
</ins><span class="cx"> static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg);
</span><span class="cx">
</span><span class="cx"> /** Declare this macro to use log routine of the server where the plugin is loaded from */
</span><span class="lines">@@ -147,7 +128,6 @@
</span><span class="cx"> {
</span><span class="cx">         /* create flite engine */
</span><span class="cx">         flite_synth_engine_t *flite_engine = (flite_synth_engine_t *) apr_palloc(pool,sizeof(flite_synth_engine_t));
</span><del>-
</del><span class="cx">         flite_engine->iChannels = 0;
</span><span class="cx">
</span><span class="cx">         /* create resource engine base */
</span><span class="lines">@@ -172,13 +152,10 @@
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_open");
</span><span class="cx">
</span><span class="cx">         flite_init();
</span><del>-        flite_engine->voices.awb = register_cmu_us_awb();
-        flite_engine->voices.kal = register_cmu_us_kal();
-        flite_engine->voices.rms = register_cmu_us_rms();
-        flite_engine->voices.slt = register_cmu_us_slt();
</del><span class="cx">
</span><del>-        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite init success");
</del><ins>+        flite_engine->voices = flite_voices_load(engine->pool);
</ins><span class="cx">
</span><ins>+        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite init success");
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -188,14 +165,36 @@
</span><span class="cx">         flite_synth_engine_t *flite_engine = (flite_synth_engine_t *) engine->obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_close");
</span><span class="cx">
</span><del>-        unregister_cmu_us_awb(flite_engine->voices.awb);
-        unregister_cmu_us_kal(flite_engine->voices.kal);
-        unregister_cmu_us_rms(flite_engine->voices.rms);
-        unregister_cmu_us_slt(flite_engine->voices.slt);
</del><ins>+        flite_voices_unload(flite_engine->voices);
</ins><span class="cx">
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+static apt_bool_t flite_synth_task_create(flite_synth_channel_t *synth_channel)
+{
+        apt_task_msg_pool_t *msg_pool = apt_task_msg_pool_create_dynamic( sizeof(flite_speak_msg_t),synth_channel->pool);
+        apt_task_vtable_t *task_vtable = 0;
+        apt_consumer_task_t *consumer_task = 0;
+
+        /* create task/thread to run flite synthesizer in */
+ consumer_task = apt_consumer_task_create(synth_channel, msg_pool, synth_channel->pool);
+        if(!consumer_task) {
+                apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to create flite speak task - channel:%d", synth_channel->iId);
+                return FALSE;
+        }
+
+        task_vtable = apt_consumer_task_vtable_get(consumer_task);
+        if(!task_vtable) {
+                apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak cannot use flite speak task vtable - channel:%d", synth_channel->iId);
+                return FALSE;
+        }
+
+        task_vtable->process_msg = flite_speak;
+        synth_channel->msg_pool = msg_pool;
+        synth_channel->task = apt_consumer_task_base_get(consumer_task);
+        return TRUE;
+}
+
</ins><span class="cx"> /** Create flite synthesizer channel derived from engine channel base */
</span><span class="cx"> static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="lines">@@ -204,30 +203,31 @@
</span><span class="cx">         mpf_codec_descriptor_t *codec_descriptor = NULL;
</span><span class="cx">
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_channel_create");
</span><ins>+#if 0
+        codec_descriptor = (mpf_codec_descriptor_t *) apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
+        mpf_codec_descriptor_init(codec_descriptor);
+        codec_descriptor->channel_count = 1;
+        codec_descriptor->payload_type = 96;
+        apt_string_set(&codec_descriptor->name,"LPCM");
+        codec_descriptor->sampling_rate = 16000;
+#endif
</ins><span class="cx">
</span><del>-//        codec_descriptor = (mpf_codec_descriptor_t *) apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
-//        mpf_codec_descriptor_init(codec_descriptor);
-//        codec_descriptor->channel_count = 1;
-//        codec_descriptor->payload_type = 96;
-//        apt_string_set(&codec_descriptor->name,"LPCM");
-//        codec_descriptor->sampling_rate = 16000;
-
</del><span class="cx">         synth_channel->flite_engine = (flite_synth_engine_t *) engine->obj;
</span><span class="cx">         synth_channel->speak_request = NULL; // no active speak request in progress
</span><ins>+        synth_channel->speak_response = NULL;
</ins><span class="cx">         synth_channel->stop_response = NULL;
</span><ins>+        synth_channel->synthesizing = FALSE;
</ins><span class="cx">         synth_channel->paused = FALSE;
</span><span class="cx">         synth_channel->pool = pool;
</span><span class="cx">         synth_channel->audio_buffer = NULL;
</span><del>-        synth_channel->voice = NULL;
</del><span class="cx">         synth_channel->iId = 0;
</span><del>-
-        if (apr_thread_mutex_create(&synth_channel->channel_guard,APR_THREAD_MUTEX_DEFAULT,pool) != APR_SUCCESS)
-        {
-                apt_log(APT_LOG_MARK, APT_PRIO_ERROR, "Failed to create channel guard");
</del><ins>+        synth_channel->task = NULL;
+        synth_channel->msg_pool = NULL;
+        if(flite_synth_task_create(synth_channel) != TRUE) {
+                apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "flite_synth_task_create failed");
</ins><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx">
</span><del>-
</del><span class="cx">         /* create engine channel base */
</span><span class="cx">         synth_channel->channel = mrcp_engine_source_channel_create(
</span><span class="cx">                         engine, /* resource engine */
</span><span class="lines">@@ -237,9 +237,9 @@
</span><span class="cx">                         codec_descriptor, /* codec descriptor might be NULL by default */
</span><span class="cx">                         pool); /* pool to allocate memory from */
</span><span class="cx">         
</span><del>-        if (!synth_channel->channel)
-        {
</del><ins>+        if(!synth_channel->channel) {
</ins><span class="cx">                 apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "flite_synth_engine_channel_create failed");
</span><ins>+                apt_task_destroy(synth_channel->task);
</ins><span class="cx">                 return NULL;                
</span><span class="cx">         }
</span><span class="cx">
</span><span class="lines">@@ -247,7 +247,6 @@
</span><span class="cx">         synth_channel->iId = ++synth_channel->flite_engine->iChannels;
</span><span class="cx">
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_channel_create created channel %d", synth_channel->iId);
</span><del>-
</del><span class="cx">         return synth_channel->channel;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -256,24 +255,12 @@
</span><span class="cx"> {
</span><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_destroy - channel %d", synth_channel->iId);
</span><del>-        if(synth_channel->task)
-        {
-                apt_task_t *task = apt_consumer_task_base_get(synth_channel->task);
-                if (!task || !apt_task_destroy(task))
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task destroy failed - channel %d", synth_channel->iId);
-                }
-                else
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task destroyed - channel %d", synth_channel->iId);
-                }
</del><ins>+        if(synth_channel->task) {
+                apt_task_destroy(synth_channel->task);
+                synth_channel->task = NULL;
</ins><span class="cx">         }
</span><span class="cx">         
</span><del>-        synth_channel->task = NULL;
</del><span class="cx">         synth_channel->flite_engine->iChannels--;
</span><del>-
-        apr_thread_mutex_destroy(synth_channel->channel_guard);
-
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -283,7 +270,15 @@
</span><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_open - channel %d", synth_channel->iId);
</span><span class="cx">
</span><del>-        synth_channel->voice = synth_channel->flite_engine->voices.awb;
</del><ins>+        if(synth_channel->task) {
+                if(apt_task_start(synth_channel->task) == TRUE) {
+                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task started - channel %d", synth_channel->iId);
+                }
+                else {
+                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task start failed - channel %d", synth_channel->iId);
+                }
+        }
+
</ins><span class="cx">         return mrcp_engine_channel_open_respond(channel,TRUE);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -292,8 +287,16 @@
</span><span class="cx"> {
</span><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_close - channel %d", synth_channel->iId);
</span><del>-        // create thread to wait for speak thread to terminate
-        flite_synth_channel_close_t(channel);
</del><ins>+
+        if(synth_channel->task) {
+                if(apt_task_terminate(synth_channel->task,TRUE) == TRUE) {
+                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task terminated - channel %d", synth_channel->iId);
+                }
+                else {
+                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task terminate failed - channel %d", synth_channel->iId);
+                }
+        }
+        mrcp_engine_channel_close_respond(channel);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -308,18 +311,6 @@
</span><span class="cx">
</span><span class="cx">         switch(request->start_line.method_id) {
</span><span class="cx">                 case SYNTHESIZER_SET_PARAMS:
</span><del>-                                // TODO set voices
-                                //        if (!strcasecmp(voice_name, "awb")) {
-                                //                synth_channel->voice = voices.awb;
-                                //        } else if (!strcasecmp(voice_name, "kal")) {
-                                //                synth_channel->voice = voices.kal;
-                                //        } else if (!strcasecmp(voice_name, "rms")) {
-                                //                synth_channel->voice = voices.rms;
-                                //        } else if (!strcasecmp(voice_name, "slt")) {
-                                //                synth_channel->voice = voices.slt;
-                                //        } else {
-                                //                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Valid voice names are awb, kal, rms or slt");
-                                //        }
</del><span class="cx">                         break;
</span><span class="cx">                 case SYNTHESIZER_GET_PARAMS:
</span><span class="cx">                         break;
</span><span class="lines">@@ -350,92 +341,67 @@
</span><span class="cx">                 mrcp_engine_channel_message_send(channel,response);
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><del>-
</del><span class="cx"> }
</span><span class="cx">
</span><del>-static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t *channel)
</del><ins>+/** Process SPEAK request */
+static apt_bool_t synth_response_construct(mrcp_message_t *response, mrcp_status_code_e status_code, mrcp_synth_completion_cause_e completion_cause)
</ins><span class="cx"> {
</span><del>-        flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
-        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_close_t - channel %d", synth_channel->iId);
-        
-        if (synth_channel->task)
-        {
-                apt_task_t *task = apt_consumer_task_base_get(synth_channel->task);
-                if (!apt_task_terminate(task,TRUE))
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task terminate failed - channel %d", synth_channel->iId);
-                }
-                else
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task terminated - channel %d", synth_channel->iId);
-                        apt_task_destroy(task);
-                        synth_channel->task = 0;
-                }
</del><ins>+        mrcp_synth_header_t *synth_header = mrcp_resource_header_prepare(response);
+        if(!synth_header) {
+                return FALSE;
</ins><span class="cx">         }
</span><del>-        mrcp_engine_channel_close_respond(channel);
</del><ins>+
+        response->start_line.status_code = status_code;
+        synth_header->completion_cause = completion_cause;
+        mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_COMPLETION_CAUSE);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-
</del><span class="cx"> /** Process SPEAK request */
</span><span class="cx"> static apt_bool_t flite_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
</span><span class="cx"> {
</span><ins>+        mrcp_generic_header_t *generic_header;
+        const char *content_type = NULL;
</ins><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
</span><ins>+        apt_task_msg_t *msg = 0;
+        flite_speak_msg_t *flite_msg = 0;
</ins><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_speak - channel %d", synth_channel->iId);
</span><span class="cx">
</span><del>-        if (!synth_channel->speak_request)
-        {
-                apt_task_msg_pool_t *msg_pool = apt_task_msg_pool_create_dynamic( sizeof(flite_speak_msg_t),synth_channel->pool);
-                apt_task_vtable_t        *task_vtable = 0;
-                apt_task_t * task = 0;
-                apt_task_msg_t *msg = 0;
-                flite_speak_msg_t *flite_msg = 0;
-
-                /* create task/thread to run flite so this function is not blocking */
-                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Create flite speak task - channel: %d", synth_channel->iId);
-         synth_channel->task = apt_consumer_task_create(synth_channel, msg_pool, synth_channel->pool);
-                if (!synth_channel->task)
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to create flite speak task - channel:%d", synth_channel->iId);
-                        return FALSE;
</del><ins>+        generic_header = mrcp_generic_header_get(request);
+        if(generic_header) {
+                /* content-type must be specified */
+                if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_TYPE) == TRUE) {
+                        content_type = generic_header->content_type.buf;
</ins><span class="cx">                 }
</span><ins>+        }
+        if(!content_type) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing Content-Type");
+                synth_response_construct(response,MRCP_STATUS_CODE_MISSING_PARAM,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                return FALSE;
+        }
</ins><span class="cx">
</span><del>-                task_vtable = apt_consumer_task_vtable_get(synth_channel->task);
-                if (!task_vtable)
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak cannot use flite speak task vtable - channel:%d", synth_channel->iId);
-                        return FALSE;
-                }
</del><ins>+        /* Flite currently supports only text/plain (no SSML) */
+        if(strstr(content_type,"text") == NULL) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Not Supported Content-Type [%s]",content_type);
+                synth_response_construct(response,MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                return FALSE;
+        }
</ins><span class="cx">
</span><del>-                task_vtable->process_msg = flite_speak;
-                synth_channel->speak_request = request;
-                
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, "Start task - channel %d", synth_channel->iId);
-                task = apt_consumer_task_base_get(synth_channel->task);
-                if (apt_task_start(task) == FALSE)
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to start task - channel: %d", synth_channel->iId);
-                        apt_task_destroy(task);
-                        return FALSE;
-                }
</del><ins>+        synth_channel->speak_request = request;
+        synth_channel->speak_response = response;
</ins><span class="cx">
</span><del>-                msg = apt_task_msg_acquire(msg_pool);
-                msg->type = TASK_MSG_USER;
-                flite_msg = (flite_speak_msg_t*) msg->data;
-                flite_msg->channel = synth_channel;
-                flite_msg->request = request;
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, "Send signal to start speech synthesis - channel:%d", synth_channel->iId);
-                if (apt_task_msg_signal(task,msg))
-                {
-                        response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
-                        mrcp_engine_channel_message_send(channel,response);
-                }
-                else
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING, "Failed to send signal to start speech synthesis - channel:%d", synth_channel->iId);
-                        apt_task_destroy(task);
-                        return FALSE;
-                }
</del><ins>+        msg = apt_task_msg_acquire(synth_channel->msg_pool);
+        msg->type = TASK_MSG_USER;
+        flite_msg = (flite_speak_msg_t*) msg->data;
+        flite_msg->channel = synth_channel;
+        flite_msg->request = request;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, "Send signal to start speech synthesis - channel:%d", synth_channel->iId);
+        if(apt_task_msg_signal(synth_channel->task,msg) != TRUE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING, "Failed to send signal to start speech synthesis - channel:%d", synth_channel->iId);
+                synth_channel->speak_request = NULL;
+                synth_channel->speak_response = NULL;
+                synth_response_construct(response,MRCP_STATUS_CODE_METHOD_FAILED,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -444,62 +410,80 @@
</span><span class="cx"> {
</span><span class="cx">         flite_speak_msg_t *flite_msg = (flite_speak_msg_t*)msg->data;
</span><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) flite_msg->channel;
</span><ins>+        cst_wave *wave = NULL;
+        cst_voice *voice = NULL;
</ins><span class="cx">         apr_time_t start = 0;
</span><span class="cx">         apr_time_t elapsed = 0;
</span><span class="cx">         apr_time_t stamp = 0;
</span><ins>+        apt_str_t *body;
+        mrcp_message_t *response;
</ins><span class="cx">
</span><del>-        mrcp_message_t *stop_response = 0;
</del><span class="cx">         mpf_codec_t * codec = mrcp_engine_source_stream_codec_get(synth_channel->channel);
</span><del>-        apr_uint16_t rate = codec->descriptor->sampling_rate;                        
</del><ins>+        apr_uint16_t rate = codec->descriptor->sampling_rate;
+        body = &synth_channel->speak_request->body;
</ins><span class="cx">
</span><ins>+        response = synth_channel->speak_response;
+        synth_channel->speak_response = NULL;
+
</ins><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "< flite_speak_msg_process speak - channel %d", synth_channel->iId);
</span><span class="cx">         
</span><del>-        // just sequential stuff
</del><ins>+        /* just sequential stuff */
</ins><span class="cx">         start = apr_time_now();        // in microsec
</span><del>-        if (synth_channel->speak_request->body.length)
-        {
-                // TODO
-                // create small units of text from synth_channel->speak_request->body.buf ( , . ? ! but ...
-                // synthesize small unit and store in audio_buffer
-                // check for stop
-                // pause resume state could improve performance
-                // you can "pause" generating new speech from a unit of text
-                // by checking the (decreasing) size of the audio_buffer
-                // no need to generate more speech samples than can be listened to...
-                cst_wave *wave = 0;
-                wave = flite_text_to_wave(synth_channel->speak_request->body.buf, synth_channel->voice);
-                if (wave && cst_wave_num_samples(wave))
-                {
-                        int generated = (cst_wave_num_samples(wave)/cst_wave_sample_rate(wave)*1000);
-                        stamp = apr_time_now();
-                        elapsed = (stamp - start)/1000;
-                        apt_log(APT_LOG_MARK, APT_PRIO_INFO, "TTS (chan %d) took %"APR_TIME_T_FMT" to generate %d of speech (in millisec)", synth_channel->iId, elapsed, generated);
</del><ins>+        if(!body->length) {
+                synth_channel->speak_request = NULL;
+                synth_response_construct(response,MRCP_STATUS_CODE_MISSING_PARAM,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                mrcp_engine_channel_message_send(synth_channel->channel,response);
+                return FALSE;
+        }
</ins><span class="cx">
</span><del>-                        if (rate != 16000)
-                        {
-                                cst_wave_resample(wave, rate);
-                                elapsed = (apr_time_now() - stamp)/1000;
-                                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "TTS resampling to %d on (chan %d) took %"APR_TIME_T_FMT" millisec", rate, synth_channel->iId, elapsed);
-                        }
-                        mpf_buffer_audio_write(synth_channel->audio_buffer, cst_wave_samples(wave), cst_wave_num_samples(wave) * 2);
-                        delete_wave(wave);
-                }
</del><ins>+        voice = flite_voices_best_match_get(
+                                                        synth_channel->flite_engine->voices,
+                                                        synth_channel->speak_request);
+        if(!voice) {
+                /* error case: no voice found, appropriate respond must be sent */
+                synth_channel->speak_request = NULL;
+                synth_response_construct(response,MRCP_STATUS_CODE_METHOD_FAILED,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                mrcp_engine_channel_message_send(synth_channel->channel,response);
+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx">
</span><del>-        apr_thread_mutex_lock(synth_channel->channel_guard);
-        stop_response = synth_channel->stop_response;
-        apr_thread_mutex_unlock(synth_channel->channel_guard);
</del><ins>+        /*
+        TODO
+        create small units of text from synth_channel->speak_request->body.buf ( , . ? ! but ...
+        synthesize small unit and store in audio_buffer
+        check for stop
+        pause resume state could improve performance
+        you can "pause" generating new speech from a unit of text
+        by checking the (decreasing) size of the audio_buffer
+        no need to generate more speech samples than can be listened to...        
+        */
</ins><span class="cx">
</span><del>-        if (!stop_response)
-        {
-                // this will notify the callback that feeds the client that synthesis is complete
-                mpf_buffer_event_write(synth_channel->audio_buffer, MEDIA_FRAME_TYPE_EVENT);
-                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "> flite_speak_msg_process speak - end of TTS - %d", synth_channel->iId);
</del><ins>+        /* send in-progress response and start synthesizing */
+        response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        mrcp_engine_channel_message_send(synth_channel->channel,response);
+        
+        synth_channel->synthesizing = TRUE;
+        wave = flite_text_to_wave(body->buf, voice);
+        if(wave && cst_wave_num_samples(wave)) {
+                int generated = (cst_wave_num_samples(wave)/cst_wave_sample_rate(wave)*1000);
+                stamp = apr_time_now();
+                elapsed = (stamp - start)/1000;
+                apt_log(APT_LOG_MARK, APT_PRIO_INFO, "TTS (chan %d) took %"APR_TIME_T_FMT" to generate %d of speech (in millisec)", synth_channel->iId, elapsed, generated);
+
+                if(rate != 16000) {
+                        cst_wave_resample(wave, rate);
+                        elapsed = (apr_time_now() - stamp)/1000;
+                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "TTS resampling to %d on (chan %d) took %"APR_TIME_T_FMT" millisec", rate, synth_channel->iId, elapsed);
+                }
+                mpf_buffer_audio_write(synth_channel->audio_buffer, cst_wave_samples(wave), cst_wave_num_samples(wave) * 2);
+                delete_wave(wave);
</ins><span class="cx">         }
</span><del>-        else
-        {
-                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "> flite_speak_msg_process speak - channel %d", synth_channel->iId);
-        }
</del><ins>+
+        // this will notify the callback that feeds the client that synthesis is complete
+        mpf_buffer_event_write(synth_channel->audio_buffer, MEDIA_FRAME_TYPE_EVENT);
+        synth_channel->synthesizing = FALSE;
+
+        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "> flite_speak_msg_process speak - end of TTS - %d", synth_channel->iId);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -510,10 +494,7 @@
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_stop - channel %d", synth_channel->iId);
</span><span class="cx">         /* store the request, make sure there is no more activity and only then send the response */
</span><span class="cx">
</span><del>-        apr_thread_mutex_lock(synth_channel->channel_guard);
</del><span class="cx">         synth_channel->stop_response = response;
</span><del>-        apr_thread_mutex_unlock(synth_channel->channel_guard);
-
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -541,29 +522,6 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
-static apt_bool_t flite_synth_stream_destroy(mpf_audio_stream_t *stream)
-{
-        apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_stream_destroy");
-        return TRUE;
-}
-
-/** Callback is called from MPF engine context to perform any action before open */
-static apt_bool_t flite_synth_stream_open(mpf_audio_stream_t *stream)
-{
-//        flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
-//        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_stream_open - channel %d", synth_channel->iId);
-        return TRUE;
-}
-
-/** Callback is called from MPF engine context to perform any action after close */
-static apt_bool_t flite_synth_stream_close(mpf_audio_stream_t *stream)
-{
-//        flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
-//        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_stream_close - channel %d", synth_channel->iId);
-        return TRUE;
-}
-
</del><span class="cx"> /** Raise SPEAK-COMPLETE event */
</span><span class="cx"> static apt_bool_t flite_synth_speak_complete_raise(flite_synth_channel_t *synth_channel)
</span><span class="cx"> {
</span><span class="lines">@@ -602,26 +560,25 @@
</span><span class="cx"> static apt_bool_t flite_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
</span><span class="cx"> {
</span><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
</span><del>-        if (synth_channel->stop_response && synth_channel->speak_request)
-        {
</del><ins>+        if(synth_channel->stop_response && synth_channel->synthesizing == FALSE) {
</ins><span class="cx">                 /* send asynchronous response to STOP request */
</span><del>-                mrcp_engine_channel_message_send(synth_channel->channel, synth_channel->stop_response);
</del><ins>+                mrcp_message_t *stop_response = synth_channel->stop_response;
+                synth_channel->stop_response = NULL;
</ins><span class="cx">                 synth_channel->speak_request = NULL;
</span><span class="cx">                 synth_channel->paused = FALSE;
</span><ins>+                mrcp_engine_channel_message_send(synth_channel->channel,stop_response);
</ins><span class="cx">                 return TRUE;
</span><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         /* check if there is active SPEAK request and it isn't in paused state */
</span><del>-        if (synth_channel->speak_request && synth_channel->paused == FALSE)
-        {
</del><ins>+        if(synth_channel->speak_request && synth_channel->paused == FALSE) {
</ins><span class="cx">                 /* normal processing */
</span><span class="cx">                 mpf_buffer_frame_read(synth_channel->audio_buffer,frame);
</span><span class="cx"> //                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_stream_read - channel %d - size %d", synth_channel->iId, mpf_buffer_get_size(synth_channel->audio_buffer));
</span><span class="cx">
</span><del>-                if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT)
-                {
</del><ins>+                if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
</ins><span class="cx">                         flite_synth_speak_complete_raise(synth_channel);
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><del>-}
</del><span class="cx">\ No newline at end of file
</span><ins>+}
</ins></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>
</body>
</html>