<!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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Jul 5 19:22:31 2009 +0000

    Enhanced flite plugin to
    - support more than one SPEAK requests in a session (SPEAK -&gt; STOP -&gt; SPEAK or SPEAK-&gt; SPEAK-COMPLETE-&gt;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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Jul 4 05:06:17 2009 +0000

    Checked content-type to be &quot;text/plain&quot; 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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
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 &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
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 &lt;stdlib.h&gt;
-#include &lt;stdio.h&gt;
</del><span class="cx"> #include &quot;apt_string.h&quot;
</span><span class="cx"> #include &quot;apt_pair.h&quot;
</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-&gt;buf ? atol(str-&gt;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-&gt;pos, &quot;%&quot;APR_SIZE_T_FMT, value);
-        if(length &lt;= 0) {
-                return FALSE;
-        }
-        stream-&gt;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-&gt;buf ? (float)atof(str-&gt;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-&gt;pos,&quot;%.2f&quot;,value);
-        if(length &lt;= 0) {
-                return FALSE;
-        }
-        stream-&gt;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-&gt;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-&gt;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 &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
</ins><span class="cx"> #include &lt;apr_uuid.h&gt;
</span><span class="cx"> #include &quot;apt_text_stream.h&quot;
</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-&gt;buf ? atol(str-&gt;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-&gt;pos, &quot;%&quot;APR_SIZE_T_FMT, value);
+        if(length &lt;= 0) {
+                return FALSE;
+        }
+        stream-&gt;pos += length;
+        return TRUE;
+}
+
+/** Parse float value */
+APT_DECLARE(float) apt_float_value_parse(const apt_str_t *str)
+{
+        return str-&gt;buf ? (float)atof(str-&gt;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-&gt;pos,&quot;%f&quot;,value);
+        if(length &lt;= 0) {
+                return FALSE;
+        }
+
+        /* remove trailing 0s (if any) */
+        end = stream-&gt;pos + length -1;
+        while(*end == 0x30 &amp;&amp; end != stream-&gt;pos) end--;
+
+        stream-&gt;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 &quot;License&quot;);
+ * 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 &quot;AS IS&quot; 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 &quot;mpf_frame.h&quot;
+
+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">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\include\mpf_frame_buffer.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mpf_jitter_buffer.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="lines">@@ -333,6 +337,10 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\src\mpf_frame_buffer.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\src\mpf_jitter_buffer.c&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</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-&gt;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 &quot;License&quot;);
+ * 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 &quot;AS IS&quot; 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 &quot;mpf_frame_buffer.h&quot;
+
+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-&gt;frame_size = frame_size;
+        buffer-&gt;frame_count = frame_count;
+        buffer-&gt;raw_data = apr_palloc(pool,buffer-&gt;frame_size*buffer-&gt;frame_count);
+        buffer-&gt;frames = apr_palloc(pool,sizeof(mpf_frame_t)*buffer-&gt;frame_count);
+        for(i=0; i&lt;buffer-&gt;frame_count; i++) {
+                buffer-&gt;frames[i].type = MEDIA_FRAME_TYPE_NONE;
+                buffer-&gt;frames[i].codec_frame.buffer = buffer-&gt;raw_data + i*buffer-&gt;frame_size;
+        }
+
+        buffer-&gt;write_pos = buffer-&gt;read_pos = 0;
+        apr_thread_mutex_create(&amp;buffer-&gt;guard,APR_THREAD_MUTEX_UNNESTED,pool);
+        return buffer;
+}
+
+void mpf_frame_buffer_destroy(mpf_frame_buffer_t *buffer)
+{
+        if(buffer-&gt;guard) {
+                apr_thread_mutex_destroy(buffer-&gt;guard);
+                buffer-&gt;guard = NULL;
+        }
+}
+
+apt_bool_t mpf_frame_buffer_restart(mpf_frame_buffer_t *buffer)
+{
+        buffer-&gt;write_pos = buffer-&gt;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-&gt;frame_count;
+        return &amp;buffer-&gt;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-&gt;codec_frame.buffer;
+        apr_size_t size = frame-&gt;codec_frame.size;
+
+        apr_thread_mutex_lock(buffer-&gt;guard);
+        while(buffer-&gt;write_pos - buffer-&gt;read_pos &lt; buffer-&gt;frame_count &amp;&amp; size &gt;= buffer-&gt;frame_size) {
+                write_frame = mpf_frame_buffer_frame_get(buffer,buffer-&gt;write_pos);
+                write_frame-&gt;type = frame-&gt;type;
+                write_frame-&gt;codec_frame.size = buffer-&gt;frame_size;
+                memcpy(
+                        write_frame-&gt;codec_frame.buffer,
+                        data,
+                        write_frame-&gt;codec_frame.size);
+
+                data = (char*)data + buffer-&gt;frame_size;
+                size -= buffer-&gt;frame_size;
+                buffer-&gt;write_pos ++;
+        }
+
+        apr_thread_mutex_unlock(buffer-&gt;guard);
+        /* if size != 0 =&gt; 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-&gt;guard);
+        if(buffer-&gt;write_pos &gt; buffer-&gt;read_pos) {
+                /* normal read */
+                mpf_frame_t *src_media_frame = mpf_frame_buffer_frame_get(buffer,buffer-&gt;read_pos);
+                media_frame-&gt;type = src_media_frame-&gt;type;
+                if(media_frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) {
+                        media_frame-&gt;codec_frame.size = src_media_frame-&gt;codec_frame.size;
+                        memcpy(
+                                media_frame-&gt;codec_frame.buffer,
+                                src_media_frame-&gt;codec_frame.buffer,
+                                media_frame-&gt;codec_frame.size);
+                }
+                if(media_frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) {
+                        media_frame-&gt;event_frame = src_media_frame-&gt;event_frame;
+                }
+                src_media_frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
+                buffer-&gt;read_pos ++;
+        }
+        else {
+                /* underflow */
+                media_frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
+        }
+        apr_thread_mutex_unlock(buffer-&gt;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-&gt;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-&gt;base.ip.length == 0) {
-                media-&gt;base.ip = config-&gt;ip;
-                media-&gt;base.ext_ip = config-&gt;ext_ip;
-        }
-        if(media-&gt;base.port == 0) {
-                media-&gt;base.port = config-&gt;rtp_port_cur;
-                config-&gt;rtp_port_cur += 2;
-                if(config-&gt;rtp_port_cur == config-&gt;rtp_port_max) {
-                        config-&gt;rtp_port_cur = config-&gt;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-&gt;base.id = remote_media-&gt;base.id;
</span><span class="cx">         }
</span><ins>+        if(local_media-&gt;base.ip.length == 0) {
+                local_media-&gt;base.ip = rtp_stream-&gt;config-&gt;ip;
+                local_media-&gt;base.ext_ip = rtp_stream-&gt;config-&gt;ext_ip;
+        }
+        if(local_media-&gt;base.port == 0) {
+                /* RTP port management */
+                apr_port_t first_port_in_search = rtp_stream-&gt;config-&gt;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-&gt;config);
-        if(mpf_rtp_socket_create(rtp_stream,local_media) == FALSE) {
</del><ins>+                do {
+                        local_media-&gt;base.port = rtp_stream-&gt;config-&gt;rtp_port_cur;
+                        rtp_stream-&gt;config-&gt;rtp_port_cur += 2;
+                        if(rtp_stream-&gt;config-&gt;rtp_port_cur == rtp_stream-&gt;config-&gt;rtp_port_max) {
+                                rtp_stream-&gt;config-&gt;rtp_port_cur = rtp_stream-&gt;config-&gt;rtp_port_min;
+                        }
+                        if(mpf_rtp_socket_create(rtp_stream,local_media) == TRUE) {
+                                is_port_ok = TRUE;
+                        }
+                } while((is_port_ok == FALSE) &amp;&amp; (first_port_in_search != rtp_stream-&gt;config-&gt;rtp_port_cur));
+                if(is_port_ok == FALSE) {
+                        local_media-&gt;base.state = MPF_MEDIA_DISABLED;
+                        status = FALSE;
+                }
+        }
+        else if(mpf_rtp_socket_create(rtp_stream,local_media) == FALSE) {
</ins><span class="cx">                 local_media-&gt;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 &quot;License&quot;);
+ * 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 &quot;AS IS&quot; 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 &lt;flite.h&gt;
+#include &lt;apr_hash.h&gt;
+#include &quot;mrcp_message.h&quot;
+
+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=&quot;h;hpp;hxx;hm;inl;inc;xsd&quot;
</span><span class="cx">                         UniqueIdentifier=&quot;{93995380-89BD-4b04-88EB-625FBE52EBFB}&quot;
</span><span class="cx">                         &gt;
</span><ins>+                        &lt;File
+                                RelativePath=&quot;.\include\flite_voices.h&quot;
+                                &gt;
+                        &lt;/File&gt;
</ins><span class="cx">                 &lt;/Filter&gt;
</span><span class="cx">                 &lt;Filter
</span><span class="cx">                         Name=&quot;src&quot;
</span><span class="cx">                         Filter=&quot;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx&quot;
</span><span class="cx">                         &gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\src\flite_voices.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\src\mrcp_flite.c&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</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 &quot;License&quot;);
+ * 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 &quot;AS IS&quot; 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 &quot;flite_voices.h&quot;
+#include &quot;mrcp_synth_header.h&quot;
+
+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-&gt;name = &quot;awb&quot;;
+        voice-&gt;self = NULL;
+        voice-&gt;register_voice = register_cmu_us_awb;
+        voice-&gt;unregister_voice = unregister_cmu_us_awb;
+        apr_hash_set(voices-&gt;table,voice-&gt;name,APR_HASH_KEY_STRING,voice);
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice-&gt;name = &quot;kal&quot;;
+        voice-&gt;self = NULL;
+        voice-&gt;register_voice = register_cmu_us_kal;
+        voice-&gt;unregister_voice = unregister_cmu_us_kal;
+        apr_hash_set(voices-&gt;table,voice-&gt;name,APR_HASH_KEY_STRING,voice);
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice-&gt;name = &quot;rms&quot;;
+        voice-&gt;self = NULL;
+        voice-&gt;register_voice = register_cmu_us_rms;
+        voice-&gt;unregister_voice = unregister_cmu_us_rms;
+        apr_hash_set(voices-&gt;table,voice-&gt;name,APR_HASH_KEY_STRING,voice);
+
+        voice = apr_palloc(pool,sizeof(flite_voice_t));
+        voice-&gt;name = &quot;slt&quot;;
+        voice-&gt;self = NULL;
+        voice-&gt;register_voice = register_cmu_us_slt;
+        voice-&gt;unregister_voice = unregister_cmu_us_slt;
+        apr_hash_set(voices-&gt;table,voice-&gt;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-&gt;pool = pool;
+        voices-&gt;table = apr_hash_make(pool);
+
+        /* init voices */
+        flite_voices_init(voices,pool);
+
+        /* register voices */
+        it = apr_hash_first(pool,voices-&gt;table);
+        /* walk through the voices and register them */
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                voice = val;
+                if(voice) {
+                        voice-&gt;self = voice-&gt;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-&gt;pool,voices-&gt;table);
+        /* walk through the voices and register them */
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                voice = val;
+                if(voice &amp;&amp; voice-&gt;self) {
+                        voice-&gt;unregister_voice(voice-&gt;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-&gt;voice_param.name.buf;
+                }
+        }
+
+        if(voice_name) {
+                /* get voice by name */
+                flite_voice_t *flite_voice;
+                flite_voice = apr_hash_get(voices-&gt;table,voice_name,APR_HASH_KEY_STRING);
+                if(flite_voice) {
+                        voice = flite_voice-&gt;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-&gt;pool,voices-&gt;table);
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                if(val) {
+                        flite_voice = val;
+                        voice = flite_voice-&gt;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 &quot;flite_voices.h&quot;
</ins><span class="cx"> #include &quot;mrcp_resource_engine.h&quot;
</span><span class="cx"> #include &quot;mrcp_synth_resource.h&quot;
</span><span class="cx"> #include &quot;mrcp_synth_header.h&quot;
</span><span class="lines">@@ -33,7 +34,6 @@
</span><span class="cx"> #include &quot;apr_time.h&quot;
</span><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><del>-#include &quot;flite.h&quot;
</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-&gt;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, &quot;flite_synth_engine_open&quot;);
</span><span class="cx"> 
</span><span class="cx">         flite_init();
</span><del>-        flite_engine-&gt;voices.awb = register_cmu_us_awb();
-        flite_engine-&gt;voices.kal = register_cmu_us_kal();
-        flite_engine-&gt;voices.rms = register_cmu_us_rms();
-        flite_engine-&gt;voices.slt = register_cmu_us_slt();
</del><span class="cx"> 
</span><del>-        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite init success&quot;);
</del><ins>+        flite_engine-&gt;voices = flite_voices_load(engine-&gt;pool);
</ins><span class="cx"> 
</span><ins>+        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite init success&quot;);
</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-&gt;obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_engine_close&quot;);
</span><span class="cx"> 
</span><del>-        unregister_cmu_us_awb(flite_engine-&gt;voices.awb);
-        unregister_cmu_us_kal(flite_engine-&gt;voices.kal);
-        unregister_cmu_us_rms(flite_engine-&gt;voices.rms);
-        unregister_cmu_us_slt(flite_engine-&gt;voices.slt);
</del><ins>+        flite_voices_unload(flite_engine-&gt;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-&gt;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-&gt;pool);
+        if(!consumer_task) {
+                apt_log(APT_LOG_MARK,APT_PRIO_ERROR, &quot;flite_synth_channel_speak failed to create flite speak task - channel:%d&quot;, synth_channel-&gt;iId);
+                return FALSE;
+        }
+
+        task_vtable = apt_consumer_task_vtable_get(consumer_task);
+        if(!task_vtable) {
+                apt_log(APT_LOG_MARK,APT_PRIO_ERROR, &quot;flite_synth_channel_speak cannot use flite speak task vtable - channel:%d&quot;, synth_channel-&gt;iId);
+                return FALSE;
+        }
+
+        task_vtable-&gt;process_msg = flite_speak;
+        synth_channel-&gt;msg_pool = msg_pool;
+        synth_channel-&gt;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, &quot;flite_synth_engine_channel_create&quot;);
</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-&gt;channel_count = 1;
+        codec_descriptor-&gt;payload_type = 96;
+        apt_string_set(&amp;codec_descriptor-&gt;name,&quot;LPCM&quot;);
+        codec_descriptor-&gt;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-&gt;channel_count = 1;
-//        codec_descriptor-&gt;payload_type = 96;
-//        apt_string_set(&amp;codec_descriptor-&gt;name,&quot;LPCM&quot;);
-//        codec_descriptor-&gt;sampling_rate = 16000;
-
</del><span class="cx">         synth_channel-&gt;flite_engine = (flite_synth_engine_t *) engine-&gt;obj;
</span><span class="cx">         synth_channel-&gt;speak_request = NULL; // no active speak request in progress
</span><ins>+        synth_channel-&gt;speak_response = NULL;
</ins><span class="cx">         synth_channel-&gt;stop_response = NULL;
</span><ins>+        synth_channel-&gt;synthesizing = FALSE;
</ins><span class="cx">         synth_channel-&gt;paused = FALSE;
</span><span class="cx">         synth_channel-&gt;pool = pool;
</span><span class="cx">         synth_channel-&gt;audio_buffer = NULL;
</span><del>-        synth_channel-&gt;voice = NULL;
</del><span class="cx">         synth_channel-&gt;iId = 0;
</span><del>-
-        if (apr_thread_mutex_create(&amp;synth_channel-&gt;channel_guard,APR_THREAD_MUTEX_DEFAULT,pool) != APR_SUCCESS) 
-        {
-                apt_log(APT_LOG_MARK, APT_PRIO_ERROR, &quot;Failed to create channel guard&quot;);
</del><ins>+        synth_channel-&gt;task = NULL;
+        synth_channel-&gt;msg_pool = NULL;
+        if(flite_synth_task_create(synth_channel) != TRUE) {
+                apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;flite_synth_task_create failed&quot;);
</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-&gt;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-&gt;channel) 
-        {
</del><ins>+        if(!synth_channel-&gt;channel) {
</ins><span class="cx">                 apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;flite_synth_engine_channel_create failed&quot;);
</span><ins>+                apt_task_destroy(synth_channel-&gt;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-&gt;iId = ++synth_channel-&gt;flite_engine-&gt;iChannels;
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_engine_channel_create created channel %d&quot;, synth_channel-&gt;iId);
</span><del>-
</del><span class="cx">         return synth_channel-&gt;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-&gt;method_obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_channel_destroy - channel %d&quot;, synth_channel-&gt;iId);
</span><del>-        if(synth_channel-&gt;task)
-        {
-                apt_task_t *task = apt_consumer_task_base_get(synth_channel-&gt;task);
-                if (!task || !apt_task_destroy(task))
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;Speak task destroy failed - channel %d&quot;, synth_channel-&gt;iId);
-                }
-                else
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Speak task destroyed - channel %d&quot;, synth_channel-&gt;iId);
-                }
</del><ins>+        if(synth_channel-&gt;task) {
+                apt_task_destroy(synth_channel-&gt;task);
+                synth_channel-&gt;task = NULL;
</ins><span class="cx">         }
</span><span class="cx">         
</span><del>-        synth_channel-&gt;task = NULL;
</del><span class="cx">         synth_channel-&gt;flite_engine-&gt;iChannels--;
</span><del>-
-        apr_thread_mutex_destroy(synth_channel-&gt;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-&gt;method_obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_channel_open - channel %d&quot;, synth_channel-&gt;iId);
</span><span class="cx"> 
</span><del>-        synth_channel-&gt;voice = synth_channel-&gt;flite_engine-&gt;voices.awb;
</del><ins>+        if(synth_channel-&gt;task) {
+                if(apt_task_start(synth_channel-&gt;task) == TRUE) {
+                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Speak task started - channel %d&quot;, synth_channel-&gt;iId);
+                }
+                else {
+                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;Speak task start failed - channel %d&quot;, synth_channel-&gt;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-&gt;method_obj;
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_channel_close - channel %d&quot;, synth_channel-&gt;iId);
</span><del>-        // create thread to wait for speak thread to terminate
-        flite_synth_channel_close_t(channel);
</del><ins>+
+        if(synth_channel-&gt;task) {
+                if(apt_task_terminate(synth_channel-&gt;task,TRUE) == TRUE) {
+                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Speak task terminated - channel %d&quot;, synth_channel-&gt;iId);
+                }
+                else {
+                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;Speak task terminate failed - channel %d&quot;, synth_channel-&gt;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-&gt;start_line.method_id) {
</span><span class="cx">                 case SYNTHESIZER_SET_PARAMS:
</span><del>-                                // TODO set voices
-                                //        if (!strcasecmp(voice_name, &quot;awb&quot;)) {
-                                //                synth_channel-&gt;voice = voices.awb;
-                                //        } else if (!strcasecmp(voice_name, &quot;kal&quot;)) {
-                                //                synth_channel-&gt;voice = voices.kal;
-                                //        } else if (!strcasecmp(voice_name, &quot;rms&quot;)) {
-                                //                synth_channel-&gt;voice = voices.rms;
-                                //        } else if (!strcasecmp(voice_name, &quot;slt&quot;)) {
-                                //                synth_channel-&gt;voice = voices.slt;
-                                //        } else {
-                                //                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Valid voice names are awb, kal, rms or slt&quot;);
-                                //        }
</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-&gt;method_obj;
-        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_channel_close_t - channel %d&quot;, synth_channel-&gt;iId);
-        
-        if (synth_channel-&gt;task) 
-        {
-                apt_task_t *task = apt_consumer_task_base_get(synth_channel-&gt;task);
-                if (!apt_task_terminate(task,TRUE))
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;Speak task terminate failed - channel %d&quot;, synth_channel-&gt;iId);
-                }
-                else
-                {
-                        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Speak task terminated - channel %d&quot;, synth_channel-&gt;iId);
-                        apt_task_destroy(task);
-                        synth_channel-&gt;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-&gt;start_line.status_code = status_code;
+        synth_header-&gt;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-&gt;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, &quot;flite_synth_channel_speak - channel %d&quot;, synth_channel-&gt;iId);
</span><span class="cx"> 
</span><del>-        if (!synth_channel-&gt;speak_request)
-        {
-                apt_task_msg_pool_t *msg_pool = apt_task_msg_pool_create_dynamic( sizeof(flite_speak_msg_t),synth_channel-&gt;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, &quot;Create flite speak task - channel: %d&quot;, synth_channel-&gt;iId);
-            synth_channel-&gt;task = apt_consumer_task_create(synth_channel, msg_pool, synth_channel-&gt;pool);
-                if (!synth_channel-&gt;task) 
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_ERROR, &quot;flite_synth_channel_speak failed to create flite speak task - channel:%d&quot;, synth_channel-&gt;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-&gt;content_type.buf;
</ins><span class="cx">                 }
</span><ins>+        }
+        if(!content_type) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Missing Content-Type&quot;);
+                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-&gt;task);
-                if (!task_vtable) 
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_ERROR, &quot;flite_synth_channel_speak cannot use flite speak task vtable - channel:%d&quot;, synth_channel-&gt;iId);
-                        return FALSE;
-                }
</del><ins>+        /* Flite currently supports only text/plain (no SSML) */
+        if(strstr(content_type,&quot;text&quot;) == NULL) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Not Supported Content-Type [%s]&quot;,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-&gt;process_msg = flite_speak;
-                synth_channel-&gt;speak_request = request;
-                
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, &quot;Start task - channel %d&quot;, synth_channel-&gt;iId);
-                task = apt_consumer_task_base_get(synth_channel-&gt;task);
-                if (apt_task_start(task) == FALSE) 
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_ERROR, &quot;flite_synth_channel_speak failed to start task - channel: %d&quot;, synth_channel-&gt;iId);
-                        apt_task_destroy(task);
-                        return FALSE;
-                }
</del><ins>+        synth_channel-&gt;speak_request = request;
+        synth_channel-&gt;speak_response = response;
</ins><span class="cx"> 
</span><del>-                msg = apt_task_msg_acquire(msg_pool);
-                msg-&gt;type = TASK_MSG_USER;
-                flite_msg = (flite_speak_msg_t*) msg-&gt;data;
-                flite_msg-&gt;channel = synth_channel;
-                flite_msg-&gt;request = request;
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, &quot;Send signal to start speech synthesis - channel:%d&quot;, synth_channel-&gt;iId);
-                if (apt_task_msg_signal(task,msg))
-                {
-                        response-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
-                        mrcp_engine_channel_message_send(channel,response);
-                }
-                else
-                {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING, &quot;Failed to send signal to start speech synthesis - channel:%d&quot;, synth_channel-&gt;iId);
-                        apt_task_destroy(task);
-                        return FALSE;
-                }
</del><ins>+        msg = apt_task_msg_acquire(synth_channel-&gt;msg_pool);
+        msg-&gt;type = TASK_MSG_USER;
+        flite_msg = (flite_speak_msg_t*) msg-&gt;data;
+        flite_msg-&gt;channel = synth_channel;
+        flite_msg-&gt;request = request;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, &quot;Send signal to start speech synthesis - channel:%d&quot;, synth_channel-&gt;iId);
+        if(apt_task_msg_signal(synth_channel-&gt;task,msg) != TRUE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING, &quot;Failed to send signal to start speech synthesis - channel:%d&quot;, synth_channel-&gt;iId);
+                synth_channel-&gt;speak_request = NULL;
+                synth_channel-&gt;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-&gt;data;
</span><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) flite_msg-&gt;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-&gt;channel);
</span><del>-        apr_uint16_t rate = codec-&gt;descriptor-&gt;sampling_rate;                        
</del><ins>+        apr_uint16_t rate = codec-&gt;descriptor-&gt;sampling_rate;
+        body = &amp;synth_channel-&gt;speak_request-&gt;body;
</ins><span class="cx"> 
</span><ins>+        response = synth_channel-&gt;speak_response;
+        synth_channel-&gt;speak_response = NULL;
+
</ins><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;&lt; flite_speak_msg_process speak - channel %d&quot;, synth_channel-&gt;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-&gt;speak_request-&gt;body.length)
-        {
-                // TODO 
-                // create small units of text from synth_channel-&gt;speak_request-&gt;body.buf ( , . ? ! but ...
-                // synthesize small unit and store in audio_buffer
-                // check for stop 
-                // pause resume state could improve performance 
-                // you can &quot;pause&quot; 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-&gt;speak_request-&gt;body.buf, synth_channel-&gt;voice);
-                if (wave &amp;&amp; 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, &quot;TTS (chan %d) took %&quot;APR_TIME_T_FMT&quot; to generate %d of speech (in millisec)&quot;, synth_channel-&gt;iId, elapsed, generated);
</del><ins>+        if(!body-&gt;length) {
+                synth_channel-&gt;speak_request = NULL;
+                synth_response_construct(response,MRCP_STATUS_CODE_MISSING_PARAM,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                mrcp_engine_channel_message_send(synth_channel-&gt;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, &quot;TTS resampling to %d on (chan %d) took %&quot;APR_TIME_T_FMT&quot; millisec&quot;, rate, synth_channel-&gt;iId, elapsed);
-                        }
-                        mpf_buffer_audio_write(synth_channel-&gt;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-&gt;flite_engine-&gt;voices,
+                                                        synth_channel-&gt;speak_request);
+        if(!voice) {
+                /* error case: no voice found, appropriate respond must be sent */
+                synth_channel-&gt;speak_request = NULL;
+                synth_response_construct(response,MRCP_STATUS_CODE_METHOD_FAILED,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
+                mrcp_engine_channel_message_send(synth_channel-&gt;channel,response);
+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        apr_thread_mutex_lock(synth_channel-&gt;channel_guard);
-        stop_response = synth_channel-&gt;stop_response; 
-        apr_thread_mutex_unlock(synth_channel-&gt;channel_guard);
</del><ins>+        /* 
+        TODO 
+        create small units of text from synth_channel-&gt;speak_request-&gt;body.buf ( , . ? ! but ...
+        synthesize small unit and store in audio_buffer
+        check for stop 
+        pause resume state could improve performance 
+        you can &quot;pause&quot; 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-&gt;audio_buffer, MEDIA_FRAME_TYPE_EVENT);
-                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;&gt; flite_speak_msg_process speak - end of TTS - %d&quot;, synth_channel-&gt;iId);
</del><ins>+        /* send in-progress response and start synthesizing */
+        response-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        mrcp_engine_channel_message_send(synth_channel-&gt;channel,response);
+        
+        synth_channel-&gt;synthesizing = TRUE;
+        wave = flite_text_to_wave(body-&gt;buf, voice);
+        if(wave &amp;&amp; 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, &quot;TTS (chan %d) took %&quot;APR_TIME_T_FMT&quot; to generate %d of speech (in millisec)&quot;, synth_channel-&gt;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, &quot;TTS resampling to %d on (chan %d) took %&quot;APR_TIME_T_FMT&quot; millisec&quot;, rate, synth_channel-&gt;iId, elapsed);
+                }
+                mpf_buffer_audio_write(synth_channel-&gt;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, &quot;&gt; flite_speak_msg_process speak - channel %d&quot;, synth_channel-&gt;iId);
-        }
</del><ins>+
+        // this will notify the callback that feeds the client that synthesis is complete
+        mpf_buffer_event_write(synth_channel-&gt;audio_buffer, MEDIA_FRAME_TYPE_EVENT);
+        synth_channel-&gt;synthesizing = FALSE;
+
+        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;&gt; flite_speak_msg_process speak - end of TTS - %d&quot;, synth_channel-&gt;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, &quot;flite_synth_channel_stop - channel %d&quot;, synth_channel-&gt;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-&gt;channel_guard);
</del><span class="cx">         synth_channel-&gt;stop_response = response;
</span><del>-        apr_thread_mutex_unlock(synth_channel-&gt;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, &quot;flite_synth_stream_destroy&quot;);
-        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-&gt;obj;
-//        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_stream_open - channel %d&quot;, synth_channel-&gt;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-&gt;obj;
-//        apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_stream_close - channel %d&quot;, synth_channel-&gt;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-&gt;obj;
</span><del>-        if (synth_channel-&gt;stop_response &amp;&amp; synth_channel-&gt;speak_request)
-        {
</del><ins>+        if(synth_channel-&gt;stop_response &amp;&amp; synth_channel-&gt;synthesizing == FALSE) {
</ins><span class="cx">                 /* send asynchronous response to STOP request */
</span><del>-                mrcp_engine_channel_message_send(synth_channel-&gt;channel, synth_channel-&gt;stop_response);
</del><ins>+                mrcp_message_t *stop_response = synth_channel-&gt;stop_response;
+                synth_channel-&gt;stop_response = NULL;
</ins><span class="cx">                 synth_channel-&gt;speak_request = NULL;
</span><span class="cx">                 synth_channel-&gt;paused = FALSE;
</span><ins>+                mrcp_engine_channel_message_send(synth_channel-&gt;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-&gt;speak_request &amp;&amp; synth_channel-&gt;paused == FALSE) 
-        {
</del><ins>+        if(synth_channel-&gt;speak_request &amp;&amp; synth_channel-&gt;paused == FALSE) {
</ins><span class="cx">                 /* normal processing */
</span><span class="cx">                 mpf_buffer_frame_read(synth_channel-&gt;audio_buffer,frame);
</span><span class="cx"> //                apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_stream_read - channel %d - size %d&quot;, synth_channel-&gt;iId, mpf_buffer_get_size(synth_channel-&gt;audio_buffer));
</span><span class="cx"> 
</span><del>-                if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) 
-                {
</del><ins>+                if((frame-&gt;type &amp; 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>