<!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][15580] </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=15580">15580</a></dd>
<dt>Author</dt> <dd>mikej</dd>
<dt>Date</dt> <dd>2009-11-20 16:00:51 -0600 (Fri, 20 Nov 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>merge upstream changes to svn <a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=2096">r2096</a>

commit 84cd8df5775fa8349c05f6ed81de752931d8ac31
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 20 06:34:01 2009 +0000

    Provided a bit cleaner solution to adjust scheduler rate (if needed).
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1296 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2a83967881043cc98f097eb7e3680fc0424811c7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 19 19:00:47 2009 +0000

    Introduced an option to run mpf scheduler n (rate) times faster that real-time.
    
    By default everything remains as is. This option aims to workaround a particular issue. Do not use this option, unless you know what you're doing.
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1295 f001bc3a-424a-0410-80a0-a715b8f413a8

commit adb09a70e3c5c8b4df1284419d8d38613079cacf
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 19 18:16:06 2009 +0000

    Added an engine for recorder resource in default config, which I forgot to do before
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1294 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7f450dd3a0f38ea22ec26a700ab494256f669657
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 18 18:16:03 2009 +0000

    Implemented RTCP receiving procedure, made other RTCP related enhancements
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1293 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c2a5dc114f639eebff0e8a2583105d51311fd743
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 18 17:59:52 2009 +0000

    Fixed timers (nodes of the list) to be properly sorted by scheduled to elapse time
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1292 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 47d6df92a8c76567a80667f1a556f930cf9718d4
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 18 17:50:07 2009 +0000

    Set one-8kHz.pcm instead of old one.pcm as default input for asrclient application
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1291 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1ac5e6c2677bdf0da009c0bd729ea9ce3c265b18
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 17 20:11:32 2009 +0000

    Loading RTCP related settings from config files (unimrcpclient.xml and unimrcpserver.xml respectively)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1290 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9587d418d1e528d7b590280aef25dc89441d55cf
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 17 20:09:28 2009 +0000

    Added policies for RTCP BYE transmission and
    also added optional reason string generation
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1289 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 707c89631ea5f03bb0944fa14acde98abc942cc0
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 17 13:18:36 2009 +0000

    Added more checking not to crash on wild pointers passed from user space
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1288 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8b447a59c3939a1ca8bb78da7ca18dcea2680e92
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 16 16:12:19 2009 +0000

    Properly tracking the state of RTP/RTCP session to send compound RTCP BYE message when needed.
    Using local and remote sockaddr in traces.
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1287 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ec172c46622e9b9d332caef9989358453669a3c8
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 14 21:24:08 2009 +0000

    Filled fields of RTCP RR report
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1286 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8dc2333148cfda12658a1b6d0eaf4521a15173bf
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 14 18:39:05 2009 +0000

    MPF timer related fixes and enhancements
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1285 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3e63923d6d1e5962205e4abba5e6e5b8a364bb68
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 14 16:29:54 2009 +0000

    Added debug trace to indicate waiting for new messages state
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1284 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9a7937cb5cf2ed669bc193ded4cd389282b42230
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 13 20:37:39 2009 +0000

    Sending first RTCP reports
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1283 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ebe5ccbdb032edfb8a45cbdd29cc4271b72b1b8f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 13 20:36:23 2009 +0000

    Added an utility function to get current NTP time
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1282 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4421f92ed549842252616802ce46e2bc3716652c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 13 18:17:02 2009 +0000

    Fixed RTCP packet fields and alignments
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1281 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 28ec22508d517720a52c5a98a5cdb252df604363
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 20:17:05 2009 +0000

    Set RTCP transmission timer if RTCP is enabled
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1280 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a7d91738c0d024600050ebc3955642f955eb6aeb
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 18:56:33 2009 +0000

    Made timer manager available for media terminations
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1279 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4940bee339c41206af57ff2b623f8211a4c11c07
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 18:50:32 2009 +0000

    Do not destroy audio streams while destroying media context, which still contains terminations. Instead just subtract terminations.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1278 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a24d8e814e4fe8d587b87c7a0103e3ecc8cabb6b
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 18:41:00 2009 +0000

    Added timer manager (missing from prev commit)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1277 f001bc3a-424a-0410-80a0-a715b8f413a8

commit bc132cbae6e761630960797234ffc76bfcd76897
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 18:38:44 2009 +0000

    Reworked timer/clock related entities.
    
    mpf_scheduler provides clock for media processing and timers
    mpf_engine uses media processing clock as it was before
    mpf_timer_manager uses timer clock to provide timers management routine (set/kill/elapse) for mpf layer
    
    mpf_timers can be used only from the context of mpf_scheduler thread (context, streams, callbacks)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1276 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f7765d18eeabb7f3d61c51f78c47f1a2667405fc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 14:59:13 2009 +0000

    Removed array of multimedia timers, only one of them is actually used.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1275 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5997acf00aebc18c78294e574d3614fcbc794ac4
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 12 14:56:34 2009 +0000

    Basically implemented RTCP session scheduler
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1274 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9ab5014493a35e1f8f8ba34031e8a884c06afc4c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 11 21:19:04 2009 +0000

    Added new methods to mpf_termination interface such as add() and subtract(). These methods are called when termination is added and subtracted from mpf_context
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1273 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6b7a388da519acbbc6ecec4ead0e381c63346402
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 11 19:18:59 2009 +0000

    Separated mpf_termination and mpf_termination_factory in order to hide mpf_termination in mpf layer and not to expose it to user space.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1272 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2148e6a7bfd42f9c9b662a2a107349476d2a4fa1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 11 18:11:20 2009 +0000

    Implemented creation of socket pair (RTP/RTCP).
    
    RTCP socket is created next to RTP. It's reasonable to create RTCP socket even in case RTCP isn't used to avoid sending ICMP packets to remote peer.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1271 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c48e8e1f286ba5e433c7a961587ced8039cde3fd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 11 05:10:03 2009 +0000

    Fixed compilation
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1270 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 99e186b3d4e7e74da4cdbfebf141b13e611d7d1c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 10 20:30:16 2009 +0000

    Added RTCP related params to rtp_config (yet to be loaded from config file)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1269 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f43ef8c5c9a8d168b38784b5a2f95df8aa9af932
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 10 20:21:52 2009 +0000

    Added skeleton for RTCP session scheduler
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1268 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c7359c5e3fe1f577a18e9dd9321865697da064cc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 10 18:39:55 2009 +0000

    Added RTCP packet
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1267 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d013ea92461e21803803707d171c63b8f163dee8
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 10 18:32:40 2009 +0000

    Fixed minor typos in comments
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1266 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1b1f313769f1375eb3eeea8c1378463a226182fa
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 21:56:33 2009 +0000

    Set jitter and ssrc of rr_stat.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1265 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a09883271b921d5ff649b66af65b91f0aab8aeaf
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 21:29:21 2009 +0000

    Calculated not only number of packets sent, but also octets (payload bytes) sent.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1264 f001bc3a-424a-0410-80a0-a715b8f413a8

commit de157f9cf11eae33485e820cf6d32aee0a4ce739
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 20:52:38 2009 +0000

    Fixed typo in file name (rtpc -&gt; rtcp)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1263 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c4363f25417e045fa56ef05ee5a1ef27c847a02d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 20:48:41 2009 +0000

    Added RTCP header and stats used in SR and RR reports
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1262 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f8a10bb46185567c68fd9785cd351f3931519d2e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 17:23:26 2009 +0000

    Reset frame type and marker before read_frame() in decoder
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1261 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a8ac67a6ee566b0b3535a4cb4ea98ca18021c077
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 16:03:45 2009 +0000

    Fixed simultaneous transmission of named events and regular audio stream
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1260 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b8fb271257862c817eae069dc65093eebdcb9ff6
Author: tomas.valenta@speechtech.cz &lt;tomas.valenta@speechtech.cz@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 9 00:18:41 2009 +0000

    DTMF generator now fully supports out-of-band digits, including long-lasting events.
    DTMF detector now fully supports both in-band and out-of-band digits.
    To do: Simultaneous in-band and out-of-band transfer (at generator side) and events' ptime support (currently CODEC_FRAME_TIME_BASE=10ms used).
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1259 f001bc3a-424a-0410-80a0-a715b8f413a8

commit df38c3338ddb51eedb0640a3e14c435258876115
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Nov 8 20:31:18 2009 +0000

    Defined RTP_TRACE and JB_TRACE as null_trace by default
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1258 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1b94caa54c41fb3c4cafe7f752888d96f9fbcd79
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Nov 8 20:19:43 2009 +0000

    Added JB_TRACE define
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1257 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 555e2c6a9340f9cf8640abd69a37a26f3a2d17ab
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Nov 8 19:39:24 2009 +0000

    Added RTP_TRACE define
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1256 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 40bc2080211e33eefc25b183e124a6c694043c90
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Nov 8 13:37:41 2009 +0000

    Do not restart rx routine if failure threshold fired on processing of named events.
    
    Usually these are minor errors, which can be safely ignored. Unfortunately there are still many broken implementations out in the field.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1255 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9b7bd4b4937a1546052c26ba957f5075b6d8c9b1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 7 21:40:30 2009 +0000

    Although host/net order of named events duration was effectively handled in mpf generator, this field as well as others should in host order for user level, including
    dtmf generator and detector entities.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1254 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3a48e36216d03459e258e4f78d314a7e12d4c4cd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 7 21:29:17 2009 +0000

    Added traces to show how to trigger start and end of named events.
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1253 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7e88afd669e77a45a175f88e09b8d68069d189bf
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 7 21:17:40 2009 +0000

    Fixed processing of named events in jitter buffer
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1252 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f547a0454c79e387536da276ef9dbde24ff09210
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 7 19:10:12 2009 +0000

    Reset, copy frame-&gt;marker where required
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1251 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a3aa75dd7aa0128c19cdaa10d87eed0f5f7d116c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Nov 7 18:36:01 2009 +0000

    Set event descriptor based on capabilities and offer/answer
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1250 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7ee88a44a398ef9a7a9847277bd96ea7a4db5f16
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 6 20:55:57 2009 +0000

    Writing named events to jitter buffer (detection of new events, tracking of event updates, ...)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1249 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0a0099e1b7f90b288dabfcd694e8dea0f5b5b609
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 6 18:21:42 2009 +0000

    Added sample DTMF recognizer scenario/session
    
    Update your umcscenarios.xml file and use 'run dtmf' from umc console
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1248 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 40bfd9392b819708312effc60833fe5bf09f0418
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Nov 6 05:42:27 2009 +0000

    Added missing -lm to resolve undefined reference to 'sin' and 'cos' used from mpf_detector and mpf_generator
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1247 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f6b4d75156532f6e6e8441021c3d59f4c2658634
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 5 20:57:54 2009 +0000

    Fixed compilation under gcc (redefinition of typedef struct)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1246 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7b72a080f717628ba7a7197eef79be1adcb8ad6a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 5 18:58:42 2009 +0000

    Fixed host/net order routine for named events.
    
    User level is in host order.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1245 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ba65dbed0e994dce789de726921d84e5c8af19bf
Author: tomas.valenta@speechtech.cz &lt;tomas.valenta@speechtech.cz@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 5 18:58:24 2009 +0000

    Added DTMF generator and detector into MPF.
    Currently just in-band (audio) digits only are fully supported. The generated tone length is currently limited to 0xFFFF RTP time units (approx 8?\194?\160s@8?\194?\160kHz); will be enhanced.
    Out-of-band generator might work, but is not complete. Out-of-band detector is not implemented yet.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1244 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e84cf0107550fe0b5df025b365bff537a3c43461
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 5 16:10:46 2009 +0000

    Set resource id if resource indeed created
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1243 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f074ded9633a148305f8182ea353e583fa549e43
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Nov 5 14:15:08 2009 +0000

    Set named events in jitter buffer
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1242 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a86daebb9db0b1ccd5b1400fa65b2d95e674a8c6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 4 22:02:33 2009 +0000

    Properly set timestamp on event packets. All the markers should be set from user level to make it work correctly.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1241 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 52a71c40fa19ee2210923cf1d3893b4da53054fb
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 4 21:58:24 2009 +0000

    Added new marker which indicates start of new segment in case of long-lasting events in order to properly set timestamp on event packets
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1240 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a7bf0a924f924798032d65cf0c2484bab86ad6ff
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 4 19:31:41 2009 +0000

    Added frame marker which indicates either start or end of event, more markers might be added in the future
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1239 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 433e5c94a0e3ee1bc39bd113bc8e0af2832df950
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Nov 4 19:09:28 2009 +0000

    Supported simultaneous transmission of events and audio data, if/when needed.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1238 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5b9acde2754550eab6cfae7f189dfcf762166a3f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 3 19:20:06 2009 +0000

    Set Max-time and Final-silence header fields in umc record session
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1237 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 25b0c6ebc7faadd3d8d15bae603d428189ee0df1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 3 19:17:20 2009 +0000

    Supported a few more header fields such as Max-time, Final-silence also set Record-URI header filed in response to STOP request or RECORD-COMPLETE event
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1236 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 56d14eebe0d57d7a4eeec68e7e74075ddabd19d2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Nov 3 17:17:36 2009 +0000

    Split complete_timeout into two parts: speech (activity detection) timeout and silence (inactivity detection) timeout
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1235 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f62b8529a3e174be452dca631ca94f27011cba05
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 2 21:09:48 2009 +0000

    Added recorder scenario/session to umc application framework.
    
    To launch basic recorder session, update your umscenarios.xml file and use &quot;run rec&quot; command
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1234 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3d1707440b7ce386a35802f724549212238e5126
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 2 21:02:33 2009 +0000

    Integrated recorder plugin into GNU build
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1233 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2e0071e66003ff4d73dc8e44a83000884f79af40
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 2 20:53:08 2009 +0000

    Added mrcprecorder to the solution
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1232 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 965bf199a93ac7b79d7e94de8a25a5c55fa18b8d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 2 20:44:19 2009 +0000

    Initially added implementation of recorder engine (plugin)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1231 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5e3e1dbca93ecc37593a4c8a091a4b039a97450d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Nov 2 17:48:46 2009 +0000

    Added state machine for recorder resource
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1230 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0ad71ee97050e33da4f39803de1132dcb7d95e48
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 27 19:06:01 2009 +0000

    Fixed core dump with large in-line grammars (<a href="http://jira.freeswitch.org/browse/Issue-52">Issue-52</a>, Thanks Asackheim)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1229 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 089756fca925b818ade79e1b009612aed8af3f36
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 27 19:00:38 2009 +0000

    Added a few more checkings
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1228 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 60e20ca963baded1e1e9e8135030d0fd6085cf83
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 27 14:49:23 2009 +0000

    Added missing #include &lt;ctype.h&gt; to compile under gcc
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1227 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7a1a5eeff14b80a795fd03f164bb03d40e586d2b
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 27 14:48:09 2009 +0000

    Fixed function prototypes to compile without warnings with -Wstrict-prototypes gcc option
    
    As John stated, int foo() is not the same as int foo(void). This is true for pure C, meantime in C++ int foo() and int foo(void) are just the same prototypes.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1226 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 744d6dc495b072f175f38ccbee4b415b88c95239
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 27 14:35:15 2009 +0000

    Properly processed nua's shutdown (Thanks John)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1225 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8000fb6d6e7503b87c8046c9bb65c56b61137f08
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 27 14:27:02 2009 +0000

    Initialized codec manager a bit later with media engine.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1224 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 036cc125672f2a05cc9847436f967778d3dd8831
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 26 17:44:48 2009 +0000

    Loading MRCP resources from config.
    
    Resources MUST be loaded first, update your unimrcpclient.xml and unimrcpserver.xml files according
      &lt;!-- MRCP resources --&gt;
      &lt;resources&gt;
        &lt;resource class=&quot;speechsynth&quot; enable=&quot;1&quot;/&gt;
        &lt;resource class=&quot;speechrecog&quot; enable=&quot;1&quot;/&gt;
        &lt;resource class=&quot;recorder&quot; enable=&quot;1&quot;/&gt;
      &lt;/resources&gt;
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1223 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0788e08c0a17bd2974cf75d6a0459ee4d6e947f6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 26 17:12:57 2009 +0000

    Do not initialize profile if no resource factory registered
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1222 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e8cc3b89b8de07a4f7a480560616b6912059a082
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 26 14:04:31 2009 +0000

    Fixed @brief description
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1221 f001bc3a-424a-0410-80a0-a715b8f413a8

commit aed93bacf17e27f2507209a22382d700dc9d17a9
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 25 19:26:22 2009 +0000

    Separated MRCP start-line related routine
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1220 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3c71e09c365a2e252a3ce64bebffa8cfafe6081c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 25 19:06:54 2009 +0000

    Stored mrcp_resource instead of mrcp_resource_id in mrcp_message.
    
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1219 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 90822e0d43710cdef2caf8f3761a56c333a6f9fa
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 24 15:28:44 2009 +0000

    Initialized resource for channel at earlier stage to remove no more required resource_id channel member
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1218 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1b42089957ee75a0da7f78fca442c94b1a88fde9
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 24 14:39:47 2009 +0000

    Moved resource loader to &quot;control&quot; folder to leave &quot;resources&quot; folder exclusively for resources.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1217 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 76940502830e53c99ed4f7e92e12382a973bef61
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 24 14:29:17 2009 +0000

    Arranged resource, resource factory and resource loader entities in a bit more clever way.
    
    Both resource name and identifier are properties of resource.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1216 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b97b51d0300668cb821b62124ab1a724b29cdbb4
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 23 18:20:10 2009 +0000

    Replaced mrcp_default_factory with mrcp_resource_loader
    
    Resource loader soon will be able to load resources based on configuration.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1215 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6e8ca2e820b6282b46169935272eb10229a7ef71
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 23 15:46:08 2009 +0000

    Applied temporarily workaround to send a named event as soon as it's received regardless what the actual packetization time is (Thanks Randy)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1214 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7fc090163d5b5eda6e12e302b4bde2729ac4cc05
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 23 13:24:53 2009 +0000

    Initialized recorder resource on start-up by default (should be configurable)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1213 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9f66366c68461fbe2c7edfe3cd15fdf213c76f79
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Oct 22 18:46:28 2009 +0000

    Added methods and events for MRCP recorder resource
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1212 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ce024776e6f03ec578cfae108cf53aab9ec1b086
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Oct 22 18:07:16 2009 +0000

    Hopefully finally fixed RTSP/MRCPv1 session management related issues, when multiple resources are offered using consecutive RTSP SETUP requests containing no SDP.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1211 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a72740ffe0169e87fe7a33e8403ccc61a7e5ad38
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Oct 22 14:53:06 2009 +0000

    Added a few accessors to mrcp_application interface in order to completely hide session interface from the application context.
    
    Session pointer SHOULD be used as an opaque pointer from now on.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1210 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 78c223cc46fedc0a8f5a76492aea7f76049cf23f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Oct 21 20:41:49 2009 +0000

    Initially added MRCP recorder resource header
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1209 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ea6b4a05b836b072cad4f2b17c312a31a516350e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Oct 21 16:19:59 2009 +0000

    Enhanced apt_task to be able to raise late start-complete event when task is not just started, but also ready to process messages.
    
    Some tasks are implicitly ready to process messages. The others still initialize some additional data. Thus, they should explicitly indicate ready state.
    As a result on_ready event will be raised to application context when it was intended to be raised. (<a href="http://jira.freeswitch.org/browse/Issue-49">Issue-49</a>)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1208 f001bc3a-424a-0410-80a0-a715b8f413a8

commit fecf6decb056e0b7232622abbf0240b230f4332f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 20 20:19:01 2009 +0000

    Better representation of abstract MRCP resource
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1207 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 813442c8b6b3d2fc202e58ea9189e2e62e4232d2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 20 17:22:56 2009 +0000

    Updated project files according
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1206 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1bc8a5b581b78a5c31f5e2ea594e87725be9b513
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 20 17:13:57 2009 +0000

    Moved files as well
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1205 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3e0bd386532d66ec7d63030910b4fa62012eeb6d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 20 17:08:40 2009 +0000

    Moved server side state machine creation from shared between client and server stacks mrcp_resource to mrcp_engine
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1204 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 07ce822cefd70b8696393ba1681179926168cb87
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 20 16:30:08 2009 +0000

    Renamed server_state_machine to state_machine.
    
    No functional changes.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1203 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 738e0b5a319f3e3c5968ffc4bc1ea649e63031c8
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 20 16:24:07 2009 +0000

    Removed client_state_machine, which was actually not implemented and unused. Renamed server_state_machine to state_machine.
    
    No functional changes.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1202 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0f576df4b9a39f6e4ffaec76056e0d45e59dbaa6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 19 18:46:57 2009 +0000

    Fixed compilation under gcc
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1201 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a1ef30ee7037f61ba8454e3447b675ebeb8a0d39
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 19 18:18:26 2009 +0000

    Added compile time define to support &quot;too long&quot; MRCP request identifiers.
    
    MRCPv2 specifies request-id as 32bit unsigned integer, while MRCPv1 doesn't limit this value.
    Some MRCPv1 clients use too long request-id. To support them #define TOO_LONG_MRCP_REQUEST_ID
    (<a href="http://jira.freeswitch.org/browse/Issue-48">Issue-48</a>)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1200 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8e560595461249c0924523f43a0a02a2f3106afe
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 18 17:54:05 2009 +0000

    Increased unimrcp version number
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1198 f001bc3a-424a-0410-80a0-a715b8f413a8

commit adbef71d8a6017c654fc3bc970120da81ea1d8e0
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 18 17:52:55 2009 +0000

    Increased plugin version number
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1197 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d19a7550d924d9482996641e7d7d617c9082c72e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 18 17:52:10 2009 +0000

    Clarified a bit plugin implementation rules
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1196 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0456d9b69f89b82b4487acb91574380eaa88b282
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 18 15:51:33 2009 +0000

    Fixed doxygen warnings
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1195 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ba29c377eda8bdc3212c49c3f217d50ba98da2d8
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 18 10:34:45 2009 +0000

    Updated the INSTALL to strengthen requirement for the dependency package.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1188 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 598434417a61d48072dad7f5e52dd7d1aabcd802
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 17 17:39:54 2009 +0000

    Added Chaitanya and Vali to the contributors list
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1185 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f3de0b40955ed4386e21a480e158f1557a957bdc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 16 15:04:25 2009 +0000

    Fixed header inheritance routine in order to not override fields which exist in original header (<a href="http://jira.freeswitch.org/browse/Issue-47">Issue-47</a>)
    
    Broken since <a href="http://fisheye.freeswitch.org/changelog/FreeSWITCH?cs=846">r846</a>
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1184 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0a9d6f344d456f283d2ab9dfd112961908fcce39
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Oct 15 15:43:17 2009 +0000

    Do not accept any messages after final TEARDOWN (session is being terminated)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1183 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0e04171d7f00a02901b8f793288e0cdd9778e0f2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Oct 15 15:09:04 2009 +0000

    Return JB_DISCARD_TOO_EARLY if buffer is full
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1182 f001bc3a-424a-0410-80a0-a715b8f413a8

commit cd0cd0c0f89988a841db4947c79bc584591db2fd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Oct 14 15:56:47 2009 +0000

    Spelled 'discovery'
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1181 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c8ee0ead88dd52dd08d4eeab8048ad8263a55a88
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 13 18:37:43 2009 +0000

    Fixed RTPS server stack processing in case there are more than one resource in the scope of the same RTSP session
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1180 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d325c4d5fa1a7b96bb47111147dde1804890d4c4
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 13 18:34:03 2009 +0000

    Set resource name for RTPS ANNOUNCE events
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1179 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6d418aa8bc5e21cd32394fecb92fc949befc56cd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Oct 13 06:09:36 2009 +0000

    Checked the return value of MrcpSessionCreate()
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1178 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7a6396943262fe550f49f8040217d4f26d39c70f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 12 18:37:17 2009 +0000

    Added convenient headers, which should be included from synth and recog plugins
    
    mrcp_synth_engine.h
    mrcp_recog_engine.h
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1177 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d16295aee7c3518a0523de15ced333918f6feb08
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 12 18:14:10 2009 +0000

    Made changes in plugins proposed earlier (resource_engine -&gt; engine)
    
    Nothing has to be done.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1176 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 27fdce12cb98e49bd61a58c93b113740d2aae1c2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 12 15:20:34 2009 +0000

    added svn props
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1175 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 354b415531d0605292d8e861590ef536803a849c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 12 13:21:40 2009 +0000

    Added support for grammars supplied inline within RECOGNIZE request in PocketSphinx plugin
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1174 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9b3889df631dfa896a84d05c3eed876d87a43f9f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 12 13:19:35 2009 +0000

    Enhanced recog session/scenario to be able to supply inline grammar within RECOGNIZE request, instead of preceding DEFINE-GRAMMAR one.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1173 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5be3d2ae0ca3ec58888bd76d46315e22671f87b3
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 11 17:19:25 2009 +0000

    Added new attribute for recog scenario to optionally specify audio source instead of default hard coded one.pcm.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1172 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1c4e5829cf2657df49c7a98e6732c1c980fef981
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 11 15:31:38 2009 +0000

    Added a couple of new umc console commands to show running sessions and available scenarios.
    
    &gt; show sessions
    &gt; show scenarios
    
    It was already possible to run new session and kill it
    
    &gt; run synth
    [1]
    
    &gt; kill 1
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1171 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4c59fe99e7d30359f416a1544c0ee84fc6784ee2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 11 08:23:48 2009 +0000

    Fixed another potential crash of client stack (leftover from previous fix).
    
    Pending session termination request should not be canceled even if termination event is received.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1170 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b966e80ea53795344c4e5c1472d3173ff71765d6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 10 19:17:53 2009 +0000

    Install *.jsgf and *.txt as well
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1169 f001bc3a-424a-0410-80a0-a715b8f413a8

commit fb12c7c19144fced8fa684f60bd3308e7099afb7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 10 19:06:24 2009 +0000

    Added sample JSGF grammar and plain text contents
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1168 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5c13e452e75c506436c6327e600f11b460e61ec3
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 10 18:57:29 2009 +0000

    Added umcscenarios.xml
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1167 f001bc3a-424a-0410-80a0-a715b8f413a8

commit fe2d1fa156764eb0f6001b5a6d0f21cc3f99df31
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 10 18:16:16 2009 +0000

    Added missing stdlib.h include
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1166 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c511584c906303db3eb5607dc94aae91c1fc307f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 10 18:12:00 2009 +0000

    Loading the attributes of predefined scenarios such as content-type, content-location, capabilities from config file.
    
    Predefined scenarios (Synthesizer, Recognizer) are also a bit enhanced, they are more customizable now...
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1165 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b2160f787f7695bc5128137309793ba5c4913da1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Oct 10 14:18:11 2009 +0000

    Fixed return value, which should be int for bitmasks
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1164 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 536460af46efc3389db9e40e584fa0331d278730
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Oct 7 13:14:47 2009 +0000

    Do not just return, but close file descriptor if config file is not a valid XML
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1163 f001bc3a-424a-0410-80a0-a715b8f413a8

commit f2f7452654a5449fc99ea5c28435fcdff651fef2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 5 17:56:42 2009 +0000

    Added umc project into the solution
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1162 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 727c402ca49c98bad25e408296cf268256f3a5d1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Oct 5 17:52:07 2009 +0000

    Added umc application into GNU build
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1161 f001bc3a-424a-0410-80a0-a715b8f413a8

commit baa849da05ab3f52612ae17ea91b89ba5def954e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Oct 4 20:58:45 2009 +0000

    Added another application (umc) built on top of libunimrcpclient.
    
    This application will eventually replace demo unimrcpclient ...
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1160 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e962a729e315cf54051d5b2eb5abbe0c6d72d4bc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 2 18:34:42 2009 +0000

    Fixed plugin_version_hdr in configure.ac (Thanks, John)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1159 f001bc3a-424a-0410-80a0-a715b8f413a8

commit cd46e9c59102734fa2c64097857b86a94403f6e0
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 2 15:24:23 2009 +0000

    Fixed APR_ARRAY_IDX related issue in apt_pair (Thanks, Anthony)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1158 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a7cc93a58d189ec805f55360c5cc7d6578566050
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Oct 2 07:45:19 2009 +0000

    Implicitly modify initial offer (RTSP/MRCPv1), if it contains disabled media stream.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1157 f001bc3a-424a-0410-80a0-a715b8f413a8

commit cc135ce9547c5caf09238b552d53085b4443b8bc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Oct 1 04:06:18 2009 +0000

    Added a user level function to associate (de-associate) external object with the session
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1156 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5364deb02ce21e10f3a8a0f13ab78473022c5248
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 30 18:24:33 2009 +0000

    Fixed crash of client stack caused by race condition on session termination.
    
    Most probably this fixes the issue reported on the discussion group recently and <a href="http://jira.freeswitch.org/browse/Issue-33">Issue-33</a>.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1155 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8c6b3def701b3e4b04b7cec344d6c83e6b147733
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Sep 29 15:54:02 2009 +0000

    Enhanced &quot;prepare&quot; utility project to install the whole apr-iconv stuff including iconv/*.so, if apr-iconv library exists. (<a href="http://jira.freeswitch.org/browse/Issue-45">Issue-45</a>)
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1154 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1a26706b602aa5aef4eb77e60656600e0efab22c
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 28 18:38:47 2009 +0000

    Fixed C++ compile error in codec_descriptor.h (<a href="http://jira.freeswitch.org/browse/Issue-44">Issue-44</a>, Thanks Vali)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1153 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 980551739dae22c9219d2987958d44ba65072cf1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 28 18:32:22 2009 +0000

    Added media path traces for mixer and multiplier. Fixed initialization of source and sink streams in them.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1152 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4d0d245f3ad93e62b64d549df4a3edfa00607eba
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 28 10:01:23 2009 +0000

    Added an example on how to specify 16Kz codecs in config
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1151 f001bc3a-424a-0410-80a0-a715b8f413a8

commit edd7d550cd0c69b7e71863fe82f825a80d75348a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 28 04:51:02 2009 +0000

    Added to project file
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1150 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 56866f06009823a8a682535d12a516295e627be9
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Sep 27 18:41:54 2009 +0000

    Using MRCP_PLUGIN_VERSION_DECLARE macro for existing plugins.
    
    Version info is a property of the plugin but not the engine as it was before.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1149 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0f33b7d3a61ee9bb2815b54e0a6f7473acd42f2d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Sep 27 18:37:08 2009 +0000

    Separated user interface (what MRCP server uses) and implementation (what plugins implement) of MRCP engines.
    
    There are a few changes plugin implementors must be aware of
    - Plugin version number must be declared in each plugin, preferably using MRCP_PLUGIN_VERSION_DECLARE macro
    - MRCP engine is renamed from mrcp_resource_engine_t to mrcp_engine_t (legacy typedef remains)
    - Instead of mrcp_resource_engine.h consider using mrcp_engine_impl.h (legacy header remains)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1148 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b10833cf2bc46e7c306fdbf27493d95b86136258
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Sep 27 09:55:54 2009 +0000

    Added missing #include stdlib.h (GNU compilation)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1147 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1601da5d00e1d04ae284578937a6d7f07df75829
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Sep 27 09:53:04 2009 +0000

    Moved, separated functionality related to loading of plugins into corresponding header and source files
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1146 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 860768fabdd91b8c50ccdbbe882455bf120d59bf
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Sep 27 09:01:27 2009 +0000

    Moved, separated functionality related to factory of MRCP engines into corresponding header and source files
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1145 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 065cb1e9a449a6692f3cc023dee14f60c8612800
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Sep 26 07:28:47 2009 +0000

    Finally applied changes to the Cepstral plugin either.
    
    Scan available voices and indicate stream capabilities upon channel creation and use decided codec descriptor on channel open
    
    Better comply with engine create/destroy open/close routine
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1144 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7d61bdeba92adcfed677619b7c92a203a8c4d94a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Sep 25 16:10:18 2009 +0000

    Finally applied changes to the plugins.
    
    Indicate stream capabilities upon channel creation and use decided codec descriptor on channel open
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1143 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 64aaee0d070a5589aa3ec162586acd78d023b343
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Sep 25 15:24:01 2009 +0000

    Modified processing of offer.
    
    1. Receive offer
    2. Create control channels and media terminations indicating their capabilities
    3. Build media topology and media path (all the descriptors are initialized at this stage)
    4. Only then open control channels
    5. Send answer
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1142 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5a35d4c20ce3f67c8cd2a6ed1440817c6d5a1f1f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Sep 25 14:31:39 2009 +0000

    Added is_open member to mrcp_engine_channel_t
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1141 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ff764c523b9a60bb6de243e928d1a399f2ed7e6a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Sep 25 14:10:01 2009 +0000

    Building RTP termination capabilities according to associated media termination(s)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1140 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6b85a37e65c2600e317440d539968a794b2212f5
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 24 21:06:54 2009 +0000

    Updated demo speech file naming convention (demo-8kHz and demo-16kHz)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1139 f001bc3a-424a-0410-80a0-a715b8f413a8

commit da1d688fac7022152ea5962fa36420a9f6e049a6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 24 20:50:27 2009 +0000

    Added/renamed 8 kHz and 16 kHz speech to be used from demos
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1138 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c54d354c1de2a273b2e5c4eeb83c75d893a4cbe5
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 24 19:55:12 2009 +0000

    Added new function to the client API to create media termination (audio stream) based on specified capabilities.
    mrcp_application_audio_termination_create()
    
    Marked the following functions as deprecated (they still remain functional though)
    mrcp_application_source_termination_create()
    mrcp_application_sink_termination_create()
    
    Upgraded demo synth and recog applications according
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1137 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a8de40f600fe129b6367af435c47e80a3f1d52d6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 24 19:10:02 2009 +0000

    Added new function for the plugins to create media termination (audio stream) based on specified capabilities.
    mrcp_engine_audio_termination_create()
    
    Marked the following functions as deprecated (they still remain functional though)
    mrcp_engine_source_channel_create()
    mrcp_engine_sink_channel_create()
    
    Upgraded Flite plugin according
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1136 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a2f6fbc628717b4f927eed5fbda64dd47027bc9b
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 23 16:59:32 2009 +0000

    Dropped any further requests from application if session is being terminated.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1135 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d27e77a39c48baa110bb96524e170ff2a6419bbc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 23 15:15:50 2009 +0000

    Modified includes to #include what is actually needed
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1134 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ede4c291d16d5fe8783e3300b2eda71137fb095a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 23 14:51:44 2009 +0000

    Reviewed mpf_codec_t and mpf_stream_t entities and relationship between them.
    
    Codec as a manipulator (encode,decode,dissect) is not a property of stream. Stream holds capabilities and active codec descriptor(s). Actual codecs (PCMU, PCMA, L16) are registered at startup and passed to encoder and decoder objects when/where needed.
    Linear PCM (LPCM, but not L16) is just an internal descriptor, it's not a codec.
    
    Everything should work as is basis. The only user level interface change is in stream_open() method, which is optional and probably is not actually used. See demos for more info.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1133 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 502ed670a75f8a94c017fbd3525bbeb928d72ac9
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Sep 22 16:55:40 2009 +0000

    Considered own capabilities while building local descriptor (codec list), added more utility functions
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1132 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9cc077274f2333a8c1c2ed01d28d396c0ba95992
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 21 15:38:56 2009 +0000

    Further enhanced stream, codec capabilities and descriptors.
    Finally those capabilities will participate in offer/answer, a few steps remain.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1131 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9ddb49bd1a1dc51c4510abee8f1a092a6bce5dab
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Sep 19 11:53:16 2009 +0000

    Using APR_ARRAY_IDX and APR_ARRAY_PUSH convenient macros to operate on APR arrays.
    
    These macros are more safe and intuitive. Unfortunately they have been added only in <a href="http://jira.freeswitch.org/browse/APR-1">APR-1</a>.3. If you still use earlier <a href="http://jira.freeswitch.org/browse/APR-1">APR-1</a>.2.x versions, consider to backport those macros, please.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1130 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c38a54eb3b65b45e8d5265144864b6419dc4824d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 17 16:57:49 2009 +0000

    Renamed mpf_stream_mode_e to mpf_stream_direction_e (send,receive or duplex), moved mpf_stream_capabilities_t to mpf_stream_descriptor.h
    
    Nothing has to be done, unless you explicitly construct and use mpf_stream_mode_e in your apps.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1129 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 28ca2617a6f85face3e7eb7a2fbe3d300b9199c6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 17 16:44:53 2009 +0000

    Fixed last commit
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1128 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 450154c862b567f8b24b30e0662ad16eda6f9855
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 17 16:25:25 2009 +0000

    Minor fix in format of vcproj version 8,00 -&gt; 8.00
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1127 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1cf803d3696d62523f6084c4ac88a528c0bd9eaa
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 16 20:59:41 2009 +0000

    Destroy resource engines on server destroy
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1126 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b08782eb2d6a4a87a0a70dc7d276957dab906223
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 16 20:40:17 2009 +0000

    Added is_open state to resource engines (<a href="http://jira.freeswitch.org/browse/Issue-42">Issue-42</a>)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1125 f001bc3a-424a-0410-80a0-a715b8f413a8

commit df037667c94449091144f36347bbb4c6dbdc1168
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 16 16:15:36 2009 +0000

    Unregister plugins at later stage from mrcp_server_destroy().
    It makes no difference for now, but from conceptual view point, it should be possible to create server once, start/stop it multiple times if needed and finally destroy it once.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1124 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1336d1b985329b32fca0c8127f3c3bd4785f9412
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 16 13:10:50 2009 +0000

    Reset existing associations and topology (if any), while processing answer from server (re-Invites).
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1123 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d83f12e3262f156bb10bb55ab5bf9407afb110b2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 14 19:12:42 2009 +0000

    Fixed spelling: transmit -&gt; transmitter, receive -&gt; receiver
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1122 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 67894e96a9c8b5db7652c8a2a34b5eecd88aa1d7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Sep 14 17:11:03 2009 +0000

    Added media path traces
    Examples:
    Source-&gt;[PCMU/8000/1]-&gt;Decoder-&gt;[LPCM/8000/1]-&gt;Bridge-&gt;[LPCM/8000/1]-&gt;Sink
    Source-&gt;[LPCM/8000/1]-&gt;Bridge-&gt;[LPCM/8000/1]-&gt;Encoder-&gt;[PCMU/8000/1]-&gt;Sink
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1121 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 35cd98bce0d462c10dfbc8beb5369e12f3de55a3
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Sep 12 17:58:23 2009 +0000

    Merged mpf_media_descriptor with mpf_rtp_media_descriptor (no need in separate base descriptor)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1120 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 689df477413bef09cda1fc2f0ba6c14f6378e088
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Sep 12 17:05:31 2009 +0000

    Using apr types (short -&gt; apr_int16_t)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1119 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c578f6ea274229afee64a4aa6faf0b0610049153
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Sep 12 16:50:10 2009 +0000

    Fixed compilation warnings under gcc
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1118 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8499d8cbc4cdadd07b60d72a5811e21b48da6f0f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Sep 12 16:16:08 2009 +0000

    Added MPF object derived new entities such as mixer (n-sources, 1-sink) and multiplier (1-source, n-sinks)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1117 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a957416aa7e536c5616d9c58725b82689bce58a0
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 10 18:47:32 2009 +0000

    Added new line at the end of the file to fix compilation warning
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1116 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3fd96c529abd99b1a4b398481e72541448c48783
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 10 16:27:14 2009 +0000

    Encapsulated creation of encoder, decoder and resampler in mpf_bridge.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1115 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4b169b670e95adec16741c2876d18f90a72fd95d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 10 16:05:25 2009 +0000

    Added skeleton for MPF resampler. Eventually external resampler should be integrated there.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1114 f001bc3a-424a-0410-80a0-a715b8f413a8

commit aa8507f6c0982ae45cdba3f44fd52fcf7ad9e372
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 9 20:39:25 2009 +0000

    Removed unused function
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1113 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2e533dbc7a24c24e03a0e2810d78b3eaad13efb6
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 9 20:32:46 2009 +0000

    Supported multiple &quot;cmid&quot; attributes per each control m-line. (Section 4.3)
    Client API still allows to define only one to one association between control channels and their corresponding media terminations. Meantime server should be flexible enough even now and support any offered association among control channels and media terminations.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1112 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e8c77db43f8c6a39f912e2b60e594c753b2b3182
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 9 18:45:41 2009 +0000

    Fixed <a href="http://jira.freeswitch.org/browse/issue-41">issue-41</a>.
    Port number must be matched too, while trying to find an existing MRCPv2 connection (Thanks asackheim)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1111 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3594fd3d2f5a3ba5ae91a885fb09b3d9322bbffd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 9 16:57:49 2009 +0000

    Fixed race condition issue in pocketsphinx plugin (Thanks Alban)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1110 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 202b654d75f5625bfdfd00adc61bb0fab000ab42
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Sep 8 15:51:58 2009 +0000

    Added define for TCP discard port used in offer/answer
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1109 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a0d61fd4ea2b0e8c1899b1420fc24c1f2515afa7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Sep 8 13:56:51 2009 +0000

    Reworked MPF context, which allows to provide custom associations among the terminations involved in the context and build topology based on association matrix.
    Client and server stacks have been modified according. Everything should work as is basis
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1108 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 54470cc5cdb35169409fe145c69046b3ad5a0c27
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Sep 8 13:50:01 2009 +0000

    Check if session-&gt;connection is a valid pointer first and only then use it
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1107 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d33217a9227ea3ecb1b3e2e360b148ece5b6be0d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 3 19:23:10 2009 +0000

    Added more MPF commands to operate (add/modify/subtract) on terminations, add/remove associations between terminations and apply/destroy topology. More to come...
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1106 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 19984cd1e5229910d9392588cba587895b05b50f
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Sep 3 17:01:10 2009 +0000

    Using apr_ring to store factory of media contexts.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1105 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 93c65ccde10d8eaa2eeec1b453c820af93b28ff2
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 2 18:43:31 2009 +0000

    Moved MPF context related public interface from mpf_user.h to mpf_engine.h
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1104 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 99d7100026ba6867daf5486c29c514b0deaa2c75
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 2 14:59:15 2009 +0000

    Removed unused function
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1103 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6f21c53584b73e79ced6dbc695178a02611cce9d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Sep 2 13:20:14 2009 +0000

    Added ability to send more than one MPF messages at once.
    Grouping of MPF messages allows to reduce thread context switches, as a result, improves the performance.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1102 f001bc3a-424a-0410-80a0-a715b8f413a8

commit b2a72d24996acf67b29b8aabfed3850da2b27ef7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 31 17:14:05 2009 +0000

    Updated Makefile
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1101 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 18647d833d4df8991bee0b1a8255c7359502e8c7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 31 17:04:09 2009 +0000

    Added stream capabilities in order to set not only single codec descriptor, but capabilities of the stream (no API changes ... yet)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1100 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ac6fe620c6d0f45ad5f7f43e04db124f2e0db69b
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Aug 28 13:10:39 2009 +0000

    Added/moved negotiated rx/tx event descriptor to mpf_stream base next to rx/tx codecs
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1099 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 481f01cefa540b3903aa6635b833bb6e894a300d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Aug 28 13:08:46 2009 +0000

    Name of the attribute should be bits_per_sample
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1098 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e22100eeb324677d214c07a3ef91504fc6c106de
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 24 18:00:43 2009 +0000

    Added Makefile targets for pocketsphinx plugin to install dictionary and model. Do nothing if installed, but not source directory of pocketsphinx is used at ./configure time. In this case, dictionary and model have to be copied manually.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1097 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 3c680289d19481ae8e62009057ef7d639fd14a00
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 24 17:41:29 2009 +0000

    Fixed compilation warnings in pocketsphinx plugin, while compiling with enabled mainatainer mode
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1096 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5d6c7e26cc6a98f59da72676aae9fd1d0d17bb9b
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 24 15:15:44 2009 +0000

    Fixed prototype of on_start and on_terminate handlers in Flite plugin
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1095 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1d3044c8137ec39b3b7dcf65f8ec5e10718c7dd3
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Aug 18 16:41:06 2009 +0000

    Fixed trailing space in MRCPv2 response-line  (interoperability with Optimsys, Thanks Roger)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1094 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e835d5e8e51d19932a2e3e3f808ec987e2901de4
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Aug 18 13:26:50 2009 +0000

    Fixed possible access violation in APT logger (<a href="http://jira.freeswitch.org/browse/Issue-40">Issue-40</a>, Thanks Vali)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1093 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2e35e28c31d4a79025d105b00c73a9d66019d144
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 17 18:31:48 2009 +0000

    Added L16 and telephone-event to yet hard coded capabilities of the server included into the response to resource discovery request
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1092 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1fa878e171b528293528566f244c5142c051ac3a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 17 18:17:07 2009 +0000

    Fixed the response message sent to RTSP DESCRIBE request. It shouldn't contain RTSP Transport header, while RTSP Transport can be present only in RTSP SETUP request/response messages. This hopefully fixes interoperability with GVP (<a href="http://jira.freeswitch.org/browse/Issue-39">Issue-39</a>, Thanks Vali).
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1091 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4e3d64c778fb3cc6a0a072d898f43b3c37e80eba
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Aug 16 06:49:54 2009 +0000

    Applied patch, which implements utility functions to transform DTMF characters and event identifiers (Thanks Vali)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1090 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 041580394f2ecdfe920cdb1e3d3d16ebceaecdbd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Aug 16 06:39:45 2009 +0000

    Applied patch, which basically implements RFC4733/RFC2833 sender procedure,
    yet to be enhanced, see <a href="http://jira.freeswitch.org/browse/Issue-31">Issue-31</a> (Thanks Chaitanya)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1089 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 947b49f9ff8e353d6bb5985f00db14942db971db
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sun Aug 16 06:28:22 2009 +0000

    Set negotiated payload type of named event for RTP transmit and receive
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1088 f001bc3a-424a-0410-80a0-a715b8f413a8

commit dc2687129335089a513127405e968b749197e002
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 15 17:47:13 2009 +0000

    Added &quot;telephone-event/101/8000&quot; to default client and server config
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1087 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 178ba987d2f89ae5b9d6684be46814014fb3df2e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 15 17:36:24 2009 +0000

    Added generation of a=fmtp SDP media level attribute, which is optional for generic codecs, but is required for telephone-event (a=fmtp:100 0-15)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1086 f001bc3a-424a-0410-80a0-a715b8f413a8

commit bfcc86e8e93fca16543e723a54132b74f3082216
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 15 16:38:46 2009 +0000

    Set SOATAG_AUDIO_AUX(&quot;telephone-event&quot;) in nua_respond to enable auxiliary codecs in response.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1085 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1287b89a349dce746b9f11f927e31b3e52b4bd9a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 15 16:33:37 2009 +0000

    Integrated named events into offer/answer, made codec descriptors related minor enhancements
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1084 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 98e9b1971e3b28fa3865ff77c3865c3e6d76d305
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 15 12:26:23 2009 +0000

    Moved matching of codec capabilities into separate function
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1083 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e6f975d55fdd89d415548bcd63ba7756dcc93b8a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Aug 13 18:32:21 2009 +0000

    Added codec descriptor of named event into codec manager to load from config (done) and further to participate in offer/answer (yet to be done)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1082 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6418912f7b96acce0e14feb474d106b8ac834cb8
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Aug 13 16:37:04 2009 +0000

    Moved named event definition into mpf_named_event.h, more stuff should be added there.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1081 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9cc4da5d75f1fca118a5b962ee9e8c5d20c7a616
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Aug 11 18:21:02 2009 +0000

    Switched libasrclient into dll in order not to expose internal stuff to application context
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1080 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 85480c95b03f727dbd11618fb42ae3ac907eddc0
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 10 07:59:54 2009 +0000

    Added plugin/engine config. The structure consists of
    - parameters which are common for all engines such as engine name and max channel count
    - table of transparent name/value string parameters, which are engine dependent
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1079 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5dfe8442ded69b773e83cb9c43b9197213ee5654
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 10 05:40:10 2009 +0000

    Initialized codec manager with 4 instead of 3 codecs to avoid later reallocations, as we actually have 4 codecs now
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1078 f001bc3a-424a-0410-80a0-a715b8f413a8

commit cb9d6d1406d4e5eb418c8a6de04eae004998a2f9
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 10 05:36:41 2009 +0000

    Fixed typo in comments (defualt -&gt; default)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1077 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 00971c82e72adde2221fdbc204571a7c7a781e5a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Aug 5 07:57:20 2009 +0000

    Added ability to get MRCP version of the channel from plugin context in order to be able to construct MRCP version dependent responses and events when/if needed.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1076 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 328ebb30c8eb5124326bf5a43f4fa588877bea9d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Aug 5 05:45:31 2009 +0000

    Set RTSP transport &quot;mode&quot; attribute in the outgoing RTSP response if it's specified in the received RTSP request
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1075 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c538367f46ef48cf157af53431ace47c6ac2be88
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Aug 5 05:42:32 2009 +0000

    Added another RTSP transport attribute (mode=)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1074 f001bc3a-424a-0410-80a0-a715b8f413a8

commit a8a7ac5d7dc2845e1294d726fc8d651b9b749472
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Mon Aug 3 19:05:17 2009 +0000

    Added ability to limit max number of engine channels in use.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1073 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 43bdbd881e763c33e1cb6fff9ac88c91fe038d07
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 1 14:44:31 2009 +0000

    Added helper function to get session MRCP version
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1072 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 7d53c0d31b12122a2ea4a200f3390ef0c78b392e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Sat Aug 1 12:54:34 2009 +0000

    Added enumeration of RTP payload types (RFC3551) project uses
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1071 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 666f5657bf8bcd2f149119d07c725ff9599b2759
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Jul 30 13:39:11 2009 +0000

    Added svn props
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1070 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 996b0d2489b377818290f7527080cbbfb8229bdc
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Jul 30 13:36:44 2009 +0000

    Updated GNU build
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1069 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 53d8fe5f0fd4379c2ea626c861f9a031c9d88349
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Thu Jul 30 13:21:52 2009 +0000

    Separated libasrclient library from asrclient application to server as a reusable basic ASR block on top of UniMRCP client stack.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1068 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8e6b678bd662127240546f95e8bf8c3a68033090
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Tue Jul 28 10:36:40 2009 +0000

    Added Michael Jerris (OS X build, FreeSWITCH build integration) and Carlos Pina Soares (RTP port management and several essential issue reports) to the project contributors
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1067 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 25f0b60b56d7ed3ab11d1779615f2c2ba90dd686
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Jul 24 16:33:17 2009 +0000

    Included asrclient into GNU build
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1066 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 316c3331b67a3504461bbf597ed3ff95c44bd053
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Jul 24 16:23:34 2009 +0000

    Introduced an alternate demo ASR client application
    usage:
      run [grammar_file] [audio_input_file] [profile_name]
    
    examples:
      run
      run grammar.xml one.pcm
      run grammar.xml one.pcm MRCPv1-Default
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1065 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 04a3b14edb3e68743df4a4b22ca5445a54c79f9a
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 19:18:21 2009 +0000

    Increased unimrcp version number
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1063 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d4b7ddc381ff0d2fb6831be473c84cd6c1da78ef
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 18:39:58 2009 +0000

    Fixed doxygen warnings
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1062 f001bc3a-424a-0410-80a0-a715b8f413a8

commit da304aa5485b2252a2826355c870108c52eac4bd
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 18:30:08 2009 +0000

    Fixed doxygen warnings
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1061 f001bc3a-424a-0410-80a0-a715b8f413a8

commit e6db110edb0a199298db5a0bdd08134543df40d7
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 18:23:34 2009 +0000

    Fixed doxygen warnings
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1060 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5b29de76a653423a02ec9329aec56429959d40c1
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 17:52:11 2009 +0000

    Updated INSTALL instructions
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1059 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 8882ecf7b8dea6959d096edecb371c213294f25d
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 17:13:29 2009 +0000

    APR-Iconv is not included in dependency pack. Thus, first check if apr-iconv.dll exists and only then try to copy it.
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1057 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 1997ed691507b5e0fdf58c3b22ce04c7a9c4fead
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Wed Jul 22 16:17:57 2009 +0000

    From now on use thread safe APR pools.
    
    Consider using the dependency package from http://code.google.com/p/unimrcp/downloads/list
    or manually apply patches over the libraries you use from
    http://www.unimrcp.org/dependencies
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1056 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5cbdaa7304b6146ff002191b7142885a18c8cf0e
Author: achaloyan &lt;achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8&gt;
Date:   Fri Jul 17 13:48:27 2009 +0000

    Raised unexpected MRCPv2 disconnect event from transport layer to client and server stacks (<a href="http://jira.freeswitch.org/browse/Issue-36">Issue-36</a>)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1055 f001bc3a-424a-0410-80a0-a715b8f413a8</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#freeswitchtrunklibsunimrcpAUTHORS">freeswitch/trunk/libs/unimrcp/AUTHORS</a></li>
<li><a href="#freeswitchtrunklibsunimrcpINSTALL">freeswitch/trunk/libs/unimrcp/INSTALL</a></li>
<li><a href="#freeswitchtrunklibsunimrcpMakefileam">freeswitch/trunk/libs/unimrcp/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcpbuildtoolspreparevcproj">freeswitch/trunk/libs/unimrcp/build/tools/prepare.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcpbuilduni_versionh">freeswitch/trunk/libs/unimrcp/build/uni_version.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpbuildvspropsunimrcpservervsprops">freeswitch/trunk/libs/unimrcp/build/vsprops/unimrcpserver.vsprops</a></li>
<li><a href="#freeswitchtrunklibsunimrcpconfunimrcpclientxml">freeswitch/trunk/libs/unimrcp/conf/unimrcpclient.xml</a></li>
<li><a href="#freeswitchtrunklibsunimrcpconfunimrcpserverxml">freeswitch/trunk/libs/unimrcp/conf/unimrcpserver.xml</a></li>
<li><a href="#freeswitchtrunklibsunimrcpconfigureac">freeswitch/trunk/libs/unimrcp/configure.ac</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_cyclic_queueh">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_logh">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_log.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_neth">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_net.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_nlsml_doch">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_poolh">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_taskh">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_task.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_test_suiteh">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_consumer_taskc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_logc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_log.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_netc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net.c</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_pairc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_poolc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_taskc">freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_task.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfMakefileam">freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_activity_detectorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_audio_file_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_bridgeh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_bridge.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_codech">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_codec_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_codec_managerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_contexth">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_context.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_decoderh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_decoder.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_encoderh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_encoder.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_engineh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_engine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_file_termination_factoryh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_frameh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_jitter_bufferh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_messageh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_message.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_objecth">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_object.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_attribsh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_defsh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_headerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_stath">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_streamh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_termination_factoryh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_streamh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_terminationh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_typesh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_types.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfmpfvcproj">freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_activity_detectorc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_audio_file_streamc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_bridgec">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_bridge.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_descriptorc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_g711c">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_linearc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_managerc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_contextc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_context.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_decoderc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_decoder.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_encoderc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_encoder.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_enginec">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_file_termination_factoryc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_frame_bufferc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_jitter_bufferc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_rtp_attribsc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.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="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_rtp_termination_factoryc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_terminationc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpMakefileam">freeswitch/trunk/libs/unimrcp/libs/mrcp/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_resourceh">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_resource_factoryh">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolsrcmrcp_resource_factoryc">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolsrcmrcp_streamc">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpincludemrcp_typesh">freeswitch/trunk/libs/unimrcp/libs/mrcp/include/mrcp_types.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmessageincludemrcp_messageh">freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_generic_headerc">freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_header_accessorc">freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_messagec">freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmrcpvcproj">freeswitch/trunk/libs/unimrcp/libs/mrcp/mrcp.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recog_headerh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_synth_headerh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_headerc">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_resourcec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_headerc">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_resourcec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpclientincludemrcp_applicationh">freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpclientincludemrcp_client_sessionh">freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpclientsrcmrcp_clientc">freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpclientsrcmrcp_client_sessionc">freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineMakefileam">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_resource_engineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginemrcpenginevcproj">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpserverincludemrcp_serverh">freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpserverincludemrcp_server_sessionh">freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpserversrcmrcp_serverc">freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpserversrcmrcp_server_sessionc">freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpsignalingincludemrcp_sessionh">freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpsignalingincludemrcp_session_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportincludemrcp_connectionh">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportincludemrcp_connection_typesh">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportincludemrcp_control_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_client_connectionc">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_connectionc">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_control_descriptorc">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_server_connectionc">freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsunirtspincludertsp_headerh">freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_clientc">freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_headerc">freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_messagec">freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_serverc">freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpmodulesmrcpsofiasipsrcmrcp_sdpc">freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpmodulesmrcpsofiasipsrcmrcp_sofiasip_client_agentc">freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpmodulesmrcpsofiasipsrcmrcp_sofiasip_server_agentc">freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpmodulesmrcpunirtspincludemrcp_unirtsp_sdph">freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpmodulesmrcpunirtspsrcmrcp_unirtsp_sdpc">freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpmodulesmrcpunirtspsrcmrcp_unirtsp_server_agentc">freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppackagesinnosetupsetupiss">freeswitch/trunk/libs/unimrcp/packages/inno-setup/setup.iss</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsMakefileam">freeswitch/trunk/libs/unimrcp/platforms/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibunimrcpclientMakefileam">freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibunimrcpclientsrcunimrcp_clientc">freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibunimrcpserverMakefileam">freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibunimrcpserversrcunimrcp_serverc">freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_bypass_applicationc">freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_recog_applicationc">freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_synth_applicationc">freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_utilc">freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsMakefileam">freeswitch/trunk/libs/unimrcp/plugins/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsdemorecogsrcdemo_recog_enginec">freeswitch/trunk/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsdemosynthsrcdemo_synth_enginec">freeswitch/trunk/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpcepstralsrcmrcp_swiftc">freeswitch/trunk/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpfliteincludeflite_voicesh">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcpflitesrcmrcp_flitec">freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcppocketsphinxMakefileam">freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcppocketsphinxincludepocketsphinx_propertiesh">freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/include/pocketsphinx_properties.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcppocketsphinxsrcmrcp_pocketsphinxc">freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcppocketsphinxsrcpocketsphinx_propertiesc">freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/pocketsphinx_properties.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcptestsmpftestsrcmpf_suitec">freeswitch/trunk/libs/unimrcp/tests/mpftest/src/mpf_suite.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcptestsmrcptestmrcptestvcproj">freeswitch/trunk/libs/unimrcp/tests/mrcptest/mrcptest.vcproj</a></li>
<li><a href="#freeswitchtrunklibsunimrcptestsmrcptestsrcparse_gen_suitec">freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/parse_gen_suite.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcptestsmrcptestsrcset_get_suitec">freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/set_get_suite.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcptestsstrtablegensrcmainc">freeswitch/trunk/libs/unimrcp/tests/strtablegen/src/main.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcpunimrcpsln">freeswitch/trunk/libs/unimrcp/unimrcp.sln</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#freeswitchtrunklibsunimrcpconfumcscenariosxml">freeswitch/trunk/libs/unimrcp/conf/umcscenarios.xml</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdatademo16kHzpcm">freeswitch/trunk/libs/unimrcp/data/demo-16kHz.pcm</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdatademo8kHzpcm">freeswitch/trunk/libs/unimrcp/data/demo-8kHz.pcm</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdatagrammarjsgf">freeswitch/trunk/libs/unimrcp/data/grammar.jsgf</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdataone16kHzpcm">freeswitch/trunk/libs/unimrcp/data/one-16kHz.pcm</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdataone8kHzpcm">freeswitch/trunk/libs/unimrcp/data/one-8kHz.pcm</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdataspeaktxt">freeswitch/trunk/libs/unimrcp/data/speak.txt</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_dtmf_detectorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_dtmf_generatorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_mixerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_mixer.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_multiplierh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_multiplier.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_named_eventh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_named_event.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_resamplerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_resampler.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtcp_packeth">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_pth">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_schedulerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_scheduler.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_stream_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_termination_factoryh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_timer_managerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_dtmf_detectorc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_dtmf_generatorc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_mixerc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_mixer.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_multiplierc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_multiplier.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_named_eventc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_named_event.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_resamplerc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_resampler.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_schedulerc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_scheduler.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_streamc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_stream.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_termination_factoryc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_timer_managerc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_resource_loaderh">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolsrcmrcp_resource_loaderc">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmessageincludemrcp_start_lineh">freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_start_linec">freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recorder_headerh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recorder_resourceh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recorder_headerc">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recorder_resourcec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_factoryh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_ifaceh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_implh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_loaderh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_pluginh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_typesh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recog_engineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recog_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recorder_engineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recorder_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_synth_engineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_synth_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_factoryc">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_ifacec">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_implc">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_loaderc">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_recog_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_recorder_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_synth_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/asr-client/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsasrclientMakefileam">freeswitch/trunk/libs/unimrcp/platforms/asr-client/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsasrclientasrclientvcproj">freeswitch/trunk/libs/unimrcp/platforms/asr-client/asrclient.vcproj</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/asr-client/src/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsasrclientsrcmainc">freeswitch/trunk/libs/unimrcp/platforms/asr-client/src/main.c</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/libasr-client/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibasrclientMakefileam">freeswitch/trunk/libs/unimrcp/platforms/libasr-client/Makefile.am</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/libasr-client/include/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibasrclientincludeasr_engineh">freeswitch/trunk/libs/unimrcp/platforms/libasr-client/include/asr_engine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibasrclientlibasrclientvcproj">freeswitch/trunk/libs/unimrcp/platforms/libasr-client/libasrclient.vcproj</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/libasr-client/src/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformslibasrclientsrcasr_enginec">freeswitch/trunk/libs/unimrcp/platforms/libasr-client/src/asr_engine.c</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/umc/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcMakefileam">freeswitch/trunk/libs/unimrcp/platforms/umc/Makefile.am</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/umc/include/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludedtmfscenarioh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfscenario.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludedtmfsessionh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfsession.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincluderecogscenarioh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogscenario.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincluderecogsessionh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogsession.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincluderecorderscenarioh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/recorderscenario.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincluderecordersessionh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/recordersession.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludesynthscenarioh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthscenario.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludesynthsessionh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthsession.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludeumcconsoleh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcconsole.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludeumcframeworkh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcframework.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludeumcscenarioh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcscenario.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcincludeumcsessionh">freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcsession.h</a></li>
<li>freeswitch/trunk/libs/unimrcp/platforms/umc/src/</li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcdtmfscenariocpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcdtmfsessioncpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfsession.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcmaincpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/main.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcrecogscenariocpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogscenario.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcrecogsessioncpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogsession.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcrecorderscenariocpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/recorderscenario.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcrecordersessioncpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/recordersession.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcsynthscenariocpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthscenario.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcsynthsessioncpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthsession.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcumcconsolecpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcconsole.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcumcframeworkcpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcframework.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcumcscenariocpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcscenario.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcsrcumcsessioncpp">freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcsession.cpp</a></li>
<li><a href="#freeswitchtrunklibsunimrcpplatformsumcumcvcproj">freeswitch/trunk/libs/unimrcp/platforms/umc/umc.vcproj</a></li>
<li>freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/</li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcprecorderMakefileam">freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/Makefile.am</a></li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcprecordermrcprecordervcproj">freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/mrcprecorder.vcproj</a></li>
<li>freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/src/</li>
<li><a href="#freeswitchtrunklibsunimrcppluginsmrcprecordersrcmrcp_recorder_enginec">freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/src/mrcp_recorder_engine.c</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#freeswitchtrunklibsunimrcpdatademopcm">freeswitch/trunk/libs/unimrcp/data/demo.pcm</a></li>
<li><a href="#freeswitchtrunklibsunimrcpdataonepcm">freeswitch/trunk/libs/unimrcp/data/one.pcm</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_media_descriptorh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_media_descriptor.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_stream_modeh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream_mode.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_timerh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_timer.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfincludempf_userh">freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_user.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmpfsrcmpf_timerc">freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_timer.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_default_factoryh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_default_factory.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recog_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_synth_state_machineh">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_state_machine.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_default_factoryc">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_default_factory.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_client_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_client_state_machine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_server_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_server_state_machine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_client_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_client_state_machine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_server_state_machinec">freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_server_state_machine.c</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_resource_pluginh">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_plugin.h</a></li>
<li><a href="#freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_resource_enginec">freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_resource_engine.c</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="freeswitchtrunklibsunimrcpAUTHORS"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/AUTHORS (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/AUTHORS        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/AUTHORS        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -4,9 +4,13 @@
</span><span class="cx"> 
</span><span class="cx"> Contributor(s):
</span><span class="cx">    Kamil Shakirov &lt;kamils80@gmail.com&gt;
</span><del>-   Anthony Masse &lt;amasse.telisma@gmail.com&gt;
</del><ins>+   Anthony Masse &lt;amasse.atwork@gmail.com&gt;
</ins><span class="cx">    Vlad Socaciu &lt;Curatica@gmail.com&gt;
</span><span class="cx">    Garmt &lt;garmt.noname@gmail.com&gt;
</span><del>-   Patrick &lt;pnunes29@gmail.com&gt;
-   Bayram &lt;bayramboyraz@gmail.com&gt;
-   Mahmoud Hassan &lt;firstmahmoud2002@gmail.com&gt;
</del><span class="cx">\ No newline at end of file
</span><ins>+   Patrick Nunes &lt;pnunes29@gmail.com&gt;
+   Bayram Boyraz &lt;bayramboyraz@gmail.com&gt;
+   Mahmoud Hassan &lt;firstmahmoud2002@gmail.com&gt;
+   Michael Jerris &lt;mike@jerris.com&gt;
+   Carlos Pina Soares
+   Chaitanya Chokkareddy &lt;chaitanya.chokkareddy@gmail.com&gt;
+   Tomas Valenta &lt;tomas.valenta@speechtech.cz&gt;
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpINSTALL"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/INSTALL (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/INSTALL        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/INSTALL        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -1,23 +1,32 @@
</span><span class="cx"> BUILD REQUIREMENTS
</span><span class="cx"> ==================
</span><del>-UniMRCP depends on a number of third party tools and libraries,
-which must be installed prior to UniMRCP build.
</del><ins>+UniMRCP depends on a number of third party tools and libraries, 
+which are required and must be installed first.
</ins><span class="cx"> 
</span><del>-1. Apache Portable Runtime [&gt;=1.2.x] (http://apr.apache.org/)
-Whenever you want to build any part of UniMRCP, you need the
-Apache Portable Runtime (APR) and the APR Utility (APR-util)
</del><ins>+The easiest and recommended way is to install an appropriate 
+dependency package from the download area, which contains APR, 
+APR-Util and Sofia-SIP libraries prepackaged for UniMRCP use.
+
+http://code.google.com/p/unimrcp/downloads/
+
+Alternatively, the original packages of APR, APR-Util and
+Sofia-SIP libraries and patches for them can be downloaded from
+
+http://www.unimrcp.org/dependencies/
+
+References:
+  
+1. Apache Portable Runtime [&gt;=1.2.x] (http://apr.apache.org/). 
+Whenever you want to build any part of UniMRCP, you need the 
+Apache Portable Runtime (APR) and the APR Utility (APR-util) 
</ins><span class="cx"> libraries.
</span><span class="cx"> 
</span><del>-2. Sofia-SIP [&gt;=1.12.6] (http://sofia-sip.sourceforge.net/)
-Sofia-SIP library is used to implement MRCPv2 specification
</del><ins>+2. Sofia-SIP [&gt;=1.12.6] (http://sofia-sip.sourceforge.net/). 
+Sofia-SIP library is used to implement MRCPv2 specification 
</ins><span class="cx"> compliant SIP signaling. Sofia-SIP is an open-source SIP User-Agent
</span><span class="cx"> library, compliant with the IETF RFC3261 specification.
</span><span class="cx"> 
</span><del>-Use the link below to download one of known to work and 
-ready to use packages of APR and Sofia-SIP libraries.
-    http://www.unimrcp.org/dependencies/
</del><span class="cx"> 
</span><del>-
</del><span class="cx"> GNU BUILD
</span><span class="cx"> ===================
</span><span class="cx"> Additional requirements
</span><span class="lines">@@ -36,9 +45,11 @@
</span><span class="cx"> Installed directory layout
</span><span class="cx"> bin      - binaries (unimrcpserver, unimrcpclient)
</span><span class="cx"> conf     - configuration files
</span><ins>+data     - data files
</ins><span class="cx"> include  - header files
</span><del>-libs     - shared (convenient) libraries
-plugins  - run-time loadable modules
</del><ins>+lib      - shared (convenient) libraries
+log      - log files
+plugin   - run-time loadable modules
</ins><span class="cx"> 
</span><span class="cx"> There are a couple of options to &quot;./configure&quot;.
</span><span class="cx"> To specify where to look for the APR and APR-util libraries
</span><span class="lines">@@ -100,4 +111,6 @@
</span><span class="cx"> Output directory layout
</span><span class="cx"> bin      - binaries (unimrcpserver, unimrcpclient) and all the required dlls
</span><span class="cx"> conf     - configuration files
</span><del>-plugins  - run-time loadable modules
</del><span class="cx">\ No newline at end of file
</span><ins>+data     - data files
+log      - log files
+plugin   - run-time loadable modules
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> 
</span><span class="cx"> def-data:
</span><span class="cx">         test -d $(datadir) || $(mkinstalldirs) $(datadir)
</span><del>-        for datafile in `find data -name *.pcm -o -name *.xml` ; do \
</del><ins>+        for datafile in `find data -name *.pcm -o -name *.xml -o -name *.jsgf -o -name *.txt` ; do \
</ins><span class="cx">             filename=`echo $$datafile | sed -e 's|^.*/||'`; \
</span><span class="cx">             $(INSTALL) -m 644 data/$$filename $(datadir); \
</span><span class="cx">         done
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpbuildtoolspreparevcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/build/tools/prepare.vcproj (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/build/tools/prepare.vcproj        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/build/tools/prepare.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx">                         &gt;
</span><span class="cx">                         &lt;Tool
</span><span class="cx">                                 Name=&quot;VCPreBuildEventTool&quot;
</span><del>-                                CommandLine=&quot;xcopy &amp;quot;$(AprDir)\$(ConfigurationName)\libapr-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(AprUtilDir)\$(ConfigurationName)\libaprutil-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(AprIconvDir)\$(ConfigurationName)\libapriconv-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\libsofia-sip-ua\$(ConfigurationName)\libsofia_sip_ua.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\pthread\pthreadVC2.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\conf&amp;quot; xcopy &amp;quot;$(SolutionDir)conf\*.xml&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\conf\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\data&amp;quot; xcopy &amp;quot;$(SolutionDir)data\*&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\data\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\log&amp;quot; mkdir &amp;quot;$(SolutionDir)$(ConfigurationName)\log\&amp;quot;&amp;#x0D;&amp;#x0A;&quot;
</del><ins>+                                CommandLine=&quot;xcopy &amp;quot;$(AprDir)\$(ConfigurationName)\libapr-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(AprUtilDir)\$(ConfigurationName)\libaprutil-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;if exist &amp;quot;$(AprIconvDir)\$(ConfigurationName)\libapriconv-1.dll&amp;quot; (&amp;#x0D;&amp;#x0A; xcopy &amp;quot;$(AprIconvDir)\$(ConfigurationName)\libapriconv-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A; if exist &amp;quot;$(AprIconvDir)\$(ConfigurationName)\iconv&amp;quot; (&amp;#x0D;&amp;#x0A;  if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\iconv&amp;quot; mkdir &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\iconv&amp;quot;&amp;#x0D;&amp;#x0A;  xcopy &amp;quot;$(AprIconvDir)\$(ConfigurationName)\iconv\*.so&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\iconv\&amp;quot; /Y&amp;#x0D;&amp;#x0A;  )&amp;#x0D;&amp;#x0A;)&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\libsofia-sip-ua\$(ConfigurationName)\libsofia_sip_ua.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\pthread\pthreadVC2.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\conf&amp;quot; xcopy &amp;quot;$(SolutionDir)conf\*.xml&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\conf\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\data&amp;quot; xcopy &amp;quot;$(SolutionDir)data\*&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\data\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\log&amp;quot; mkdir &amp;quot;$(SolutionDir)$(ConfigurationName)\log\&amp;quot;&amp;#x0D;&amp;#x0A;&quot;
</ins><span class="cx">                                 ExcludedFromBuild=&quot;false&quot;
</span><span class="cx">                         /&gt;
</span><span class="cx">                         &lt;Tool
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx">                         &gt;
</span><span class="cx">                         &lt;Tool
</span><span class="cx">                                 Name=&quot;VCPreBuildEventTool&quot;
</span><del>-                                CommandLine=&quot;xcopy &amp;quot;$(AprDir)\$(ConfigurationName)\libapr-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(AprUtilDir)\$(ConfigurationName)\libaprutil-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(AprIconvDir)\$(ConfigurationName)\libapriconv-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\libsofia-sip-ua\$(ConfigurationName)\libsofia_sip_ua.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\pthread\pthreadVC2.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\conf&amp;quot; xcopy &amp;quot;$(SolutionDir)conf\*.xml&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\conf\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\data&amp;quot; xcopy &amp;quot;$(SolutionDir)data\*&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\data\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\log&amp;quot; mkdir &amp;quot;$(SolutionDir)$(ConfigurationName)\log\&amp;quot;&amp;#x0D;&amp;#x0A;&quot;
</del><ins>+                                CommandLine=&quot;xcopy &amp;quot;$(AprDir)\$(ConfigurationName)\libapr-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(AprUtilDir)\$(ConfigurationName)\libaprutil-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;if exist &amp;quot;$(AprIconvDir)\$(ConfigurationName)\libapriconv-1.dll&amp;quot; (&amp;#x0D;&amp;#x0A; xcopy &amp;quot;$(AprIconvDir)\$(ConfigurationName)\libapriconv-1.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A; if exist &amp;quot;$(AprIconvDir)\$(ConfigurationName)\iconv&amp;quot; (&amp;#x0D;&amp;#x0A;  if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\iconv&amp;quot; mkdir &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\iconv&amp;quot;&amp;#x0D;&amp;#x0A;  xcopy &amp;quot;$(AprIconvDir)\$(ConfigurationName)\iconv\*.so&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\iconv\&amp;quot; /Y&amp;#x0D;&amp;#x0A;  )&amp;#x0D;&amp;#x0A;)&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\libsofia-sip-ua\$(ConfigurationName)\libsofia_sip_ua.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;xcopy &amp;quot;$(SofiaDir)\win32\pthread\pthreadVC2.dll&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\bin\&amp;quot; /Y&amp;#x0D;&amp;#x0A;&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\conf&amp;quot; xcopy &amp;quot;$(SolutionDir)conf\*.xml&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\conf\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\data&amp;quot; xcopy &amp;quot;$(SolutionDir)data\*&amp;quot; &amp;quot;$(SolutionDir)$(ConfigurationName)\data\&amp;quot; /Y&amp;#x0D;&amp;#x0A;if not exist &amp;quot;$(SolutionDir)$(ConfigurationName)\log&amp;quot; mkdir &amp;quot;$(SolutionDir)$(ConfigurationName)\log\&amp;quot;&amp;#x0D;&amp;#x0A;&quot;
</ins><span class="cx">                         /&gt;
</span><span class="cx">                         &lt;Tool
</span><span class="cx">                                 Name=&quot;VCCustomBuildTool&quot;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpbuilduni_versionh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/build/uni_version.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/build/uni_version.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/build/uni_version.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -39,7 +39,7 @@
</span><span class="cx">  * Minor API changes that do not cause binary compatibility problems.
</span><span class="cx">  * Reset to 0 when upgrading UNI_MAJOR_VERSION
</span><span class="cx">  */
</span><del>-#define UNI_MINOR_VERSION   6
</del><ins>+#define UNI_MINOR_VERSION   8
</ins><span class="cx"> 
</span><span class="cx"> /** patch level 
</span><span class="cx">  * The Patch Level never includes API changes, simply bug fixes.
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpbuildvspropsunimrcpservervsprops"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/build/vsprops/unimrcpserver.vsprops (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/build/vsprops/unimrcpserver.vsprops        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/build/vsprops/unimrcpserver.vsprops        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,6 +15,6 @@
</span><span class="cx">         /&gt;
</span><span class="cx">         &lt;UserMacro
</span><span class="cx">                 Name=&quot;UniMRCPServerLibs&quot;
</span><del>-                Value=&quot;libunimrcpserver.lib mrcpserver.lib mrcpsignaling.lib mrcp.lib aprtoolkit.lib libaprutil-1.lib libapr-1.lib libsofia_sip_ua.lib ws2_32.lib winmm.lib&quot;
</del><ins>+                Value=&quot;libunimrcpserver.lib mrcpserver.lib mrcpsignaling.lib mrcpengine.lib mrcp.lib aprtoolkit.lib libaprutil-1.lib libapr-1.lib libsofia_sip_ua.lib ws2_32.lib winmm.lib&quot;
</ins><span class="cx">         /&gt;
</span><span class="cx"> &lt;/VisualStudioPropertySheet&gt;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpconfumcscenariosxml"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/conf/umcscenarios.xml (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/conf/umcscenarios.xml                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/conf/umcscenarios.xml        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,96 @@
</span><ins>+&lt;!-- 
+UniMRCP Client Scenarios.
+There are predefined, named scenarios, which you can customize and use.
+Currently available scenarios are
+1. class=&quot;Synthesizer&quot;
+2. class=&quot;Recognizer&quot;
+3. class=&quot;Recorder&quot;
+4. class=&quot;DtmfRecofnizer&quot;
+
+More than one scenario of the same type (class) can be defined.
+The name (not class) of the scenario is used to run it from console.
+For instance,
+&gt; run synth
+--&gt;
+
+&lt;umcscenarios&gt;
+  &lt;scenario name=&quot;synth&quot; class=&quot;Synthesizer&quot; profile=&quot;MRCPv2-Default&quot;&gt;
+    &lt;resource-discovery enable=&quot;0&quot;/&gt;
+    &lt;speak enable=&quot;1&quot; content-type=&quot;application/synthesis+ssml&quot; content-location=&quot;speak.xml&quot;/&gt;
+    &lt;!-- &lt;speak enable=&quot;1&quot; content-type=&quot;text/plain&quot; content-location=&quot;speak.txt&quot;/&gt; --&gt;
+
+    &lt;termination enable=&quot;1&quot;&gt;
+      &lt;capabilities&gt;
+        &lt;codec name=&quot;LPCM&quot; rates=&quot;8000 16000&quot;/&gt;
+        &lt;!-- &lt;codec name=&quot;PCMU&quot; rates=&quot;8000 16000&quot;/&gt; --&gt;
+      &lt;/capabilities&gt;
+    &lt;/termination&gt;
+    &lt;!-- 
+    &lt;rtp-termination enable=&quot;1&quot; ip=&quot;127.0.0.1&quot; port=&quot;5678&quot;&gt;
+      &lt;codecs=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 telephone-event/101/8000&quot;/&gt;
+    &lt;/rtp-termination&gt;
+    --&gt;
+  &lt;/scenario&gt;
+
+  &lt;scenario name=&quot;recog&quot; class=&quot;Recognizer&quot; profile=&quot;MRCPv2-Default&quot;&gt;
+    &lt;resource-discovery enable=&quot;0&quot;/&gt;
+    &lt;define-grammar enable=&quot;1&quot; content-type=&quot;application/srgs+xml&quot; content-location=&quot;grammar.xml&quot;/&gt;
+    &lt;!-- &lt;define-grammar enable=&quot;1&quot; content-type=&quot;application/grammar+xml&quot; content-location=&quot;grammar.xml&quot;/&gt; --&gt;
+    &lt;!-- &lt;define-grammar enable=&quot;1&quot; content-type=&quot;application/x-jsgf&quot; content-location=&quot;grammar.jsgf&quot;/&gt; --&gt;
+    &lt;recognize enable=&quot;1&quot;/&gt;
+    &lt;!-- &lt;recognize enable=&quot;1&quot; audio-source=&quot;one-8kHz.pcm&quot;/&gt; --&gt;
+    &lt;!-- &lt;recognize enable=&quot;1&quot; content-type=&quot;application/srgs+xml&quot; content-location=&quot;grammar.xml&quot;/&gt; --&gt;
+
+    &lt;termination enable=&quot;1&quot;&gt;
+      &lt;capabilities&gt;
+        &lt;codec name=&quot;LPCM&quot; rates=&quot;8000 16000&quot;/&gt;
+        &lt;!-- &lt;codec name=&quot;PCMU&quot; rates=&quot;8000 16000&quot;/&gt; --&gt;
+      &lt;/capabilities&gt;
+    &lt;/termination&gt;
+    &lt;!-- 
+    &lt;rtp-termination enable=&quot;1&quot; ip=&quot;127.0.0.1&quot; port=&quot;5678&quot;&gt;
+      &lt;codecs=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 telephone-event/101/8000&quot;/&gt;
+    &lt;/rtp-termination&gt;
+    --&gt;
+  &lt;/scenario&gt;
+
+  &lt;scenario name=&quot;rec&quot; class=&quot;Recorder&quot; profile=&quot;MRCPv2-Default&quot;&gt;
+    &lt;resource-discovery enable=&quot;0&quot;/&gt;
+    &lt;record enable=&quot;1&quot;/&gt;
+
+    &lt;termination enable=&quot;1&quot;&gt;
+      &lt;capabilities&gt;
+        &lt;codec name=&quot;LPCM&quot; rates=&quot;8000 16000&quot;/&gt;
+        &lt;!-- &lt;codec name=&quot;PCMU&quot; rates=&quot;8000 16000&quot;/&gt; --&gt;
+      &lt;/capabilities&gt;
+    &lt;/termination&gt;
+    &lt;!-- 
+    &lt;rtp-termination enable=&quot;1&quot; ip=&quot;127.0.0.1&quot; port=&quot;5678&quot;&gt;
+      &lt;codecs=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 telephone-event/101/8000&quot;/&gt;
+    &lt;/rtp-termination&gt;
+    --&gt;
+  &lt;/scenario&gt;
+
+  &lt;scenario name=&quot;dtmf&quot; class=&quot;DtmfRecognizer&quot; profile=&quot;MRCPv2-Default&quot;&gt;
+    &lt;resource-discovery enable=&quot;0&quot;/&gt;
+    &lt;recognize enable=&quot;1&quot; content-type=&quot;text/uri-list&quot; grammar=&quot;builtin:dtmf/digits&quot; digits=&quot;1234&quot;/&gt; --&gt;
+
+    &lt;termination enable=&quot;1&quot;&gt;
+      &lt;capabilities&gt;
+        &lt;codec name=&quot;LPCM&quot; rates=&quot;8000 16000&quot;/&gt;
+        &lt;!-- &lt;codec name=&quot;PCMU&quot; rates=&quot;8000 16000&quot;/&gt; --&gt;
+      &lt;/capabilities&gt;
+    &lt;/termination&gt;
+    &lt;!-- 
+    &lt;rtp-termination enable=&quot;1&quot; ip=&quot;127.0.0.1&quot; port=&quot;5678&quot;&gt;
+      &lt;codecs=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 telephone-event/101/8000&quot;/&gt;
+    &lt;/rtp-termination&gt;
+    --&gt;
+  &lt;/scenario&gt;
+
+  &lt;!-- It'd be great to have scriptable custom scenarios as well.
+  &lt;scenario name=&quot;custom&quot; class=&quot;UmcXml&quot;&gt;
+  &lt;/scenario&gt;
+  --&gt;
+
+&lt;/umcscenarios&gt;
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpconfunimrcpclientxml"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/conf/unimrcpclient.xml (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/conf/unimrcpclient.xml        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/conf/unimrcpclient.xml        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -1,5 +1,12 @@
</span><span class="cx"> &lt;!-- UniMRCP client document --&gt;
</span><span class="cx"> &lt;unimrcpclient&gt;
</span><ins>+  &lt;!-- MRCP resources --&gt;
+  &lt;resources&gt;
+    &lt;resource class=&quot;speechsynth&quot; enable=&quot;1&quot;/&gt;
+    &lt;resource class=&quot;speechrecog&quot; enable=&quot;1&quot;/&gt;
+    &lt;resource class=&quot;recorder&quot; enable=&quot;1&quot;/&gt;
+  &lt;/resources&gt;
+
</ins><span class="cx">   &lt;!-- Client settings (signaling, media, ...) --&gt;
</span><span class="cx">   &lt;settings&gt;
</span><span class="cx">     &lt;!-- SIP, RTSP signaling agents --&gt;
</span><span class="lines">@@ -50,7 +57,21 @@
</span><span class="cx">         &lt;!-- &lt;param name=&quot;playout-delay&quot; value=&quot;50&quot;/&gt; --&gt;
</span><span class="cx">         &lt;!-- &lt;param name=&quot;max-playout-delay&quot; value=&quot;200&quot;/&gt; --&gt;
</span><span class="cx">         &lt;!-- &lt;param name=&quot;ptime&quot; value=&quot;20&quot;/&gt; --&gt;
</span><del>-        &lt;param name=&quot;codecs&quot; value=&quot;PCMU PCMA L16/96/8000&quot;/&gt;
</del><ins>+        &lt;param name=&quot;codecs&quot; value=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 telephone-event/101/8000&quot;/&gt;
+        &lt;!-- &lt;param name=&quot;codecs&quot; value=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 PCMA/98/16000 L16/99/16000&quot;/&gt; --&gt;
+
+        &lt;!-- enable/disable rtcp support --&gt;
+        &lt;param name=&quot;rtcp&quot; value=&quot;0&quot;/&gt;
+        &lt;!-- rtcp bye policies (rtcp must be enabled first)
+             0 - disable rtcp bye
+             1 - send rtcp bye at the end of session
+             2 - send rtcp bye also at the end of each talkspurt (input)
+        --&gt;
+        &lt;param name=&quot;rtcp-bye&quot; value=&quot;1&quot;/&gt;
+        &lt;!-- rtcp transmission interval in msec (set 0 to disable) --&gt;
+        &lt;param name=&quot;rtcp-tx-interval&quot; value=&quot;5000&quot;/&gt;
+        &lt;!-- period (timeout) to check for new rtcp messages in msec (set 0 to disable) --&gt;
+        &lt;param name=&quot;rtcp-rx-resolution&quot; value=&quot;1000&quot;/&gt;
</ins><span class="cx">       &lt;/rtp&gt;
</span><span class="cx">     &lt;/media&gt;
</span><span class="cx">   &lt;/settings&gt;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpconfunimrcpserverxml"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/conf/unimrcpserver.xml (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/conf/unimrcpserver.xml        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/conf/unimrcpserver.xml        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -1,5 +1,12 @@
</span><span class="cx"> &lt;!-- unimrcpserver document --&gt;
</span><span class="cx"> &lt;unimrcpserver&gt;
</span><ins>+  &lt;!-- MRCP resources --&gt;
+  &lt;resources&gt;
+    &lt;resource class=&quot;speechsynth&quot; enable=&quot;1&quot;/&gt;
+    &lt;resource class=&quot;speechrecog&quot; enable=&quot;1&quot;/&gt;
+    &lt;resource class=&quot;recorder&quot; enable=&quot;1&quot;/&gt;
+  &lt;/resources&gt;
+
</ins><span class="cx">   &lt;!-- Server settings (signaling, media, ...) --&gt;
</span><span class="cx">   &lt;settings&gt;
</span><span class="cx">     &lt;!-- SIP, RTSP signaling agents --&gt;
</span><span class="lines">@@ -46,8 +53,22 @@
</span><span class="cx">         &lt;!-- &lt;param name=&quot;playout-delay&quot; value=&quot;50&quot;/&gt; --&gt;
</span><span class="cx">         &lt;!-- &lt;param name=&quot;max-playout-delay&quot; value=&quot;200&quot;/&gt; --&gt;
</span><span class="cx">         &lt;!-- &lt;param name=&quot;ptime&quot; value=&quot;20&quot;/&gt; --&gt;
</span><del>-        &lt;param name=&quot;codecs&quot; value=&quot;PCMU PCMA L16/96/8000&quot;/&gt;
</del><ins>+        &lt;param name=&quot;codecs&quot; value=&quot;PCMU PCMA L16/96/8000 telephone-event/101/8000&quot;/&gt;
+        &lt;!-- &lt;param name=&quot;codecs&quot; value=&quot;PCMU PCMA L16/96/8000 PCMU/97/16000 PCMA/98/16000 L16/99/16000&quot;/&gt; --&gt;
</ins><span class="cx">         &lt;!-- &lt;param name=&quot;own-preference&quot; value=&quot;1&quot;/&gt; --&gt;
</span><ins>+
+        &lt;!-- enable/disable rtcp support --&gt;
+        &lt;param name=&quot;rtcp&quot; value=&quot;0&quot;/&gt;
+        &lt;!-- rtcp bye policies (rtcp must be enabled first)
+             0 - disable rtcp bye
+             1 - send rtcp bye at the end of session
+             2 - send rtcp bye also at the end of each talkspurt (input)
+        --&gt;
+        &lt;param name=&quot;rtcp-bye&quot; value=&quot;1&quot;/&gt;
+        &lt;!-- rtcp transmission interval in msec --&gt;
+        &lt;param name=&quot;rtcp-tx-interval&quot; value=&quot;5000&quot;/&gt;
+        &lt;!-- period (timeout) to check for new rtcp messages in msec (set 0 to disable) --&gt;
+        &lt;param name=&quot;rtcp-rx-resolution&quot; value=&quot;1000&quot;/&gt;
</ins><span class="cx">       &lt;/rtp&gt;
</span><span class="cx">     &lt;/media&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -58,6 +79,7 @@
</span><span class="cx">       &lt;engine name=&quot;Flite-1&quot; class=&quot;mrcpflite&quot; enable=&quot;0&quot;/&gt;
</span><span class="cx">       &lt;engine name=&quot;Demo-Synth-1&quot; class=&quot;demosynth&quot; enable=&quot;1&quot;/&gt;
</span><span class="cx">       &lt;engine name=&quot;Demo-Recog-1&quot; class=&quot;demorecog&quot; enable=&quot;1&quot;/&gt;
</span><ins>+      &lt;engine name=&quot;Recorder-1&quot; class=&quot;mrcprecorder&quot; enable=&quot;1&quot;/&gt;
</ins><span class="cx">     &lt;/plugin&gt;
</span><span class="cx">   &lt;/settings&gt;
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpconfigureac"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/configure.ac (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/configure.ac        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/configure.ac        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -3,7 +3,7 @@
</span><span class="cx"> 
</span><span class="cx"> AC_PREREQ(2.57)
</span><span class="cx"> 
</span><del>-AC_INIT([unimrcp],[0.6.0])
</del><ins>+AC_INIT([unimrcp],[0.8.0])
</ins><span class="cx"> 
</span><span class="cx"> AC_CONFIG_AUX_DIR([build])
</span><span class="cx"> AC_CONFIG_MACRO_DIR([build/acmacros])
</span><span class="lines">@@ -31,7 +31,7 @@
</span><span class="cx"> # Get version information
</span><span class="cx"> get_version=&quot;build/get-version.sh&quot;
</span><span class="cx"> version_hdr=&quot;build/uni_version.h&quot;
</span><del>-plugin_version_hdr=&quot;libs/mrcp-engine/include/mrcp_resource_plugin.h&quot;
</del><ins>+plugin_version_hdr=&quot;libs/mrcp-engine/include/mrcp_engine_plugin.h&quot;
</ins><span class="cx"> UNI_DOTTED_VERSION=&quot;`$get_version all $version_hdr UNI`&quot;
</span><span class="cx"> UNI_LT_VERSION=&quot;-version-info `$get_version libtool $version_hdr UNI`&quot;
</span><span class="cx"> PLUGIN_LT_VERSION=&quot;-version-info `$get_version libtool $plugin_version_hdr PLUGIN`&quot;
</span><span class="lines">@@ -117,6 +117,15 @@
</span><span class="cx"> AM_CONDITIONAL([DEMORECOG_PLUGIN],[test &quot;${enable_demorecog_plugin}&quot; = &quot;yes&quot;])
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+#Enable recorder plugin
+AC_ARG_ENABLE(recorder-plugin,
+    [AC_HELP_STRING([--disable-recorder-plugin  ],[exclude recorder plugin from build])],
+    [enable_recorder_plugin=&quot;$enableval&quot;],
+    [enable_recorder_plugin=&quot;yes&quot;])
+
+AM_CONDITIONAL([RECORDER_PLUGIN],[test &quot;${enable_recorder_plugin}&quot; = &quot;yes&quot;])
+
+
</ins><span class="cx"> #Enable Cepstral Swift plugin
</span><span class="cx"> AC_ARG_ENABLE(cepstral-plugin,
</span><span class="cx">     [AC_HELP_STRING([--disable-cepstral-plugin  ],[exclude cepstral plugin from build])],
</span><span class="lines">@@ -182,6 +191,7 @@
</span><span class="cx">   plugins/mrcp-cepstral/Makefile
</span><span class="cx">   plugins/mrcp-pocketsphinx/Makefile
</span><span class="cx">   plugins/mrcp-flite/Makefile
</span><ins>+  plugins/mrcp-recorder/Makefile
</ins><span class="cx">   plugins/demo-synth/Makefile
</span><span class="cx">   plugins/demo-recog/Makefile
</span><span class="cx">   platforms/Makefile
</span><span class="lines">@@ -189,6 +199,9 @@
</span><span class="cx">   platforms/libunimrcp-client/Makefile
</span><span class="cx">   platforms/unimrcp-server/Makefile
</span><span class="cx">   platforms/unimrcp-client/Makefile
</span><ins>+  platforms/libasr-client/Makefile
+  platforms/asr-client/Makefile
+  platforms/umc/Makefile
</ins><span class="cx">   tests/Makefile
</span><span class="cx">   tests/apttest/Makefile
</span><span class="cx">   tests/mpftest/Makefile
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpdatademo16kHzpcm"></a>
<div class="binary"><h4>Added: freeswitch/trunk/libs/unimrcp/data/demo-16kHz.pcm</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: freeswitch/trunk/libs/unimrcp/data/demo-16kHz.pcm
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:mime-type
</span><span class="cx">   + application/octet-stream
</span><a id="freeswitchtrunklibsunimrcpdatademo8kHzpcm"></a>
<div class="binary"><h4>Added: freeswitch/trunk/libs/unimrcp/data/demo-8kHz.pcm</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: freeswitch/trunk/libs/unimrcp/data/demo-8kHz.pcm
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:mime-type
</span><span class="cx">   + application/octet-stream
</span><a id="freeswitchtrunklibsunimrcpdatademopcm"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/data/demo.pcm</h4></div>
<a id="freeswitchtrunklibsunimrcpdatagrammarjsgf"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/data/grammar.jsgf (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/data/grammar.jsgf                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/data/grammar.jsgf        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,3 @@
</span><ins>+#JSGF V1.0;
+grammar digits;
+public &lt;numbers&gt; = (one | two | three);
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpdataone16kHzpcm"></a>
<div class="binary"><h4>Added: freeswitch/trunk/libs/unimrcp/data/one-16kHz.pcm</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: freeswitch/trunk/libs/unimrcp/data/one-16kHz.pcm
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:mime-type
</span><span class="cx">   + application/octet-stream
</span><a id="freeswitchtrunklibsunimrcpdataone8kHzpcm"></a>
<div class="binary"><h4>Added: freeswitch/trunk/libs/unimrcp/data/one-8kHz.pcm</h4>
<pre class="diff"><span>
<span class="cx">(Binary files differ)
</span></span></pre></div>
<span class="cx">Property changes on: freeswitch/trunk/libs/unimrcp/data/one-8kHz.pcm
</span><span class="cx">___________________________________________________________________
</span><span class="cx">Name: svn:mime-type
</span><span class="cx">   + application/octet-stream
</span><a id="freeswitchtrunklibsunimrcpdataonepcm"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/data/one.pcm</h4></div>
<a id="freeswitchtrunklibsunimrcpdataspeaktxt"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/data/speak.txt (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/data/speak.txt                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/data/speak.txt        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+Hello World.
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_cyclic_queueh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><ins>+/** Default size (number of elements) of cyclic queue */
</ins><span class="cx"> #define CYCLIC_QUEUE_DEFAULT_SIZE        100
</span><span class="cx"> 
</span><span class="cx"> /** Opaque cyclic queue declaration */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_logh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_log.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_log.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_log.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -98,12 +98,12 @@
</span><span class="cx"> /**
</span><span class="cx">  * Destroy the singleton instance of the logger.
</span><span class="cx">  */
</span><del>-APT_DECLARE(apt_bool_t) apt_log_instance_destroy();
</del><ins>+APT_DECLARE(apt_bool_t) apt_log_instance_destroy(void);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Get the singleton instance of the logger.
</span><span class="cx">  */
</span><del>-APT_DECLARE(apt_logger_t*) apt_log_instance_get();
</del><ins>+APT_DECLARE(apt_logger_t*) apt_log_instance_get(void);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Set the singleton instance of the logger.
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx"> /**
</span><span class="cx">  * Close the log file.
</span><span class="cx">  */
</span><del>-APT_DECLARE(apt_bool_t) apt_log_file_close();
</del><ins>+APT_DECLARE(apt_bool_t) apt_log_file_close(void);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Set the logging output.
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_neth"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_net.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_net.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_net.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -33,6 +33,14 @@
</span><span class="cx">  */
</span><span class="cx"> apt_bool_t apt_ip_get(char **addr, apr_pool_t *pool);
</span><span class="cx"> 
</span><ins>+
+/**
+ * Get current NTP time
+ * @param sec the seconds of the NTP time to return
+ * @param frac the fractions of the NTP time to return
+ */
+void apt_ntp_time_get(apr_uint32_t *sec, apr_uint32_t *frac);
+
</ins><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__APT_NET_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_nlsml_doch"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -30,16 +30,16 @@
</span><span class="cx"> /** Load NLSML document */
</span><span class="cx"> APT_DECLARE(apr_xml_doc*) nlsml_doc_load(const apt_str_t *data, apr_pool_t *pool);
</span><span class="cx"> 
</span><del>-/** Get the first &lt;interpretation&gt; element */
</del><ins>+/** Get the first interpretation element */
</ins><span class="cx"> APT_DECLARE(apr_xml_elem*) nlsml_first_interpret_get(const apr_xml_doc *doc);
</span><span class="cx"> 
</span><del>-/** Get the next &lt;interpretation&gt; element */
</del><ins>+/** Get the next interpretation element */
</ins><span class="cx"> APT_DECLARE(apr_xml_elem*) nlsml_next_interpret_get(const apr_xml_elem *interpret);
</span><span class="cx"> 
</span><del>-/** Get &lt;instance&gt; and &lt;input&gt; elements of &lt;interpretation&gt; element */
</del><ins>+/** Get instance and input elements of interpretation element */
</ins><span class="cx"> APT_DECLARE(apt_bool_t) nlsml_interpret_results_get(const apr_xml_elem *interpret, apr_xml_elem **instance, apr_xml_elem **input);
</span><span class="cx"> 
</span><del>-/** Get specified atrribute of &lt;input&gt; */
</del><ins>+/** Get specified atrribute of input element */
</ins><span class="cx"> APT_DECLARE(const char *) nlsml_input_attrib_get(const apr_xml_elem *input, const char *attrib, apt_bool_t recursive);
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_poolh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -34,7 +34,7 @@
</span><span class="cx"> /**
</span><span class="cx">  * Create APR pool
</span><span class="cx">  */
</span><del>-APT_DECLARE(apr_pool_t*) apt_pool_create();
</del><ins>+APT_DECLARE(apr_pool_t*) apt_pool_create(void);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Create APR subpool pool
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_taskh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_task.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_task.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_task.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -55,8 +55,8 @@
</span><span class="cx"> APT_DECLARE(apt_bool_t) apt_task_destroy(apt_task_t *task);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Add slave task.
- * @param task the task to add slave task to
</del><ins>+ * Add child task.
+ * @param task the task to add child task to
</ins><span class="cx">  * @param child_task the child task to add
</span><span class="cx">  */
</span><span class="cx"> APT_DECLARE(apt_bool_t) apt_task_add(apt_task_t *task, apt_task_t *child_task);
</span><span class="lines">@@ -158,6 +158,19 @@
</span><span class="cx"> APT_DECLARE(const char*) apt_task_name_get(apt_task_t *task);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Enable/disable auto ready mode.
+ * @param task the task to set mode for
+ * @param auto_ready the enabled/disabled auto ready mode
+ */
+APT_DECLARE(void) apt_task_auto_ready_set(apt_task_t *task, apt_bool_t auto_ready);
+
+/**
+ * Explicitly indicate task is ready to process messages.
+ * @param task the task
+ */
+APT_DECLARE(apt_bool_t) apt_task_ready(apt_task_t *task);
+
+/**
</ins><span class="cx">  * Hold task execution.
</span><span class="cx">  * @param msec the time to hold
</span><span class="cx">  */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitincludeapt_test_suiteh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx"> /**
</span><span class="cx">  * Create test framework.
</span><span class="cx">  */
</span><del>-APT_DECLARE(apt_test_framework_t*) apt_test_framework_create();
</del><ins>+APT_DECLARE(apt_test_framework_t*) apt_test_framework_create(void);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Destroy test framework.
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_consumer_taskc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,6 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;apr_queue.h&gt;
</span><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><ins>+#include &quot;apt_log.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> struct apt_consumer_task_t {
</span><span class="cx">         void        *obj;
</span><span class="lines">@@ -85,6 +86,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         while(running) {
</span><ins>+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Wait for Task Messages [%s]&quot;,apt_task_name_get(task));
</ins><span class="cx">                 rv = apr_queue_pop(consumer_task-&gt;msg_queue,&amp;msg);
</span><span class="cx">                 if(rv == APR_SUCCESS) {
</span><span class="cx">                         if(msg) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_logc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_log.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_log.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_log.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -257,7 +257,7 @@
</span><span class="cx">         log_entry[offset++] = '\n';
</span><span class="cx">         log_entry[offset] = '\0';
</span><span class="cx">         if((apt_logger-&gt;mode &amp; APT_LOG_OUTPUT_CONSOLE) == APT_LOG_OUTPUT_CONSOLE) {
</span><del>-                printf(log_entry);
</del><ins>+                fwrite(log_entry,offset,1,stdout);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if((apt_logger-&gt;mode &amp; APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE &amp;&amp; apt_logger-&gt;file_data) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_netc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -33,3 +33,20 @@
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><ins>+
+/** Seconds from  Jan 1 1900 to Jan 1 1970 */
+#define NTP_TIME_OFFSET 2208988800UL
+
+/** Get current NTP time */
+void apt_ntp_time_get(apr_uint32_t *sec, apr_uint32_t *frac)
+{
+        apr_uint32_t t;
+        apr_uint32_t usec;
+        
+        apr_time_t now = apr_time_now();
+        *sec = (apr_uint32_t)apr_time_sec(now) + NTP_TIME_OFFSET;
+
+        usec = (apr_uint32_t) apr_time_usec(now);
+        t = (usec * 1825) &gt;&gt; 5;
+        *frac = ((usec &lt;&lt; 12) + (usec &lt;&lt; 8) - t);
+}
</ins></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 (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx">                 vtable-&gt;destroy = apt_net_client_task_on_destroy;
</span><span class="cx">                 vtable-&gt;signal_msg = apt_net_client_task_msg_signal;
</span><span class="cx">         }
</span><ins>+        apt_task_auto_ready_set(task-&gt;base,FALSE);
</ins><span class="cx"> 
</span><span class="cx">         task-&gt;msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
</span><span class="cx">         apr_thread_mutex_create(&amp;task-&gt;guard,APR_THREAD_MUTEX_UNNESTED,pool);
</span><span class="lines">@@ -279,6 +280,9 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* explicitly indicate task is ready to process messages */
+        apt_task_ready(task-&gt;base);
+
</ins><span class="cx">         while(running) {
</span><span class="cx">                 status = apt_pollset_poll(task-&gt;pollset, -1, &amp;num, &amp;ret_pfd);
</span><span class="cx">                 if(status != APR_SUCCESS) {
</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 (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -89,6 +89,7 @@
</span><span class="cx">                 vtable-&gt;destroy = apt_net_server_task_on_destroy;
</span><span class="cx">                 vtable-&gt;signal_msg = apt_net_server_task_msg_signal;
</span><span class="cx">         }
</span><ins>+        apt_task_auto_ready_set(task-&gt;base,FALSE);
</ins><span class="cx"> 
</span><span class="cx">         task-&gt;msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
</span><span class="cx">         apr_thread_mutex_create(&amp;task-&gt;guard,APR_THREAD_MUTEX_UNNESTED,pool);
</span><span class="lines">@@ -324,6 +325,9 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* explicitly indicate task is ready to process messages */
+        apt_task_ready(task-&gt;base);
+
</ins><span class="cx">         while(running) {
</span><span class="cx">                 status = apt_pollset_poll(task-&gt;pollset, -1, &amp;num, &amp;ret_pfd);
</span><span class="cx">                 if(status != APR_SUCCESS) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_pairc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -34,8 +34,8 @@
</span><span class="cx">         }
</span><span class="cx">         arr = apr_array_copy(pool,src_arr);
</span><span class="cx">         for(i=0; i&lt;arr-&gt;nelts; i++) {
</span><del>-                pair = (apt_pair_t*)arr-&gt;elts + i;
-                src_pair = (const apt_pair_t*)src_arr-&gt;elts + i;
</del><ins>+                pair = &amp;APR_ARRAY_IDX(arr,i,apt_pair_t);
+                src_pair = &amp;APR_ARRAY_IDX(src_arr,i,const apt_pair_t);
</ins><span class="cx">                 apt_pair_copy(pair,src_pair,pool);
</span><span class="cx">         }
</span><span class="cx">         return arr;
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         apt_pair_t *pair;
</span><span class="cx">         for(i=0; i&lt;arr-&gt;nelts; i++) {
</span><del>-                pair = (apt_pair_t*)arr-&gt;elts + i;
</del><ins>+                pair = &amp;APR_ARRAY_IDX(arr,i,apt_pair_t);
</ins><span class="cx">                 if(apt_string_compare(&amp;pair-&gt;name,name) == TRUE) {
</span><span class="cx">                         return pair;
</span><span class="cx">                 }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_poolc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,7 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;apt_pool.h&quot;
</span><span class="cx"> 
</span><del>-//#define OWN_ALLOCATOR_PER_POOL
</del><ins>+#define OWN_ALLOCATOR_PER_POOL
</ins><span class="cx"> 
</span><span class="cx"> APT_DECLARE(apr_pool_t*) apt_pool_create()
</span><span class="cx"> {
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx">                         apr_allocator_owner_set(allocator,pool);
</span><span class="cx">                         apr_thread_mutex_create(&amp;mutex,APR_THREAD_MUTEX_NESTED,pool);
</span><span class="cx">                         apr_allocator_mutex_set(allocator,mutex);
</span><ins>+                        apr_pool_mutex_set(pool,mutex); 
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> #else
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsaprtoolkitsrcapt_taskc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_task.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_task.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/apr-toolkit/src/apt_task.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx">         apt_obj_list_t      *child_tasks;   /* list of the child (slave) tasks */
</span><span class="cx">         apr_size_t           pending_start; /* number of pending start requests */
</span><span class="cx">         apr_size_t           pending_term;  /* number of pending terminate requests */
</span><ins>+        apt_bool_t           auto_ready;    /* if TRUE, task is implicitly ready to process messages */
</ins><span class="cx">         const char          *name;          /* name of the task */
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -75,6 +76,7 @@
</span><span class="cx">         task-&gt;child_tasks = apt_list_create(pool);
</span><span class="cx">         task-&gt;pending_start = 0;
</span><span class="cx">         task-&gt;pending_term = 0;
</span><ins>+        task-&gt;auto_ready = TRUE;
</ins><span class="cx">         task-&gt;name = &quot;Task&quot;;
</span><span class="cx">         return task;
</span><span class="cx"> }
</span><span class="lines">@@ -386,6 +388,23 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+APT_DECLARE(void) apt_task_auto_ready_set(apt_task_t *task, apt_bool_t auto_ready)
+{
+        task-&gt;auto_ready = auto_ready;
+}
+
+APT_DECLARE(apt_bool_t) apt_task_ready(apt_task_t *task)
+{
+        if(task-&gt;auto_ready == TRUE) {
+                return FALSE;
+        }
+
+        /* start child tasks (if any) */
+        apt_task_child_start(task);
+        return TRUE;
+}
+
+
</ins><span class="cx"> static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *data)
</span><span class="cx"> {
</span><span class="cx">         apt_task_t *task = data;
</span><span class="lines">@@ -398,8 +417,10 @@
</span><span class="cx">         task-&gt;state = TASK_STATE_RUNNING;
</span><span class="cx">         apr_thread_mutex_unlock(task-&gt;data_guard);
</span><span class="cx"> 
</span><del>-        /* start child tasks (if any) */
-        apt_task_child_start(task);
</del><ins>+        if(task-&gt;auto_ready == TRUE) {
+                /* start child tasks (if any) */
+                apt_task_child_start(task);
+        }
</ins><span class="cx"> 
</span><span class="cx">         /* run task */
</span><span class="cx">         if(task-&gt;vtable.run) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -18,17 +18,24 @@
</span><span class="cx">                            include/mpf_codec_descriptor.h \
</span><span class="cx">                            include/mpf_codec_manager.h \
</span><span class="cx">                            include/mpf_context.h \
</span><ins>+                           include/mpf_dtmf_detector.h \
+                           include/mpf_dtmf_generator.h \
</ins><span class="cx">                            include/mpf_engine.h \
</span><span class="cx">                            include/mpf_frame.h \
</span><span class="cx">                            include/mpf_frame_buffer.h \
</span><span class="cx">                            include/mpf_message.h \
</span><ins>+                           include/mpf_mixer.h \
+                           include/mpf_multiplier.h \
+                           include/mpf_named_event.h \
</ins><span class="cx">                            include/mpf_object.h \
</span><span class="cx">                            include/mpf_stream.h \
</span><del>-                           include/mpf_stream_mode.h \
</del><ins>+                           include/mpf_stream_descriptor.h \
</ins><span class="cx">                            include/mpf_termination.h \
</span><ins>+                           include/mpf_termination_factory.h \
</ins><span class="cx">                            include/mpf_rtp_termination_factory.h \
</span><span class="cx">                            include/mpf_file_termination_factory.h \
</span><del>-                           include/mpf_timer.h \
</del><ins>+                           include/mpf_scheduler.h \
+                           include/mpf_timer_manager.h \
</ins><span class="cx">                            include/mpf_types.h \
</span><span class="cx">                            include/mpf_encoder.h \
</span><span class="cx">                            include/mpf_decoder.h \
</span><span class="lines">@@ -39,8 +46,9 @@
</span><span class="cx">                            include/mpf_rtp_stat.h \
</span><span class="cx">                            include/mpf_rtp_defs.h \
</span><span class="cx">                            include/mpf_rtp_attribs.h \
</span><del>-                           include/mpf_media_descriptor.h \
-                           include/mpf_user.h
</del><ins>+                           include/mpf_rtp_pt.h \
+                           include/mpf_rtcp_packet.h \
+                           include/mpf_resampler.h
</ins><span class="cx"> 
</span><span class="cx"> libmpf_la_SOURCES        = codecs/g711/g711.c \
</span><span class="cx">                            src/mpf_activity_detector.c \
</span><span class="lines">@@ -52,14 +60,23 @@
</span><span class="cx">                            src/mpf_codec_linear.c \
</span><span class="cx">                            src/mpf_codec_manager.c \
</span><span class="cx">                            src/mpf_context.c \
</span><ins>+                           src/mpf_dtmf_detector.c \
+                           src/mpf_dtmf_generator.c \
</ins><span class="cx">                            src/mpf_engine.c \
</span><ins>+                           src/mpf_mixer.c \
+                           src/mpf_multiplier.c \
+                           src/mpf_named_event.c \
</ins><span class="cx">                            src/mpf_termination.c \
</span><ins>+                           src/mpf_termination_factory.c \
</ins><span class="cx">                            src/mpf_rtp_termination_factory.c \
</span><span class="cx">                            src/mpf_file_termination_factory.c \
</span><span class="cx">                            src/mpf_frame_buffer.c \
</span><del>-                           src/mpf_timer.c \
</del><ins>+                           src/mpf_scheduler.c \
+                           src/mpf_timer_manager.c \
</ins><span class="cx">                            src/mpf_encoder.c \
</span><span class="cx">                            src/mpf_decoder.c \
</span><span class="cx">                            src/mpf_jitter_buffer.c \
</span><span class="cx">                            src/mpf_rtp_stream.c \
</span><del>-                           src/mpf_rtp_attribs.c
</del><ins>+                           src/mpf_rtp_attribs.c \
+                           src/mpf_resampler.c \
+                           src/mpf_stream.c
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_activity_detectorh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_frame.h&quot;
</span><del>-#include &quot;mpf_codec.h&quot;
</del><ins>+#include &quot;mpf_codec_descriptor.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="lines">@@ -51,9 +51,12 @@
</span><span class="cx"> /** Set noinput timeout */
</span><span class="cx"> MPF_DECLARE(void) mpf_activity_detector_noinput_timeout_set(mpf_activity_detector_t *detector, apr_size_t noinput_timeout);
</span><span class="cx"> 
</span><del>-/** Set transition complete timeout */
-MPF_DECLARE(void) mpf_activity_detector_complete_timeout_set(mpf_activity_detector_t *detector, apr_size_t complete_timeout);
</del><ins>+/** Set timeout required to trigger speech (transition from inactive to active state) */
+MPF_DECLARE(void) mpf_activity_detector_speech_timeout_set(mpf_activity_detector_t *detector, apr_size_t speech_timeout);
</ins><span class="cx"> 
</span><ins>+/** Set timeout required to trigger silence (transition from active to inactive state) */
+MPF_DECLARE(void) mpf_activity_detector_silence_timeout_set(mpf_activity_detector_t *detector, apr_size_t silence_timeout);
+
</ins><span class="cx"> /** Process current frame, return detected event if any */
</span><span class="cx"> MPF_DECLARE(mpf_detector_event_e) mpf_activity_detector_process(mpf_activity_detector_t *detector, const mpf_frame_t *frame);
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_audio_file_descriptorh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,31 +23,30 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &lt;stdio.h&gt;
</span><del>-#include &quot;mpf_stream_mode.h&quot;
-#include &quot;mpf_codec_descriptor.h&quot;
</del><ins>+#include &quot;mpf_stream_descriptor.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** FILE_READER is defined as STREAM_MODE_RECEIVE */
-#define FILE_READER STREAM_MODE_RECEIVE
-/** FILE_WRITER is defined as STREAM_MODE_SEND */
-#define FILE_WRITER STREAM_MODE_SEND
</del><ins>+/** FILE_READER defined as a stream source */
+#define FILE_READER STREAM_DIRECTION_RECEIVE
+/** FILE_WRITER defined as a stream sink */
+#define FILE_WRITER STREAM_DIRECTION_SEND
</ins><span class="cx"> 
</span><span class="cx"> /** Audio file descriptor declaration */
</span><span class="cx"> typedef struct mpf_audio_file_descriptor_t mpf_audio_file_descriptor_t;
</span><span class="cx"> 
</span><span class="cx"> /** Audio file descriptor */
</span><span class="cx"> struct mpf_audio_file_descriptor_t {
</span><del>-        /** Indicate what descriptor for (reader and/or write) */
-        mpf_stream_mode_e      mask;
</del><ins>+        /** Indicate descriptor type (reader and/or writer) */
+        mpf_stream_direction_e  mask;
</ins><span class="cx">         /** Codec descriptor to use for audio file read/write */
</span><del>-        mpf_codec_descriptor_t codec_descriptor;
</del><ins>+        mpf_codec_descriptor_t *codec_descriptor;
</ins><span class="cx">         /** File handle to read audio stream */
</span><del>-        FILE                  *read_handle;
</del><ins>+        FILE                   *read_handle;
</ins><span class="cx">         /** File handle to write audio stream */
</span><del>-        FILE                  *write_handle;
</del><ins>+        FILE                   *write_handle;
</ins><span class="cx">         /** Max size of file  */
</span><del>-        apr_size_t             max_write_size;
</del><ins>+        apr_size_t              max_write_size;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_bridgeh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_bridge.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_bridge.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_bridge.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -30,19 +30,16 @@
</span><span class="cx">  * Create bridge of audio streams.
</span><span class="cx">  * @param source the source audio stream
</span><span class="cx">  * @param sink the sink audio stream
</span><ins>+ * @param codec_manager the codec manager
</ins><span class="cx">  * @param pool the pool to allocate memory from
</span><span class="cx">  */
</span><del>-MPF_DECLARE(mpf_object_t*) mpf_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool);
</del><ins>+MPF_DECLARE(mpf_object_t*) mpf_bridge_create(
+                                                                mpf_audio_stream_t *source, 
+                                                                mpf_audio_stream_t *sink, 
+                                                                const mpf_codec_manager_t *codec_manager,
+                                                                apr_pool_t *pool);
</ins><span class="cx"> 
</span><del>-/**
- * Create bridge of audio streams with the same codec descriptor.
- * @param source the source audio stream
- * @param sink the sink audio stream
- * @param pool the pool to allocate memory from
- */
-MPF_DECLARE(mpf_object_t*) mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool);
</del><span class="cx"> 
</span><del>-
</del><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_BRIDGE_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_codech"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -39,9 +39,6 @@
</span><span class="cx">         const mpf_codec_attribs_t    *attribs;
</span><span class="cx">         /** Optional static codec descriptor (pt &lt; 96) */
</span><span class="cx">         const mpf_codec_descriptor_t *static_descriptor;
</span><del>-        
-        /** Negotiated codec descriptor */
-        mpf_codec_descriptor_t       *descriptor;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Table of codec virtual methods */
</span><span class="lines">@@ -77,7 +74,6 @@
</span><span class="cx">         codec-&gt;vtable = vtable;
</span><span class="cx">         codec-&gt;attribs = attribs;
</span><span class="cx">         codec-&gt;static_descriptor = descriptor;
</span><del>-        codec-&gt;descriptor = NULL;
</del><span class="cx">         return codec;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -92,7 +88,6 @@
</span><span class="cx">         codec-&gt;vtable = src_codec-&gt;vtable;
</span><span class="cx">         codec-&gt;attribs = src_codec-&gt;attribs;
</span><span class="cx">         codec-&gt;static_descriptor = src_codec-&gt;static_descriptor;
</span><del>-        codec-&gt;descriptor = src_codec-&gt;descriptor;
</del><span class="cx">         return codec;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -100,14 +95,9 @@
</span><span class="cx"> static APR_INLINE apt_bool_t mpf_codec_open(mpf_codec_t *codec)
</span><span class="cx"> {
</span><span class="cx">         apt_bool_t rv = TRUE;
</span><del>-        if(codec-&gt;descriptor) {
-                if(codec-&gt;vtable-&gt;open) {
-                        rv = codec-&gt;vtable-&gt;open(codec);
-                }
</del><ins>+        if(codec-&gt;vtable-&gt;open) {
+                rv = codec-&gt;vtable-&gt;open(codec);
</ins><span class="cx">         }
</span><del>-        else {
-                rv = FALSE;
-        }
</del><span class="cx">         return rv;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_codec_descriptorh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -41,17 +41,22 @@
</span><span class="cx">         MPF_SAMPLE_RATE_8000  = 0x01,
</span><span class="cx">         MPF_SAMPLE_RATE_16000 = 0x02,
</span><span class="cx">         MPF_SAMPLE_RATE_32000 = 0x04,
</span><del>-        MPF_SAMPLE_RATE_48000 = 0x08
</del><ins>+        MPF_SAMPLE_RATE_48000 = 0x08,
+
+        MPF_SAMPLE_RATE_SUPPORTED =        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000 | 
+                                                                MPF_SAMPLE_RATE_32000 | MPF_SAMPLE_RATE_48000
</ins><span class="cx"> } mpf_sample_rates_e;
</span><span class="cx"> 
</span><span class="cx"> /** Codec descriptor declaration */
</span><span class="cx"> typedef struct mpf_codec_descriptor_t mpf_codec_descriptor_t;
</span><ins>+/** Codec attributes declaration */
+typedef struct mpf_codec_attribs_t mpf_codec_attribs_t;
</ins><span class="cx"> /** Codec list declaration */
</span><span class="cx"> typedef struct mpf_codec_list_t mpf_codec_list_t;
</span><ins>+/** Codec capabilities declaration */
+typedef struct mpf_codec_capabilities_t mpf_codec_capabilities_t;
</ins><span class="cx"> /** Codec frame declaration */
</span><span class="cx"> typedef struct mpf_codec_frame_t mpf_codec_frame_t;
</span><del>-/** Codec attributes declaration */
-typedef struct mpf_codec_attribs_t mpf_codec_attribs_t;
</del><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> /** Codec descriptor */
</span><span class="lines">@@ -65,38 +70,48 @@
</span><span class="cx">         /** Channel count */
</span><span class="cx">         apr_byte_t   channel_count;
</span><span class="cx">         /** Codec dependent additional format */
</span><del>-        const char  *format;
</del><ins>+        apt_str_t    format;
</ins><span class="cx">         /**  Enabled/disabled state */
</span><span class="cx">         apt_bool_t   enabled;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** List of codec descriptors */
</span><span class="cx"> struct mpf_codec_list_t {
</span><del>-        /** Dynamic array of mpf_codec_descriptor_t */
</del><ins>+        /** Dynamic array of codec descriptors (mpf_codec_descriptor_t) */
</ins><span class="cx">         apr_array_header_t     *descriptor_arr;
</span><del>-        /** Preffered codec descriptor */
-        mpf_codec_descriptor_t *preffered;
</del><ins>+        /** Preffered primary (audio/video codec) descriptor from descriptor_arr */
+        mpf_codec_descriptor_t *primary_descriptor;
+        /** Preffered named event (telephone-event) descriptor from descriptor_arr */
+        mpf_codec_descriptor_t *event_descriptor;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-/** Codec frame */
-struct mpf_codec_frame_t {
-        /** Raw buffer, which may contain encoded or decoded data */
-        void      *buffer;
-        /** Buffer size */
-        apr_size_t size;
-};
-
</del><span class="cx"> /** Codec attributes */
</span><span class="cx"> struct mpf_codec_attribs_t {
</span><span class="cx">         /** Codec name */
</span><span class="cx">         apt_str_t  name;
</span><span class="cx">         /** Bits per sample */
</span><del>-        apr_byte_t bits_per_samples;
</del><ins>+        apr_byte_t bits_per_sample;
</ins><span class="cx">         /** Supported sampling rates (mpf_sample_rates_e) */
</span><span class="cx">         int        sample_rates;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+/** List of codec attributes (capabilities) */
+struct mpf_codec_capabilities_t {
+        /** Dynamic array of codec attributes (mpf_codec_attrribs_t) */
+        apr_array_header_t *attrib_arr;
+        /** Allow/support named events */
+        apt_bool_t          allow_named_events;
+};
</ins><span class="cx"> 
</span><ins>+/** Codec frame */
+struct mpf_codec_frame_t {
+        /** Raw buffer, which may contain encoded or decoded data */
+        void      *buffer;
+        /** Buffer size */
+        apr_size_t size;
+};
+
+
</ins><span class="cx"> /** Initialize codec descriptor */
</span><span class="cx"> static APR_INLINE void mpf_codec_descriptor_init(mpf_codec_descriptor_t *descriptor)
</span><span class="cx"> {
</span><span class="lines">@@ -104,14 +119,22 @@
</span><span class="cx">         apt_string_reset(&amp;descriptor-&gt;name);
</span><span class="cx">         descriptor-&gt;sampling_rate = 0;
</span><span class="cx">         descriptor-&gt;channel_count = 0;
</span><del>-        descriptor-&gt;format = NULL;
</del><ins>+        apt_string_reset(&amp;descriptor-&gt;format);
</ins><span class="cx">         descriptor-&gt;enabled = TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Initialize codec descriptor */
+static APR_INLINE  mpf_codec_descriptor_t* mpf_codec_descriptor_create(apr_pool_t *pool)
+{
+        mpf_codec_descriptor_t *descriptor = (mpf_codec_descriptor_t*) apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
+        mpf_codec_descriptor_init(descriptor);
+        return descriptor;
+}
+
</ins><span class="cx"> /** Calculate encoded frame size in bytes */
</span><span class="cx"> static APR_INLINE apr_size_t mpf_codec_frame_size_calculate(const mpf_codec_descriptor_t *descriptor, const mpf_codec_attribs_t *attribs)
</span><span class="cx"> {
</span><del>-        return descriptor-&gt;channel_count * attribs-&gt;bits_per_samples * CODEC_FRAME_TIME_BASE * 
</del><ins>+        return descriptor-&gt;channel_count * attribs-&gt;bits_per_sample * CODEC_FRAME_TIME_BASE * 
</ins><span class="cx">                         descriptor-&gt;sampling_rate / 1000 / 8; /* 1000 - msec per sec, 8 - bits per byte */
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -127,17 +150,22 @@
</span><span class="cx">         return channel_count * BYTES_PER_SAMPLE * CODEC_FRAME_TIME_BASE * sampling_rate / 1000;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
+
</ins><span class="cx"> /** Reset list of codec descriptors */
</span><span class="cx"> static APR_INLINE void mpf_codec_list_reset(mpf_codec_list_t *codec_list)
</span><span class="cx"> {
</span><span class="cx">         codec_list-&gt;descriptor_arr = NULL;
</span><del>-        codec_list-&gt;preffered = NULL;
</del><ins>+        codec_list-&gt;primary_descriptor = NULL;
+        codec_list-&gt;event_descriptor = NULL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Initialize list of codec descriptors */
</span><span class="cx"> static APR_INLINE void mpf_codec_list_init(mpf_codec_list_t *codec_list, apr_size_t initial_count, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         codec_list-&gt;descriptor_arr = apr_array_make(pool,(int)initial_count, sizeof(mpf_codec_descriptor_t));
</span><ins>+        codec_list-&gt;primary_descriptor = NULL;
+        codec_list-&gt;event_descriptor = NULL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Copy list of codec descriptors */
</span><span class="lines">@@ -149,7 +177,7 @@
</span><span class="cx"> /** Increment number of codec descriptors in the list and return the descriptor to fill */
</span><span class="cx"> static APR_INLINE mpf_codec_descriptor_t* mpf_codec_list_add(mpf_codec_list_t *codec_list)
</span><span class="cx"> {
</span><del>-        mpf_codec_descriptor_t* descriptor = (mpf_codec_descriptor_t*)apr_array_push(codec_list-&gt;descriptor_arr);
</del><ins>+        mpf_codec_descriptor_t *descriptor = (mpf_codec_descriptor_t*)apr_array_push(codec_list-&gt;descriptor_arr);
</ins><span class="cx">         mpf_codec_descriptor_init(descriptor);
</span><span class="cx">         return descriptor;
</span><span class="cx"> }
</span><span class="lines">@@ -161,22 +189,93 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Get codec descriptor by index */
</span><del>-static APR_INLINE mpf_codec_descriptor_t* mpf_codec_get(const mpf_codec_list_t *codec_list, apr_size_t id)
</del><ins>+static APR_INLINE mpf_codec_descriptor_t* mpf_codec_list_descriptor_get(const mpf_codec_list_t *codec_list, apr_size_t id)
</ins><span class="cx"> {
</span><del>-        mpf_codec_descriptor_t *descriptor;
</del><span class="cx">         if(id &gt;= (apr_size_t)codec_list-&gt;descriptor_arr-&gt;nelts) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><del>-        descriptor = (mpf_codec_descriptor_t*)codec_list-&gt;descriptor_arr-&gt;elts;
-        return descriptor + id;
</del><ins>+        return &amp;APR_ARRAY_IDX(codec_list-&gt;descriptor_arr,id,mpf_codec_descriptor_t);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Create linear PCM descriptor */
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_lpcm_descriptor_create(apr_uint16_t sampling_rate, apr_byte_t channel_count, apr_pool_t *pool);
+
+/** Create codec descriptor by capabilities */
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_descriptor_create_by_capabilities(const mpf_codec_capabilities_t *capabilities, const mpf_codec_descriptor_t *peer, apr_pool_t *pool);
+
</ins><span class="cx"> /** Match two codec descriptors */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_codec_descriptor_match(const mpf_codec_descriptor_t *descriptor1, const mpf_codec_descriptor_t *descriptor2);
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_codec_descriptors_match(const mpf_codec_descriptor_t *descriptor1, const mpf_codec_descriptor_t *descriptor2);
+
+/** Match specified codec descriptor and the default lpcm one */
+MPF_DECLARE(apt_bool_t) mpf_codec_lpcm_descriptor_match(const mpf_codec_descriptor_t *descriptor);
+
+/** Match codec descriptor by attribs specified */
+MPF_DECLARE(apt_bool_t) mpf_codec_descriptor_match_by_attribs(mpf_codec_descriptor_t *descriptor, const mpf_codec_descriptor_t *static_descriptor, const mpf_codec_attribs_t *attribs);
+
+
+
+/** Initialize codec capabilities */
+static APR_INLINE void mpf_codec_capabilities_init(mpf_codec_capabilities_t *capabilities, apr_size_t initial_count, apr_pool_t *pool)
+{
+        capabilities-&gt;attrib_arr = apr_array_make(pool,(int)initial_count, sizeof(mpf_codec_attribs_t));
+        capabilities-&gt;allow_named_events = TRUE;
+}
+
+/** Clone codec capabilities */
+static APR_INLINE void mpf_codec_capabilities_clone(mpf_codec_capabilities_t *capabilities, const mpf_codec_capabilities_t *src_capabilities, apr_pool_t *pool)
+{
+        capabilities-&gt;attrib_arr = apr_array_copy(pool,src_capabilities-&gt;attrib_arr);
+        capabilities-&gt;allow_named_events = src_capabilities-&gt;allow_named_events;
+}
+
+/** Merge codec capabilities */
+static APR_INLINE apt_bool_t mpf_codec_capabilities_merge(mpf_codec_capabilities_t *capabilities, const mpf_codec_capabilities_t *src_capabilities, apr_pool_t *pool)
+{
+        if(capabilities-&gt;allow_named_events == FALSE &amp;&amp; src_capabilities-&gt;allow_named_events == TRUE) {
+                capabilities-&gt;allow_named_events = src_capabilities-&gt;allow_named_events;
+        }
+        capabilities-&gt;attrib_arr = apr_array_append(pool,capabilities-&gt;attrib_arr,src_capabilities-&gt;attrib_arr);
+        return TRUE;
+}
+
+/** Add codec capabilities */
+static APR_INLINE apt_bool_t mpf_codec_capabilities_add(mpf_codec_capabilities_t *capabilities, int sample_rates, const char *codec_name)
+{
+        mpf_codec_attribs_t *attribs = (mpf_codec_attribs_t*)apr_array_push(capabilities-&gt;attrib_arr);
+        apt_string_set(&amp;attribs-&gt;name,codec_name);
+        attribs-&gt;sample_rates = sample_rates;
+        attribs-&gt;bits_per_sample = 0;
+        return TRUE;
+}
+
+/** Add default (liear PCM) capabilities */
+MPF_DECLARE(apt_bool_t) mpf_codec_default_capabilities_add(mpf_codec_capabilities_t *capabilities);
+
+/** Validate codec capabilities */
+static APR_INLINE apt_bool_t mpf_codec_capabilities_validate(mpf_codec_capabilities_t *capabilities)
+{
+        if(apr_is_empty_array(capabilities-&gt;attrib_arr) == TRUE) {
+                mpf_codec_default_capabilities_add(capabilities);
+        }
+        return TRUE;
+}
+
+
+
+/** Find matched descriptor in codec list */
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_list_descriptor_find(const mpf_codec_list_t *codec_list, const mpf_codec_descriptor_t *descriptor);
+
+/** Modify codec list according to capabilities specified */
+MPF_DECLARE(apt_bool_t) mpf_codec_list_modify(mpf_codec_list_t *codec_list, const mpf_codec_capabilities_t *capabilities);
+
</ins><span class="cx"> /** Intersect two codec lists */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_codec_list_intersect(mpf_codec_list_t *codec_list1, mpf_codec_list_t *codec_list2);
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_codec_lists_intersect(mpf_codec_list_t *codec_list1, mpf_codec_list_t *codec_list2);
</ins><span class="cx"> 
</span><span class="cx"> 
</span><ins>+/** Get sampling rate mask (mpf_sample_rate_e) by integer value  */
+MPF_DECLARE(int) mpf_sample_rate_mask_get(apr_uint16_t sampling_rate);
+
+
</ins><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_CODEC_DESCRIPTOR_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_codec_managerh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -39,9 +39,6 @@
</span><span class="cx"> /** Get (allocate) codec by codec descriptor */
</span><span class="cx"> MPF_DECLARE(mpf_codec_t*) mpf_codec_manager_codec_get(const mpf_codec_manager_t *codec_manager, mpf_codec_descriptor_t *descriptor, apr_pool_t *pool);
</span><span class="cx"> 
</span><del>-/** Get (allocate) default codec */
-MPF_DECLARE(mpf_codec_t*) mpf_codec_manager_default_codec_get(const mpf_codec_manager_t *codec_manager, apr_pool_t *pool);
-
</del><span class="cx"> /** Get (allocate) list of available codecs */
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_codec_manager_codec_list_get(const mpf_codec_manager_t *codec_manager, mpf_codec_list_t *codec_list, apr_pool_t *pool);
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_contexth"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_context.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_context.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_context.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,33 +22,54 @@
</span><span class="cx">  * @brief MPF Context
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &quot;mpf_object.h&quot;
-#include &quot;apt_obj_list.h&quot;
</del><ins>+#include &quot;mpf_types.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** Definition of table item used in context */
-typedef void* table_item_t;
</del><ins>+/** Opaque factory of media contexts */
+typedef struct mpf_context_factory_t mpf_context_factory_t;

+/**
+ * Create factory of media contexts.
+ */
+MPF_DECLARE(mpf_context_factory_t*) mpf_context_factory_create(apr_pool_t *pool); 
</ins><span class="cx"> 
</span><del>-/** Media processing context */
-struct mpf_context_t {
-    /** Pool to allocate memory from */
-        apr_pool_t        *pool;
-    /** External object */
-        void              *obj;
-    /** Set when context is addded to the list to ensure quick find on delete */
-        apt_list_elem_t   *elem;
</del><ins>+/**
+ * Destroy factory of media contexts.
+ */
+MPF_DECLARE(void) mpf_context_factory_destroy(mpf_context_factory_t *factory); 
</ins><span class="cx"> 
</span><del>-        /** Max number of terminations */
-        apr_size_t          max_termination_count;
-        /** Current number of terminations */
-        apr_size_t          termination_count;
-        /** Table, which holds terminations and topology */
-        table_item_t      **table;
-};
</del><ins>+/**
+ * Process factory of media contexts.
+ */
+MPF_DECLARE(apt_bool_t) mpf_context_factory_process(mpf_context_factory_t *factory);
</ins><span class="cx"> 
</span><ins>+/**
+ * Create MPF context.
+ * @param factory the factory context belongs to
+ * @param obj the external object associated with context
+ * @param max_termination_count the max number of terminations in context
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_context_t*) mpf_context_create(
+                                                                mpf_context_factory_t *factory, 
+                                                                void *obj, 
+                                                                apr_size_t max_termination_count, 
+                                                                apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Destroy MPF context.
+ * @param context the context to destroy
+ */
+MPF_DECLARE(apt_bool_t) mpf_context_destroy(mpf_context_t *context);
+
+/**
+ * Get external object associated with MPF context.
+ * @param context the context to get object from
+ */
+MPF_DECLARE(void*) mpf_context_object_get(mpf_context_t *context);
+
+/**
</ins><span class="cx">  * Add termination to context.
</span><span class="cx">  * @param context the context to add termination to
</span><span class="cx">  * @param termination the termination to add
</span><span class="lines">@@ -63,22 +84,42 @@
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_context_termination_subtract(mpf_context_t *context, mpf_termination_t *termination);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Add association between specified terminations.
+ * @param context the context to add association in the scope of
+ * @param termination1 the first termination to associate
+ * @param termination2 the second termination to associate
+ */
+MPF_DECLARE(apt_bool_t) mpf_context_association_add(mpf_context_t *context, mpf_termination_t *termination1, mpf_termination_t *termination2);
+
+/**
+ * Remove association between specified terminations.
+ * @param context the context to remove association in the scope of
+ * @param termination1 the first termination
+ * @param termination2 the second termination
+ */
+MPF_DECLARE(apt_bool_t) mpf_context_association_remove(mpf_context_t *context, mpf_termination_t *termination1, mpf_termination_t *termination2);
+
+/**
+ * Reset assigned associations and destroy applied topology.
+ * @param context the context to reset associations for
+ */
+MPF_DECLARE(apt_bool_t) mpf_context_associations_reset(mpf_context_t *context);
+
+/**
</ins><span class="cx">  * Apply topology.
</span><del>- * @param context the context which holds the termination
- * @param termination the termination to apply toplogy for
</del><ins>+ * @param context the context to apply topology for
</ins><span class="cx">  */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_context_topology_apply(mpf_context_t *context, mpf_termination_t *termination);
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_topology_apply(mpf_context_t *context);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Destroy topology.
</span><del>- * @param context the context which holds the termination
- * @param termination the termination to destroy toplogy for
</del><ins>+ * @param context the context to destroy topology for
</ins><span class="cx">  */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_context_topology_destroy(mpf_context_t *context, mpf_termination_t *termination);
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_topology_destroy(mpf_context_t *context);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Process context.
</span><del>- * @param context the context
</del><ins>+ * @param context the context to process
</ins><span class="cx">  */
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_context_process(mpf_context_t *context);
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_decoderh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_decoder.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_decoder.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_decoder.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -29,9 +29,10 @@
</span><span class="cx"> /**
</span><span class="cx">  * Create audio stream decoder.
</span><span class="cx">  * @param source the source to get encoded stream from
</span><ins>+ * @param codec the codec to use for decode
</ins><span class="cx">  * @param pool the pool to allocate memory from
</span><span class="cx">  */
</span><del>-MPF_DECLARE(mpf_audio_stream_t*) mpf_decoder_create(mpf_audio_stream_t *source, apr_pool_t *pool);
</del><ins>+MPF_DECLARE(mpf_audio_stream_t*) mpf_decoder_create(mpf_audio_stream_t *source, mpf_codec_t *codec, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_dtmf_detectorh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,121 @@
</span><ins>+/*
+ * Copyright 2009 Tomas Valenta, 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_DTMF_DETECTOR_H__
+#define __MPF_DTMF_DETECTOR_H__
+
+/*
+ * @file mpf_dtmf_detector.h
+ * @brief DTMF detector
+ *
+ * Detector of DTMF tones sent both out-of-band (RFC4733) and in-band (audio).
+ */
+
+#include &quot;apr.h&quot;
+#include &quot;apr_pools.h&quot;
+#include &quot;apt.h&quot;
+#include &quot;mpf_frame.h&quot;
+#include &quot;mpf_stream.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** DTMF detector band */
+typedef enum mpf_dtmf_detector_band_e {
+        /** Detect tones in-band */
+        MPF_DTMF_DETECTOR_INBAND  = 0x1,
+        /** Detect named events out-of-band */
+        MPF_DTMF_DETECTOR_OUTBAND = 0x2,
+        /** Detect both in-band and out-of-band digits */
+        MPF_DTMF_DETECTOR_BOTH = MPF_DTMF_DETECTOR_INBAND | MPF_DTMF_DETECTOR_OUTBAND
+} mpf_dtmf_detector_band_e;
+
+/** Opaque MPF DTMF detector structure definition */
+typedef struct mpf_dtmf_detector_t mpf_dtmf_detector_t;
+
+
+/**
+ * Create MPF DTMF detector (advanced).
+ * @param stream      A stream to get digits from.
+ * @param band        One of:
+ *   - MPF_DTMF_DETECTOR_INBAND: detect audible tones only
+ *   - MPF_DTMF_DETECTOR_OUTBAND: detect out-of-band named-events only
+ *   - MPF_DTMF_DETECTOR_BOTH: detect digits in both bands if supported by
+ *     stream. When out-of-band digit arrives, in-band detection is turned off.
+ * @param pool        Memory pool to allocate DTMF detector from.
+ * @return The object or NULL on error.
+ * @see mpf_dtmf_detector_create
+ */
+MPF_DECLARE(struct mpf_dtmf_detector_t *) mpf_dtmf_detector_create_ex(
+                                                                const struct mpf_audio_stream_t *stream,
+                                                                enum mpf_dtmf_detector_band_e band,
+                                                                struct apr_pool_t *pool);
+
+/**
+ * Create MPF DTMF detector (simple). Calls mpf_dtmf_detector_create_ex
+ * with band = MPF_DTMF_DETECTOR_BOTH if out-of-band supported by the stream,
+ * MPF_DTMF_DETECTOR_INBAND otherwise.
+ * @param stream      A stream to get digits from.
+ * @param pool        Memory pool to allocate DTMF detector from.
+ * @return The object or NULL on error.
+ * @see mpf_dtmf_detector_create_ex
+ */
+static APR_INLINE struct mpf_dtmf_detector_t *mpf_dtmf_detector_create(
+                                                                const struct mpf_audio_stream_t *stream,
+                                                                struct apr_pool_t *pool)
+{
+        return mpf_dtmf_detector_create_ex(stream,
+                stream-&gt;tx_event_descriptor ? MPF_DTMF_DETECTOR_BOTH : MPF_DTMF_DETECTOR_INBAND,
+                pool);
+}
+
+/**
+ * Get DTMF digit from buffer of digits detected so far and remove it.
+ * @param detector  The detector.
+ * @return DTMF character [0-9*#A-D] or NUL if the buffer is empty.
+ */
+MPF_DECLARE(char) mpf_dtmf_detector_digit_get(struct mpf_dtmf_detector_t *detector);
+
+/**
+ * Retrieve how many digits was lost due to full buffer.
+ * @param detector  The detector.
+ * @return Number of lost digits.
+ */
+MPF_DECLARE(apr_size_t) mpf_dtmf_detector_digits_lost(const struct mpf_dtmf_detector_t *detector);
+
+/**
+ * Empty the buffer and reset detection states.
+ * @param detector  The detector.
+ */
+MPF_DECLARE(void) mpf_dtmf_detector_reset(struct mpf_dtmf_detector_t *detector);
+
+/**
+ * Detect DTMF digits in the frame.
+ * @param detector  The detector.
+ * @param frame     Frame object passed in stream_write().
+ */
+MPF_DECLARE(void) mpf_dtmf_detector_get_frame(
+                                                                struct mpf_dtmf_detector_t *detector,
+                                                                const struct mpf_frame_t *frame);
+
+/**
+ * Free all resources associated with the detector.
+ * @param detector  The detector.
+ */
+MPF_DECLARE(void) mpf_dtmf_detector_destroy(struct mpf_dtmf_detector_t *detector);
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_DTMF_DETECTOR_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_dtmf_generatorh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,131 @@
</span><ins>+/*
+ * Copyright 2009 Tomas Valenta, 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_DTMF_GENERATOR_H__
+#define __MPF_DTMF_GENERATOR_H__
+
+/*
+ * @file mpf_named_event.h
+ * @brief DTMF generator
+ *
+ * Generator used to send DTMF tones. Capable to send digits
+ * either in-band as audible tones or out-of-band according
+ * to RFC4733.
+ */
+
+#include &quot;apr_pools.h&quot;
+#include &quot;apt.h&quot;
+#include &quot;mpf_frame.h&quot;
+#include &quot;mpf_stream.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** DTMF generator band */
+typedef enum mpf_dtmf_generator_band_e {
+        /** Generate tones in-band */
+        MPF_DTMF_GENERATOR_INBAND  = 0x1,
+        /** Generate named events out-of-band */
+        MPF_DTMF_GENERATOR_OUTBAND = 0x2,
+        /** Generate both tones and named events */
+        MPF_DTMF_GENERATOR_BOTH = MPF_DTMF_GENERATOR_INBAND | MPF_DTMF_GENERATOR_OUTBAND
+} mpf_dtmf_generator_band_e;
+
+/** Opaque MPF DTMF generator structure definition */
+typedef struct mpf_dtmf_generator_t mpf_dtmf_generator_t;
+
+
+/**
+ * Create MPF DTMF generator (advanced).
+ * @param stream      A stream to transport digits via.
+ * @param band        MPF_DTMF_GENERATOR_INBAND or MPF_DTMF_GENERATOR_OUTBAND
+ * @param tone_ms     Tone duration in milliseconds.
+ * @param silence_ms  Inter-digit silence in milliseconds.
+ * @param pool        Memory pool to allocate DTMF generator from.
+ * @return The object or NULL on error.
+ * @see mpf_dtmf_generator_create
+ */
+MPF_DECLARE(struct mpf_dtmf_generator_t *) mpf_dtmf_generator_create_ex(
+                                                                const struct mpf_audio_stream_t *stream,
+                                                                enum mpf_dtmf_generator_band_e band,
+                                                                apr_size_t tone_ms,
+                                                                apr_size_t silence_ms,
+                                                                struct apr_pool_t *pool);
+
+/**
+ * Create MPF DTMF generator (simple). Calls mpf_dtmf_generator_create_ex
+ * with band = MPF_DTMF_GENERATOR_OUTBAND if supported by the stream or
+ * MPF_DTMF_GENERATOR_INBAND otherwise, tone_ms = 70, silence_ms = 50.
+ * @param stream      A stream to transport digits via.
+ * @param pool        Memory pool to allocate DTMF generator from.
+ * @return The object or NULL on error.
+ * @see mpf_dtmf_generator_create_ex
+ */
+static APR_INLINE struct mpf_dtmf_generator_t *mpf_dtmf_generator_create(
+                                                                const struct mpf_audio_stream_t *stream,
+                                                                struct apr_pool_t *pool)
+{
+        return mpf_dtmf_generator_create_ex(stream,
+                stream-&gt;rx_event_descriptor ? MPF_DTMF_GENERATOR_OUTBAND : MPF_DTMF_GENERATOR_INBAND,
+                70, 50, pool);
+}
+
+/**
+ * Add DTMF digits to the queue.
+ * @param generator The generator.
+ * @param digits    DTMF character sequence [0-9*#A-D].
+ * @return TRUE if ok, FALSE if there are too many digits.
+ */
+MPF_DECLARE(apt_bool_t) mpf_dtmf_generator_enqueue(
+                                                                struct mpf_dtmf_generator_t *generator,
+                                                                const char *digits);
+
+/**
+ * Empty the queue and immediately stop generating.
+ * @param generator The generator.
+ */
+MPF_DECLARE(void) mpf_dtmf_generator_reset(struct mpf_dtmf_generator_t *generator);
+
+/**
+ * Check state of the generator.
+ * @param generator The generator.
+ * @return TRUE if generating a digit or there are digits waiting in queue.
+ * FALSE if the queue is empty or generating silence after the last digit.
+ */
+MPF_DECLARE(apt_bool_t) mpf_dtmf_generator_sending(const struct mpf_dtmf_generator_t *generator);
+
+/**
+ * Put frame into the stream.
+ * @param generator The generator.
+ * @param frame     Frame object passed in stream_read().
+ * @return TRUE if frame with tone (both in-band and out-of-band) was generated,
+ * FALSE otherwise. In contrast to mpf_dtmf_generator_sending, returns FALSE even
+ * if generating inter-digit silence. In other words returns TRUE iff the frame
+ * object was filled with data. This method MUST be called for each frame for
+ * proper timing.
+ */
+MPF_DECLARE(apt_bool_t) mpf_dtmf_generator_put_frame(
+                                                                struct mpf_dtmf_generator_t *generator,
+                                                                struct mpf_frame_t *frame);
+
+/**
+ * Free all resources associated with the generator.
+ * @param generator The generator.
+ */
+MPF_DECLARE(void) mpf_dtmf_generator_destroy(struct mpf_dtmf_generator_t *generator);
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_DTMF_GENERATOR_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_encoderh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_encoder.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_encoder.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_encoder.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -29,9 +29,10 @@
</span><span class="cx"> /**
</span><span class="cx">  * Create audio stream encoder.
</span><span class="cx">  * @param sink the sink to write encoded stream to
</span><ins>+ * @param codec the codec to use for encode
</ins><span class="cx">  * @param pool the pool to allocate memory from
</span><span class="cx">  */
</span><del>-MPF_DECLARE(mpf_audio_stream_t*) mpf_encoder_create(mpf_audio_stream_t *sink, apr_pool_t *pool);
</del><ins>+MPF_DECLARE(mpf_audio_stream_t*) mpf_encoder_create(mpf_audio_stream_t *sink, mpf_codec_t *codec, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_engineh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_engine.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_engine.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_engine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -27,11 +27,15 @@
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><ins>+/** MPF task message definition */
+typedef apt_task_msg_t mpf_task_msg_t;
+
</ins><span class="cx"> /**
</span><span class="cx">  * Create MPF engine.
</span><ins>+ * @param rate the rate (n times faster than real-time)
</ins><span class="cx">  * @param pool the pool to allocate memory from
</span><span class="cx">  */
</span><del>-MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool);
</del><ins>+MPF_DECLARE(mpf_engine_t*) mpf_engine_create(unsigned long rate, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Create MPF codec manager.
</span><span class="lines">@@ -47,6 +51,31 @@
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_engine_codec_manager_register(mpf_engine_t *engine, const mpf_codec_manager_t *codec_manager);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Create MPF context.
+ * @param engine the engine to create context for
+ * @param obj the external object associated with context
+ * @param max_termination_count the max number of terminations in context
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_context_t*) mpf_engine_context_create(
+                                                                mpf_engine_t *engine, 
+                                                                void *obj, 
+                                                                apr_size_t max_termination_count, 
+                                                                apr_pool_t *pool);
+
+/**
+ * Destroy MPF context.
+ * @param context the context to destroy
+ */
+MPF_DECLARE(apt_bool_t) mpf_engine_context_destroy(mpf_context_t *context);
+
+/**
+ * Get external object associated with MPF context.
+ * @param context the context to get object from
+ */
+MPF_DECLARE(void*) mpf_engine_context_object_get(mpf_context_t *context);
+
+/**
</ins><span class="cx">  * Get task.
</span><span class="cx">  * @param engine the engine to get task from
</span><span class="cx">  */
</span><span class="lines">@@ -59,7 +88,61 @@
</span><span class="cx">  */
</span><span class="cx"> MPF_DECLARE(void) mpf_engine_task_msg_type_set(mpf_engine_t *engine, apt_task_msg_type_e type);
</span><span class="cx"> 
</span><ins>+/**
+ * Create task message(if not created) and add MPF termination message to it.
+ * @param engine the engine task message belongs to
+ * @param command_id the MPF command identifier
+ * @param context the context to add termination to
+ * @param termination the termination to add
+ * @param descriptor the termination dependent descriptor
+ * @param task_msg the task message to create and add constructed MPF message to
+ */
+MPF_DECLARE(apt_bool_t) mpf_engine_termination_message_add(
+                                                        mpf_engine_t *engine,
+                                                        mpf_command_type_e command_id,
+                                                        mpf_context_t *context,
+                                                        mpf_termination_t *termination,
+                                                        void *descriptor,
+                                                        mpf_task_msg_t **task_msg);
</ins><span class="cx"> 
</span><ins>+/**
+ * Create task message(if not created) and add MPF association message to it.
+ * @param engine the engine task message belongs to
+ * @param command_id the MPF command identifier
+ * @param context the context to add association of terminations for
+ * @param termination the termination to associate
+ * @param assoc_termination the termination to associate
+ * @param task_msg the task message to create and add constructed MPF message to
+ */
+MPF_DECLARE(apt_bool_t) mpf_engine_assoc_message_add(
+                                                        mpf_engine_t *engine,
+                                                        mpf_command_type_e command_id,
+                                                        mpf_context_t *context,
+                                                        mpf_termination_t *termination,
+                                                        mpf_termination_t *assoc_termination,
+                                                        mpf_task_msg_t **task_msg);
+
+/**
+ * Create task message(if not created) and add MPF topology message to it.
+ * @param engine the engine task message belongs to
+ * @param command_id the MPF command identifier
+ * @param context the context to modify topology for
+ * @param task_msg the task message to create and add constructed MPF message to
+ */
+MPF_DECLARE(apt_bool_t) mpf_engine_topology_message_add(
+                                                        mpf_engine_t *engine,
+                                                        mpf_command_type_e command_id,
+                                                        mpf_context_t *context,
+                                                        mpf_task_msg_t **task_msg);
+
+/**
+ * Send MPF task message.
+ * @param engine the engine to send task message to
+ * @param task_msg the task message to send
+ */
+MPF_DECLARE(apt_bool_t) mpf_engine_message_send(mpf_engine_t *engine, mpf_task_msg_t **task_msg);
+
+
</ins><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_ENGINE_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_file_termination_factoryh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,7 +22,7 @@
</span><span class="cx">  * @brief MPF File Termination Factory
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &quot;mpf_types.h&quot;
</del><ins>+#include &quot;mpf_termination_factory.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_frameh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_frame.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,6 +23,7 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_codec_descriptor.h&quot;
</span><ins>+#include &quot;mpf_named_event.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="lines">@@ -31,42 +32,26 @@
</span><span class="cx">         MEDIA_FRAME_TYPE_NONE  = 0x0, /**&lt; none */
</span><span class="cx">         MEDIA_FRAME_TYPE_AUDIO = 0x1, /**&lt; audio frame */
</span><span class="cx">         MEDIA_FRAME_TYPE_VIDEO = 0x2, /**&lt; video frame */
</span><del>-        MEDIA_FRAME_TYPE_EVENT = 0x4  /**&lt; named event frame (RFC2833) */
</del><ins>+        MEDIA_FRAME_TYPE_EVENT = 0x4  /**&lt; named event frame (RFC4733/RFC2833) */
</ins><span class="cx"> } mpf_frame_type_e;
</span><span class="cx"> 
</span><del>-/** Named event declaration */
-typedef struct mpf_named_event_frame_t mpf_named_event_frame_t;
</del><ins>+/** Media frame marker */
+typedef enum {
+        MPF_MARKER_NONE,           /**&lt; none */
+        MPF_MARKER_START_OF_EVENT, /**&lt; start of event */
+        MPF_MARKER_END_OF_EVENT,   /**&lt; end of event */
+        MPF_MARKER_NEW_SEGMENT,    /**&lt; start of new segment (long-lasting events) */
+} mpf_frame_marker_e;
+
</ins><span class="cx"> /** Media frame declaration */
</span><span class="cx"> typedef struct mpf_frame_t mpf_frame_t;
</span><span class="cx"> 
</span><del>-
-/** Named event (RFC2833, out-of-band DTMF) */
-struct mpf_named_event_frame_t {
-        /** event (DTMF, tone) identifier */
-        apr_uint32_t event_id: 8;
-#if (APR_IS_BIGENDIAN == 1)
-        /** end of event */
-        apr_uint32_t edge:     1;
-        /** reserved */
-        apr_uint32_t reserved: 1;
-        /** tone volume */
-        apr_uint32_t volume:   6;
-#else
-        /** tone volume */
-        apr_uint32_t volume:   6;
-        /** reserved */
-        apr_uint32_t reserved: 1;
-        /** end of event */
-        apr_uint32_t edge:     1;
-#endif
-        /** event duration */
-        apr_uint32_t duration: 16;
-};
-
</del><span class="cx"> /** Media frame */
</span><span class="cx"> struct mpf_frame_t {
</span><span class="cx">         /** frame type (audio/video/named-event) mpf_frame_type_e */
</span><span class="cx">         int                     type;
</span><ins>+        /** frame marker (start-of-event,end-of-event) mpf_frame_marker_e */
+        int                     marker;
</ins><span class="cx">         /** codec frame */
</span><span class="cx">         mpf_codec_frame_t       codec_frame;
</span><span class="cx">         /** named-event frame */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_jitter_bufferh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -41,7 +41,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> /** Create jitter buffer */
</span><del>-mpf_jitter_buffer_t* mpf_jitter_buffer_create(mpf_jb_config_t *jb_config, mpf_codec_t *codec, apr_pool_t *pool);
</del><ins>+mpf_jitter_buffer_t* mpf_jitter_buffer_create(mpf_jb_config_t *jb_config, mpf_codec_descriptor_t *descriptor, mpf_codec_t *codec, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> /** Destroy jitter buffer */
</span><span class="cx"> void mpf_jitter_buffer_destroy(mpf_jitter_buffer_t *jb);
</span><span class="lines">@@ -50,10 +50,10 @@
</span><span class="cx"> apt_bool_t mpf_jitter_buffer_restart(mpf_jitter_buffer_t *jb);
</span><span class="cx"> 
</span><span class="cx"> /** Write audio data to jitter buffer */
</span><del>-jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, mpf_codec_t *codec, void *buffer, apr_size_t size, apr_uint32_t ts);
</del><ins>+jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, void *buffer, apr_size_t size, apr_uint32_t ts);
</ins><span class="cx"> 
</span><span class="cx"> /** Write named event to jitter buffer */
</span><del>-jb_result_t mpf_jitter_buffer_write_named_event(mpf_jitter_buffer_t *jb, mpf_named_event_frame_t *named_event, apr_uint32_t ts);
</del><ins>+jb_result_t mpf_jitter_buffer_event_write(mpf_jitter_buffer_t *jb, const mpf_named_event_frame_t *named_event, apr_uint32_t ts, apr_byte_t marker);
</ins><span class="cx"> 
</span><span class="cx"> /** Read media frame from jitter buffer */
</span><span class="cx"> apt_bool_t mpf_jitter_buffer_read(mpf_jitter_buffer_t *jb, mpf_frame_t *media_frame);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_media_descriptorh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_media_descriptor.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_messageh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_message.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_message.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_message.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -26,6 +26,9 @@
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><ins>+/** Max number of messages grouped in a container */
+#define MAX_MPF_MESSAGE_COUNT 5
+
</ins><span class="cx"> /** Enumeration of MPF message types */
</span><span class="cx"> typedef enum {
</span><span class="cx">         MPF_MESSAGE_TYPE_REQUEST,  /**&lt; request message */
</span><span class="lines">@@ -40,16 +43,22 @@
</span><span class="cx"> } mpf_status_code_e;
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-/** Enumeration of commands */
</del><ins>+/** Enumeration of MPF commands */
</ins><span class="cx"> typedef enum {
</span><del>-        MPF_COMMAND_ADD,     /**&lt; add termination to context */
-        MPF_COMMAND_MODIFY,  /**&lt; modify termination properties */
-        MPF_COMMAND_SUBTRACT,/**&lt; subtract termination from context */ 
-        MPF_COMMAND_MOVE     /**&lt; move termination to another context */
</del><ins>+        MPF_ADD_TERMINATION,     /**&lt; add termination to context */
+        MPF_MODIFY_TERMINATION,  /**&lt; modify termination properties */
+        MPF_SUBTRACT_TERMINATION,/**&lt; subtract termination from context */
+        MPF_ADD_ASSOCIATION,     /**&lt; add association between terminations */
+        MPF_REMOVE_ASSOCIATION,  /**&lt; remove association between terminations */
+        MPF_RESET_ASSOCIATIONS,  /**&lt; reset associations among terminations (also destroy topology) */
+        MPF_APPLY_TOPOLOGY,      /**&lt; apply topology based on assigned associations */
+        MPF_DESTROY_TOPOLOGY     /**&lt; destroy applied topology */
</ins><span class="cx"> } mpf_command_type_e;
</span><span class="cx"> 
</span><span class="cx"> /** MPF message declaration */
</span><span class="cx"> typedef struct mpf_message_t mpf_message_t;
</span><ins>+/** MPF message container declaration */
+typedef struct mpf_message_container_t mpf_message_container_t;
</ins><span class="cx"> 
</span><span class="cx"> /** MPF message definition */
</span><span class="cx"> struct mpf_message_t {
</span><span class="lines">@@ -64,10 +73,20 @@
</span><span class="cx">         mpf_context_t     *context;
</span><span class="cx">         /** Termination */
</span><span class="cx">         mpf_termination_t *termination;
</span><ins>+        /** Associated termination */
+        mpf_termination_t *assoc_termination;
</ins><span class="cx">         /** Termination type dependent descriptor */
</span><span class="cx">         void              *descriptor;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+/** MPF message container definition */
+struct mpf_message_container_t {
+        /** Number of actual messages */
+        apr_size_t    count;
+        /** Array of messages */
+        mpf_message_t messages[MAX_MPF_MESSAGE_COUNT];
+};
+
</ins><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_MESSAGE_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_mixerh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_mixer.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_mixer.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_mixer.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,47 @@
</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_MIXER_H__
+#define __MPF_MIXER_H__
+
+/**
+ * @file mpf_mixer.h
+ * @brief MPF Stream Mixer (n-sources, 1-sink)
+ */ 
+
+#include &quot;mpf_object.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/**
+ * Create audio stream mixer.
+ * @param source_arr the array of audio sources
+ * @param source_count the number of audio sources
+ * @param sink the audio sink
+ * @param codec_manager the codec manager
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
+                                                                mpf_audio_stream_t **source_arr, 
+                                                                apr_size_t source_count, 
+                                                                mpf_audio_stream_t *sink, 
+                                                                const mpf_codec_manager_t *codec_manager,
+                                                                apr_pool_t *pool);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_MIXER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_multiplierh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_multiplier.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_multiplier.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_multiplier.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,47 @@
</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_MULTIPLIER_H__
+#define __MPF_MULTIPLIER_H__
+
+/**
+ * @file mpf_multiplier.h
+ * @brief MPF Stream Multiplier (1-source, n-sinks)
+ */ 
+
+#include &quot;mpf_object.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/**
+ * Create audio stream multiplier.
+ * @param source the audio source
+ * @param sink_arr the array of audio sinks
+ * @param sink_count the number of audio sinks
+ * @param codec_manager the codec manager
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
+                                                                mpf_audio_stream_t *source,
+                                                                mpf_audio_stream_t **sink_arr,
+                                                                apr_size_t sink_count,
+                                                                const mpf_codec_manager_t *codec_manager,
+                                                                apr_pool_t *pool);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_MULTIPLIER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_named_eventh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_named_event.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_named_event.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_named_event.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,71 @@
</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_NAMED_EVENT_H__
+#define __MPF_NAMED_EVENT_H__
+
+/**
+ * @file mpf_named_event.h
+ * @brief MPF Named Events (RFC4733/RFC2833)
+ */ 
+
+#include &quot;mpf_codec_descriptor.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Named event declaration */
+typedef struct mpf_named_event_frame_t mpf_named_event_frame_t;
+
+
+/** Named event (RFC4733/RFC2833, out-of-band DTMF) */
+struct mpf_named_event_frame_t {
+        /** event (DTMF, tone) identifier */
+        apr_uint32_t event_id: 8;
+#if (APR_IS_BIGENDIAN == 1)
+        /** end of event */
+        apr_uint32_t edge:     1;
+        /** reserved */
+        apr_uint32_t reserved: 1;
+        /** tone volume */
+        apr_uint32_t volume:   6;
+#else
+        /** tone volume */
+        apr_uint32_t volume:   6;
+        /** reserved */
+        apr_uint32_t reserved: 1;
+        /** end of event */
+        apr_uint32_t edge:     1;
+#endif
+        /** event duration */
+        apr_uint32_t duration: 16;
+};
+
+/** Create named event descriptor */
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_event_descriptor_create(apr_uint16_t sampling_rate, apr_pool_t *pool);
+
+/** Check whether the specified descriptor is named event one */
+MPF_DECLARE(apt_bool_t) mpf_event_descriptor_check(const mpf_codec_descriptor_t *descriptor);
+
+/** Convert DTMF character to event identifier */
+MPF_DECLARE(apr_uint32_t) mpf_dtmf_char_to_event_id(const char dtmf_char);
+
+/** Convert event identifier to DTMF character */
+MPF_DECLARE(char) mpf_event_id_to_dtmf_char(const apr_uint32_t event_id);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_NAMED_EVENT_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_objecth"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_object.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_object.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_object.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,30 +23,52 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_types.h&quot;
</span><del>-#include &quot;mpf_frame.h&quot;
</del><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> /** MPF object declaration */
</span><span class="cx"> typedef struct mpf_object_t mpf_object_t;
</span><span class="cx"> 
</span><del>-/** Base for media processing objects */
</del><ins>+/** Media processing objects base */
</ins><span class="cx"> struct mpf_object_t {
</span><del>-        /** Audio stream source */
-        mpf_audio_stream_t *source;
-        /** Audio stream sink */
-        mpf_audio_stream_t *sink;
-
-        /** Media frame used to read data from source and write it to sink */
-        mpf_frame_t         frame;
-
</del><ins>+        /** Virtual destroy */
+        apt_bool_t (*destroy)(mpf_object_t *object);
</ins><span class="cx">         /** Virtual process */
</span><span class="cx">         apt_bool_t (*process)(mpf_object_t *object);
</span><del>-        /** Virtual destroy */
-        apt_bool_t (*destroy)(mpf_object_t *object);
</del><ins>+        /** Virtual trace of media path */
+        void (*trace)(mpf_object_t *object);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+/** Initialize object */
+static APR_INLINE void mpf_object_init(mpf_object_t *object)
+{
+        object-&gt;destroy = NULL;
+        object-&gt;process = NULL;
+        object-&gt;trace = NULL;
+}
</ins><span class="cx"> 
</span><ins>+/** Destroy object */
+static APR_INLINE void mpf_object_destroy(mpf_object_t *object)
+{
+        if(object-&gt;destroy)
+                object-&gt;destroy(object);
+}
+
+/** Process object */
+static APR_INLINE void mpf_object_process(mpf_object_t *object)
+{
+        if(object-&gt;process)
+                object-&gt;process(object);
+}
+
+/** Trace media path */
+static APR_INLINE void mpf_object_trace(mpf_object_t *object)
+{
+        if(object-&gt;trace)
+                object-&gt;trace(object);
+}
+
+
</ins><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_OBJECT_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_resamplerh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_resampler.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_resampler.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_resampler.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,40 @@
</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_RESAMPLER_H__
+#define __MPF_RESAMPLER_H__
+
+/**
+ * @file mpf_resampler.h
+ * @brief MPF Stream Resampler
+ */ 
+
+#include &quot;mpf_stream.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/**
+ * Create audio stream resampler.
+ * @param source the source stream to resample
+ * @param sink the sink stream to resample to
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_audio_stream_t*) mpf_resampler_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_RESAMPLER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtcp_packeth"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,200 @@
</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_RTCP_PACKET_H__
+#define __MPF_RTCP_PACKET_H__
+
+/**
+ * @file mpf_rtcp_packet.h
+ * @brief RTCP Packet Definition
+ */ 
+
+#include &quot;mpf_rtp_stat.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+
+/** RTCP payload (packet) types */
+typedef enum {
+        RTCP_SR   = 200,
+        RTCP_RR   = 201,
+        RTCP_SDES = 202,
+        RTCP_BYE  = 203,
+        RTCP_APP  = 204
+} rtcp_type_e;
+
+/** RTCP SDES types */
+typedef enum {
+        RTCP_SDES_END   = 0,
+        RTCP_SDES_CNAME = 1,
+        RTCP_SDES_NAME  = 2,
+        RTCP_SDES_EMAIL = 3,
+        RTCP_SDES_PHONE = 4,
+        RTCP_SDES_LOC   = 5,
+        RTCP_SDES_TOOL  = 6,
+        RTCP_SDES_NOTE  = 7,
+        RTCP_SDES_PRIV  = 8
+} rtcp_sdes_type_e;
+
+/** RTCP header declaration */
+typedef struct rtcp_header_t rtcp_header_t;
+/** RTCP packet declaration */
+typedef struct rtcp_packet_t rtcp_packet_t;
+/** SDES item declaration*/
+typedef struct rtcp_sdes_item_t rtcp_sdes_item_t;
+
+
+/** RTCP header */
+struct rtcp_header_t {
+#if (APR_IS_BIGENDIAN == 1)
+        /** protocol version */
+        unsigned int version: 2;
+        /** padding flag */
+        unsigned int padding: 1;
+        /** varies by packet type */
+        unsigned int count:   5;
+        /** packet type */
+        unsigned int pt:      8;
+#else
+        /** varies by packet type */
+        unsigned int count:   5;
+        /** padding flag */
+        unsigned int padding: 1;
+        /** protocol version */
+        unsigned int version: 2;
+        /** packet type */
+        unsigned int pt:      8;
+#endif        
+        
+        /** packet length in words, w/o this word */
+        unsigned int length:  16;
+};
+
+/** SDES item */
+struct rtcp_sdes_item_t {
+        /** type of item (rtcp_sdes_type_t) */
+        apr_byte_t type;
+        /* length of item (in octets) */
+        apr_byte_t length;
+        /* text, not null-terminated */
+        char       data[1];
+};
+
+/** RTCP packet */
+struct rtcp_packet_t {
+        /** common header */
+        rtcp_header_t header;
+        union {
+                /** sender report (SR) */
+                struct {
+                        /** sr stat */
+                        rtcp_sr_stat_t sr_stat;
+                        /** variable-length list rr stats */
+                        rtcp_rr_stat_t rr_stat[1];
+                } sr;
+
+                /** reception report (RR) */
+                struct {
+                        /** receiver generating this report */
+                        apr_uint32_t   ssrc;
+                        /** variable-length list rr stats */
+                        rtcp_rr_stat_t rr_stat[1];
+                } rr;
+
+                /** source description (SDES) */
+                struct {
+                        /** first SSRC/CSRC */
+                        apr_uint32_t     ssrc;
+                        /** list of SDES items */
+                        rtcp_sdes_item_t item[1];
+                } sdes;
+
+                /** BYE */
+                struct {
+                        /** list of sources */
+                        apr_uint32_t ssrc[1];
+                        /* optional length of reason string (in octets) */
+                        apr_byte_t   length;
+                        /* optional reason string, not null-terminated */
+                        char         data[1];
+                } bye;
+        } r;
+};
+
+/** Initialize RTCP header */
+static APR_INLINE void rtcp_header_init(rtcp_header_t *header, rtcp_type_e pt)
+{
+        header-&gt;version = RTP_VERSION;
+        header-&gt;padding = 0;
+        header-&gt;count = 0;
+        header-&gt;pt = pt;
+        header-&gt;length = 0;
+}
+
+static APR_INLINE void rtcp_header_length_set(rtcp_header_t *header, apr_size_t length)
+{
+        header-&gt;length = htons((apr_uint16_t)length / 4 - 1);
+}
+
+static APR_INLINE void rtcp_sr_hton(rtcp_sr_stat_t *sr_stat)
+{
+        sr_stat-&gt;ssrc = htonl(sr_stat-&gt;ssrc);
+        sr_stat-&gt;ntp_sec = htonl(sr_stat-&gt;ntp_sec);
+        sr_stat-&gt;ntp_frac = htonl(sr_stat-&gt;ntp_frac);
+        sr_stat-&gt;rtp_ts = htonl(sr_stat-&gt;rtp_ts);
+        sr_stat-&gt;sent_packets = htonl(sr_stat-&gt;sent_packets);
+        sr_stat-&gt;sent_octets = htonl(sr_stat-&gt;sent_octets);
+}
+
+static APR_INLINE void rtcp_sr_ntoh(rtcp_sr_stat_t *sr_stat)
+{
+        sr_stat-&gt;ssrc = ntohl(sr_stat-&gt;ssrc);
+        sr_stat-&gt;ntp_sec = ntohl(sr_stat-&gt;ntp_sec);
+        sr_stat-&gt;ntp_frac = ntohl(sr_stat-&gt;ntp_frac);
+        sr_stat-&gt;rtp_ts = ntohl(sr_stat-&gt;rtp_ts);
+        sr_stat-&gt;sent_packets = ntohl(sr_stat-&gt;sent_packets);
+        sr_stat-&gt;sent_octets = ntohl(sr_stat-&gt;sent_octets);
+}
+
+static APR_INLINE void rtcp_rr_hton(rtcp_rr_stat_t *rr_stat)
+{
+        rr_stat-&gt;ssrc = htonl(rr_stat-&gt;ssrc);
+        rr_stat-&gt;last_seq =        htonl(rr_stat-&gt;last_seq);
+        rr_stat-&gt;jitter = htonl(rr_stat-&gt;jitter);
+
+#if (APR_IS_BIGENDIAN == 0)
+        rr_stat-&gt;lost = ((rr_stat-&gt;lost &gt;&gt; 16) &amp; 0x000000ff) |
+                                                (rr_stat-&gt;lost &amp; 0x0000ff00) |
+                                                        ((rr_stat-&gt;lost &lt;&lt; 16) &amp; 0x00ff0000);
+#endif
+}
+
+static APR_INLINE void rtcp_rr_ntoh(rtcp_rr_stat_t *rr_stat)
+{
+        rr_stat-&gt;ssrc = ntohl(rr_stat-&gt;ssrc);
+        rr_stat-&gt;last_seq =        ntohl(rr_stat-&gt;last_seq);
+        rr_stat-&gt;jitter = ntohl(rr_stat-&gt;jitter);
+
+#if (APR_IS_BIGENDIAN == 0)
+        rr_stat-&gt;lost = ((rr_stat-&gt;lost &gt;&gt; 16) &amp; 0x000000ff) |
+                                                (rr_stat-&gt;lost &amp; 0x0000ff00) |
+                                                        ((rr_stat-&gt;lost &lt;&lt; 16) &amp; 0x00ff0000);
+#endif
+}
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_RTCP_PACKET_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_attribsh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,8 +22,7 @@
</span><span class="cx">  * @brief RTP Attributes (SDP)
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &quot;mpf_media_descriptor.h&quot;
-#include &quot;mpf_stream_mode.h&quot;
</del><ins>+#include &quot;mpf_rtp_descriptor.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="lines">@@ -47,8 +46,8 @@
</span><span class="cx"> /** Find audio media attribute identifier by attribute name */
</span><span class="cx"> MPF_DECLARE(mpf_rtp_attrib_e) mpf_rtp_attrib_id_find(const apt_str_t *attrib);
</span><span class="cx"> 
</span><del>-/** Get string by stream mode (send/receive) */
-MPF_DECLARE(const apt_str_t*) mpf_stream_mode_str_get(mpf_stream_mode_e direction);
</del><ins>+/** Get string by RTP direction (send/receive) */
+MPF_DECLARE(const apt_str_t*) mpf_rtp_direction_str_get(mpf_stream_direction_e direction);
</ins><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_defsh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -41,56 +41,58 @@
</span><span class="cx"> /** Deviation threshold is used to trigger drift in timestamps */
</span><span class="cx"> #define DEVIATION_THRESHOLD 4000
</span><span class="cx"> 
</span><del>-/** RTP receive history declaration */
</del><ins>+/** RTP receiver history declaration */
</ins><span class="cx"> typedef struct rtp_rx_history_t rtp_rx_history_t;
</span><del>-/** RTP receive periodic history declaration */
</del><ins>+/** RTP receiver periodic history declaration */
</ins><span class="cx"> typedef struct rtp_rx_periodic_history_t rtp_rx_periodic_history_t;
</span><span class="cx"> /** RTP receiver declaration */
</span><span class="cx"> typedef struct rtp_receiver_t rtp_receiver_t;
</span><span class="cx"> /** RTP transmitter declaration */
</span><span class="cx"> typedef struct rtp_transmitter_t rtp_transmitter_t;
</span><span class="cx"> 
</span><del>-/** History of RTP receive */
</del><ins>+/** History of RTP receiver */
</ins><span class="cx"> struct rtp_rx_history_t {
</span><del>-        /** Updated on every seq num wrap around*/
-        apr_uint32_t           seq_cycles;
</del><ins>+        /** Updated on every seq num wrap around */
+        apr_uint32_t seq_cycles;
</ins><span class="cx"> 
</span><span class="cx">         /** First seq num received */
</span><del>-        apr_uint16_t           seq_num_base;
</del><ins>+        apr_uint16_t seq_num_base;
</ins><span class="cx">         /** Max seq num received */
</span><del>-        apr_uint16_t           seq_num_max;
</del><ins>+        apr_uint16_t seq_num_max;
</ins><span class="cx"> 
</span><span class="cx">         /** Last timestamp received */
</span><del>-        apr_uint32_t           ts_last;
</del><ins>+        apr_uint32_t ts_last;
</ins><span class="cx">         /** Local time measured on last packet received */
</span><del>-        apr_time_t             time_last;
</del><ins>+        apr_time_t   time_last;
</ins><span class="cx"> 
</span><span class="cx">         /** New ssrc, which is in probation */
</span><del>-        apr_uint32_t           ssrc_new;
</del><ins>+        apr_uint32_t ssrc_new;
</ins><span class="cx">         /** Period of ssrc probation */
</span><del>-        apr_byte_t             ssrc_probation;
</del><ins>+        apr_byte_t   ssrc_probation;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-/** Periodic history of RTP receive (initialized after every N packets) */
</del><ins>+/** Periodic history of RTP receiver (initialized after every N packets) */
</ins><span class="cx"> struct rtp_rx_periodic_history_t {
</span><span class="cx">         /** Number of packets received */
</span><del>-        apr_uint32_t           received_prior;
</del><ins>+        apr_uint32_t received_prior;
+        /** Number of packets expected */
+        apr_uint32_t expected_prior;
</ins><span class="cx">         /** Number of packets discarded */
</span><del>-        apr_uint32_t           discarded_prior;
</del><ins>+        apr_uint32_t discarded_prior;
</ins><span class="cx"> 
</span><span class="cx">         /** Min jitter */
</span><del>-        apr_uint32_t           jitter_min;
</del><ins>+        apr_uint32_t jitter_min;
</ins><span class="cx">         /** Max jitter */
</span><del>-        apr_uint32_t           jitter_max;
</del><ins>+        apr_uint32_t jitter_max;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-/** Reset RTP receive history */
</del><ins>+/** Reset RTP receiver history */
</ins><span class="cx"> static APR_INLINE void mpf_rtp_rx_history_reset(rtp_rx_history_t *rx_history)
</span><span class="cx"> {
</span><span class="cx">         memset(rx_history,0,sizeof(rtp_rx_history_t));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Reset RTP receive periodic history */
</del><ins>+/** Reset RTP receiver periodic history */
</ins><span class="cx"> static APR_INLINE void mpf_rtp_rx_periodic_history_reset(rtp_rx_periodic_history_t *rx_periodic_history)
</span><span class="cx"> {
</span><span class="cx">         memset(rx_periodic_history,0,sizeof(rtp_rx_periodic_history_t));
</span><span class="lines">@@ -98,13 +100,12 @@
</span><span class="cx"> 
</span><span class="cx"> /** RTP receiver */
</span><span class="cx"> struct rtp_receiver_t {
</span><del>-        /** Payload type of named-event packets (RFC2833) */
-        apr_byte_t                event_pt;
-
</del><span class="cx">         /** Jitter buffer */
</span><span class="cx">         mpf_jitter_buffer_t      *jb;
</span><span class="cx"> 
</span><del>-        /** RTP receive statistics to report */
</del><ins>+        /** RTCP statistics used in RR */
+        rtcp_rr_stat_t            rr_stat;
+        /** RTP receiver statistics */
</ins><span class="cx">         rtp_rx_stat_t             stat;
</span><span class="cx">         /** RTP history */
</span><span class="cx">         rtp_rx_history_t          history;
</span><span class="lines">@@ -115,10 +116,6 @@
</span><span class="cx"> 
</span><span class="cx"> /** RTP transmitter */
</span><span class="cx"> struct rtp_transmitter_t {
</span><del>-        /** RTP stream ssrc */
-        apr_uint32_t    ssrc;
-        /** Payload type of named-event packets (RFC2833) */
-        apr_byte_t      event_pt;
</del><span class="cx">         /** Packetization time in msec */
</span><span class="cx">         apr_uint16_t    ptime;
</span><span class="cx"> 
</span><span class="lines">@@ -135,24 +132,25 @@
</span><span class="cx">         apr_uint16_t    last_seq_num;
</span><span class="cx">         /** Current timestamp (samples processed) */
</span><span class="cx">         apr_uint32_t    timestamp;
</span><ins>+        /** Event timestamp base */
+        apr_uint32_t    timestamp_base;
</ins><span class="cx"> 
</span><span class="cx">         /** RTP packet payload */
</span><span class="cx">         char           *packet_data;
</span><span class="cx">         /** RTP packet payload size */
</span><span class="cx">         apr_size_t      packet_size;
</span><span class="cx"> 
</span><del>-        /** RTP transmit statistics to report */
-        rtp_tx_stat_t   stat;
</del><ins>+        /** RTCP statistics used in SR */
+        rtcp_sr_stat_t  sr_stat;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> /** Initialize RTP receiver */
</span><span class="cx"> static APR_INLINE void rtp_receiver_init(rtp_receiver_t *receiver)
</span><span class="cx"> {
</span><del>-        receiver-&gt;event_pt = 0;
-
</del><span class="cx">         receiver-&gt;jb = NULL;
</span><span class="cx"> 
</span><ins>+        mpf_rtcp_rr_stat_reset(&amp;receiver-&gt;rr_stat);
</ins><span class="cx">         mpf_rtp_rx_stat_reset(&amp;receiver-&gt;stat);
</span><span class="cx">         mpf_rtp_rx_history_reset(&amp;receiver-&gt;history);
</span><span class="cx">         mpf_rtp_rx_periodic_history_reset(&amp;receiver-&gt;periodic_history);
</span><span class="lines">@@ -161,8 +159,6 @@
</span><span class="cx"> /** Initialize RTP transmitter */
</span><span class="cx"> static APR_INLINE void rtp_transmitter_init(rtp_transmitter_t *transmitter)
</span><span class="cx"> {
</span><del>-        transmitter-&gt;ssrc = 0;
-        transmitter-&gt;event_pt = 0;
</del><span class="cx">         transmitter-&gt;ptime = 0;
</span><span class="cx"> 
</span><span class="cx">         transmitter-&gt;packet_frames = 0;
</span><span class="lines">@@ -172,11 +168,12 @@
</span><span class="cx">         transmitter-&gt;inactivity = 0;
</span><span class="cx">         transmitter-&gt;last_seq_num = 0;
</span><span class="cx">         transmitter-&gt;timestamp = 0;
</span><ins>+        transmitter-&gt;timestamp_base = 0;
</ins><span class="cx"> 
</span><span class="cx">         transmitter-&gt;packet_data = NULL;
</span><span class="cx">         transmitter-&gt;packet_size = 0;
</span><span class="cx"> 
</span><del>-        mpf_rtp_tx_stat_reset(&amp;transmitter-&gt;stat);
</del><ins>+        mpf_rtcp_sr_stat_reset(&amp;transmitter-&gt;sr_stat);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_descriptorh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,9 +22,9 @@
</span><span class="cx">  * @brief MPF RTP Stream Descriptor
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &quot;mpf_stream_mode.h&quot;
-#include &quot;mpf_media_descriptor.h&quot;
-#include &quot;mpf_codec_descriptor.h&quot;
</del><ins>+#include &lt;apr_network_io.h&gt;
+#include &quot;apt_string.h&quot;
+#include &quot;mpf_stream_descriptor.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="lines">@@ -39,23 +39,38 @@
</span><span class="cx"> /** Jitter buffer configuration declaration */
</span><span class="cx"> typedef struct mpf_jb_config_t mpf_jb_config_t;
</span><span class="cx"> 
</span><ins>+/** MPF media state */
+typedef enum {
+        MPF_MEDIA_DISABLED, /**&lt; disabled media */
+        MPF_MEDIA_ENABLED   /**&lt; enabled media */
+} mpf_media_state_e;
</ins><span class="cx"> 
</span><span class="cx"> /** RTP media (local/remote) descriptor */
</span><span class="cx"> struct mpf_rtp_media_descriptor_t {
</span><del>-        /** Media descriptor base */
-        mpf_media_descriptor_t base;
</del><ins>+        /** Media state (disabled/enabled)*/
+        mpf_media_state_e      state;
+        /** Ip address */
+        apt_str_t              ip;
+        /** External (NAT) Ip address */
+        apt_str_t              ext_ip;
+        /** Port */
+        apr_port_t             port;
</ins><span class="cx">         /** Stream mode (send/receive) */
</span><del>-        mpf_stream_mode_e      mode;
</del><ins>+        mpf_stream_direction_e direction;
</ins><span class="cx">         /** Packetization time */
</span><span class="cx">         apr_uint16_t           ptime;
</span><span class="cx">         /** Codec list */
</span><span class="cx">         mpf_codec_list_t       codec_list;
</span><span class="cx">         /** Media identifier */
</span><span class="cx">         apr_size_t             mid;
</span><ins>+        /** Position, order in SDP message (0,1,...) */
+        apr_size_t             id;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** RTP stream descriptor */
</span><span class="cx"> struct mpf_rtp_stream_descriptor_t {
</span><ins>+        /** Stream capabilities */
+        mpf_stream_capabilities_t  *capabilities;
</ins><span class="cx">         /** Local media descriptor */
</span><span class="cx">         mpf_rtp_media_descriptor_t *local;
</span><span class="cx">         /** Remote media descriptor */
</span><span class="lines">@@ -82,43 +97,62 @@
</span><span class="cx">         apr_byte_t adaptive;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+typedef enum {
+        RTCP_BYE_DISABLE,       /**&lt; disable RTCP BYE transmission */
+        RTCP_BYE_PER_SESSION,   /**&lt; transmit RTCP BYE at the end of session */
+        RTCP_BYE_PER_TALKSPURT, /**&lt; transmit RTCP BYE at the end of each talkspurt (input) */
+} rtcp_bye_policy_e;
+
</ins><span class="cx"> /** RTP config */
</span><span class="cx"> struct mpf_rtp_config_t {
</span><span class="cx">         /** Local IP address to bind to */
</span><del>-        apt_str_t ip;
</del><ins>+        apt_str_t         ip;
</ins><span class="cx">         /** External (NAT) IP address */
</span><del>-        apt_str_t ext_ip;
</del><ins>+        apt_str_t         ext_ip;
</ins><span class="cx">         /** Min RTP port */
</span><del>-        apr_port_t rtp_port_min;
</del><ins>+        apr_port_t        rtp_port_min;
</ins><span class="cx">         /** Max RTP port */
</span><del>-        apr_port_t rtp_port_max;
</del><ins>+        apr_port_t        rtp_port_max;
</ins><span class="cx">         /** Current RTP port */
</span><del>-        apr_port_t rtp_port_cur;
</del><ins>+        apr_port_t        rtp_port_cur;
</ins><span class="cx">         /** Packetization time */
</span><del>-        apr_uint16_t ptime;
</del><ins>+        apr_uint16_t      ptime;
</ins><span class="cx">         /** Codec list */
</span><del>-        mpf_codec_list_t codec_list;
-        /** Preference in offer/anser: 1 - own(local) preference, 0 - remote preference */
-        apt_bool_t own_preferrence;
</del><ins>+        mpf_codec_list_t  codec_list;
+        /** Preference in offer/anwser: 1 - own(local) preference, 0 - remote preference */
+        apt_bool_t        own_preferrence;
+        /** Enable/disable RTCP support */
+        apt_bool_t        rtcp;
+        /** RTCP BYE policy */
+        rtcp_bye_policy_e rtcp_bye_policy;
+        /** RTCP report transmission interval */
+        apr_uint16_t      rtcp_tx_interval;
+        /** RTCP rx resolution (timeout to check for a new RTCP message) */
+        apr_uint16_t      rtcp_rx_resolution;
</ins><span class="cx">         /** Jitter buffer config */
</span><del>-        mpf_jb_config_t jb_config;
</del><ins>+        mpf_jb_config_t   jb_config;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Initialize media descriptor */
</span><span class="cx"> static APR_INLINE void mpf_rtp_media_descriptor_init(mpf_rtp_media_descriptor_t *media)
</span><span class="cx"> {
</span><del>-        mpf_media_descriptor_init(&amp;media-&gt;base);
-        media-&gt;mode = STREAM_MODE_NONE;
</del><ins>+        media-&gt;state = MPF_MEDIA_DISABLED;
+        apt_string_reset(&amp;media-&gt;ip);
+        apt_string_reset(&amp;media-&gt;ext_ip);
+        media-&gt;port = 0;
+        media-&gt;direction = STREAM_DIRECTION_NONE;
</ins><span class="cx">         media-&gt;ptime = 0;
</span><span class="cx">         mpf_codec_list_reset(&amp;media-&gt;codec_list);
</span><span class="cx">         media-&gt;mid = 0;
</span><ins>+        media-&gt;id = 0;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Initialize stream descriptor */
</span><del>-static APR_INLINE void mpf_rtp_stream_descriptor_init(mpf_rtp_stream_descriptor_t *stream)
</del><ins>+static APR_INLINE void mpf_rtp_stream_descriptor_init(mpf_rtp_stream_descriptor_t *descriptor)
</ins><span class="cx"> {
</span><del>-        stream-&gt;local = NULL;
-        stream-&gt;remote = NULL;
</del><ins>+        descriptor-&gt;capabilities = NULL;
+        descriptor-&gt;local = NULL;
+        descriptor-&gt;remote = NULL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Initialize RTP termination descriptor */
</span><span class="lines">@@ -149,7 +183,12 @@
</span><span class="cx">         rtp_config-&gt;ptime = 0;
</span><span class="cx">         mpf_codec_list_init(&amp;rtp_config-&gt;codec_list,0,pool);
</span><span class="cx">         rtp_config-&gt;own_preferrence = FALSE;
</span><ins>+        rtp_config-&gt;rtcp = FALSE;
+        rtp_config-&gt;rtcp_bye_policy = RTCP_BYE_DISABLE;
+        rtp_config-&gt;rtcp_tx_interval = 0;
+        rtp_config-&gt;rtcp_rx_resolution = 0;
</ins><span class="cx">         mpf_jb_config_init(&amp;rtp_config-&gt;jb_config);
</span><ins>+
</ins><span class="cx">         return rtp_config;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_headerh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -26,7 +26,7 @@
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** Protocol version. */
</del><ins>+/** Protocol version */
</ins><span class="cx"> #define RTP_VERSION 2
</span><span class="cx"> 
</span><span class="cx"> /** RTP header declaration */
</span><span class="lines">@@ -74,8 +74,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** RTP extension header */
</span><del>-struct rtp_extension_header_t
-{
</del><ins>+struct rtp_extension_header_t {
</ins><span class="cx">         /** profile */
</span><span class="cx">         apr_uint16_t profile;
</span><span class="cx">         /** length */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_pth"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,44 @@
</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_RTP_PT_H__
+#define __MPF_RTP_PT_H__
+
+/**
+ * @file mpf_rtp_pt.h
+ * @brief RTP Payload Types (RFC3551)
+ */ 
+
+#include &quot;mpf.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** RTP payload types */
+typedef enum {
+        RTP_PT_PCMU        =  0, /**&lt; PCMU          Audio 8kHz 1  */
+        RTP_PT_PCMA        =  8, /**&lt; PCMA          Audio 8kHz 1  */
+
+        RTP_PT_CN          =  13, /**&lt; Comfort Noise Audio 8kHz 1  */
+
+        RTP_PT_DYNAMIC     =  96, /**&lt; Start of dynamic payload types */
+        RTP_PT_DYNAMIC_MAX = 127, /**&lt; End of dynamic payload types  */
+
+        RTP_PT_UNKNOWN     = 128  /**&lt; Unknown (invalid) payload type */
+} mpf_rtp_pt_e;
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_RTP_PT_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_stath"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -19,60 +19,90 @@
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * @file mpf_rtp_stat.h
</span><del>- * @brief RTP Statistics
</del><ins>+ * @brief RTP/RTCP Statistics
</ins><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf.h&quot;
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** RTP transmit statistics declaration */
-typedef struct rtp_tx_stat_t rtp_tx_stat_t;
-/** RTP receive statistics declaration */
</del><ins>+/** RTP receiver statistics */
</ins><span class="cx"> typedef struct rtp_rx_stat_t rtp_rx_stat_t;
</span><span class="cx"> 
</span><ins>+/** RTCP statistics used in Sender Report (SR) */
+typedef struct rtcp_sr_stat_t rtcp_sr_stat_t;
+/** RTCP statistics used in Receiver Report (RR) */
+typedef struct rtcp_rr_stat_t rtcp_rr_stat_t;
</ins><span class="cx"> 
</span><del>-/** RTP transmit statistics */
-struct rtp_tx_stat_t {
-        /** number of RTP packets received */
-        apr_uint32_t    sent_packets;
</del><span class="cx"> 
</span><del>-        /* more to come */
-};
-
-/** RTP receive statistics */
</del><ins>+/** RTP receiver statistics */
</ins><span class="cx"> struct rtp_rx_stat_t {
</span><span class="cx">         /** number of valid RTP packets received */
</span><del>-        apr_uint32_t           received_packets;
</del><ins>+        apr_uint32_t received_packets;
</ins><span class="cx">         /** number of invalid RTP packets received */
</span><del>-        apr_uint32_t           invalid_packets;
</del><ins>+        apr_uint32_t invalid_packets;
</ins><span class="cx"> 
</span><span class="cx">         /** number of discarded in jitter buffer packets */
</span><del>-        apr_uint32_t           discarded_packets;
</del><ins>+        apr_uint32_t discarded_packets;
</ins><span class="cx">         /** number of ignored packets */
</span><del>-        apr_uint32_t           ignored_packets;
</del><ins>+        apr_uint32_t ignored_packets;
</ins><span class="cx"> 
</span><span class="cx">         /** number of lost in network packets */
</span><del>-        apr_uint32_t           lost_packets;
</del><ins>+        apr_uint32_t lost_packets;
</ins><span class="cx"> 
</span><span class="cx">         /** number of restarts */
</span><del>-        apr_byte_t             restarts;
</del><ins>+        apr_byte_t   restarts;
+};
</ins><span class="cx"> 
</span><del>-        /** network jitter (rfc3550) */
-        apr_uint32_t           jitter;
</del><ins>+/** RTCP statistics used in Sender Report (SR)  */
+struct rtcp_sr_stat_t {
+        /** sender source identifier */
+        apr_uint32_t ssrc;
+        /** NTP timestamp (seconds) */
+        apr_uint32_t ntp_sec;
+        /** NTP timestamp (fractions) */
+        apr_uint32_t ntp_frac;
+        /** RTP timestamp */
+        apr_uint32_t rtp_ts;
+        /* packets sent */
+        apr_uint32_t sent_packets;
+        /* octets (bytes) sent */
+        apr_uint32_t sent_octets;
+};
</ins><span class="cx"> 
</span><del>-        /** source id of received RTP stream */
-        apr_uint32_t           ssrc;
</del><ins>+/** RTCP statistics used in Receiver Report (RR) */
+struct rtcp_rr_stat_t {
+        /** source identifier of RTP stream being received */
+        apr_uint32_t ssrc;
+        /** fraction lost since last SR/RR */
+        apr_uint32_t fraction:8;
+        /** cumulative number of packets lost (signed!) */
+        apr_int32_t  lost:24;
+        /** extended last sequence number received */
+        apr_uint32_t last_seq;
+        /** interarrival jitter (RFC3550) */
+        apr_uint32_t jitter;
+        /** last SR packet from this source */
+        apr_uint32_t lsr;
+        /** delay since last SR packet */
+        apr_uint32_t dlsr;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-/** Reset RTP transmit statistics */
-static APR_INLINE void mpf_rtp_tx_stat_reset(rtp_tx_stat_t *tx_stat)
</del><ins>+
+/** Reset RTCP SR statistics */
+static APR_INLINE void mpf_rtcp_sr_stat_reset(rtcp_sr_stat_t *sr_stat)
</ins><span class="cx"> {
</span><del>-        memset(tx_stat,0,sizeof(rtp_tx_stat_t));
</del><ins>+        memset(sr_stat,0,sizeof(rtcp_sr_stat_t));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Reset RTP receive statistics */
</del><ins>+/** Reset RTCP RR statistics */
+static APR_INLINE void mpf_rtcp_rr_stat_reset(rtcp_rr_stat_t *rr_stat)
+{
+        memset(rr_stat,0,sizeof(rtcp_rr_stat_t));
+}
+
+/** Reset RTP receiver statistics */
</ins><span class="cx"> static APR_INLINE void mpf_rtp_rx_stat_reset(rtp_rx_stat_t *rx_stat)
</span><span class="cx"> {
</span><span class="cx">         memset(rx_stat,0,sizeof(rtp_rx_stat_t));
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_streamh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -36,6 +36,18 @@
</span><span class="cx"> MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termination, mpf_rtp_config_t *config, apr_pool_t *pool);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Add/enable RTP stream.
+ * @param stream RTP stream to add
+ */
+MPF_DECLARE(apt_bool_t) mpf_rtp_stream_add(mpf_audio_stream_t *stream);
+
+/**
+ * Subtract/disable RTP stream.
+ * @param stream RTP stream to subtract
+ */
+MPF_DECLARE(apt_bool_t) mpf_rtp_stream_remove(mpf_audio_stream_t *stream);
+
+/**
</ins><span class="cx">  * Modify RTP stream.
</span><span class="cx">  * @param stream RTP stream to modify
</span><span class="cx">  * @param descriptor the descriptor to modify stream according
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_rtp_termination_factoryh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,8 +22,7 @@
</span><span class="cx">  * @brief MPF RTP Termination Factory
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &lt;apr_network_io.h&gt;
-#include &quot;mpf_types.h&quot;
</del><ins>+#include &quot;mpf_termination_factory.h&quot;
</ins><span class="cx"> #include &quot;mpf_rtp_descriptor.h&quot;
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_schedulerh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_scheduler.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_scheduler.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_scheduler.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,61 @@
</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_SCHEDULER_H__
+#define __MPF_SCHEDULER_H__
+
+/**
+ * @file mpf_scheduler.h
+ * @brief MPF Scheduler (High Resolution Clock for Media Processing and Timer)
+ */ 
+
+#include &quot;mpf_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Prototype of scheduler callback */
+typedef void (*mpf_scheduler_proc_f)(mpf_scheduler_t *scheduler, void *obj);
+
+/** Create scheduler */
+MPF_DECLARE(mpf_scheduler_t*) mpf_scheduler_create(unsigned long rate, apr_pool_t *pool);
+
+/** Destroy scheduler */
+MPF_DECLARE(void) mpf_scheduler_destroy(mpf_scheduler_t *scheduler);
+
+/** Set media processing clock */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_media_clock_set(
+                                                                mpf_scheduler_t *scheduler,
+                                                                unsigned long resolution,
+                                                                mpf_scheduler_proc_f proc,
+                                                                void *obj);
+
+/** Set timer clock */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_timer_clock_set(
+                                                                mpf_scheduler_t *scheduler,
+                                                                unsigned long resolution,
+                                                                mpf_scheduler_proc_f proc,
+                                                                void *obj);
+
+/** Start scheduler */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_start(mpf_scheduler_t *scheduler);
+
+/** Stop scheduler */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_stop(mpf_scheduler_t *scheduler);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_SCHEDULER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_streamh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,13 +23,14 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_types.h&quot;
</span><del>-#include &quot;mpf_stream_mode.h&quot;
</del><span class="cx"> #include &quot;mpf_frame.h&quot;
</span><ins>+#include &quot;mpf_stream_descriptor.h&quot;
</ins><span class="cx"> #include &quot;mpf_codec.h&quot;
</span><ins>+#include &quot;apt_text_stream.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** Opaque audio stream virtual table declaration */
</del><ins>+/** Declaration of virtual table of audio stream */
</ins><span class="cx"> typedef struct mpf_audio_stream_vtable_t mpf_audio_stream_vtable_t;
</span><span class="cx"> 
</span><span class="cx"> /** Audio stream */
</span><span class="lines">@@ -40,20 +41,28 @@
</span><span class="cx">         const mpf_audio_stream_vtable_t *vtable;
</span><span class="cx">         /** Back pointer */
</span><span class="cx">         mpf_termination_t               *termination;
</span><del>-        /** Stream mode (send/receive) */
-        mpf_stream_mode_e                mode;
-        /** Receive codec */
-        mpf_codec_t                     *rx_codec;
-        /** Transmit codec */
-        mpf_codec_t                     *tx_codec;
</del><ins>+
+        /** Stream capabilities */
+        const mpf_stream_capabilities_t *capabilities;
+
+        /** Stream direction send/receive (bitmask of mpf_stream_direction_e) */
+        mpf_stream_direction_e           direction;
+        /** Rx codec descriptor */
+        mpf_codec_descriptor_t          *rx_descriptor;
+        /** Rx event descriptor */
+        mpf_codec_descriptor_t          *rx_event_descriptor;
+        /** Tx codec descriptor */
+        mpf_codec_descriptor_t          *tx_descriptor;
+        /** Tx event descriptor */
+        mpf_codec_descriptor_t          *tx_event_descriptor;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Video stream */
</span><span class="cx"> struct mpf_video_stream_t {
</span><span class="cx">         /** Back pointer */
</span><span class="cx">         mpf_termination_t               *termination;
</span><del>-        /** Stream mode (send/receive) */
-        mpf_stream_mode_e                mode;
</del><ins>+        /** Stream direction send/receive (bitmask of mpf_stream_direction_e) */
+        mpf_stream_direction_e           direction;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Table of audio stream virtual methods */
</span><span class="lines">@@ -62,34 +71,40 @@
</span><span class="cx">         apt_bool_t (*destroy)(mpf_audio_stream_t *stream);
</span><span class="cx"> 
</span><span class="cx">         /** Virtual open receiver method */
</span><del>-        apt_bool_t (*open_rx)(mpf_audio_stream_t *stream);
</del><ins>+        apt_bool_t (*open_rx)(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx">         /** Virtual close receiver method */
</span><span class="cx">         apt_bool_t (*close_rx)(mpf_audio_stream_t *stream);
</span><span class="cx">         /** Virtual read frame method */
</span><span class="cx">         apt_bool_t (*read_frame)(mpf_audio_stream_t *stream, mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="cx">         /** Virtual open transmitter method */
</span><del>-        apt_bool_t (*open_tx)(mpf_audio_stream_t *stream);
</del><ins>+        apt_bool_t (*open_tx)(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx">         /** Virtual close transmitter method */
</span><span class="cx">         apt_bool_t (*close_tx)(mpf_audio_stream_t *stream);
</span><span class="cx">         /** Virtual write frame method */
</span><span class="cx">         apt_bool_t (*write_frame)(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
</span><ins>+
+        /** Virtual trace method */
+        void (*trace)(mpf_audio_stream_t *stream, mpf_stream_direction_e direction, apt_text_stream_t *output);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> /** Create audio stream */
</span><del>-static APR_INLINE mpf_audio_stream_t* mpf_audio_stream_create(void *obj, const mpf_audio_stream_vtable_t *vtable, mpf_stream_mode_e mode, apr_pool_t *pool)
-{
-        mpf_audio_stream_t *stream = (mpf_audio_stream_t*)apr_palloc(pool,sizeof(mpf_audio_stream_t));
-        stream-&gt;obj = obj;
-        stream-&gt;vtable = vtable;
-        stream-&gt;termination = NULL;
-        stream-&gt;mode = mode;
-        stream-&gt;rx_codec = NULL;
-        stream-&gt;tx_codec = NULL;
-        return stream;
-}
</del><ins>+MPF_DECLARE(mpf_audio_stream_t*) mpf_audio_stream_create(void *obj, const mpf_audio_stream_vtable_t *vtable, const mpf_stream_capabilities_t *capabilities, apr_pool_t *pool);
</ins><span class="cx"> 
</span><ins>+/** Validate audio stream receiver */
+MPF_DECLARE(apt_bool_t) mpf_audio_stream_rx_validate(
+                                                        mpf_audio_stream_t *stream,
+                                                        const mpf_codec_descriptor_t *descriptor,
+                                                        const mpf_codec_descriptor_t *event_descriptor,
+                                                        apr_pool_t *pool);
+
+/** Validate audio stream transmitter */
+MPF_DECLARE(apt_bool_t) mpf_audio_stream_tx_validate(
+                                                        mpf_audio_stream_t *stream, 
+                                                        const mpf_codec_descriptor_t *descriptor, 
+                                                        const mpf_codec_descriptor_t *event_descriptor, 
+                                                        apr_pool_t *pool);
+
</ins><span class="cx"> /** Destroy audio stream */
</span><span class="cx"> static APR_INLINE apt_bool_t mpf_audio_stream_destroy(mpf_audio_stream_t *stream)
</span><span class="cx"> {
</span><span class="lines">@@ -98,15 +113,15 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Open audio stream receive */
-static APR_INLINE apt_bool_t mpf_audio_stream_rx_open(mpf_audio_stream_t *stream)
</del><ins>+/** Open audio stream receiver */
+static APR_INLINE apt_bool_t mpf_audio_stream_rx_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         if(stream-&gt;vtable-&gt;open_rx)
</span><del>-                return stream-&gt;vtable-&gt;open_rx(stream);
</del><ins>+                return stream-&gt;vtable-&gt;open_rx(stream,codec);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Close audio stream receive */
</del><ins>+/** Close audio stream receiver */
</ins><span class="cx"> static APR_INLINE apt_bool_t mpf_audio_stream_rx_close(mpf_audio_stream_t *stream)
</span><span class="cx"> {
</span><span class="cx">         if(stream-&gt;vtable-&gt;close_rx)
</span><span class="lines">@@ -122,15 +137,15 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Open audio stream transmit */
-static APR_INLINE apt_bool_t mpf_audio_stream_tx_open(mpf_audio_stream_t *stream)
</del><ins>+/** Open audio stream transmitter */
+static APR_INLINE apt_bool_t mpf_audio_stream_tx_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         if(stream-&gt;vtable-&gt;open_tx)
</span><del>-                return stream-&gt;vtable-&gt;open_tx(stream);
</del><ins>+                return stream-&gt;vtable-&gt;open_tx(stream,codec);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Close audio stream transmit */
</del><ins>+/** Close audio stream transmitter */
</ins><span class="cx"> static APR_INLINE apt_bool_t mpf_audio_stream_tx_close(mpf_audio_stream_t *stream)
</span><span class="cx"> {
</span><span class="cx">         if(stream-&gt;vtable-&gt;close_tx)
</span><span class="lines">@@ -146,6 +161,9 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Trace media path */
+MPF_DECLARE(void) mpf_audio_stream_trace(mpf_audio_stream_t *stream, mpf_stream_direction_e direction, apt_text_stream_t *output);
+
</ins><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_STREAM_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_stream_descriptorh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,88 @@
</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_STREAM_DESCRIPTOR_H__
+#define __MPF_STREAM_DESCRIPTOR_H__
+
+/**
+ * @file mpf_stream_descriptor.h
+ * @brief MPF Stream Descriptor
+ */ 
+
+#include &quot;mpf_codec_descriptor.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Stream capabilities declaration */
+typedef struct mpf_stream_capabilities_t mpf_stream_capabilities_t;
+
+/** Stream directions (none, send, receive, duplex) */
+typedef enum {
+        STREAM_DIRECTION_NONE    = 0x0, /**&lt; none */
+        STREAM_DIRECTION_SEND    = 0x1, /**&lt; send (sink) */
+        STREAM_DIRECTION_RECEIVE = 0x2, /**&lt; receive (source) */
+
+        STREAM_DIRECTION_DUPLEX  = STREAM_DIRECTION_SEND | STREAM_DIRECTION_RECEIVE /**&lt; duplex */
+} mpf_stream_direction_e; 
+
+
+/** Stream capabilities */
+struct mpf_stream_capabilities_t {
+        /** Supported directions either send, receive or bidirectional stream (bitmask of mpf_stream_direction_e) */
+        mpf_stream_direction_e   direction;
+        /** Codec capabilities (supported codecs and named events) */
+        mpf_codec_capabilities_t codecs;
+};
+
+/** Create stream capabilities */
+MPF_DECLARE(mpf_stream_capabilities_t*) mpf_stream_capabilities_create(mpf_stream_direction_e directions, apr_pool_t *pool);
+
+/** Create source stream capabilities */
+static APR_INLINE mpf_stream_capabilities_t* mpf_source_stream_capabilities_create(apr_pool_t *pool)
+{
+        return mpf_stream_capabilities_create(STREAM_DIRECTION_RECEIVE,pool);
+}
+
+/** Create sink stream capabilities */
+static APR_INLINE mpf_stream_capabilities_t* mpf_sink_stream_capabilities_create(apr_pool_t *pool)
+{
+        return mpf_stream_capabilities_create(STREAM_DIRECTION_SEND,pool);
+}
+
+/** Clone stream capabilities */
+MPF_DECLARE(mpf_stream_capabilities_t*) mpf_stream_capabilities_clone(const mpf_stream_capabilities_t *src_capabilities, apr_pool_t *pool);
+
+/** Merge stream capabilities */
+MPF_DECLARE(apt_bool_t) mpf_stream_capabilities_merge(mpf_stream_capabilities_t *capabilities, const mpf_stream_capabilities_t *src_capabilities, apr_pool_t *pool);
+
+
+/** Get reverse direction */
+static APR_INLINE mpf_stream_direction_e mpf_stream_reverse_direction_get(mpf_stream_direction_e direction)
+{
+        mpf_stream_direction_e rev_direction = direction;
+        if(rev_direction == STREAM_DIRECTION_SEND) {
+                rev_direction = STREAM_DIRECTION_RECEIVE;
+        }
+        else if(rev_direction == STREAM_DIRECTION_RECEIVE) {
+                rev_direction = STREAM_DIRECTION_SEND;
+        }
+        return rev_direction;
+}
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_STREAM_DESCRIPTOR_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_stream_modeh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_stream_mode.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_terminationh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -29,6 +29,23 @@
</span><span class="cx"> /** Prototype of termination event handler */
</span><span class="cx"> typedef apt_bool_t (*mpf_termination_event_handler_f)(mpf_termination_t *termination, int event_id, void *descriptor);
</span><span class="cx"> 
</span><ins>+/** Termination vtable declaration */
+typedef struct mpf_termination_vtable_t mpf_termination_vtable_t;
+
+/** Table of termination virtual methods */
+struct mpf_termination_vtable_t {
+        /** Virtual termination destroy method */
+        apt_bool_t (*destroy)(mpf_termination_t *termination);
+
+        /** Virtual termination add method */
+        apt_bool_t (*add)(mpf_termination_t *termination, void *descriptor);
+        /** Virtual termination modify method */
+        apt_bool_t (*modify)(mpf_termination_t *termination, void *descriptor);
+        /** Virtual termination subtract method */
+        apt_bool_t (*subtract)(mpf_termination_t *termination);
+};
+
+
</ins><span class="cx"> /** MPF Termination */
</span><span class="cx"> struct mpf_termination_t {
</span><span class="cx">         /** Pool to allocate memory from */
</span><span class="lines">@@ -41,6 +58,8 @@
</span><span class="cx">         mpf_termination_event_handler_f event_handler;
</span><span class="cx">         /** Codec manager */
</span><span class="cx">         const mpf_codec_manager_t      *codec_manager;
</span><ins>+        /** Timer manager */
+        mpf_timer_manager_t            *timer_manager;
</ins><span class="cx">         /** Termination factory entire termination created by */
</span><span class="cx">         mpf_termination_factory_t      *termination_factory;
</span><span class="cx">         /** Table of virtual methods */
</span><span class="lines">@@ -54,15 +73,6 @@
</span><span class="cx">         mpf_video_stream_t             *video_stream;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-/** MPF termination factory */
-struct mpf_termination_factory_t {
-        /** Virtual create */
-        mpf_termination_t* (*create_termination)(mpf_termination_factory_t *factory, void *obj, apr_pool_t *pool);
-
-        /* more to add */
-};
-
-
</del><span class="cx"> /**
</span><span class="cx">  * Create MPF termination base.
</span><span class="cx">  * @param termination_factory the termination factory
</span><span class="lines">@@ -81,6 +91,13 @@
</span><span class="cx">                                                                                 apr_pool_t *pool);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Add MPF termination.
+ * @param termination the termination to add
+ * @param descriptor the termination specific descriptor
+ */
+MPF_DECLARE(apt_bool_t) mpf_termination_add(mpf_termination_t *termination, void *descriptor);
+
+/**
</ins><span class="cx">  * Modify MPF termination.
</span><span class="cx">  * @param termination the termination to modify
</span><span class="cx">  * @param descriptor the termination specific descriptor
</span><span class="lines">@@ -88,48 +105,12 @@
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_termination_modify(mpf_termination_t *termination, void *descriptor);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Validate MPF termination.
- * @param termination the termination to validate
</del><ins>+ * Subtract MPF termination.
+ * @param termination the termination to subtract
</ins><span class="cx">  */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_termination_validate(mpf_termination_t *termination);
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_termination_subtract(mpf_termination_t *termination);
</ins><span class="cx"> 
</span><del>-/**
- * Destroy MPF termination.
- * @param termination the termination to destroy
- */
-MPF_DECLARE(apt_bool_t) mpf_termination_destroy(mpf_termination_t *termination);
</del><span class="cx"> 
</span><del>-/**
- * Get associated object.
- * @param termination the termination to get object from
- */
-MPF_DECLARE(void*) mpf_termination_object_get(mpf_termination_t *termination);
-
-
-/**
- * Create MPF termination by termination factory.
- * @param termination_factory the termination factory to create termination from
- * @param obj the external object associated with termination
- * @param pool the pool to allocate memory from
- */
-MPF_DECLARE(mpf_termination_t*) mpf_termination_create(
-                                                                                mpf_termination_factory_t *termination_factory,
-                                                                                void *obj,
-                                                                                apr_pool_t *pool);
-
-/**
- * Create raw MPF termination.
- * @param obj the external object associated with termination
- * @param audio_stream the audio stream of the termination
- * @param video_stream the video stream of the termination
- * @param pool the pool to allocate memory from
- */
-MPF_DECLARE(mpf_termination_t*) mpf_raw_termination_create(
-                                                                                void *obj,
-                                                                                mpf_audio_stream_t *audio_stream, 
-                                                                                mpf_video_stream_t *video_stream, 
-                                                                                apr_pool_t *pool);
-
</del><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_TERMINATION_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_termination_factoryh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,88 @@
</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_TERMINATION_FACTORY_H__
+#define __MPF_TERMINATION_FACTORY_H__
+
+/**
+ * @file mpf_termination_factory.h
+ * @brief MPF Termination Factory
+ */ 
+
+#include &quot;mpf_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** MPF termination factory */
+struct mpf_termination_factory_t {
+        /** Virtual create */
+        mpf_termination_t* (*create_termination)(mpf_termination_factory_t *factory, void *obj, apr_pool_t *pool);
+};
+
+
+
+/**
+ * Create MPF termination from termination factory.
+ * @param termination_factory the termination factory to create termination from
+ * @param obj the external object associated with termination
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_termination_t*) mpf_termination_create(
+                                                                                mpf_termination_factory_t *termination_factory,
+                                                                                void *obj,
+                                                                                apr_pool_t *pool);
+
+/**
+ * Create raw MPF termination.
+ * @param obj the external object associated with termination
+ * @param audio_stream the audio stream of the termination
+ * @param video_stream the video stream of the termination
+ * @param pool the pool to allocate memory from
+ */
+MPF_DECLARE(mpf_termination_t*) mpf_raw_termination_create(
+                                                                                void *obj,
+                                                                                mpf_audio_stream_t *audio_stream, 
+                                                                                mpf_video_stream_t *video_stream, 
+                                                                                apr_pool_t *pool);
+
+/**
+ * Destroy MPF termination.
+ * @param termination the termination to destroy
+ */
+MPF_DECLARE(apt_bool_t) mpf_termination_destroy(mpf_termination_t *termination);
+
+/**
+ * Get associated object.
+ * @param termination the termination to get object from
+ */
+MPF_DECLARE(void*) mpf_termination_object_get(mpf_termination_t *termination);
+
+/**
+ * Get audio stream.
+ * @param termination the termination to get audio stream from
+ */
+MPF_DECLARE(mpf_audio_stream_t*) mpf_termination_audio_stream_get(mpf_termination_t *termination);
+
+/**
+ * Get video stream.
+ * @param termination the termination to get video stream from
+ */
+MPF_DECLARE(mpf_video_stream_t*) mpf_termination_video_stream_get(mpf_termination_t *termination);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_TERMINATION_FACTORY_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_timerh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_timer.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_timer_managerh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,53 @@
</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_TIMER_MANAGER_H__
+#define __MPF_TIMER_MANAGER_H__
+
+/**
+ * @file mpf_timer_manager.h
+ * @brief MPF Timer Management
+ */ 
+
+#include &quot;mpf_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+
+/** Prototype of timer callback */
+typedef void (*mpf_timer_proc_f)(mpf_timer_t *timer, void *obj);
+
+
+/** Create timer manager */
+MPF_DECLARE(mpf_timer_manager_t*) mpf_timer_manager_create(mpf_scheduler_t *scheduler, apr_pool_t *pool);
+
+/** Destroy timer manager */
+MPF_DECLARE(void) mpf_timer_manager_destroy(mpf_timer_manager_t *timer_manager);
+
+
+/** Create timer */
+MPF_DECLARE(mpf_timer_t*) mpf_timer_create(mpf_timer_manager_t *timer_manager, mpf_timer_proc_f proc, void *obj, apr_pool_t *pool);
+
+/** Set one-shot timer */
+MPF_DECLARE(apt_bool_t) mpf_timer_set(mpf_timer_t *timer, apr_uint32_t timeout);
+
+/** Kill timer */
+MPF_DECLARE(apt_bool_t) mpf_timer_kill(mpf_timer_t *timer);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MPF_TIMER_MANAGER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_typesh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_types.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_types.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_types.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -29,9 +29,18 @@
</span><span class="cx"> /** Opaque MPF engine declaration */
</span><span class="cx"> typedef struct mpf_engine_t mpf_engine_t;
</span><span class="cx"> 
</span><ins>+/** Opaque MPF scheduler declaration */
+typedef struct mpf_scheduler_t mpf_scheduler_t;
+
</ins><span class="cx"> /** Opaque codec manager declaration */
</span><span class="cx"> typedef struct mpf_codec_manager_t mpf_codec_manager_t;
</span><span class="cx"> 
</span><ins>+/** Opaque MPF timer manager declaration */
+typedef struct mpf_timer_manager_t mpf_timer_manager_t;
+
+/** Opaque MPF timer declaration */
+typedef struct mpf_timer_t mpf_timer_t;
+
</ins><span class="cx"> /** Opaque MPF context declaration */
</span><span class="cx"> typedef struct mpf_context_t mpf_context_t;
</span><span class="cx"> 
</span><span class="lines">@@ -47,17 +56,7 @@
</span><span class="cx"> /** Opaque MPF video stream declaration */
</span><span class="cx"> typedef struct mpf_video_stream_t mpf_video_stream_t;
</span><span class="cx"> 
</span><del>-/** Termination vtable declaration */
-typedef struct mpf_termination_vtable_t mpf_termination_vtable_t;
</del><span class="cx"> 
</span><del>-/** Table of termination virtual methods */
-struct mpf_termination_vtable_t {
-        /** Virtual termination destroy method */
-        apt_bool_t (*destroy)(mpf_termination_t *termination);
-        /** Virtual termination modify method */
-        apt_bool_t (*modify)(mpf_termination_t *termination, void *descriptor);
-};
-
</del><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MPF_TYPES_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfincludempf_userh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mpf/include/mpf_user.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmpfmpfvcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/mpf.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -192,6 +192,14 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\include\mpf_dtmf_detector.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mpf_dtmf_generator.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mpf_encoder.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="lines">@@ -216,18 +224,34 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mpf_media_descriptor.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mpf_message.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mpf_message.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mpf_mixer.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\include\mpf_multiplier.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mpf_named_event.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mpf_object.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\include\mpf_resampler.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mpf_rtcp_packet.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mpf_rtp_attribs.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="lines">@@ -244,6 +268,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_rtp_pt.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mpf_rtp_stat.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="lines">@@ -256,11 +284,15 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\include\mpf_scheduler.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mpf_stream.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mpf_stream_mode.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mpf_stream_descriptor.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><span class="lines">@@ -268,15 +300,15 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mpf_timer.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mpf_termination_factory.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mpf_types.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mpf_timer_manager.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mpf_user.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mpf_types.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                 &lt;/Filter&gt;
</span><span class="lines">@@ -325,6 +357,14 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\src\mpf_dtmf_detector.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mpf_dtmf_generator.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\src\mpf_encoder.c&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="lines">@@ -345,6 +385,22 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\src\mpf_mixer.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mpf_multiplier.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mpf_named_event.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mpf_resampler.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\src\mpf_rtp_attribs.c&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="lines">@@ -357,13 +413,25 @@
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\src\mpf_scheduler.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mpf_stream.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\src\mpf_termination.c&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\src\mpf_timer.c&quot;
</del><ins>+                                RelativePath=&quot;.\src\mpf_termination_factory.c&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><ins>+                        &lt;File
+                                RelativePath=&quot;.\src\mpf_timer_manager.c&quot;
+                                &gt;
+                        &lt;/File&gt;
</ins><span class="cx">                 &lt;/Filter&gt;
</span><span class="cx">         &lt;/Files&gt;
</span><span class="cx">         &lt;Globals&gt;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_activity_detectorc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -28,17 +28,19 @@
</span><span class="cx"> /** Activity detector */
</span><span class="cx"> struct mpf_activity_detector_t {
</span><span class="cx">         /* voice activity (silence) level threshold */
</span><del>-        apr_size_t level_threshold;
</del><ins>+        apr_size_t           level_threshold;
</ins><span class="cx"> 
</span><del>-        /* period of activity/inactivity required to complete/raise an event */
-        apr_size_t complete_timeout;
</del><ins>+        /* period of activity required to complete transition to active state */
+        apr_size_t           speech_timeout;
+        /* period of inactivity required to complete transition to inactive state */
+        apr_size_t           silence_timeout;
</ins><span class="cx">         /* noinput timeout */
</span><del>-        apr_size_t noinput_timeout;
</del><ins>+        apr_size_t           noinput_timeout;
</ins><span class="cx"> 
</span><span class="cx">         /* current state */
</span><del>-        apt_bool_t state;
</del><ins>+        mpf_detector_state_e state;
</ins><span class="cx">         /* duration spent in current state  */
</span><del>-        apr_size_t duration;
</del><ins>+        apr_size_t           duration;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Create activity detector */
</span><span class="lines">@@ -46,7 +48,8 @@
</span><span class="cx"> {
</span><span class="cx">         mpf_activity_detector_t *detector = apr_palloc(pool,sizeof(mpf_activity_detector_t));
</span><span class="cx">         detector-&gt;level_threshold = 2; /* 0 .. 255 */
</span><del>-        detector-&gt;complete_timeout = 300; /* 0.3 s */
</del><ins>+        detector-&gt;speech_timeout = 300; /* 0.3 s */
+        detector-&gt;silence_timeout = 300; /* 0.3 s */
</ins><span class="cx">         detector-&gt;noinput_timeout = 5000; /* 5 s */
</span><span class="cx">         detector-&gt;duration = 0;
</span><span class="cx">         detector-&gt;state = DETECTOR_STATE_INACTIVITY;
</span><span class="lines">@@ -72,13 +75,19 @@
</span><span class="cx">         detector-&gt;noinput_timeout = noinput_timeout;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Set transition complete timeout */
-MPF_DECLARE(void) mpf_activity_detector_complete_timeout_set(mpf_activity_detector_t *detector, apr_size_t complete_timeout)
</del><ins>+/** Set timeout required to trigger speech (transition from inactive to active state) */
+MPF_DECLARE(void) mpf_activity_detector_speech_timeout_set(mpf_activity_detector_t *detector, apr_size_t speech_timeout)
</ins><span class="cx"> {
</span><del>-        detector-&gt;complete_timeout = complete_timeout;
</del><ins>+        detector-&gt;speech_timeout = speech_timeout;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Set timeout required to trigger silence (transition from active to inactive state) */
+MPF_DECLARE(void) mpf_activity_detector_silence_timeout_set(mpf_activity_detector_t *detector, apr_size_t silence_timeout)
+{
+        detector-&gt;silence_timeout = silence_timeout;
+}
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> static APR_INLINE void mpf_activity_detector_state_change(mpf_activity_detector_t *detector, mpf_detector_state_e state)
</span><span class="cx"> {
</span><span class="cx">         detector-&gt;duration = 0;
</span><span class="lines">@@ -133,7 +142,7 @@
</span><span class="cx">         else if(detector-&gt;state == DETECTOR_STATE_ACTIVITY_TRANSITION) {
</span><span class="cx">                 if(level &gt;= detector-&gt;level_threshold) {
</span><span class="cx">                         detector-&gt;duration += CODEC_FRAME_TIME_BASE;
</span><del>-                        if(detector-&gt;duration &gt;= detector-&gt;complete_timeout) {
</del><ins>+                        if(detector-&gt;duration &gt;= detector-&gt;speech_timeout) {
</ins><span class="cx">                                 /* finally detected activity */
</span><span class="cx">                                 det_event = MPF_DETECTOR_EVENT_ACTIVITY;
</span><span class="cx">                                 mpf_activity_detector_state_change(detector,DETECTOR_STATE_ACTIVITY);
</span><span class="lines">@@ -160,7 +169,7 @@
</span><span class="cx">                 }
</span><span class="cx">                 else {
</span><span class="cx">                         detector-&gt;duration += CODEC_FRAME_TIME_BASE;
</span><del>-                        if(detector-&gt;duration &gt;= detector-&gt;complete_timeout) {
</del><ins>+                        if(detector-&gt;duration &gt;= detector-&gt;silence_timeout) {
</ins><span class="cx">                                 /* detected inactivity */
</span><span class="cx">                                 det_event = MPF_DETECTOR_EVENT_INACTIVITY;
</span><span class="cx">                                 mpf_activity_detector_state_change(detector,DETECTOR_STATE_INACTIVITY);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_audio_file_streamc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -50,7 +50,7 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_audio_file_reader_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t mpf_audio_file_reader_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -76,7 +76,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_audio_file_writer_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t mpf_audio_file_writer_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -116,15 +116,21 @@
</span><span class="cx"> MPF_DECLARE(mpf_audio_stream_t*) mpf_file_stream_create(mpf_termination_t *termination, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mpf_audio_file_stream_t *file_stream = apr_palloc(pool,sizeof(mpf_audio_file_stream_t));
</span><del>-        file_stream-&gt;audio_stream = mpf_audio_stream_create(file_stream,&amp;vtable,STREAM_MODE_NONE,pool);
-        file_stream-&gt;audio_stream-&gt;termination = termination;
</del><ins>+        mpf_stream_capabilities_t *capabilities = mpf_stream_capabilities_create(STREAM_DIRECTION_DUPLEX,pool);
+        mpf_audio_stream_t *audio_stream = mpf_audio_stream_create(file_stream,&amp;vtable,capabilities,pool);
+        if(!audio_stream) {
+                return NULL;
+        }
+        audio_stream-&gt;termination = termination;
</ins><span class="cx"> 
</span><ins>+        file_stream-&gt;audio_stream = audio_stream;
</ins><span class="cx">         file_stream-&gt;write_handle = NULL;
</span><span class="cx">         file_stream-&gt;read_handle = NULL;
</span><span class="cx">         file_stream-&gt;eof = FALSE;
</span><span class="cx">         file_stream-&gt;max_write_size = 0;
</span><span class="cx">         file_stream-&gt;cur_write_size = 0;
</span><del>-        return file_stream-&gt;audio_stream;
</del><ins>+
+        return audio_stream;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_file_stream_modify(mpf_audio_stream_t *stream, mpf_audio_file_descriptor_t *descriptor)
</span><span class="lines">@@ -136,12 +142,9 @@
</span><span class="cx">                 }
</span><span class="cx">                 file_stream-&gt;read_handle = descriptor-&gt;read_handle;
</span><span class="cx">                 file_stream-&gt;eof = FALSE;
</span><del>-                stream-&gt;mode |= FILE_READER;
</del><ins>+                stream-&gt;direction |= FILE_READER;
</ins><span class="cx"> 
</span><del>-                stream-&gt;rx_codec = mpf_codec_manager_codec_get(
-                                                                stream-&gt;termination-&gt;codec_manager,
-                                                                &amp;descriptor-&gt;codec_descriptor,
-                                                                stream-&gt;termination-&gt;pool);
</del><ins>+                stream-&gt;rx_descriptor = descriptor-&gt;codec_descriptor;
</ins><span class="cx">         }
</span><span class="cx">         if(descriptor-&gt;mask &amp; FILE_WRITER) {
</span><span class="cx">                 if(file_stream-&gt;write_handle) {
</span><span class="lines">@@ -150,12 +153,9 @@
</span><span class="cx">                 file_stream-&gt;write_handle = descriptor-&gt;write_handle;
</span><span class="cx">                 file_stream-&gt;max_write_size = descriptor-&gt;max_write_size;
</span><span class="cx">                 file_stream-&gt;cur_write_size = 0;
</span><del>-                stream-&gt;mode |= FILE_WRITER;
</del><ins>+                stream-&gt;direction |= FILE_WRITER;
</ins><span class="cx"> 
</span><del>-                stream-&gt;tx_codec = mpf_codec_manager_codec_get(
-                                                                stream-&gt;termination-&gt;codec_manager,
-                                                                &amp;descriptor-&gt;codec_descriptor,
-                                                                stream-&gt;termination-&gt;pool);
</del><ins>+                stream-&gt;tx_descriptor = descriptor-&gt;codec_descriptor;
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_bridgec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_bridge.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_bridge.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_bridge.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,98 +15,199 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_bridge.h&quot;
</span><del>-#include &quot;mpf_stream.h&quot;
</del><ins>+#include &quot;mpf_encoder.h&quot;
+#include &quot;mpf_decoder.h&quot;
+#include &quot;mpf_resampler.h&quot;
+#include &quot;mpf_codec_manager.h&quot;
</ins><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><ins>+typedef struct mpf_bridge_t mpf_bridge_t;
+
+/** MPF bridge derived from MPF object */
+struct mpf_bridge_t {
+        /** MPF bridge base */
+        mpf_object_t        base;
+        /** Audio stream source */
+        mpf_audio_stream_t *source;
+        /** Audio stream sink */
+        mpf_audio_stream_t *sink;
+
+        /** Media frame used to read data from source and write it to sink */
+        mpf_frame_t         frame;
+};
+
</ins><span class="cx"> static apt_bool_t mpf_bridge_process(mpf_object_t *object)
</span><span class="cx"> {
</span><del>-        object-&gt;frame.type = MEDIA_FRAME_TYPE_NONE;
-        object-&gt;source-&gt;vtable-&gt;read_frame(object-&gt;source,&amp;object-&gt;frame);
</del><ins>+        mpf_bridge_t *bridge = (mpf_bridge_t*) object;
+        bridge-&gt;frame.type = MEDIA_FRAME_TYPE_NONE;
+        bridge-&gt;frame.marker = MPF_MARKER_NONE;
+        bridge-&gt;source-&gt;vtable-&gt;read_frame(bridge-&gt;source,&amp;bridge-&gt;frame);
</ins><span class="cx">         
</span><del>-        if((object-&gt;frame.type &amp; MEDIA_FRAME_TYPE_AUDIO) == 0) {
-                memset(        object-&gt;frame.codec_frame.buffer,
</del><ins>+        if((bridge-&gt;frame.type &amp; MEDIA_FRAME_TYPE_AUDIO) == 0) {
+                memset(        bridge-&gt;frame.codec_frame.buffer,
</ins><span class="cx">                                 0,
</span><del>-                                object-&gt;frame.codec_frame.size);
</del><ins>+                                bridge-&gt;frame.codec_frame.size);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        object-&gt;sink-&gt;vtable-&gt;write_frame(object-&gt;sink,&amp;object-&gt;frame);
</del><ins>+        bridge-&gt;sink-&gt;vtable-&gt;write_frame(bridge-&gt;sink,&amp;bridge-&gt;frame);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_null_bridge_process(mpf_object_t *object)
</span><span class="cx"> {
</span><del>-        object-&gt;frame.type = MEDIA_FRAME_TYPE_NONE;
-        object-&gt;source-&gt;vtable-&gt;read_frame(object-&gt;source,&amp;object-&gt;frame);
-        object-&gt;sink-&gt;vtable-&gt;write_frame(object-&gt;sink,&amp;object-&gt;frame);
</del><ins>+        mpf_bridge_t *bridge = (mpf_bridge_t*) object;
+        bridge-&gt;frame.type = MEDIA_FRAME_TYPE_NONE;
+        bridge-&gt;source-&gt;vtable-&gt;read_frame(bridge-&gt;source,&amp;bridge-&gt;frame);
+        bridge-&gt;sink-&gt;vtable-&gt;write_frame(bridge-&gt;sink,&amp;bridge-&gt;frame);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void mpf_bridge_trace(mpf_object_t *object)
+{
+        mpf_bridge_t *bridge = (mpf_bridge_t*) object;
+        char buf[1024];
+        apr_size_t offset;
</ins><span class="cx"> 
</span><ins>+        apt_text_stream_t output;
+        apt_text_stream_init(&amp;output,buf,sizeof(buf)-1);
+
+        mpf_audio_stream_trace(bridge-&gt;source,STREAM_DIRECTION_RECEIVE,&amp;output);
+        
+        offset = output.pos - output.text.buf;
+        output.pos += apr_snprintf(output.pos, output.text.length - offset,
+                &quot;-&gt;Bridge-&gt;&quot;);
+
+        mpf_audio_stream_trace(bridge-&gt;sink,STREAM_DIRECTION_SEND,&amp;output);
+
+        *output.pos = '\0';
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,output.text.buf);
+}
+
+
</ins><span class="cx"> static apt_bool_t mpf_bridge_destroy(mpf_object_t *object)
</span><span class="cx"> {
</span><del>-        mpf_object_t *bridge = object;
</del><ins>+        mpf_bridge_t *bridge = (mpf_bridge_t*) object;
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Destroy Audio Bridge&quot;);
</span><span class="cx">         mpf_audio_stream_rx_close(bridge-&gt;source);
</span><span class="cx">         mpf_audio_stream_tx_close(bridge-&gt;sink);
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static mpf_object_t* mpf_bridge_base_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool)
</del><ins>+static mpf_bridge_t* mpf_bridge_base_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        mpf_object_t *bridge;
</del><ins>+        mpf_bridge_t *bridge;
</ins><span class="cx">         if(!source || !sink) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        bridge = apr_palloc(pool,sizeof(mpf_object_t));
</del><ins>+        bridge = apr_palloc(pool,sizeof(mpf_bridge_t));
</ins><span class="cx">         bridge-&gt;source = source;
</span><span class="cx">         bridge-&gt;sink = sink;
</span><del>-        bridge-&gt;process = mpf_bridge_process;
-        bridge-&gt;destroy = mpf_bridge_destroy;
-
-        if(mpf_audio_stream_rx_open(source) == FALSE) {
-                return NULL;
-        }
-        if(mpf_audio_stream_tx_open(sink) == FALSE) {
-                mpf_audio_stream_rx_close(source);
-                return NULL;
-        }
</del><ins>+        mpf_object_init(&amp;bridge-&gt;base);
+        bridge-&gt;base.destroy = mpf_bridge_destroy;
+        bridge-&gt;base.process = mpf_bridge_process;
+        bridge-&gt;base.trace = mpf_bridge_trace;
</ins><span class="cx">         return bridge;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_object_t*) mpf_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool)
</del><ins>+static mpf_object_t* mpf_linear_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         mpf_codec_descriptor_t *descriptor;
</span><span class="cx">         apr_size_t frame_size;
</span><del>-        mpf_object_t *bridge;
-        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Create Audio Bridge&quot;);
</del><ins>+        mpf_bridge_t *bridge;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Create Linear Audio Bridge&quot;);
</ins><span class="cx">         bridge = mpf_bridge_base_create(source,sink,pool);
</span><span class="cx">         if(!bridge) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        descriptor = source-&gt;rx_codec-&gt;descriptor;
</del><ins>+        descriptor = source-&gt;rx_descriptor;
</ins><span class="cx">         frame_size = mpf_codec_linear_frame_size_calculate(descriptor-&gt;sampling_rate,descriptor-&gt;channel_count);
</span><span class="cx">         bridge-&gt;frame.codec_frame.size = frame_size;
</span><span class="cx">         bridge-&gt;frame.codec_frame.buffer = apr_palloc(pool,frame_size);
</span><del>-        return bridge;
</del><ins>+        
+        if(mpf_audio_stream_rx_open(source,NULL) == FALSE) {
+                return NULL;
+        }
+        if(mpf_audio_stream_tx_open(sink,NULL) == FALSE) {
+                mpf_audio_stream_rx_close(source);
+                return NULL;
+        }
+        return &amp;bridge-&gt;base;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_object_t*) mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool)
</del><ins>+static mpf_object_t* mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         mpf_codec_t *codec;
</span><span class="cx">         apr_size_t frame_size;
</span><del>-        mpf_object_t *bridge;
-        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Create Audio Null Bridge&quot;);
</del><ins>+        mpf_bridge_t *bridge;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Create Null Audio Bridge&quot;);
</ins><span class="cx">         bridge = mpf_bridge_base_create(source,sink,pool);
</span><span class="cx">         if(!bridge) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><del>-        bridge-&gt;process = mpf_null_bridge_process;
</del><ins>+        bridge-&gt;base.process = mpf_null_bridge_process;
</ins><span class="cx"> 
</span><del>-        codec = source-&gt;rx_codec;
-        frame_size = mpf_codec_frame_size_calculate(codec-&gt;descriptor,codec-&gt;attribs);
</del><ins>+        codec = mpf_codec_manager_codec_get(codec_manager,source-&gt;rx_descriptor,pool);
+        if(!codec) {
+                return NULL;
+        }
+
+        frame_size = mpf_codec_frame_size_calculate(source-&gt;rx_descriptor,codec-&gt;attribs);
</ins><span class="cx">         bridge-&gt;frame.codec_frame.size = frame_size;
</span><span class="cx">         bridge-&gt;frame.codec_frame.buffer = apr_palloc(pool,frame_size);
</span><del>-        return bridge;
</del><ins>+
+        if(mpf_audio_stream_rx_open(source,codec) == FALSE) {
+                return NULL;
+        }
+        if(mpf_audio_stream_tx_open(sink,codec) == FALSE) {
+                mpf_audio_stream_rx_close(source);
+                return NULL;
+        }
+        return &amp;bridge-&gt;base;
</ins><span class="cx"> }
</span><ins>+
+MPF_DECLARE(mpf_object_t*) mpf_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
+{
+        if(!source || !sink) {
+                return NULL;
+        }
+
+        if(mpf_audio_stream_rx_validate(source,sink-&gt;tx_descriptor,sink-&gt;tx_event_descriptor,pool) == FALSE ||
+                mpf_audio_stream_tx_validate(sink,source-&gt;rx_descriptor,source-&gt;rx_event_descriptor,pool) == FALSE) {
+                return NULL;
+        }
+
+        if(mpf_codec_descriptors_match(source-&gt;rx_descriptor,sink-&gt;tx_descriptor) == TRUE) {
+                return mpf_null_bridge_create(source,sink,codec_manager,pool);
+        }
+
+        if(mpf_codec_lpcm_descriptor_match(source-&gt;rx_descriptor) == FALSE) {
+                mpf_codec_t *codec = mpf_codec_manager_codec_get(codec_manager,source-&gt;rx_descriptor,pool);
+                if(codec) {
+                        /* set decoder before bridge */
+                        mpf_audio_stream_t *decoder = mpf_decoder_create(source,codec,pool);
+                        source = decoder;
+                }
+        }
+
+        if(mpf_codec_lpcm_descriptor_match(sink-&gt;tx_descriptor) == FALSE) {
+                mpf_codec_t *codec = mpf_codec_manager_codec_get(codec_manager,sink-&gt;tx_descriptor,pool);
+                if(codec) {
+                        /* set encoder after bridge */
+                        mpf_audio_stream_t *encoder = mpf_encoder_create(sink,codec,pool);
+                        sink = encoder;
+                }
+        }
+
+        if(source-&gt;rx_descriptor-&gt;sampling_rate != sink-&gt;tx_descriptor-&gt;sampling_rate) {
+                /* set resampler before bridge */
+                mpf_audio_stream_t *resampler = mpf_resampler_create(source,sink,pool);
+                if(!resampler) {
+                        return NULL;
+                }
+                source = resampler;
+        }
+
+        return mpf_linear_bridge_create(source,sink,codec_manager,pool);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_descriptorc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,12 +15,84 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_codec_descriptor.h&quot;
</span><ins>+#include &quot;mpf_named_event.h&quot;
+#include &quot;mpf_rtp_pt.h&quot;
</ins><span class="cx"> 
</span><ins>+/* linear PCM (host horder) */
+#define LPCM_CODEC_NAME        &quot;LPCM&quot;
+#define LPCM_CODEC_NAME_LENGTH (sizeof(LPCM_CODEC_NAME)-1)
+
+/* linear PCM atrributes */
+static const mpf_codec_attribs_t lpcm_attribs = {
+        {LPCM_CODEC_NAME, LPCM_CODEC_NAME_LENGTH},    /* codec name */
+        16,                                           /* bits per sample */
+        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000 |
+        MPF_SAMPLE_RATE_32000 | MPF_SAMPLE_RATE_48000 /* supported sampling rates */
+};
+
+/** Find matched attribs in codec capabilities by descriptor specified */
+static mpf_codec_attribs_t* mpf_codec_capabilities_attribs_find(const mpf_codec_capabilities_t *capabilities, const mpf_codec_descriptor_t *descriptor);
+
+
+/** Get sampling rate mask (mpf_sample_rate_e) by integer value  */
+MPF_DECLARE(int) mpf_sample_rate_mask_get(apr_uint16_t sampling_rate)
+{
+        switch(sampling_rate) {
+                case 8000:
+                        return MPF_SAMPLE_RATE_8000;
+                case 16000:
+                        return MPF_SAMPLE_RATE_16000;
+                case 32000:
+                        return MPF_SAMPLE_RATE_32000;
+                case 48000:
+                        return MPF_SAMPLE_RATE_48000;
+        }
+        return MPF_SAMPLE_RATE_NONE;
+}
+
+static APR_INLINE apt_bool_t mpf_sampling_rate_check(apr_uint16_t sampling_rate, int mask)
+{
+        return (mpf_sample_rate_mask_get(sampling_rate) &amp; mask) ? TRUE : FALSE;
+}
+
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_lpcm_descriptor_create(apr_uint16_t sampling_rate, apr_byte_t channel_count, apr_pool_t *pool)
+{
+        mpf_codec_descriptor_t *descriptor = mpf_codec_descriptor_create(pool);
+        descriptor-&gt;payload_type = RTP_PT_UNKNOWN;
+        descriptor-&gt;name = lpcm_attribs.name;
+        descriptor-&gt;sampling_rate = sampling_rate;
+        descriptor-&gt;channel_count = channel_count;
+        return descriptor;
+}
+
+/** Create codec descriptor by capabilities */
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_descriptor_create_by_capabilities(const mpf_codec_capabilities_t *capabilities, const mpf_codec_descriptor_t *peer, apr_pool_t *pool)
+{
+        mpf_codec_descriptor_t *descriptor;
+        mpf_codec_attribs_t *attribs = NULL;
+        if(capabilities &amp;&amp; peer) {
+                attribs = mpf_codec_capabilities_attribs_find(capabilities,peer);
+        }
+        
+        if(!attribs) {
+                return mpf_codec_lpcm_descriptor_create(8000,1,pool);
+        }
+
+        descriptor = mpf_codec_descriptor_create(pool);
+        *descriptor = *peer;
+        if(apt_string_compare(&amp;peer-&gt;name,&amp;attribs-&gt;name) == FALSE) {
+                descriptor-&gt;payload_type = RTP_PT_UNKNOWN;
+                descriptor-&gt;name = attribs-&gt;name;
+        }
+        return descriptor;
+}
+
+
</ins><span class="cx"> /** Match two codec descriptors */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_codec_descriptor_match(const mpf_codec_descriptor_t *descriptor1, const mpf_codec_descriptor_t *descriptor2)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_codec_descriptors_match(const mpf_codec_descriptor_t *descriptor1, const mpf_codec_descriptor_t *descriptor2)
</ins><span class="cx"> {
</span><span class="cx">         apt_bool_t match = FALSE;
</span><del>-        if(descriptor1-&gt;payload_type &lt; 96 &amp;&amp; descriptor2-&gt;payload_type &lt; 96) {
</del><ins>+        if(descriptor1-&gt;payload_type &lt; RTP_PT_DYNAMIC &amp;&amp; descriptor2-&gt;payload_type &lt; RTP_PT_DYNAMIC) {
</ins><span class="cx">                 if(descriptor1-&gt;payload_type == descriptor2-&gt;payload_type) {
</span><span class="cx">                         match = TRUE;
</span><span class="cx">                 }
</span><span class="lines">@@ -36,37 +108,158 @@
</span><span class="cx">         return match;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Match specified codec descriptor and the default lpcm one */
+MPF_DECLARE(apt_bool_t) mpf_codec_lpcm_descriptor_match(const mpf_codec_descriptor_t *descriptor)
+{
+        return apt_string_compare(&amp;descriptor-&gt;name,&amp;lpcm_attribs.name);
+}
+
+/** Add default (liear PCM) capabilities */
+MPF_DECLARE(apt_bool_t) mpf_codec_default_capabilities_add(mpf_codec_capabilities_t *capabilities)
+{
+        return mpf_codec_capabilities_add(capabilities,MPF_SAMPLE_RATE_8000,lpcm_attribs.name.buf);
+}
+
+/** Match codec descriptors by attribs specified */
+MPF_DECLARE(apt_bool_t) mpf_codec_descriptor_match_by_attribs(mpf_codec_descriptor_t *descriptor, const mpf_codec_descriptor_t *static_descriptor, const mpf_codec_attribs_t *attribs)
+{
+        apt_bool_t match = FALSE;
+        if(descriptor-&gt;payload_type &lt; RTP_PT_DYNAMIC) {
+                if(static_descriptor &amp;&amp; static_descriptor-&gt;payload_type == descriptor-&gt;payload_type) {
+                        descriptor-&gt;name = static_descriptor-&gt;name;
+                        descriptor-&gt;sampling_rate = static_descriptor-&gt;sampling_rate;
+                        descriptor-&gt;channel_count = static_descriptor-&gt;channel_count;
+                        match = TRUE;
+                }
+        }
+        else {
+                if(apt_string_compare(&amp;attribs-&gt;name,&amp;descriptor-&gt;name) == TRUE) {
+                        if(mpf_sampling_rate_check(descriptor-&gt;sampling_rate,attribs-&gt;sample_rates) == TRUE) {
+                                match = TRUE;
+                        }
+                }
+        }
+        return match;
+}
+
+/** Find matched descriptor in codec list */
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_codec_list_descriptor_find(const mpf_codec_list_t *codec_list, const mpf_codec_descriptor_t *descriptor)
+{
+        int i;
+        mpf_codec_descriptor_t *matched_descriptor;
+        for(i=0; i&lt;codec_list-&gt;descriptor_arr-&gt;nelts; i++) {
+                matched_descriptor = &amp;APR_ARRAY_IDX(codec_list-&gt;descriptor_arr,i,mpf_codec_descriptor_t);
+                if(mpf_codec_descriptors_match(descriptor,matched_descriptor) == TRUE) {
+                        return matched_descriptor;
+                }
+        }
+        return NULL;
+}
+
+/** Find matched attribs in codec capabilities by descriptor specified */
+static mpf_codec_attribs_t* mpf_codec_capabilities_attribs_find(const mpf_codec_capabilities_t *capabilities, const mpf_codec_descriptor_t *descriptor)
+{
+        int i;
+        mpf_codec_attribs_t *attribs;
+        for(i=0; i&lt;capabilities-&gt;attrib_arr-&gt;nelts; i++) {
+                attribs = &amp;APR_ARRAY_IDX(capabilities-&gt;attrib_arr,i,mpf_codec_attribs_t);
+                if(mpf_sampling_rate_check(descriptor-&gt;sampling_rate,attribs-&gt;sample_rates) == TRUE) {
+                        return attribs;
+                }
+        }
+        return NULL;
+}
+
+/** Modify codec list according to capabilities specified */
+MPF_DECLARE(apt_bool_t) mpf_codec_list_modify(mpf_codec_list_t *codec_list, const mpf_codec_capabilities_t *capabilities)
+{
+        int i;
+        mpf_codec_descriptor_t *descriptor;
+        if(!capabilities) {
+                return FALSE;
+        }
+
+        for(i=0; i&lt;codec_list-&gt;descriptor_arr-&gt;nelts; i++) {
+                descriptor = &amp;APR_ARRAY_IDX(codec_list-&gt;descriptor_arr,i,mpf_codec_descriptor_t);
+                /* match capabilities */
+                if(!mpf_codec_capabilities_attribs_find(capabilities,descriptor)) {
+                        descriptor-&gt;enabled = FALSE;
+                }
+        }
+
+        return TRUE;
+}
+
</ins><span class="cx"> /** Intersect two codec lists */
</span><del>-MPF_DECLARE(apt_bool_t) mpf_codec_list_intersect(mpf_codec_list_t *codec_list1, mpf_codec_list_t *codec_list2)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_codec_lists_intersect(mpf_codec_list_t *codec_list1, mpf_codec_list_t *codec_list2)
</ins><span class="cx"> {
</span><span class="cx">         int i;
</span><del>-        int j;
</del><span class="cx">         mpf_codec_descriptor_t *descriptor1;
</span><span class="cx">         mpf_codec_descriptor_t *descriptor2;
</span><del>-        codec_list1-&gt;preffered = NULL;
-        codec_list2-&gt;preffered = NULL;
-        /* find only one match, set the matched codec as preffered, disable the others */
</del><ins>+        codec_list1-&gt;primary_descriptor = NULL;
+        codec_list1-&gt;event_descriptor = NULL;
+        codec_list2-&gt;primary_descriptor = NULL;
+        codec_list2-&gt;event_descriptor = NULL;
+        /* find only one match for primary and named event descriptors, 
+        set the matched descriptors as preffered, disable the others */
</ins><span class="cx">         for(i=0; i&lt;codec_list1-&gt;descriptor_arr-&gt;nelts; i++) {
</span><del>-                descriptor1 = (mpf_codec_descriptor_t*)codec_list1-&gt;descriptor_arr-&gt;elts + i;
-                if(codec_list1-&gt;preffered) {
-                        descriptor1-&gt;enabled = FALSE;
</del><ins>+                descriptor1 = &amp;APR_ARRAY_IDX(codec_list1-&gt;descriptor_arr,i,mpf_codec_descriptor_t);
+                if(descriptor1-&gt;enabled == FALSE) {
+                        /* this descriptor has been already disabled, process only enabled ones */
</ins><span class="cx">                         continue;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                for(j=0; j&lt;codec_list2-&gt;descriptor_arr-&gt;nelts; j++) {
-                        descriptor2 = (mpf_codec_descriptor_t*)codec_list2-&gt;descriptor_arr-&gt;elts + j;
-
-                        descriptor1-&gt;enabled = mpf_codec_descriptor_match(descriptor1,descriptor2);
-                        if(descriptor1-&gt;enabled == TRUE) {
-                                codec_list1-&gt;preffered = descriptor1;
-                                codec_list2-&gt;preffered = descriptor2;
-                                break;
</del><ins>+                /* check whether this is a named event descriptor */
+                if(mpf_event_descriptor_check(descriptor1) == TRUE) {
+                        /* named event descriptor */
+                        if(codec_list1-&gt;event_descriptor) {
+                                /* named event descriptor has been already set, disable this one */
+                                descriptor1-&gt;enabled = FALSE;
</ins><span class="cx">                         }
</span><ins>+                        else {
+                                /* find if there is a match */
+                                descriptor2 = mpf_codec_list_descriptor_find(codec_list2,descriptor1);
+                                if(descriptor2 &amp;&amp; descriptor2-&gt;enabled == TRUE) {
+                                        descriptor1-&gt;enabled = TRUE;
+                                        codec_list1-&gt;event_descriptor = descriptor1;
+                                        codec_list2-&gt;event_descriptor = descriptor2;
+                                }
+                                else {
+                                        /* no match found, disable this descriptor */
+                                        descriptor1-&gt;enabled = FALSE;
+                                }
+                        }
</ins><span class="cx">                 }
</span><ins>+                else {
+                        /* primary descriptor */
+                        if(codec_list1-&gt;primary_descriptor) {
+                                /* primary descriptor has been already set, disable this one */
+                                descriptor1-&gt;enabled = FALSE;
+                        }
+                        else {
+                                /* find if there is a match */
+                                descriptor2 = mpf_codec_list_descriptor_find(codec_list2,descriptor1);
+                                if(descriptor2 &amp;&amp; descriptor2-&gt;enabled == TRUE) {
+                                        descriptor1-&gt;enabled = TRUE;
+                                        codec_list1-&gt;primary_descriptor = descriptor1;
+                                        codec_list2-&gt;primary_descriptor = descriptor2;
+                                }
+                                else {
+                                        /* no match found, disable this descriptor */
+                                        descriptor1-&gt;enabled = FALSE;
+                                }
+                        }
+                }
</ins><span class="cx">         }
</span><del>-        for(j=0; j&lt;codec_list2-&gt;descriptor_arr-&gt;nelts; j++) {
-                descriptor2 = (mpf_codec_descriptor_t*)codec_list2-&gt;descriptor_arr-&gt;elts + j;
-                descriptor2-&gt;enabled = (codec_list2-&gt;preffered == descriptor2) ? TRUE : FALSE;
</del><ins>+
+        for(i=0; i&lt;codec_list2-&gt;descriptor_arr-&gt;nelts; i++) {
+                descriptor2 = &amp;APR_ARRAY_IDX(codec_list2-&gt;descriptor_arr,i,mpf_codec_descriptor_t);
+                if(descriptor2 == codec_list2-&gt;primary_descriptor || descriptor2 == codec_list2-&gt;event_descriptor) {
+                        descriptor2-&gt;enabled = TRUE;
+                }
+                else {
+                        descriptor2-&gt;enabled = FALSE;
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return TRUE;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_g711c"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,6 +15,7 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_codec.h&quot;
</span><ins>+#include &quot;mpf_rtp_pt.h&quot;
</ins><span class="cx"> #include &quot;g711/g711.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #define G711u_CODEC_NAME        &quot;PCMU&quot;
</span><span class="lines">@@ -35,14 +36,14 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t g711u_encode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
</span><span class="cx"> {
</span><del>-        const short *decode_buf;
</del><ins>+        const apr_int16_t *decode_buf;
</ins><span class="cx">         unsigned char *encode_buf;
</span><del>-        apr_uint32_t i;
</del><ins>+        apr_size_t i;
</ins><span class="cx"> 
</span><span class="cx">         decode_buf = frame_in-&gt;buffer;
</span><span class="cx">         encode_buf = frame_out-&gt;buffer;
</span><span class="cx"> 
</span><del>-        frame_out-&gt;size = frame_in-&gt;size / sizeof(short);
</del><ins>+        frame_out-&gt;size = frame_in-&gt;size / sizeof(apr_int16_t);
</ins><span class="cx"> 
</span><span class="cx">         for(i=0; i&lt;frame_out-&gt;size; i++) {
</span><span class="cx">                 encode_buf[i] = linear_to_ulaw(decode_buf[i]);
</span><span class="lines">@@ -53,14 +54,14 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t g711u_decode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
</span><span class="cx"> {
</span><del>-        short *decode_buf;
</del><ins>+        apr_int16_t *decode_buf;
</ins><span class="cx">         const unsigned char *encode_buf;
</span><del>-        apr_uint32_t i;
</del><ins>+        apr_size_t i;
</ins><span class="cx"> 
</span><span class="cx">         decode_buf = frame_out-&gt;buffer;
</span><span class="cx">         encode_buf = frame_in-&gt;buffer;
</span><span class="cx"> 
</span><del>-        frame_out-&gt;size = frame_in-&gt;size * sizeof(short);
</del><ins>+        frame_out-&gt;size = frame_in-&gt;size * sizeof(apr_int16_t);
</ins><span class="cx"> 
</span><span class="cx">         for(i=0; i&lt;frame_in-&gt;size; i++) {
</span><span class="cx">                 decode_buf[i] = ulaw_to_linear(encode_buf[i]);
</span><span class="lines">@@ -71,14 +72,14 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t g711a_encode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
</span><span class="cx"> {
</span><del>-        const short *decode_buf;
</del><ins>+        const apr_int16_t *decode_buf;
</ins><span class="cx">         unsigned char *encode_buf;
</span><del>-        apr_uint32_t i;
</del><ins>+        apr_size_t i;
</ins><span class="cx"> 
</span><span class="cx">         decode_buf = frame_in-&gt;buffer;
</span><span class="cx">         encode_buf = frame_out-&gt;buffer;
</span><span class="cx"> 
</span><del>-        frame_out-&gt;size = frame_in-&gt;size / sizeof(short);
</del><ins>+        frame_out-&gt;size = frame_in-&gt;size / sizeof(apr_int16_t);
</ins><span class="cx"> 
</span><span class="cx">         for(i=0; i&lt;frame_out-&gt;size; i++) {
</span><span class="cx">                 encode_buf[i] = linear_to_alaw(decode_buf[i]);
</span><span class="lines">@@ -89,14 +90,14 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t g711a_decode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
</span><span class="cx"> {
</span><del>-        short *decode_buf;
</del><ins>+        apr_int16_t *decode_buf;
</ins><span class="cx">         const unsigned char *encode_buf;
</span><del>-        apr_uint32_t i;
</del><ins>+        apr_size_t i;
</ins><span class="cx"> 
</span><span class="cx">         decode_buf = frame_out-&gt;buffer;
</span><span class="cx">         encode_buf = frame_in-&gt;buffer;
</span><span class="cx"> 
</span><del>-        frame_out-&gt;size = frame_in-&gt;size * sizeof(short);
</del><ins>+        frame_out-&gt;size = frame_in-&gt;size * sizeof(apr_int16_t);
</ins><span class="cx"> 
</span><span class="cx">         for(i=0; i&lt;frame_in-&gt;size; i++) {
</span><span class="cx">                 decode_buf[i] = alaw_to_linear(encode_buf[i]);
</span><span class="lines">@@ -122,20 +123,20 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static const mpf_codec_descriptor_t g711u_descriptor = {
</span><del>-        0,
</del><ins>+        RTP_PT_PCMU,
</ins><span class="cx">         {G711u_CODEC_NAME, G711u_CODEC_NAME_LENGTH},
</span><span class="cx">         8000,
</span><span class="cx">         1,
</span><del>-        NULL,
</del><ins>+        {NULL, 0},
</ins><span class="cx">         TRUE
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static const mpf_codec_descriptor_t g711a_descriptor = {
</span><del>-        8,
</del><ins>+        RTP_PT_PCMA,
</ins><span class="cx">         {G711a_CODEC_NAME, G711a_CODEC_NAME_LENGTH},
</span><span class="cx">         8000,
</span><span class="cx">         1,
</span><del>-        NULL,
</del><ins>+        {NULL,0},
</ins><span class="cx">         TRUE
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_linearc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -17,11 +17,8 @@
</span><span class="cx"> #define APR_WANT_BYTEFUNC
</span><span class="cx"> #include &lt;apr_want.h&gt;
</span><span class="cx"> #include &quot;mpf_codec.h&quot;
</span><ins>+#include &quot;mpf_rtp_pt.h&quot;
</ins><span class="cx"> 
</span><del>-/* linear 16-bit PCM (host horder) */
-#define LPCM_CODEC_NAME        &quot;LPCM&quot;
-#define LPCM_CODEC_NAME_LENGTH (sizeof(LPCM_CODEC_NAME)-1)
-
</del><span class="cx"> /* linear 16-bit PCM (RFC3551) */
</span><span class="cx"> #define L16_CODEC_NAME        &quot;L16&quot;
</span><span class="cx"> #define L16_CODEC_NAME_LENGTH (sizeof(L16_CODEC_NAME)-1)
</span><span class="lines">@@ -40,9 +37,9 @@
</span><span class="cx"> static apt_bool_t l16_encode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
</span><span class="cx"> {
</span><span class="cx">         apr_uint32_t i;
</span><del>-        const short *buf_in = frame_in-&gt;buffer;
-        short *buf_out = frame_out-&gt;buffer;
-        apr_size_t samples = frame_in-&gt;size / sizeof(short);
</del><ins>+        const apr_int16_t *buf_in = frame_in-&gt;buffer;
+        apr_int16_t *buf_out = frame_out-&gt;buffer;
+        apr_size_t samples = frame_in-&gt;size / sizeof(apr_int16_t);
</ins><span class="cx"> 
</span><span class="cx">         frame_out-&gt;size = frame_in-&gt;size;
</span><span class="cx"> 
</span><span class="lines">@@ -56,9 +53,9 @@
</span><span class="cx"> static apt_bool_t l16_decode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
</span><span class="cx"> {
</span><span class="cx">         apr_uint32_t i;
</span><del>-        const short *buf_in = frame_in-&gt;buffer;
-        short *buf_out = frame_out-&gt;buffer;
-        apr_size_t samples = frame_in-&gt;size / sizeof(short);
</del><ins>+        const apr_int16_t *buf_in = frame_in-&gt;buffer;
+        apr_int16_t *buf_out = frame_out-&gt;buffer;
+        apr_size_t samples = frame_in-&gt;size / sizeof(apr_int16_t);
</ins><span class="cx"> 
</span><span class="cx">         frame_out-&gt;size = frame_in-&gt;size;
</span><span class="cx"> 
</span><span class="lines">@@ -69,12 +66,6 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
-
-static const mpf_codec_vtable_t lpcm_vtable = {
-        NULL
-};
-
</del><span class="cx"> static const mpf_codec_vtable_t l16_vtable = {
</span><span class="cx">         l16_open,
</span><span class="cx">         l16_close,
</span><span class="lines">@@ -83,13 +74,6 @@
</span><span class="cx">         NULL
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-static const mpf_codec_attribs_t lpcm_attribs = {
-        {LPCM_CODEC_NAME, LPCM_CODEC_NAME_LENGTH},    /* codec name */
-        16,                                           /* bits per sample */
-        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000 |
-        MPF_SAMPLE_RATE_32000 | MPF_SAMPLE_RATE_48000 /* supported sampling rates */
-};
-
</del><span class="cx"> static const mpf_codec_attribs_t l16_attribs = {
</span><span class="cx">         {L16_CODEC_NAME, L16_CODEC_NAME_LENGTH},      /* codec name */
</span><span class="cx">         16,                                           /* bits per sample */
</span><span class="lines">@@ -97,23 +81,6 @@
</span><span class="cx">         MPF_SAMPLE_RATE_32000 | MPF_SAMPLE_RATE_48000 /* supported sampling rates */
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-mpf_codec_descriptor_t* mpf_codec_lpcm_descriptor_create(apr_uint16_t sampling_rate, apr_byte_t channel_count, apr_pool_t *pool)
-{
-        mpf_codec_descriptor_t *descriptor = apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
-        mpf_codec_descriptor_init(descriptor);
-        descriptor-&gt;payload_type = 96;
-        descriptor-&gt;name.buf = LPCM_CODEC_NAME;
-        descriptor-&gt;name.length = LPCM_CODEC_NAME_LENGTH;
-        descriptor-&gt;sampling_rate = sampling_rate;
-        descriptor-&gt;channel_count = channel_count;
-        return descriptor;
-}
-
-mpf_codec_t* mpf_codec_lpcm_create(apr_pool_t *pool)
-{
-        return mpf_codec_create(&amp;lpcm_vtable,&amp;lpcm_attribs,NULL,pool);
-}
-
</del><span class="cx"> mpf_codec_t* mpf_codec_l16_create(apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         return mpf_codec_create(&amp;l16_vtable,&amp;l16_attribs,NULL,pool);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_codec_managerc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,25 +16,28 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;stdlib.h&gt;
</span><span class="cx"> #include &quot;mpf_codec_manager.h&quot;
</span><ins>+#include &quot;mpf_rtp_pt.h&quot;
+#include &quot;mpf_named_event.h&quot;
</ins><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> struct mpf_codec_manager_t {
</span><span class="cx">         /** Memory pool */
</span><del>-        apr_pool_t   *pool;
</del><ins>+        apr_pool_t             *pool;
</ins><span class="cx"> 
</span><del>-        /** Dynamic array of codecs (mpf_codec_t*) */
-        apr_array_header_t *codec_arr;
</del><ins>+        /** Dynamic (resizable) array of codecs (mpf_codec_t*) */
+        apr_array_header_t     *codec_arr;
+        /** Default named event descriptor */
+        mpf_codec_descriptor_t *event_descriptor;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-mpf_codec_descriptor_t* mpf_codec_lpcm_descriptor_create(apr_uint16_t sampling_rate, apr_byte_t channel_count, apr_pool_t *pool);
-
</del><span class="cx"> MPF_DECLARE(mpf_codec_manager_t*) mpf_codec_manager_create(apr_size_t codec_count, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mpf_codec_manager_t *codec_manager = apr_palloc(pool,sizeof(mpf_codec_manager_t));
</span><span class="cx">         codec_manager-&gt;pool = pool;
</span><span class="cx">         codec_manager-&gt;codec_arr = apr_array_make(pool,(int)codec_count,sizeof(mpf_codec_t*));
</span><ins>+        codec_manager-&gt;event_descriptor = mpf_event_descriptor_create(8000,pool);
</ins><span class="cx">         return codec_manager;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -45,64 +48,34 @@
</span><span class="cx"> 
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_codec_manager_codec_register(mpf_codec_manager_t *codec_manager, mpf_codec_t *codec)
</span><span class="cx"> {
</span><del>-        mpf_codec_t **slot;
</del><span class="cx">         if(!codec || !codec-&gt;attribs || !codec-&gt;attribs-&gt;name.buf) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Register Codec [%s]&quot;,codec-&gt;attribs-&gt;name.buf);
</span><span class="cx"> 
</span><del>-        slot = apr_array_push(codec_manager-&gt;codec_arr);
-        *slot = codec;
</del><ins>+        APR_ARRAY_PUSH(codec_manager-&gt;codec_arr,mpf_codec_t*) = codec;
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MPF_DECLARE(mpf_codec_t*) mpf_codec_manager_codec_get(const mpf_codec_manager_t *codec_manager, mpf_codec_descriptor_t *descriptor, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         int i;
</span><del>-        mpf_codec_t *codec = NULL;
-        mpf_codec_t *ret_codec = NULL;
</del><ins>+        mpf_codec_t *codec;
</ins><span class="cx">         if(!descriptor) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         for(i=0; i&lt;codec_manager-&gt;codec_arr-&gt;nelts; i++) {
</span><del>-                codec = ((mpf_codec_t**)codec_manager-&gt;codec_arr-&gt;elts)[i];
-                if(descriptor-&gt;payload_type &lt; 96) {
-                        if(codec-&gt;static_descriptor &amp;&amp; codec-&gt;static_descriptor-&gt;payload_type == descriptor-&gt;payload_type) {
-                                descriptor-&gt;name = codec-&gt;static_descriptor-&gt;name;
-                                descriptor-&gt;sampling_rate = codec-&gt;static_descriptor-&gt;sampling_rate;
-                                descriptor-&gt;channel_count = codec-&gt;static_descriptor-&gt;channel_count;
-                                break;
-                        }
</del><ins>+                codec = APR_ARRAY_IDX(codec_manager-&gt;codec_arr,i,mpf_codec_t*);
+                if(mpf_codec_descriptor_match_by_attribs(descriptor,codec-&gt;static_descriptor,codec-&gt;attribs) == TRUE) {
+                        return mpf_codec_clone(codec,pool);
</ins><span class="cx">                 }
</span><del>-                else {
-                        if(apt_string_compare(&amp;codec-&gt;attribs-&gt;name,&amp;descriptor-&gt;name) == TRUE) {
-                                /* sampling rate must be checked as well */
-                                break;
-                        }
-                }
</del><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(i == codec_manager-&gt;codec_arr-&gt;nelts) {
-                /* no match found */
-                return NULL;
-        }
-        if(codec) {
-                ret_codec = mpf_codec_clone(codec,pool);
-                ret_codec-&gt;descriptor = descriptor;
-        }
-        return ret_codec;
</del><ins>+        return NULL;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_codec_t*) mpf_codec_manager_default_codec_get(const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
-{
-        mpf_codec_t *codec;
-        mpf_codec_descriptor_t *descriptor = mpf_codec_lpcm_descriptor_create(8000,1,pool);
-        codec = mpf_codec_manager_codec_get(codec_manager,descriptor,pool);
-        return codec;
-}
-
</del><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_codec_manager_codec_list_get(const mpf_codec_manager_t *codec_manager, mpf_codec_list_t *codec_list, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         const mpf_codec_descriptor_t *static_descriptor;
</span><span class="lines">@@ -112,7 +85,7 @@
</span><span class="cx"> 
</span><span class="cx">         mpf_codec_list_init(codec_list,codec_manager-&gt;codec_arr-&gt;nelts,pool);
</span><span class="cx">         for(i=0; i&lt;codec_manager-&gt;codec_arr-&gt;nelts; i++) {
</span><del>-                codec = ((mpf_codec_t**)codec_manager-&gt;codec_arr-&gt;elts)[i];
</del><ins>+                codec = APR_ARRAY_IDX(codec_manager-&gt;codec_arr,i,mpf_codec_t*);
</ins><span class="cx">                 static_descriptor = codec-&gt;static_descriptor;
</span><span class="cx">                 if(static_descriptor) {
</span><span class="cx">                         descriptor = mpf_codec_list_add(codec_list);
</span><span class="lines">@@ -121,6 +94,12 @@
</span><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+        if(codec_manager-&gt;event_descriptor) {
+                descriptor = mpf_codec_list_add(codec_list);
+                if(descriptor) {
+                        *descriptor = *codec_manager-&gt;event_descriptor;
+                }
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -138,26 +117,35 @@
</span><span class="cx">                 apt_string_assign(&amp;name,str,pool);
</span><span class="cx">                 /* find codec by name */
</span><span class="cx">                 codec = mpf_codec_manager_codec_find(codec_manager,&amp;name);
</span><del>-                if(!codec) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Such Codec [%s]&quot;,str);
-                        return FALSE;
-                }
</del><ins>+                if(codec) {
+                        descriptor = mpf_codec_list_add(codec_list);
+                        descriptor-&gt;name = name;
</ins><span class="cx"> 
</span><del>-                descriptor = mpf_codec_list_add(codec_list);
-                descriptor-&gt;name = name;
-
-                /* set defualt attributes */
-                if(codec-&gt;static_descriptor) {
-                        descriptor-&gt;payload_type = codec-&gt;static_descriptor-&gt;payload_type;
-                        descriptor-&gt;sampling_rate = codec-&gt;static_descriptor-&gt;sampling_rate;
-                        descriptor-&gt;channel_count = codec-&gt;static_descriptor-&gt;channel_count;
</del><ins>+                        /* set default attributes */
+                        if(codec-&gt;static_descriptor) {
+                                descriptor-&gt;payload_type = codec-&gt;static_descriptor-&gt;payload_type;
+                                descriptor-&gt;sampling_rate = codec-&gt;static_descriptor-&gt;sampling_rate;
+                                descriptor-&gt;channel_count = codec-&gt;static_descriptor-&gt;channel_count;
+                        }
+                        else {
+                                descriptor-&gt;payload_type = RTP_PT_DYNAMIC;
+                                descriptor-&gt;sampling_rate = 8000;
+                                descriptor-&gt;channel_count = 1;
+                        }
</ins><span class="cx">                 }
</span><span class="cx">                 else {
</span><del>-                        descriptor-&gt;payload_type = 96;
-                        descriptor-&gt;sampling_rate = 8000;
-                        descriptor-&gt;channel_count = 1;
</del><ins>+                        mpf_codec_descriptor_t *event_descriptor = codec_manager-&gt;event_descriptor;
+                        if(event_descriptor &amp;&amp; apt_string_compare(&amp;event_descriptor-&gt;name,&amp;name) == TRUE) {
+                                descriptor = mpf_codec_list_add(codec_list);
+                                *descriptor = *event_descriptor;
+                        }
+                        else {
+                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Such Codec [%s]&quot;,str);
+                                return FALSE;
+                        }
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">                 /* parse optional payload type */
</span><span class="cx">                 str = apr_strtok(codec_desc_str, separator, &amp;state);
</span><span class="cx">                 if(str) {
</span><span class="lines">@@ -200,7 +188,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         mpf_codec_t *codec;
</span><span class="cx">         for(i=0; i&lt;codec_manager-&gt;codec_arr-&gt;nelts; i++) {
</span><del>-                codec = ((mpf_codec_t**)codec_manager-&gt;codec_arr-&gt;elts)[i];
</del><ins>+                codec = APR_ARRAY_IDX(codec_manager-&gt;codec_arr,i,mpf_codec_t*);
</ins><span class="cx">                 if(apt_string_compare(&amp;codec-&gt;attribs-&gt;name,codec_name) == TRUE) {
</span><span class="cx">                         return codec;
</span><span class="cx">                 }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_contextc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_context.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_context.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_context.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -14,30 +14,126 @@
</span><span class="cx">  * limitations under the License.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#ifdef WIN32
+#pragma warning(disable: 4127)
+#endif
+#include &lt;apr_ring.h&gt; 
</ins><span class="cx"> #include &quot;mpf_context.h&quot;
</span><span class="cx"> #include &quot;mpf_termination.h&quot;
</span><span class="cx"> #include &quot;mpf_stream.h&quot;
</span><del>-#include &quot;mpf_encoder.h&quot;
-#include &quot;mpf_decoder.h&quot;
</del><span class="cx"> #include &quot;mpf_bridge.h&quot;
</span><ins>+#include &quot;mpf_multiplier.h&quot;
+#include &quot;mpf_mixer.h&quot;
</ins><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><del>-static mpf_object_t* mpf_context_connection_create(mpf_context_t *context, mpf_termination_t *src_termination, mpf_termination_t *sink_termination);
</del><ins>+/** Item of the association matrix */
+typedef struct {
+        unsigned char on;
+} matrix_item_t;
</ins><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_context_t*) mpf_context_create(void *obj, apr_size_t max_termination_count, apr_pool_t *pool)
</del><ins>+/** Item of the association matrix header */
+typedef struct {
+        mpf_termination_t *termination;
+        unsigned char      tx_count;
+        unsigned char      rx_count;
+} header_item_t;
+
+/** Media processing context */
+struct mpf_context_t {
+        /** Ring entry */
+        APR_RING_ENTRY(mpf_context_t) link;
+        /** Back pointer to the context factory */
+        mpf_context_factory_t        *factory;
+        /** Pool to allocate memory from */
+        apr_pool_t                   *pool;
+        /** External object */
+        void                         *obj;
+
+        /** Max number of terminations in the context */
+        apr_size_t                    capacity;
+        /** Current number of terminations in the context */
+        apr_size_t                    count;
+        /** Header of the association matrix */
+        header_item_t                *header;
+        /** Association matrix, which represents the topology */
+        matrix_item_t                **matrix;
+
+        /** Array of media processing objects constructed while 
+        applying topology based on association matrix */
+        apr_array_header_t           *mpf_objects;
+};
+
+/** Factory of media contexts */
+struct mpf_context_factory_t {
+        /** Ring head */
+        APR_RING_HEAD(mpf_context_head_t, mpf_context_t) head;
+};
+
+
+static APR_INLINE apt_bool_t stream_direction_compatibility_check(mpf_termination_t *termination1, mpf_termination_t *termination2);
+static mpf_object_t* mpf_context_bridge_create(mpf_context_t *context, apr_size_t i);
+static mpf_object_t* mpf_context_multiplier_create(mpf_context_t *context, apr_size_t i);
+static mpf_object_t* mpf_context_mixer_create(mpf_context_t *context, apr_size_t j);
+
+
+MPF_DECLARE(mpf_context_factory_t*) mpf_context_factory_create(apr_pool_t *pool)
</ins><span class="cx"> {
</span><ins>+        mpf_context_factory_t *factory = apr_palloc(pool, sizeof(mpf_context_factory_t));
+        APR_RING_INIT(&amp;factory-&gt;head, mpf_context_t, link);
+        return factory;
+}
+
+MPF_DECLARE(void) mpf_context_factory_destroy(mpf_context_factory_t *factory)
+{
+        mpf_context_t *context;
+        while(!APR_RING_EMPTY(&amp;factory-&gt;head, mpf_context_t, link)) {
+                context = APR_RING_FIRST(&amp;factory-&gt;head);
+                mpf_context_destroy(context);
+                APR_RING_REMOVE(context, link);
+        }
+}
+
+MPF_DECLARE(apt_bool_t) mpf_context_factory_process(mpf_context_factory_t *factory)
+{
+        mpf_context_t *context;
+        for(context = APR_RING_FIRST(&amp;factory-&gt;head);
+                        context != APR_RING_SENTINEL(&amp;factory-&gt;head, mpf_context_t, link);
+                                context = APR_RING_NEXT(context, link)) {
+                
+                mpf_context_process(context);
+        }
+
+        return TRUE;
+}
+

+MPF_DECLARE(mpf_context_t*) mpf_context_create(
+                                                                mpf_context_factory_t *factory,
+                                                                void *obj,
+                                                                apr_size_t max_termination_count,
+                                                                apr_pool_t *pool)
+{
</ins><span class="cx">         apr_size_t i,j;
</span><ins>+        matrix_item_t *matrix_item;
+        header_item_t *header_item;
</ins><span class="cx">         mpf_context_t *context = apr_palloc(pool,sizeof(mpf_context_t));
</span><ins>+        context-&gt;factory = factory;
</ins><span class="cx">         context-&gt;obj = obj;
</span><span class="cx">         context-&gt;pool = pool;
</span><del>-        context-&gt;elem = NULL;
-        context-&gt;max_termination_count = max_termination_count;
-        context-&gt;termination_count = 0;
-        context-&gt;table = apr_palloc(pool,sizeof(table_item_t)*max_termination_count);
-        for(i=0; i&lt;max_termination_count; i++) {
-                context-&gt;table[i] = apr_palloc(pool,sizeof(table_item_t)*max_termination_count);
-                for(j=0; j&lt;max_termination_count; j++) {
-                        context-&gt;table[i][j] = NULL;
</del><ins>+        context-&gt;capacity = max_termination_count;
+        context-&gt;count = 0;
+        context-&gt;mpf_objects = apr_array_make(pool,1,sizeof(mpf_object_t*));
+        context-&gt;header = apr_palloc(pool,context-&gt;capacity * sizeof(header_item_t));
+        context-&gt;matrix = apr_palloc(pool,context-&gt;capacity * sizeof(matrix_item_t*));
+        for(i=0; i&lt;context-&gt;capacity; i++) {
+                header_item = &amp;context-&gt;header[i];
+                header_item-&gt;termination = NULL;
+                header_item-&gt;tx_count = 0;
+                header_item-&gt;rx_count = 0;
+                context-&gt;matrix[i] = apr_palloc(pool,context-&gt;capacity * sizeof(matrix_item_t));
+                for(j=0; j&lt;context-&gt;capacity; j++) {
+                        matrix_item = &amp;context-&gt;matrix[i][j];
+                        matrix_item-&gt;on = 0;
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -47,15 +143,12 @@
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_context_destroy(mpf_context_t *context)
</span><span class="cx"> {
</span><span class="cx">         apr_size_t i;
</span><del>-        apr_size_t count = context-&gt;max_termination_count;
</del><span class="cx">         mpf_termination_t *termination;
</span><del>-        for(i=0; i&lt;count; i++){
-                termination = context-&gt;table[i][i];
</del><ins>+        for(i=0; i&lt;context-&gt;capacity; i++){
+                termination = context-&gt;header[i].termination;
</ins><span class="cx">                 if(termination) {
</span><span class="cx">                         mpf_context_termination_subtract(context,termination);
</span><del>-                        if(termination-&gt;audio_stream) {
-                                mpf_audio_stream_destroy(termination-&gt;audio_stream);
-                        }
</del><ins>+                        mpf_termination_subtract(termination);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -69,164 +162,376 @@
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_context_termination_add(mpf_context_t *context, mpf_termination_t *termination)
</span><span class="cx"> {
</span><span class="cx">         apr_size_t i;
</span><del>-        apr_size_t count = context-&gt;max_termination_count;
-        for(i=0; i&lt;count; i++) {
-                if(!context-&gt;table[i][i]) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add Termination&quot;);
-                        context-&gt;table[i][i] = termination;
-                        termination-&gt;slot = i;
-                        context-&gt;termination_count++;
-                        return TRUE;
</del><ins>+        header_item_t *header_item;
+        for(i=0; i&lt;context-&gt;capacity; i++) {
+                header_item = &amp;context-&gt;header[i];
+                if(header_item-&gt;termination) {
+                        continue;
</ins><span class="cx">                 }
</span><ins>+                if(!context-&gt;count) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add Context&quot;);
+                        APR_RING_INSERT_TAIL(&amp;context-&gt;factory-&gt;head,context,mpf_context_t,link);
+                }
+
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add Termination&quot;);
+                header_item-&gt;termination = termination;
+                header_item-&gt;tx_count = 0;
+                header_item-&gt;rx_count = 0;
+                
+                termination-&gt;slot = i;
+                context-&gt;count++;
+                return TRUE;
</ins><span class="cx">         }
</span><span class="cx">         return FALSE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_context_termination_subtract(mpf_context_t *context, mpf_termination_t *termination)
</span><span class="cx"> {
</span><ins>+        header_item_t *header_item1;
+        header_item_t *header_item2;
+        matrix_item_t *item;
+        apr_size_t j,k;
</ins><span class="cx">         apr_size_t i = termination-&gt;slot;
</span><del>-        if(i &gt;= context-&gt;max_termination_count) {
</del><ins>+        if(i &gt;= context-&gt;capacity) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        if(context-&gt;table[i][i] != termination) {
</del><ins>+        header_item1 = &amp;context-&gt;header[i];
+        if(header_item1-&gt;termination != termination) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract Termination&quot;);
</span><del>-        context-&gt;table[i][i] = NULL;
</del><ins>+        for(j=0,k=0; j&lt;context-&gt;capacity &amp;&amp; k&lt;context-&gt;count; j++) {
+                header_item2 = &amp;context-&gt;header[j];
+                if(!header_item2-&gt;termination) {
+                        continue;
+                }
+                k++;
+
+                item = &amp;context-&gt;matrix[i][j];
+                if(item-&gt;on) {
+                        item-&gt;on = 0;
+                        header_item1-&gt;tx_count--;
+                        header_item2-&gt;rx_count--;
+                }
+
+                item = &amp;context-&gt;matrix[j][i];
+                if(item-&gt;on) {
+                        item-&gt;on = 0;
+                        header_item2-&gt;tx_count--;
+                        header_item1-&gt;rx_count--;
+                }
+        }
+        header_item1-&gt;termination = NULL;
+
</ins><span class="cx">         termination-&gt;slot = (apr_size_t)-1;
</span><del>-        context-&gt;termination_count--;
</del><ins>+        context-&gt;count--;
+        if(!context-&gt;count) {
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Remove Context&quot;);
+                APR_RING_REMOVE(context,link);
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(apt_bool_t) mpf_context_process(mpf_context_t *context)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_association_add(mpf_context_t *context, mpf_termination_t *termination1, mpf_termination_t *termination2)
</ins><span class="cx"> {
</span><del>-        mpf_object_t *object;
-        apr_size_t i,j;
-        for(i=0; i&lt;context-&gt;max_termination_count; i++) {
-                for(j=0; j&lt;context-&gt;max_termination_count; j++) {
-                        if(i==j) continue;
</del><ins>+        header_item_t *header_item1;
+        matrix_item_t *matrix_item1;
+        header_item_t *header_item2;
+        matrix_item_t *matrix_item2;
+        apr_size_t i = termination1-&gt;slot;
+        apr_size_t j = termination2-&gt;slot;
+        if(i &gt;= context-&gt;capacity || j &gt;= context-&gt;capacity) {
+                return FALSE;
+        }
</ins><span class="cx"> 
</span><del>-                        object = context-&gt;table[i][j];
-                        if(object &amp;&amp; object-&gt;process) {
-                                object-&gt;process(object);
-                        }
</del><ins>+        header_item1 = &amp;context-&gt;header[i];
+        header_item2 = &amp;context-&gt;header[j];
+
+        if(header_item1-&gt;termination != termination1 || header_item2-&gt;termination != termination2) {
+                return FALSE;
+        }
+
+        matrix_item1 = &amp;context-&gt;matrix[i][j];
+        matrix_item2 = &amp;context-&gt;matrix[j][i];
+
+        /* 1 -&gt; 2 */
+        if(!matrix_item1-&gt;on) {
+                if(stream_direction_compatibility_check(header_item1-&gt;termination,header_item2-&gt;termination) == TRUE) {
+                        matrix_item1-&gt;on = 1;
+                        header_item1-&gt;tx_count ++;
+                        header_item2-&gt;rx_count ++;
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+
+        /* 2 -&gt; 1 */
+        if(!matrix_item2-&gt;on) {
+                if(stream_direction_compatibility_check(header_item2-&gt;termination,header_item1-&gt;termination) == TRUE) {
+                        matrix_item2-&gt;on = 1;
+                        header_item2-&gt;tx_count ++;
+                        header_item1-&gt;rx_count ++;
+                }
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(apt_bool_t) mpf_context_topology_apply(mpf_context_t *context, mpf_termination_t *termination)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_association_remove(mpf_context_t *context, mpf_termination_t *termination1, mpf_termination_t *termination2)
</ins><span class="cx"> {
</span><del>-        apr_size_t i,j;
-        mpf_object_t *object;
-        mpf_termination_t *sink_termination;
-        mpf_termination_t *source_termination;
-        if(context-&gt;termination_count &lt;= 1) {
-                /* at least 2 terminations are required to apply topology on them */
-                return TRUE;
</del><ins>+        header_item_t *header_item1;
+        matrix_item_t *matrix_item1;
+        header_item_t *header_item2;
+        matrix_item_t *matrix_item2;
+        apr_size_t i = termination1-&gt;slot;
+        apr_size_t j = termination2-&gt;slot;
+        if(i &gt;= context-&gt;capacity || j &gt;= context-&gt;capacity) {
+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        i = termination-&gt;slot;
-        for(j=0; j&lt;context-&gt;max_termination_count; j++) {
-                if(i == j) continue;
</del><ins>+        header_item1 = &amp;context-&gt;header[i];
+        header_item2 = &amp;context-&gt;header[j];
</ins><span class="cx"> 
</span><del>-                sink_termination = context-&gt;table[j][j];
-                object = mpf_context_connection_create(context,termination,sink_termination);
-                if(object) {
-                        context-&gt;table[i][j] = object;
-                }
</del><ins>+        if(header_item1-&gt;termination != termination1 || header_item2-&gt;termination != termination2) {
+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        j = termination-&gt;slot;
-        for(i=0; i&lt;context-&gt;max_termination_count; i++) {
-                if(i == j) continue;
</del><ins>+        matrix_item1 = &amp;context-&gt;matrix[i][j];
+        matrix_item2 = &amp;context-&gt;matrix[j][i];
</ins><span class="cx"> 
</span><del>-                source_termination = context-&gt;table[i][i];
-                object = mpf_context_connection_create(context,source_termination,termination);
-                if(object) {
-                        context-&gt;table[i][j] = object;
-                }
</del><ins>+        /* 1 -&gt; 2 */
+        if(matrix_item1-&gt;on == 1) {
+                matrix_item1-&gt;on = 0;
+                header_item1-&gt;tx_count --;
+                header_item2-&gt;rx_count --;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* 2 -&gt; 1 */
+        if(matrix_item2-&gt;on == 1) {
+                matrix_item2-&gt;on = 0;
+                header_item2-&gt;tx_count --;
+                header_item1-&gt;rx_count --;
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(apt_bool_t) mpf_context_topology_destroy(mpf_context_t *context, mpf_termination_t *termination)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_associations_reset(mpf_context_t *context)
</ins><span class="cx"> {
</span><del>-        apr_size_t i,j;
-        mpf_object_t *object;
-        if(context-&gt;termination_count &lt;= 1) {
-                /* at least 2 terminations are required to destroy topology */
-                return TRUE;
-        }
</del><ins>+        apr_size_t i,j,k;
+        header_item_t *header_item1;
+        header_item_t *header_item2;
+        matrix_item_t *item;
</ins><span class="cx"> 
</span><del>-        i = termination-&gt;slot;
-        for(j=0; j&lt;context-&gt;max_termination_count; j++) {
-                if(i == j) continue;
</del><ins>+        /* destroy existing topology / if any */
+        mpf_context_topology_destroy(context);
</ins><span class="cx"> 
</span><del>-                object = context-&gt;table[i][j];
-                if(object) {
-                        if(object-&gt;destroy) {
-                                object-&gt;destroy(object);
</del><ins>+        /* reset assigned associations */
+        for(i=0,k=0; i&lt;context-&gt;capacity &amp;&amp; k&lt;context-&gt;count; i++) {
+                header_item1 = &amp;context-&gt;header[i];
+                if(!header_item1-&gt;termination) {
+                        continue;
+                }
+                k++;
+                
+                if(!header_item1-&gt;tx_count &amp;&amp; !header_item1-&gt;rx_count) {
+                        continue;
+                }
+                
+                for(j=i; j&lt;context-&gt;capacity; j++) {
+                        header_item2 = &amp;context-&gt;header[j];
+                        if(!header_item2-&gt;termination) {
+                                continue;
</ins><span class="cx">                         }
</span><del>-                        context-&gt;table[i][j] = NULL;
</del><ins>+                        
+                        item = &amp;context-&gt;matrix[i][j];
+                        if(item-&gt;on) {
+                                item-&gt;on = 0;
+                                header_item1-&gt;tx_count--;
+                                header_item2-&gt;rx_count--;
+                        }
+
+                        item = &amp;context-&gt;matrix[j][i];
+                        if(item-&gt;on) {
+                                item-&gt;on = 0;
+                                header_item2-&gt;tx_count--;
+                                header_item1-&gt;rx_count--;
+                        }
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+        return TRUE;
+}
</ins><span class="cx"> 
</span><del>-        j = termination-&gt;slot;
-        for(i=0; i&lt;context-&gt;max_termination_count; i++) {
-                if(i == j) continue;
</del><ins>+static apt_bool_t mpf_context_object_add(mpf_context_t *context, mpf_object_t *object)
+{
+        if(!object) {
+                return FALSE;
+        }
+        
+        APR_ARRAY_PUSH(context-&gt;mpf_objects, mpf_object_t*) = object;
+#if 1
+        mpf_object_trace(object);
+#endif
+        return TRUE;
+}
</ins><span class="cx"> 
</span><del>-                object = context-&gt;table[i][j];
-                if(object) {
-                        if(object-&gt;destroy) {
-                                object-&gt;destroy(object);
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_topology_apply(mpf_context_t *context)
+{
+        apr_size_t i,k;
+        header_item_t *header_item;
+        mpf_object_t *object;
+        
+        /* first destroy existing topology / if any */
+        mpf_context_topology_destroy(context);
+
+        for(i=0,k=0; i&lt;context-&gt;capacity &amp;&amp; k&lt;context-&gt;count; i++) {
+                header_item = &amp;context-&gt;header[i];
+                if(!header_item-&gt;termination) {
+                        continue;
+                }
+                k++;
+                
+                if(header_item-&gt;tx_count &gt; 0) {
+                        object = NULL;
+                        if(header_item-&gt;tx_count == 1) {
+                                object = mpf_context_bridge_create(context,i);
</ins><span class="cx">                         }
</span><del>-                        context-&gt;table[i][j] = NULL;
</del><ins>+                        else { /* tx_count &gt; 1 */
+                                object = mpf_context_multiplier_create(context,i);
+                        }
+
+                        mpf_context_object_add(context,object);
</ins><span class="cx">                 }
</span><ins>+                if(header_item-&gt;rx_count &gt; 1) {
+                        object = mpf_context_mixer_create(context,i);
+                        mpf_context_object_add(context,object);
+                }
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static mpf_object_t* mpf_context_connection_create(mpf_context_t *context, mpf_termination_t *src_termination, mpf_termination_t *sink_termination)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_context_topology_destroy(mpf_context_t *context)
</ins><span class="cx"> {
</span><del>-        mpf_object_t *object = NULL;
-        mpf_audio_stream_t *source;
-        mpf_audio_stream_t *sink;
-        if(!src_termination || !sink_termination) {
-                return NULL;
</del><ins>+        if(context-&gt;mpf_objects-&gt;nelts) {
+                int i;
+                mpf_object_t *object;
+                for(i=0; i&lt;context-&gt;mpf_objects-&gt;nelts; i++) {
+                        object = APR_ARRAY_IDX(context-&gt;mpf_objects,i,mpf_object_t*);
+                        mpf_object_destroy(object);
+                }
+                apr_array_clear(context-&gt;mpf_objects);
</ins><span class="cx">         }
</span><del>-        source = src_termination-&gt;audio_stream;
-        sink = sink_termination-&gt;audio_stream;
-        if(source &amp;&amp; (source-&gt;mode &amp; STREAM_MODE_RECEIVE) == STREAM_MODE_RECEIVE &amp;&amp;
-                sink &amp;&amp; (sink-&gt;mode &amp; STREAM_MODE_SEND) == STREAM_MODE_SEND) {
-                mpf_codec_t *rx_codec = source-&gt;rx_codec;
-                mpf_codec_t *tx_codec = sink-&gt;tx_codec;
-                if(rx_codec &amp;&amp; tx_codec) {
-                        if(mpf_codec_descriptor_match(rx_codec-&gt;descriptor,tx_codec-&gt;descriptor) == TRUE) {
-                                object = mpf_null_bridge_create(source,sink,context-&gt;pool);
-                        }
-                        else {
-                                if(rx_codec-&gt;descriptor-&gt;sampling_rate != tx_codec-&gt;descriptor-&gt;sampling_rate) {
-                                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,
-                                                &quot;Resampling is not supported now. &quot;
-                                                &quot;Try to configure and use the same sampling rate on both ends&quot;);
-                                        return NULL;
-                                }
-                                if(rx_codec-&gt;vtable &amp;&amp; rx_codec-&gt;vtable-&gt;decode) {
-                                        /* set decoder before bridge */
-                                        mpf_audio_stream_t *decoder = mpf_decoder_create(source,context-&gt;pool);
-                                        source = decoder;
-                                }
-                                if(tx_codec-&gt;vtable &amp;&amp; tx_codec-&gt;vtable-&gt;encode) {
-                                        /* set encoder after bridge */
-                                        mpf_audio_stream_t *encoder = mpf_encoder_create(sink,context-&gt;pool);
-                                        sink = encoder;
-                                }
-                                object = mpf_bridge_create(source,sink,context-&gt;pool);
-                        }
</del><ins>+        return TRUE;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_context_process(mpf_context_t *context)
+{
+        int i;
+        mpf_object_t *object;
+        for(i=0; i&lt;context-&gt;mpf_objects-&gt;nelts; i++) {
+                object = APR_ARRAY_IDX(context-&gt;mpf_objects,i,mpf_object_t*);
+                if(object &amp;&amp; object-&gt;process) {
+                        object-&gt;process(object);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        return object;
</del><ins>+        return TRUE;
</ins><span class="cx"> }
</span><ins>+
+
+static mpf_object_t* mpf_context_bridge_create(mpf_context_t *context, apr_size_t i)
+{
+        header_item_t *header_item1 = &amp;context-&gt;header[i];
+        header_item_t *header_item2;
+        matrix_item_t *item;
+        apr_size_t j;
+        for(j=0; j&lt;context-&gt;capacity; j++) {
+                header_item2 = &amp;context-&gt;header[j];
+                if(!header_item2-&gt;termination) {
+                        continue;
+                }
+                item = &amp;context-&gt;matrix[i][j];
+                if(!item-&gt;on) {
+                        continue;
+                }
+
+                if(header_item2-&gt;rx_count &gt; 1) {
+                        /* mixer will be created instead */
+                        return NULL;
+                }
+                
+                /* create bridge i -&gt; j */
+                if(header_item1-&gt;termination &amp;&amp; header_item2-&gt;termination) {
+                        return mpf_bridge_create(
+                                header_item1-&gt;termination-&gt;audio_stream,
+                                header_item2-&gt;termination-&gt;audio_stream,
+                                header_item1-&gt;termination-&gt;codec_manager,
+                                context-&gt;pool);
+                }
+        }
+        return NULL;
+}
+
+static mpf_object_t* mpf_context_multiplier_create(mpf_context_t *context, apr_size_t i)
+{
+        mpf_audio_stream_t **sink_arr;
+        header_item_t *header_item1 = &amp;context-&gt;header[i];
+        header_item_t *header_item2;
+        matrix_item_t *item;
+        apr_size_t j,k;
+        sink_arr = apr_palloc(context-&gt;pool,header_item1-&gt;tx_count * sizeof(mpf_audio_stream_t*));
+        for(j=0,k=0; j&lt;context-&gt;capacity &amp;&amp; k&lt;header_item1-&gt;tx_count; j++) {
+                header_item2 = &amp;context-&gt;header[j];
+                if(!header_item2-&gt;termination) {
+                        continue;
+                }
+                item = &amp;context-&gt;matrix[i][j];
+                if(!item-&gt;on) {
+                        continue;
+                }
+                sink_arr[k] = header_item2-&gt;termination-&gt;audio_stream;
+                k++;
+        }
+        return mpf_multiplier_create(
+                                header_item1-&gt;termination-&gt;audio_stream,
+                                sink_arr,
+                                header_item1-&gt;tx_count,
+                                header_item1-&gt;termination-&gt;codec_manager,
+                                context-&gt;pool);
+}
+
+static mpf_object_t* mpf_context_mixer_create(mpf_context_t *context, apr_size_t j)
+{
+        mpf_audio_stream_t **source_arr;
+        header_item_t *header_item1 = &amp;context-&gt;header[j];
+        header_item_t *header_item2;
+        matrix_item_t *item;
+        apr_size_t i,k;
+        source_arr = apr_palloc(context-&gt;pool,header_item1-&gt;rx_count * sizeof(mpf_audio_stream_t*));
+        for(i=0,k=0; i&lt;context-&gt;capacity &amp;&amp; k&lt;header_item1-&gt;rx_count; i++) {
+                header_item2 = &amp;context-&gt;header[i];
+                if(!header_item2-&gt;termination) {
+                        continue;
+                }
+                item = &amp;context-&gt;matrix[i][j];
+                if(!item-&gt;on) {
+                        continue;
+                }
+                source_arr[k] = header_item2-&gt;termination-&gt;audio_stream;
+                k++;
+        }
+        return mpf_mixer_create(
+                                source_arr,
+                                header_item1-&gt;rx_count,
+                                header_item1-&gt;termination-&gt;audio_stream,
+                                header_item1-&gt;termination-&gt;codec_manager,
+                                context-&gt;pool);
+}
+
+static APR_INLINE apt_bool_t stream_direction_compatibility_check(mpf_termination_t *termination1, mpf_termination_t *termination2)
+{
+        mpf_audio_stream_t *source = termination1-&gt;audio_stream;
+        mpf_audio_stream_t *sink = termination2-&gt;audio_stream;
+        if(source &amp;&amp; (source-&gt;direction &amp; STREAM_DIRECTION_RECEIVE) == STREAM_DIRECTION_RECEIVE &amp;&amp;
+                sink &amp;&amp; (sink-&gt;direction &amp; STREAM_DIRECTION_SEND) == STREAM_DIRECTION_SEND) {
+                return TRUE;
+        }
+        return FALSE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_decoderc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_decoder.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_decoder.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_decoder.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> struct mpf_decoder_t {
</span><span class="cx">         mpf_audio_stream_t *base;
</span><span class="cx">         mpf_audio_stream_t *source;
</span><ins>+        mpf_codec_t        *codec;
</ins><span class="cx">         mpf_frame_t         frame_in;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -32,10 +33,10 @@
</span><span class="cx">         return mpf_audio_stream_destroy(decoder-&gt;source);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_decoder_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t mpf_decoder_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         mpf_decoder_t *decoder = stream-&gt;obj;
</span><del>-        return mpf_audio_stream_rx_open(decoder-&gt;source);
</del><ins>+        return mpf_audio_stream_rx_open(decoder-&gt;source,decoder-&gt;codec);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_decoder_close(mpf_audio_stream_t *stream)
</span><span class="lines">@@ -47,21 +48,42 @@
</span><span class="cx"> static apt_bool_t mpf_decoder_process(mpf_audio_stream_t *stream, mpf_frame_t *frame)
</span><span class="cx"> {
</span><span class="cx">         mpf_decoder_t *decoder = stream-&gt;obj;
</span><ins>+        decoder-&gt;frame_in.type = MEDIA_FRAME_TYPE_NONE;
+        decoder-&gt;frame_in.marker = MPF_MARKER_NONE;
</ins><span class="cx">         if(mpf_audio_stream_frame_read(decoder-&gt;source,&amp;decoder-&gt;frame_in) != TRUE) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         frame-&gt;type = decoder-&gt;frame_in.type;
</span><ins>+        frame-&gt;marker = decoder-&gt;frame_in.marker;
</ins><span class="cx">         if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
</span><span class="cx">                 frame-&gt;event_frame = decoder-&gt;frame_in.event_frame;
</span><span class="cx">         }
</span><span class="cx">         if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) == MEDIA_FRAME_TYPE_AUDIO) {
</span><del>-                mpf_codec_decode(decoder-&gt;source-&gt;rx_codec,&amp;decoder-&gt;frame_in.codec_frame,&amp;frame-&gt;codec_frame);
</del><ins>+                mpf_codec_decode(decoder-&gt;codec,&amp;decoder-&gt;frame_in.codec_frame,&amp;frame-&gt;codec_frame);
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void mpf_decoder_trace(mpf_audio_stream_t *stream, mpf_stream_direction_e direction, apt_text_stream_t *output)
+{
+        apr_size_t offset;
+        mpf_codec_descriptor_t *descriptor;
+        mpf_decoder_t *decoder = stream-&gt;obj;
</ins><span class="cx"> 
</span><ins>+        mpf_audio_stream_trace(decoder-&gt;source,direction,output);
+
+        descriptor = decoder-&gt;base-&gt;rx_descriptor;
+        if(descriptor) {
+                offset = output-&gt;pos - output-&gt;text.buf;
+                output-&gt;pos += apr_snprintf(output-&gt;pos, output-&gt;text.length - offset,
+                        &quot;-&gt;Decoder-&gt;[%s/%d/%d]&quot;,
+                        descriptor-&gt;name.buf,
+                        descriptor-&gt;sampling_rate,
+                        descriptor-&gt;channel_count);
+        }
+}
+
</ins><span class="cx"> static const mpf_audio_stream_vtable_t vtable = {
</span><span class="cx">         mpf_decoder_destroy,
</span><span class="cx">         mpf_decoder_open,
</span><span class="lines">@@ -69,24 +91,34 @@
</span><span class="cx">         mpf_decoder_process,
</span><span class="cx">         NULL,
</span><span class="cx">         NULL,
</span><del>-        NULL
</del><ins>+        NULL,
+        mpf_decoder_trace
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_audio_stream_t*) mpf_decoder_create(mpf_audio_stream_t *source, apr_pool_t *pool)
</del><ins>+MPF_DECLARE(mpf_audio_stream_t*) mpf_decoder_create(mpf_audio_stream_t *source, mpf_codec_t *codec, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         apr_size_t frame_size;
</span><del>-        mpf_codec_t *codec;
</del><span class="cx">         mpf_decoder_t *decoder;
</span><del>-        if(!source || !source-&gt;rx_codec) {
</del><ins>+        mpf_stream_capabilities_t *capabilities;
+        if(!source || !codec) {
</ins><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx">         decoder = apr_palloc(pool,sizeof(mpf_decoder_t));
</span><del>-        decoder-&gt;base = mpf_audio_stream_create(decoder,&amp;vtable,STREAM_MODE_RECEIVE,pool);
</del><ins>+        capabilities = mpf_stream_capabilities_create(STREAM_DIRECTION_RECEIVE,pool);
+        decoder-&gt;base = mpf_audio_stream_create(decoder,&amp;vtable,capabilities,pool);
+        if(!decoder-&gt;base) {
+                return NULL;
+        }
+        decoder-&gt;base-&gt;rx_descriptor = mpf_codec_lpcm_descriptor_create(
+                source-&gt;rx_descriptor-&gt;sampling_rate,
+                source-&gt;rx_descriptor-&gt;channel_count,
+                pool);
+        decoder-&gt;base-&gt;rx_event_descriptor = source-&gt;rx_event_descriptor;
+
</ins><span class="cx">         decoder-&gt;source = source;
</span><ins>+        decoder-&gt;codec = codec;
</ins><span class="cx"> 
</span><del>-        codec = source-&gt;rx_codec;
-        frame_size = mpf_codec_frame_size_calculate(codec-&gt;descriptor,codec-&gt;attribs);
-        decoder-&gt;base-&gt;rx_codec = codec;
</del><ins>+        frame_size = mpf_codec_frame_size_calculate(source-&gt;rx_descriptor,codec-&gt;attribs);
</ins><span class="cx">         decoder-&gt;frame_in.codec_frame.size = frame_size;
</span><span class="cx">         decoder-&gt;frame_in.codec_frame.buffer = apr_palloc(pool,frame_size);
</span><span class="cx">         return decoder-&gt;base;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_dtmf_detectorc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,299 @@
</span><ins>+/*
+ * Copyright 2009 Tomas Valenta, 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_dtmf_detector.h&quot;
+#include &quot;apr_thread_mutex.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;mpf_named_event.h&quot;
+#include &lt;math.h&gt;
+
+#ifndef M_PI
+#        define M_PI 3.141592653589793238462643
+#endif
+
+/** Max detected DTMF digits buffer length */
+#define MPF_DTMFDET_BUFFER_LEN  32
+
+/** Number of DTMF frequencies */
+#define DTMF_FREQUENCIES         8
+
+/** Window length in samples (at 8kHz) for Goertzel's frequency analysis */
+#define GOERTZEL_SAMPLES_8K    102
+
+/** See RFC4733 */
+#define DTMF_EVENT_ID_MAX       15  /* 0123456789*#ABCD */
+
+/**
+ * Goertzel frequency detector (second-order IIR filter) state:
+ *
+ * s(t) = x(t) + coef * s(t-1) - s(t-2), where s(0)=0; s(1) = 0;
+ * x(t) is the input signal
+ *
+ * Then energy of frequency f in the signal is:
+ * X(f)X'(f) = s(t-2)^2 + s(t-1)^2 - coef*s(t-2)*s(t-1)
+ */
+typedef struct goertzel_state_t {
+        /** coef = cos(2*pi*f_tone/f_sampling) */
+        double coef;
+        /** s(t-2) or resulting energy @see goertzel_state_t */
+        double s1;
+        /** s(t-1) @see goertzel_state_t */
+        double s2;
+} goertzel_state_t;
+
+/** DTMF frequencies */
+static const double dtmf_freqs[DTMF_FREQUENCIES] = {
+         697,  770,  852,  941,  /* Row frequencies */
+        1209, 1336, 1477, 1633}; /* Col frequencies */
+
+/** [row, col] major frequency to digit mapping */
+static const char freq2digits[DTMF_FREQUENCIES/2][DTMF_FREQUENCIES/2] =
+        { { '1', '2', '3', 'A' },
+          { '4', '5', '6', 'B' },
+          { '7', '8', '9', 'C' },
+          { '*', '0', '#', 'D' } };
+
+/** Media Processing Framework's Dual Tone Multiple Frequncy detector */
+struct mpf_dtmf_detector_t {
+        /** Mutex to guard the buffer */
+        struct apr_thread_mutex_t     *mutex;
+        /** Recognizer band */
+        enum mpf_dtmf_detector_band_e  band;
+        /** Detected digits buffer */
+        char                           buf[MPF_DTMFDET_BUFFER_LEN+1];
+        /** Number of digits in the buffer */
+        apr_size_t                     digits;
+        /** Number of lost digits due to full buffer */
+        apr_size_t                     lost_digits;
+        /** Frequency analyzators */
+        struct goertzel_state_t        energies[DTMF_FREQUENCIES];
+        /** Total energy of signal */
+        double                         totenergy;
+        /** Number of samples in a window */
+        apr_size_t                     wsamples;
+        /** Number of samples processed */
+        apr_size_t                     nsamples;
+        /** Previously detected and last reported digits */
+        char                           last1, last2, curr;
+};
+
+
+MPF_DECLARE(struct mpf_dtmf_detector_t *) mpf_dtmf_detector_create_ex(
+                                                                const struct mpf_audio_stream_t *stream,
+                                                                enum mpf_dtmf_detector_band_e band,
+                                                                struct apr_pool_t *pool)
+{
+        apr_status_t status;
+        struct mpf_dtmf_detector_t *det;
+        int flg_band = band;
+
+        if (!stream-&gt;tx_descriptor) flg_band &amp;= ~MPF_DTMF_DETECTOR_INBAND;
+/*
+        Event descriptor is not important actually
+        if (!stream-&gt;tx_event_descriptor) flg_band &amp;= ~MPF_DTMF_DETECTOR_OUTBAND;
+*/
+        if (!flg_band) return NULL;
+
+        det = apr_palloc(pool, sizeof(mpf_dtmf_detector_t));
+        if (!det) return NULL;
+        status = apr_thread_mutex_create(&amp;det-&gt;mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+        if (status != APR_SUCCESS) return NULL;
+
+        det-&gt;band = (enum mpf_dtmf_detector_band_e) flg_band;
+        det-&gt;buf[0] = 0;
+        det-&gt;digits = 0;
+        det-&gt;lost_digits = 0;
+
+        if (det-&gt;band &amp; MPF_DTMF_DETECTOR_INBAND) {
+                apr_size_t i;
+                for (i = 0; i &lt; DTMF_FREQUENCIES; i++) {
+                        det-&gt;energies[i].coef = 2 * cos(2 * M_PI * dtmf_freqs[i] /
+                                stream-&gt;tx_descriptor-&gt;sampling_rate);
+                        det-&gt;energies[i].s1 = 0;
+                        det-&gt;energies[i].s2 = 0;
+                }
+                det-&gt;nsamples = 0;
+                det-&gt;wsamples = GOERTZEL_SAMPLES_8K * (stream-&gt;tx_descriptor-&gt;sampling_rate / 8000);
+                det-&gt;last1 = det-&gt;last2 = det-&gt;curr = 0;
+                det-&gt;totenergy = 0;
+        }
+
+        return det;
+}
+
+MPF_DECLARE(char) mpf_dtmf_detector_digit_get(struct mpf_dtmf_detector_t *detector)
+{
+        char digit;
+        apr_thread_mutex_lock(detector-&gt;mutex);
+        digit = detector-&gt;buf[0];
+        if (digit) {
+                strcpy(detector-&gt;buf, detector-&gt;buf + 1);
+                detector-&gt;digits--;
+        }
+        apr_thread_mutex_unlock(detector-&gt;mutex);
+        return digit;
+}
+
+MPF_DECLARE(apr_size_t) mpf_dtmf_detector_digits_lost(const struct mpf_dtmf_detector_t *detector)
+{
+        return detector-&gt;lost_digits;
+}
+
+MPF_DECLARE(void) mpf_dtmf_detector_reset(struct mpf_dtmf_detector_t *detector)
+{
+        apr_thread_mutex_lock(detector-&gt;mutex);
+        detector-&gt;buf[0] = 0;
+        detector-&gt;lost_digits = 0;
+        detector-&gt;digits = 0;
+        detector-&gt;curr = detector-&gt;last1 = detector-&gt;last2 = 0;
+        detector-&gt;nsamples = 0;
+        detector-&gt;totenergy = 0;
+        apr_thread_mutex_unlock(detector-&gt;mutex);
+}
+
+static APR_INLINE void mpf_dtmf_detector_add_digit(
+                                                                struct mpf_dtmf_detector_t *detector,
+                                                                char digit)
+{
+        if (!digit) return;
+        apr_thread_mutex_lock(detector-&gt;mutex);
+        if (detector-&gt;digits &lt; MPF_DTMFDET_BUFFER_LEN) {
+                detector-&gt;buf[detector-&gt;digits++] = digit;
+                detector-&gt;buf[detector-&gt;digits] = 0;
+        } else
+                detector-&gt;lost_digits++;
+        apr_thread_mutex_unlock(detector-&gt;mutex);
+}
+
+static APR_INLINE void goertzel_sample(
+                                                                struct mpf_dtmf_detector_t *detector,
+                                                                apr_int16_t sample)
+{
+        apr_size_t i;
+        double s;
+        for (i = 0; i &lt; DTMF_FREQUENCIES; i++) {
+                s = detector-&gt;energies[i].s1;
+                detector-&gt;energies[i].s1 = detector-&gt;energies[i].s2;
+                detector-&gt;energies[i].s2 = sample +
+                        detector-&gt;energies[i].coef * detector-&gt;energies[i].s1 - s;
+        }
+        detector-&gt;totenergy += sample * sample;
+}
+
+static void goertzel_energies_digit(struct mpf_dtmf_detector_t *detector)
+{
+        apr_size_t i, rmax = 0, cmax = 0;
+        double reng = 0, ceng = 0;
+        char digit = 0;
+
+        /* Calculate energies and maxims */
+        for (i = 0; i &lt; DTMF_FREQUENCIES; i++) {
+                double eng = detector-&gt;energies[i].s1 * detector-&gt;energies[i].s1 +
+                        detector-&gt;energies[i].s2 * detector-&gt;energies[i].s2 -
+                        detector-&gt;energies[i].coef * detector-&gt;energies[i].s1 * detector-&gt;energies[i].s2;
+                if (i &lt; DTMF_FREQUENCIES/2) {
+                        if (eng &gt; reng) {
+                                rmax = i;
+                                reng = eng;
+                        }
+                } else {
+                        if (eng &gt; ceng) {
+                                cmax = i;
+                                ceng = eng;
+                        }
+                }
+        }
+
+        if ((reng &lt; 8.0e8 * detector-&gt;wsamples / GOERTZEL_SAMPLES_8K) ||
+                (ceng &lt; 8.0e8 * detector-&gt;wsamples / GOERTZEL_SAMPLES_8K))
+        {
+                /* energy not high enough */
+        } else if ((ceng &gt; reng) &amp;&amp; (reng &lt; ceng * 0.398)) {  /* twist &gt; 4dB, error */
+                /* Twist check
+                 * CEPT =&gt; twist &lt; 6dB
+                 * AT&amp;T =&gt; forward twist &lt; 4dB and reverse twist &lt; 8dB
+                 *  -ndB &lt; 10 log10( v1 / v2 ), where v1 &lt; v2
+                 *  -4dB &lt; 10 log10( v1 / v2 )
+                 *  -0.4  &lt; log10( v1 / v2 )
+                 *  0.398 &lt; v1 / v2
+                 *  0.398 * v2 &lt; v1
+                 */
+        } else if ((ceng &lt; reng) &amp;&amp; (ceng &lt; reng * 0.158)) {  /* twist &gt; 8db, error */
+                /* Reverse twist check failed */
+        } else if (0.025 * detector-&gt;totenergy &gt; (reng + ceng)) {  /* 16db */
+                /* Signal energy to total energy ratio test failed */
+        } else {
+                digit = freq2digits[rmax][cmax - DTMF_FREQUENCIES/2];
+        }
+
+        /* Three successive detections will trigger the detection */
+        if (digit != detector-&gt;curr) {
+                if (digit &amp;&amp; ((detector-&gt;last1 == digit) &amp;&amp; (detector-&gt;last2 == digit))) {
+                        detector-&gt;curr = digit;
+                        mpf_dtmf_detector_add_digit(detector, digit);
+                } else if ((detector-&gt;last1 != detector-&gt;curr) &amp;&amp; (detector-&gt;last2 != detector-&gt;curr)) {
+                        detector-&gt;curr = 0;
+                }
+        }
+        detector-&gt;last1 = detector-&gt;last2;
+        detector-&gt;last2 = digit;
+
+        /* Reset Goertzel's detectors */
+        for (i = 0; i &lt; DTMF_FREQUENCIES; i++) {
+                detector-&gt;energies[i].s1 = 0;
+                detector-&gt;energies[i].s2 = 0;
+        }
+        detector-&gt;totenergy = 0;
+}
+
+MPF_DECLARE(void) mpf_dtmf_detector_get_frame(
+                                                                struct mpf_dtmf_detector_t *detector,
+                                                                const struct mpf_frame_t *frame)
+{
+        if ((detector-&gt;band &amp; MPF_DTMF_DETECTOR_OUTBAND) &amp;&amp;
+                (frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) &amp;&amp;
+                (frame-&gt;event_frame.event_id &lt;= DTMF_EVENT_ID_MAX) &amp;&amp;
+                (frame-&gt;marker == MPF_MARKER_START_OF_EVENT))
+        {
+                if (detector-&gt;band &amp; MPF_DTMF_DETECTOR_INBAND) {
+                        detector-&gt;band &amp;= ~MPF_DTMF_DETECTOR_INBAND;
+                        apt_log(APT_LOG_MARK, APT_PRIO_INFO, &quot;Out-of-band digit arrived, turning &quot;
+                                &quot;in-band DTMF detector off&quot;);
+                }
+                mpf_dtmf_detector_add_digit(detector, mpf_event_id_to_dtmf_char(
+                        frame-&gt;event_frame.event_id));
+                return;
+        }
+
+        if ((detector-&gt;band &amp; MPF_DTMF_DETECTOR_INBAND) &amp;&amp; (frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO)) {
+                apr_int16_t *samples = frame-&gt;codec_frame.buffer;
+                apr_size_t i;
+
+                for (i = 0; i &lt; frame-&gt;codec_frame.size / 2; i++) {
+                        goertzel_sample(detector, samples[i]);
+                        if (++detector-&gt;nsamples &gt;= detector-&gt;wsamples) {
+                                goertzel_energies_digit(detector);
+                                detector-&gt;nsamples = 0;
+                        }
+                }
+        }
+}
+
+MPF_DECLARE(void) mpf_dtmf_detector_destroy(struct mpf_dtmf_detector_t *detector)
+{
+        apr_thread_mutex_destroy(detector-&gt;mutex);
+        detector-&gt;mutex = NULL;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_dtmf_generatorc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,347 @@
</span><ins>+/*
+ * Copyright 2009 Tomas Valenta, 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_dtmf_generator.h&quot;
+#include &quot;apr.h&quot;
+#include &quot;apr_thread_mutex.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;mpf_named_event.h&quot;
+#include &lt;math.h&gt;
+
+#ifndef M_PI
+#        define M_PI 3.141592653589793238462643
+#endif
+
+/** Max DTMF digits waiting to be sent */
+#define MPF_DTMFGEN_QUEUE_LEN  32
+
+/** See RFC4733 */
+#define DTMF_EVENT_ID_MAX      15  /* 0123456789*#ABCD */
+
+/** See RFC4733 */
+#define DTMF_EVENT_VOLUME      10
+
+/** Amplitude of single sine wave from tone generator */
+#define DTMF_SINE_AMPLITUDE 12288
+
+/** State of the DTMF generator */
+typedef enum mpf_dtmf_generator_state_e {
+        /** Ready to generate next digit in queue */
+        DTMF_GEN_STATE_IDLE,
+        /** Generating tone */
+        DTMF_GEN_STATE_TONE,
+        /** Retransmitting final RTP packet */
+        DTMF_GEN_STATE_ENDING,
+        /** Generating silence between tones */
+        DTMF_GEN_STATE_SILENCE
+} mpf_dtmf_generator_state_e;
+
+/**
+ * Sine wave generator (second-order IIR filter) state:
+ *
+ * s(t) = Amp*sin(2*pi*f_tone/f_sampling*t)
+ *
+ * s(t) = coef * s(t-1) - s(t-2); s(0)=0; s(1)=Amp*sin(2*pi*f_tone/f_sampling)
+ */
+typedef struct sine_state_t {
+        /** coef = cos(2*pi*f_tone/f_sampling) */
+        double coef;
+        /** s(t-2) @see sine_state_t */
+        double s1;
+        /** s(t-1) @see sine_state_t */
+        double s2;
+} sine_state_t;
+
+/** Mapping event_it to frequency pair */
+static const double dtmf_freq[DTMF_EVENT_ID_MAX+1][2] = {
+        {941, 1336},  /* 0 */
+        {697, 1209},  /* 1 */
+        {697, 1336},  /* 2 */
+        {697, 1477},  /* 3 */
+        {770, 1209},  /* 4 */
+        {770, 1336},  /* 5 */
+        {770, 1477},  /* 6 */
+        {852, 1209},  /* 7 */
+        {852, 1336},  /* 8 */
+        {852, 1477},  /* 9 */
+        {941, 1209},  /* * */
+        {941, 1477},  /* # */
+        {697, 1633},  /* A */
+        {770, 1633},  /* B */
+        {852, 1633},  /* C */
+        {941, 1633}   /* D */
+};
+
+/** Media Processing Framework's Dual Tone Multiple Frequncy generator */
+struct mpf_dtmf_generator_t {
+        /** Generator state */
+        enum mpf_dtmf_generator_state_e  state;
+        /** In-band or out-of-band */
+        enum mpf_dtmf_generator_band_e   band;
+        /** Mutex to guard the queue */
+        struct apr_thread_mutex_t       *mutex;
+        /** Queue of digits to generate */
+        char                             queue[MPF_DTMFGEN_QUEUE_LEN+1];
+        /** DTMF event_id according to RFC4733 */
+        apr_byte_t                       event_id;
+        /** Duration in RTP units: (sample_rate / 1000) * milliseconds */
+        apr_uint32_t                     tone_duration;
+        /** Duration of inter-digit silence @see tone_duration */
+        apr_uint32_t                     silence_duration;
+        /** Multipurpose counter; mostly in RTP time units */
+        apr_uint32_t                     counter;
+        /** Frame duration in RTP units */
+        apr_uint32_t                     frame_duration;
+        /** RTP named event duration (0..0xFFFF) */
+        apr_uint32_t                     event_duration;
+        /** Set MPF_MARKER_NEW_SEGMENT in the next event frame */
+        apt_bool_t                       new_segment;
+        /** Lower frequency generator */
+        struct sine_state_t              sine1;
+        /** Higher frequency generator */
+        struct sine_state_t              sine2;
+        /** Sampling rate of audio in Hz; used in tone generator */
+        apr_size_t                       sample_rate_audio;
+        /** Sampling rate of telephone-events in Hz; used for timing */
+        apr_size_t                       sample_rate_events;
+        /** How often to issue event packet */
+        apr_size_t                       events_ptime;
+        /** Milliseconds elapsed since last event packet */
+        apr_size_t                       since_last_event;
+};
+
+
+MPF_DECLARE(struct mpf_dtmf_generator_t *) mpf_dtmf_generator_create_ex(
+                                                                const struct mpf_audio_stream_t *stream,
+                                                                enum mpf_dtmf_generator_band_e band,
+                                                                apr_size_t tone_ms,
+                                                                apr_size_t silence_ms,
+                                                                struct apr_pool_t *pool)
+{
+        struct mpf_dtmf_generator_t *gen;
+        apr_status_t status;
+        int flg_band = band;
+
+        if (!stream-&gt;rx_descriptor) flg_band &amp;= ~MPF_DTMF_GENERATOR_INBAND;
+        if (!stream-&gt;rx_event_descriptor) flg_band &amp;= ~MPF_DTMF_GENERATOR_OUTBAND;
+        if (!flg_band) return NULL;
+
+        gen = apr_palloc(pool, sizeof(struct mpf_dtmf_generator_t));
+        if (!gen) return NULL;
+        status = apr_thread_mutex_create(&amp;gen-&gt;mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+        if (status != APR_SUCCESS) return NULL;
+        gen-&gt;band = (enum mpf_dtmf_generator_band_e) flg_band;
+        gen-&gt;queue[0] = 0;
+        gen-&gt;state = DTMF_GEN_STATE_IDLE;
+        if (stream-&gt;rx_descriptor)
+                gen-&gt;sample_rate_audio = stream-&gt;rx_descriptor-&gt;sampling_rate;
+        gen-&gt;sample_rate_events = stream-&gt;rx_event_descriptor ?
+                stream-&gt;rx_event_descriptor-&gt;sampling_rate : gen-&gt;sample_rate_audio;
+        gen-&gt;frame_duration = gen-&gt;sample_rate_events / 1000 * CODEC_FRAME_TIME_BASE;
+        gen-&gt;tone_duration = gen-&gt;sample_rate_events / 1000 * tone_ms;
+        gen-&gt;silence_duration = gen-&gt;sample_rate_events / 1000 * silence_ms;
+        gen-&gt;events_ptime = CODEC_FRAME_TIME_BASE;  /* Should be got from event_descriptor */
+        return gen;
+}
+
+
+MPF_DECLARE(apt_bool_t) mpf_dtmf_generator_enqueue(
+                                                                struct mpf_dtmf_generator_t *generator,
+                                                                const char *digits)
+{
+        apr_size_t qlen, dlen;
+        apt_bool_t ret;
+
+        dlen = strlen(digits);
+        apr_thread_mutex_lock(generator-&gt;mutex);
+        qlen = strlen(generator-&gt;queue);
+        if (qlen + dlen &gt; MPF_DTMFGEN_QUEUE_LEN) {
+                ret = FALSE;
+                apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;DTMF queue too short (%d), &quot;
+                        &quot;cannot add %d digit%s, already has %d&quot;, MPF_DTMFGEN_QUEUE_LEN,
+                        dlen, dlen &gt; 1 ? &quot;s&quot; : &quot;&quot;, qlen);
+        } else {
+                strcpy(generator-&gt;queue + qlen, digits);
+                ret = TRUE;
+        }
+        apr_thread_mutex_unlock(generator-&gt;mutex);
+        return ret;
+}
+
+
+MPF_DECLARE(void) mpf_dtmf_generator_reset(struct mpf_dtmf_generator_t *generator)
+{
+        apr_thread_mutex_lock(generator-&gt;mutex);
+        generator-&gt;state = DTMF_GEN_STATE_IDLE;
+        generator-&gt;queue[0] = 0;
+        apr_thread_mutex_unlock(generator-&gt;mutex);
+}
+
+
+MPF_DECLARE(apt_bool_t) mpf_dtmf_generator_sending(const struct mpf_dtmf_generator_t *generator)
+{
+        return *generator-&gt;queue || ((generator-&gt;state != DTMF_GEN_STATE_IDLE) &amp;&amp;
+                (generator-&gt;state != DTMF_GEN_STATE_SILENCE));
+}
+
+
+MPF_DECLARE(apt_bool_t) mpf_dtmf_generator_put_frame(
+                                                                struct mpf_dtmf_generator_t *generator,
+                                                                struct mpf_frame_t *frame)
+{
+        apr_thread_mutex_lock(generator-&gt;mutex);
+        if ((generator-&gt;state == DTMF_GEN_STATE_IDLE) &amp;&amp; *generator-&gt;queue) {
+                /* Get next valid digit from queue */
+                do {
+                        generator-&gt;event_id = (apr_byte_t) mpf_dtmf_char_to_event_id(*generator-&gt;queue);
+                        strcpy(generator-&gt;queue, generator-&gt;queue + 1);
+                } while (*generator-&gt;queue &amp;&amp; (generator-&gt;event_id &gt; DTMF_EVENT_ID_MAX));
+                /* Reset state */
+                if (generator-&gt;event_id &lt;= DTMF_EVENT_ID_MAX) {
+                        generator-&gt;state = DTMF_GEN_STATE_TONE;
+                        generator-&gt;counter = 0;
+                        generator-&gt;event_duration = 0;
+                        generator-&gt;since_last_event = generator-&gt;events_ptime;
+                        generator-&gt;new_segment = FALSE;
+                        /* Initialize tone generator */
+                        if (generator-&gt;band &amp; MPF_DTMF_GENERATOR_INBAND) {
+                                double omega;
+
+                                omega = 2 * M_PI * dtmf_freq[generator-&gt;event_id][0] / generator-&gt;sample_rate_audio;
+                                generator-&gt;sine1.s1 = 0;
+                                generator-&gt;sine1.s2 = DTMF_SINE_AMPLITUDE * sin(omega);
+                                generator-&gt;sine1.coef = 2 * cos(omega);
+
+                                omega = 2 * M_PI * dtmf_freq[generator-&gt;event_id][1] / generator-&gt;sample_rate_audio;
+                                generator-&gt;sine2.s1 = 0;
+                                generator-&gt;sine2.s2 = DTMF_SINE_AMPLITUDE * sin(omega);
+                                generator-&gt;sine2.coef = 2 * cos(omega);
+                        }
+                }
+        }
+        apr_thread_mutex_unlock(generator-&gt;mutex);
+        if (generator-&gt;state == DTMF_GEN_STATE_IDLE) return FALSE;
+
+        if (generator-&gt;state == DTMF_GEN_STATE_TONE) {
+                generator-&gt;counter += generator-&gt;frame_duration;
+                generator-&gt;event_duration += generator-&gt;frame_duration;
+                if (generator-&gt;band &amp; MPF_DTMF_GENERATOR_INBAND) {
+                        apr_size_t i;
+                        apr_int16_t *samples = (apr_int16_t *) frame-&gt;codec_frame.buffer;
+                        double s;
+
+                        frame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+                        /* Tone generator */
+                        for (i = 0; i &lt; frame-&gt;codec_frame.size / 2; i++) {
+                                s = generator-&gt;sine1.s1;
+                                generator-&gt;sine1.s1 = generator-&gt;sine1.s2;
+                                generator-&gt;sine1.s2 = generator-&gt;sine1.coef * generator-&gt;sine1.s1 - s;
+                                samples[i] = (apr_int16_t) (s + generator-&gt;sine2.s1);
+                                s = generator-&gt;sine2.s1;
+                                generator-&gt;sine2.s1 = generator-&gt;sine2.s2;
+                                generator-&gt;sine2.s2 = generator-&gt;sine2.coef * generator-&gt;sine2.s1 - s;
+                        }
+                }
+                if (generator-&gt;band &amp; MPF_DTMF_GENERATOR_OUTBAND) {
+                        generator-&gt;since_last_event += CODEC_FRAME_TIME_BASE;
+                        if (generator-&gt;since_last_event &gt;= generator-&gt;events_ptime)
+                                generator-&gt;since_last_event = 0;
+                        else
+                                return TRUE;
+                        frame-&gt;type |= MEDIA_FRAME_TYPE_EVENT;
+                        frame-&gt;event_frame.reserved = 0;
+                        frame-&gt;event_frame.event_id = generator-&gt;event_id;
+                        frame-&gt;event_frame.volume = DTMF_EVENT_VOLUME;
+                        if (generator-&gt;counter &gt;= generator-&gt;tone_duration) {
+                                generator-&gt;state = DTMF_GEN_STATE_ENDING;
+                                generator-&gt;counter = 0;
+                                frame-&gt;event_frame.edge = 1;
+                                frame-&gt;marker = MPF_MARKER_END_OF_EVENT;
+                                if (generator-&gt;event_duration &gt; 0xFFFF) {
+                                        /* Shorten the tone a bit instead of lenghtening */
+                                        generator-&gt;new_segment = TRUE;
+                                        frame-&gt;event_frame.duration = 0xFFFF;
+                                        generator-&gt;event_duration = 0;
+                                } else
+                                        frame-&gt;event_frame.duration = generator-&gt;event_duration;
+                        } else {
+                                frame-&gt;event_frame.edge = 0;
+                                if (generator-&gt;counter == generator-&gt;frame_duration)  /* First chunk of event */
+                                        frame-&gt;marker = MPF_MARKER_START_OF_EVENT;
+                                else if (generator-&gt;new_segment) {
+                                        frame-&gt;marker = MPF_MARKER_NEW_SEGMENT;
+                                        generator-&gt;new_segment = FALSE;
+                                } else
+                                        frame-&gt;marker = MPF_MARKER_NONE;
+                                if (generator-&gt;event_duration &gt; 0xFFFF) {
+                                        frame-&gt;event_frame.duration = 0xFFFF;
+                                        generator-&gt;event_duration = 0;
+                                        generator-&gt;new_segment = TRUE;
+                                } else
+                                        frame-&gt;event_frame.duration = generator-&gt;event_duration;
+                        }
+                        return TRUE;
+                }  /* MPF_DTMF_GENERATOR_OUTBAND */
+                if (generator-&gt;counter &gt;= generator-&gt;tone_duration) {
+                        generator-&gt;state = DTMF_GEN_STATE_SILENCE;
+                        generator-&gt;counter = 0;
+                }
+                return TRUE;
+        }
+        else if (generator-&gt;state == DTMF_GEN_STATE_ENDING) {
+                generator-&gt;since_last_event += CODEC_FRAME_TIME_BASE;
+                if (generator-&gt;since_last_event &gt;= generator-&gt;events_ptime)
+                        generator-&gt;since_last_event = 0;
+                else
+                        return TRUE;
+                generator-&gt;counter++;
+                frame-&gt;type |= MEDIA_FRAME_TYPE_EVENT;
+                frame-&gt;marker = MPF_MARKER_END_OF_EVENT;
+                frame-&gt;event_frame.event_id = generator-&gt;event_id;
+                frame-&gt;event_frame.volume = DTMF_EVENT_VOLUME;
+                frame-&gt;event_frame.reserved = 0;
+                frame-&gt;event_frame.edge = 1;
+                if (generator-&gt;new_segment)
+                        /* Tone was shortened a little bit */
+                        frame-&gt;event_frame.duration = 0xFFFF;
+                else
+                        frame-&gt;event_frame.duration = generator-&gt;event_duration;
+                if (generator-&gt;counter &gt;= 2) {
+                        generator-&gt;state = DTMF_GEN_STATE_SILENCE;
+                        generator-&gt;counter *= generator-&gt;frame_duration;
+                }
+                if (generator-&gt;band &amp; MPF_DTMF_GENERATOR_INBAND) {
+                        frame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+                        memset(frame-&gt;codec_frame.buffer, 0, frame-&gt;codec_frame.size);
+                }
+                return TRUE;
+        }
+        else if (generator-&gt;state == DTMF_GEN_STATE_SILENCE) {
+                generator-&gt;counter += generator-&gt;frame_duration;
+                if (generator-&gt;counter &gt;= generator-&gt;silence_duration)
+                        generator-&gt;state = DTMF_GEN_STATE_IDLE;
+        }
+
+        return FALSE;
+}
+
+
+MPF_DECLARE(void) mpf_dtmf_generator_destroy(struct mpf_dtmf_generator_t *generator)
+{
+        mpf_dtmf_generator_reset(generator);
+        apr_thread_mutex_destroy(generator-&gt;mutex);
+        generator-&gt;mutex = NULL;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_encoderc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_encoder.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_encoder.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_encoder.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,6 +22,7 @@
</span><span class="cx"> struct mpf_encoder_t {
</span><span class="cx">         mpf_audio_stream_t *base;
</span><span class="cx">         mpf_audio_stream_t *sink;
</span><ins>+        mpf_codec_t        *codec;
</ins><span class="cx">         mpf_frame_t         frame_out;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -32,10 +33,10 @@
</span><span class="cx">         return mpf_audio_stream_destroy(encoder-&gt;sink);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_encoder_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t mpf_encoder_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         mpf_encoder_t *encoder = stream-&gt;obj;
</span><del>-        return mpf_audio_stream_tx_open(encoder-&gt;sink);
</del><ins>+        return mpf_audio_stream_tx_open(encoder-&gt;sink,encoder-&gt;codec);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_encoder_close(mpf_audio_stream_t *stream)
</span><span class="lines">@@ -49,16 +50,36 @@
</span><span class="cx">         mpf_encoder_t *encoder = stream-&gt;obj;
</span><span class="cx"> 
</span><span class="cx">         encoder-&gt;frame_out.type = frame-&gt;type;
</span><ins>+        encoder-&gt;frame_out.marker = frame-&gt;marker;
</ins><span class="cx">         if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
</span><span class="cx">                 encoder-&gt;frame_out.event_frame = frame-&gt;event_frame;
</span><span class="cx">         }
</span><span class="cx">         if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) == MEDIA_FRAME_TYPE_AUDIO) {
</span><del>-                mpf_codec_encode(encoder-&gt;sink-&gt;tx_codec,&amp;frame-&gt;codec_frame,&amp;encoder-&gt;frame_out.codec_frame);
</del><ins>+                mpf_codec_encode(encoder-&gt;codec,&amp;frame-&gt;codec_frame,&amp;encoder-&gt;frame_out.codec_frame);
</ins><span class="cx">         }
</span><span class="cx">         return mpf_audio_stream_frame_write(encoder-&gt;sink,&amp;encoder-&gt;frame_out);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void mpf_encoder_trace(mpf_audio_stream_t *stream, mpf_stream_direction_e direction, apt_text_stream_t *output)
+{
+        apr_size_t offset;
+        mpf_codec_descriptor_t *descriptor;
+        mpf_encoder_t *encoder = stream-&gt;obj;
</ins><span class="cx"> 
</span><ins>+        descriptor = encoder-&gt;base-&gt;tx_descriptor;
+        if(descriptor) {
+                offset = output-&gt;pos - output-&gt;text.buf;
+                output-&gt;pos += apr_snprintf(output-&gt;pos, output-&gt;text.length - offset,
+                        &quot;[%s/%d/%d]-&gt;Encoder-&gt;&quot;,
+                        descriptor-&gt;name.buf,
+                        descriptor-&gt;sampling_rate,
+                        descriptor-&gt;channel_count);
+        }
+
+        mpf_audio_stream_trace(encoder-&gt;sink,direction,output);
+}
+
+
</ins><span class="cx"> static const mpf_audio_stream_vtable_t vtable = {
</span><span class="cx">         mpf_encoder_destroy,
</span><span class="cx">         NULL,
</span><span class="lines">@@ -66,24 +87,34 @@
</span><span class="cx">         NULL,
</span><span class="cx">         mpf_encoder_open,
</span><span class="cx">         mpf_encoder_close,
</span><del>-        mpf_encoder_process
</del><ins>+        mpf_encoder_process,
+        mpf_encoder_trace
</ins><span class="cx"> };
</span><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_audio_stream_t*) mpf_encoder_create(mpf_audio_stream_t *sink, apr_pool_t *pool)
</del><ins>+MPF_DECLARE(mpf_audio_stream_t*) mpf_encoder_create(mpf_audio_stream_t *sink, mpf_codec_t *codec, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         apr_size_t frame_size;
</span><del>-        mpf_codec_t *codec;
</del><span class="cx">         mpf_encoder_t *encoder;
</span><del>-        if(!sink || !sink-&gt;tx_codec) {
</del><ins>+        mpf_stream_capabilities_t *capabilities;
+        if(!sink || !codec) {
</ins><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx">         encoder = apr_palloc(pool,sizeof(mpf_encoder_t));
</span><del>-        encoder-&gt;base = mpf_audio_stream_create(encoder,&amp;vtable,STREAM_MODE_SEND,pool);
</del><ins>+        capabilities = mpf_stream_capabilities_create(STREAM_DIRECTION_SEND,pool);
+        encoder-&gt;base = mpf_audio_stream_create(encoder,&amp;vtable,capabilities,pool);
+        if(!encoder-&gt;base) {
+                return NULL;
+        }
+        encoder-&gt;base-&gt;tx_descriptor = mpf_codec_lpcm_descriptor_create(
+                sink-&gt;tx_descriptor-&gt;sampling_rate,
+                sink-&gt;tx_descriptor-&gt;channel_count,
+                pool);
+        encoder-&gt;base-&gt;tx_event_descriptor = sink-&gt;tx_event_descriptor;
+        
</ins><span class="cx">         encoder-&gt;sink = sink;
</span><ins>+        encoder-&gt;codec = codec;
</ins><span class="cx"> 
</span><del>-        codec = sink-&gt;tx_codec;
-        frame_size = mpf_codec_frame_size_calculate(codec-&gt;descriptor,codec-&gt;attribs);
-        encoder-&gt;base-&gt;tx_codec = codec;
</del><ins>+        frame_size = mpf_codec_frame_size_calculate(sink-&gt;tx_descriptor,codec-&gt;attribs);
</ins><span class="cx">         encoder-&gt;frame_out.codec_frame.size = frame_size;
</span><span class="cx">         encoder-&gt;frame_out.codec_frame.buffer = apr_palloc(pool,frame_size);
</span><span class="cx">         return encoder-&gt;base;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_enginec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_engine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,13 +15,13 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_engine.h&quot;
</span><del>-#include &quot;mpf_user.h&quot;
</del><span class="cx"> #include &quot;mpf_context.h&quot;
</span><span class="cx"> #include &quot;mpf_termination.h&quot;
</span><span class="cx"> #include &quot;mpf_stream.h&quot;
</span><del>-#include &quot;mpf_timer.h&quot;
</del><ins>+#include &quot;mpf_scheduler.h&quot;
</ins><span class="cx"> #include &quot;mpf_codec_descriptor.h&quot;
</span><span class="cx"> #include &quot;mpf_codec_manager.h&quot;
</span><ins>+#include &quot;mpf_timer_manager.h&quot;
</ins><span class="cx"> #include &quot;apt_obj_list.h&quot;
</span><span class="cx"> #include &quot;apt_cyclic_queue.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="lines">@@ -34,36 +34,35 @@
</span><span class="cx">         apt_task_msg_type_e        task_msg_type;
</span><span class="cx">         apr_thread_mutex_t        *request_queue_guard;
</span><span class="cx">         apt_cyclic_queue_t        *request_queue;
</span><del>-        apt_obj_list_t            *contexts;
-        mpf_timer_t               *timer;
</del><ins>+        mpf_context_factory_t     *context_factory;
+        mpf_scheduler_t           *scheduler;
+        mpf_timer_manager_t       *timer_manager;
</ins><span class="cx">         const mpf_codec_manager_t *codec_manager;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-static void mpf_engine_main(mpf_timer_t *timer, void *data);
</del><ins>+static void mpf_engine_main(mpf_scheduler_t *scheduler, void *data);
</ins><span class="cx"> static apt_bool_t mpf_engine_destroy(apt_task_t *task);
</span><span class="cx"> static apt_bool_t mpf_engine_start(apt_task_t *task);
</span><span class="cx"> static apt_bool_t mpf_engine_terminate(apt_task_t *task);
</span><span class="cx"> static apt_bool_t mpf_engine_msg_signal(apt_task_t *task, apt_task_msg_t *msg);
</span><span class="cx"> static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg);
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_engine_contexts_destroy(mpf_engine_t *engine);
</del><span class="cx"> 
</span><del>-mpf_codec_t* mpf_codec_lpcm_create(apr_pool_t *pool);
</del><span class="cx"> mpf_codec_t* mpf_codec_l16_create(apr_pool_t *pool);
</span><span class="cx"> mpf_codec_t* mpf_codec_g711u_create(apr_pool_t *pool);
</span><span class="cx"> mpf_codec_t* mpf_codec_g711a_create(apr_pool_t *pool);
</span><span class="cx"> 
</span><del>-MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool)
</del><ins>+MPF_DECLARE(mpf_engine_t*) mpf_engine_create(unsigned long rate, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         apt_task_vtable_t *vtable;
</span><span class="cx">         apt_task_msg_pool_t *msg_pool;
</span><span class="cx">         mpf_engine_t *engine = apr_palloc(pool,sizeof(mpf_engine_t));
</span><span class="cx">         engine-&gt;pool = pool;
</span><span class="cx">         engine-&gt;request_queue = NULL;
</span><del>-        engine-&gt;contexts = NULL;
</del><ins>+        engine-&gt;context_factory = NULL;
</ins><span class="cx">         engine-&gt;codec_manager = NULL;
</span><span class="cx"> 
</span><del>-        msg_pool = apt_task_msg_pool_create_dynamic(sizeof(mpf_message_t),pool);
</del><ins>+        msg_pool = apt_task_msg_pool_create_dynamic(sizeof(mpf_message_container_t),pool);
</ins><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Create &quot;MPF_TASK_NAME);
</span><span class="cx">         engine-&gt;task = apt_task_create(engine,msg_pool,pool);
</span><span class="lines">@@ -84,14 +83,36 @@
</span><span class="cx"> 
</span><span class="cx">         engine-&gt;task_msg_type = TASK_MSG_USER;
</span><span class="cx"> 
</span><ins>+        engine-&gt;context_factory = mpf_context_factory_create(engine-&gt;pool);
</ins><span class="cx">         engine-&gt;request_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
</span><span class="cx">         apr_thread_mutex_create(&amp;engine-&gt;request_queue_guard,APR_THREAD_MUTEX_UNNESTED,engine-&gt;pool);
</span><span class="cx"> 
</span><del>-        engine-&gt;contexts = apt_list_create(engine-&gt;pool);
</del><ins>+        engine-&gt;scheduler = mpf_scheduler_create(rate,engine-&gt;pool);
+        mpf_scheduler_media_clock_set(engine-&gt;scheduler,CODEC_FRAME_TIME_BASE,mpf_engine_main,engine);
</ins><span class="cx"> 
</span><ins>+        engine-&gt;timer_manager = mpf_timer_manager_create(engine-&gt;scheduler,engine-&gt;pool);
</ins><span class="cx">         return engine;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MPF_DECLARE(mpf_context_t*) mpf_engine_context_create(
+                                                                mpf_engine_t *engine, 
+                                                                void *obj, 
+                                                                apr_size_t max_termination_count, 
+                                                                apr_pool_t *pool)
+{
+        return mpf_context_create(engine-&gt;context_factory,obj,max_termination_count,pool);
+}
+
+MPF_DECLARE(apt_bool_t) mpf_engine_context_destroy(mpf_context_t *context)
+{
+        return mpf_context_destroy(context);
+}
+
+MPF_DECLARE(void*) mpf_engine_context_object_get(mpf_context_t *context)
+{
+        return mpf_context_object_get(context);
+}
+
</ins><span class="cx"> MPF_DECLARE(apt_task_t*) mpf_task_get(mpf_engine_t *engine)
</span><span class="cx"> {
</span><span class="cx">         return engine-&gt;task;
</span><span class="lines">@@ -102,12 +123,109 @@
</span><span class="cx">         engine-&gt;task_msg_type = type;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static mpf_message_t* mpf_engine_message_get(mpf_engine_t *engine, mpf_task_msg_t **task_msg)
+{
+        mpf_message_container_t *container;
+        mpf_message_t *mpf_message;
+        if(*task_msg) {
+                container = (mpf_message_container_t*) (*task_msg)-&gt;data;
+                if(container-&gt;count &gt;= MAX_MPF_MESSAGE_COUNT) {
+                        /* container has been already filled,
+                        implicitly send the requests and get new task message */
+                        mpf_engine_message_send(engine,task_msg);
+                        return mpf_engine_message_get(engine,task_msg);
+                }
+        }
+        else {
+                *task_msg = apt_task_msg_get(engine-&gt;task);
+                container = (mpf_message_container_t*) (*task_msg)-&gt;data;
+                container-&gt;count = 0;
+        }
+
+        mpf_message = &amp;container-&gt;messages[container-&gt;count];
+        container-&gt;count++;
+        return mpf_message;
+}
+
+
+MPF_DECLARE(apt_bool_t) mpf_engine_termination_message_add(
+                                                        mpf_engine_t *engine,
+                                                        mpf_command_type_e command_id,
+                                                        mpf_context_t *context,
+                                                        mpf_termination_t *termination,
+                                                        void *descriptor,
+                                                        mpf_task_msg_t **task_msg)
+{
+        mpf_message_t *mpf_message = mpf_engine_message_get(engine,task_msg);
+        if(!mpf_message) {
+                return FALSE;
+        }
+        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
+        mpf_message-&gt;command_id = command_id;
+        mpf_message-&gt;context = context;
+        mpf_message-&gt;termination = termination;
+        mpf_message-&gt;assoc_termination = NULL;
+        mpf_message-&gt;descriptor = descriptor;
+        return TRUE;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_engine_assoc_message_add(
+                                                        mpf_engine_t *engine,
+                                                        mpf_command_type_e command_id,
+                                                        mpf_context_t *context,
+                                                        mpf_termination_t *termination,
+                                                        mpf_termination_t *assoc_termination,
+                                                        mpf_task_msg_t **task_msg)
+{
+        mpf_message_t *mpf_message = mpf_engine_message_get(engine,task_msg);
+        if(!mpf_message) {
+                return FALSE;
+        }
+        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
+        mpf_message-&gt;command_id = command_id;
+        mpf_message-&gt;context = context;
+        mpf_message-&gt;termination = termination;
+        mpf_message-&gt;assoc_termination = assoc_termination;
+        mpf_message-&gt;descriptor = NULL;
+        return TRUE;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_engine_topology_message_add(
+                                                        mpf_engine_t *engine,
+                                                        mpf_command_type_e command_id,
+                                                        mpf_context_t *context,
+                                                        mpf_task_msg_t **task_msg)
+{
+        mpf_message_t *mpf_message = mpf_engine_message_get(engine,task_msg);
+        if(!mpf_message) {
+                return FALSE;
+        }
+        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
+        mpf_message-&gt;command_id = command_id;
+        mpf_message-&gt;context = context;
+        mpf_message-&gt;termination = NULL;
+        mpf_message-&gt;assoc_termination = NULL;
+        mpf_message-&gt;descriptor = NULL;
+        return TRUE;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_engine_message_send(mpf_engine_t *engine, mpf_task_msg_t **task_msg)
+{
+        apt_bool_t status = FALSE;
+        if(*task_msg) {
+                status = apt_task_msg_signal(engine-&gt;task,*task_msg);
+                *task_msg = NULL;
+        }
+        return status;
+}
+
</ins><span class="cx"> static apt_bool_t mpf_engine_destroy(apt_task_t *task)
</span><span class="cx"> {
</span><span class="cx">         mpf_engine_t *engine = apt_task_object_get(task);
</span><span class="cx"> 
</span><del>-        apt_list_destroy(engine-&gt;contexts);
-
</del><ins>+        mpf_timer_manager_destroy(engine-&gt;timer_manager);
+        mpf_scheduler_destroy(engine-&gt;scheduler);
+        mpf_context_factory_destroy(engine-&gt;context_factory);
</ins><span class="cx">         apt_cyclic_queue_destroy(engine-&gt;request_queue);
</span><span class="cx">         apr_thread_mutex_destroy(engine-&gt;request_queue_guard);
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -117,7 +235,7 @@
</span><span class="cx"> {
</span><span class="cx">         mpf_engine_t *engine = apt_task_object_get(task);
</span><span class="cx"> 
</span><del>-        engine-&gt;timer = mpf_timer_start(CODEC_FRAME_TIME_BASE,mpf_engine_main,engine,engine-&gt;pool);
</del><ins>+        mpf_scheduler_start(engine-&gt;scheduler);
</ins><span class="cx">         apt_task_child_start(task);
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -126,28 +244,16 @@
</span><span class="cx"> {
</span><span class="cx">         mpf_engine_t *engine = apt_task_object_get(task);
</span><span class="cx"> 
</span><del>-        mpf_timer_stop(engine-&gt;timer);
-        mpf_engine_contexts_destroy(engine);
</del><ins>+        mpf_scheduler_stop(engine-&gt;scheduler);
</ins><span class="cx">         apt_task_child_terminate(task);
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_engine_contexts_destroy(mpf_engine_t *engine)
-{
-        mpf_context_t *context;
-        context = apt_list_pop_front(engine-&gt;contexts);
-        while(context) {
-                mpf_context_destroy(context);
-                
-                context = apt_list_pop_front(engine-&gt;contexts);
-        }
-        return TRUE;
-}
-
</del><span class="cx"> static apt_bool_t mpf_engine_event_raise(mpf_termination_t *termination, int event_id, void *descriptor)
</span><span class="cx"> {
</span><span class="cx">         apt_task_msg_t *task_msg;
</span><del>-        mpf_message_t *event_msg;
</del><ins>+        mpf_message_container_t *event_msg;
+        mpf_message_t *mpf_message;
</ins><span class="cx">         mpf_engine_t *engine;
</span><span class="cx">         engine = termination-&gt;event_handler_obj;
</span><span class="cx">         if(!engine) {
</span><span class="lines">@@ -156,13 +262,16 @@
</span><span class="cx"> 
</span><span class="cx">         task_msg = apt_task_msg_get(engine-&gt;task);
</span><span class="cx">         task_msg-&gt;type = engine-&gt;task_msg_type;
</span><del>-        event_msg = (mpf_message_t*) task_msg-&gt;data;
-        event_msg-&gt;command_id = event_id;
-        event_msg-&gt;message_type = MPF_MESSAGE_TYPE_EVENT;
-        event_msg-&gt;status_code = MPF_STATUS_CODE_SUCCESS;
-        event_msg-&gt;context = NULL;
-        event_msg-&gt;termination = termination;
-        event_msg-&gt;descriptor = descriptor;
</del><ins>+        event_msg = (mpf_message_container_t*) task_msg-&gt;data;
+        mpf_message = event_msg-&gt;messages;
+        event_msg-&gt;count = 1;
+
+        mpf_message-&gt;command_id = event_id;
+        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_EVENT;
+        mpf_message-&gt;status_code = MPF_STATUS_CODE_SUCCESS;
+        mpf_message-&gt;context = NULL;
+        mpf_message-&gt;termination = termination;
+        mpf_message-&gt;descriptor = descriptor;
</ins><span class="cx">         
</span><span class="cx">         return apt_task_msg_parent_signal(engine-&gt;task,task_msg);
</span><span class="cx"> }
</span><span class="lines">@@ -181,86 +290,103 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg)
</span><span class="cx"> {
</span><ins>+        apr_size_t i;
</ins><span class="cx">         mpf_engine_t *engine = apt_task_object_get(task);
</span><span class="cx">         apt_task_msg_t *response_msg;
</span><del>-        mpf_message_t *response;
</del><ins>+        mpf_message_container_t *response;
+        mpf_message_t *mpf_response;
</ins><span class="cx">         mpf_context_t *context;
</span><span class="cx">         mpf_termination_t *termination;
</span><del>-        const mpf_message_t *request = (const mpf_message_t*) msg-&gt;data;
</del><ins>+        const mpf_message_t *mpf_request;
+        const mpf_message_container_t *request = (const mpf_message_container_t*) msg-&gt;data;
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Message&quot;);
</span><del>-        if(request-&gt;message_type != MPF_MESSAGE_TYPE_REQUEST) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Invalid MPF Message Type [%d]&quot;,request-&gt;message_type);
-                return FALSE;
-        }
</del><span class="cx"> 
</span><span class="cx">         response_msg = apt_task_msg_get(engine-&gt;task);
</span><span class="cx">         response_msg-&gt;type = engine-&gt;task_msg_type;
</span><del>-        response = (mpf_message_t*) response_msg-&gt;data;
</del><ins>+        response = (mpf_message_container_t*) response_msg-&gt;data;
</ins><span class="cx">         *response = *request;
</span><del>-        response-&gt;message_type = MPF_MESSAGE_TYPE_RESPONSE;
-        response-&gt;status_code = MPF_STATUS_CODE_SUCCESS;
-        context = request-&gt;context;
-        termination = request-&gt;termination;
-        switch(request-&gt;command_id) {
-                case MPF_COMMAND_ADD:
-                {
-                        termination-&gt;event_handler_obj = engine;
-                        termination-&gt;event_handler = mpf_engine_event_raise;
-                        termination-&gt;codec_manager = engine-&gt;codec_manager;
-                        if(request-&gt;descriptor) {
-                                mpf_termination_modify(termination,request-&gt;descriptor);
</del><ins>+        for(i=0; i&lt;request-&gt;count; i++) {
+                mpf_request = &amp;request-&gt;messages[i];
+                mpf_response = &amp;response-&gt;messages[i];
+
+                if(mpf_request-&gt;message_type != MPF_MESSAGE_TYPE_REQUEST) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Invalid MPF Message Type [%d]&quot;,mpf_request-&gt;message_type);
+                        continue;
+                }
+
+                mpf_response-&gt;message_type = MPF_MESSAGE_TYPE_RESPONSE;
+                mpf_response-&gt;status_code = MPF_STATUS_CODE_SUCCESS;
+                context = mpf_request-&gt;context;
+                termination = mpf_request-&gt;termination;
+                switch(mpf_request-&gt;command_id) {
+                        case MPF_ADD_TERMINATION:
+                        {
+                                termination-&gt;event_handler_obj = engine;
+                                termination-&gt;event_handler = mpf_engine_event_raise;
+                                termination-&gt;codec_manager = engine-&gt;codec_manager;
+                                termination-&gt;timer_manager = engine-&gt;timer_manager;
+
+                                mpf_termination_add(termination,mpf_request-&gt;descriptor);
+                                if(mpf_context_termination_add(context,termination) == FALSE) {
+                                        mpf_termination_subtract(termination);
+                                        mpf_response-&gt;status_code = MPF_STATUS_CODE_FAILURE;
+                                        break;
+                                }
+                                break;
</ins><span class="cx">                         }
</span><del>-                        mpf_termination_validate(termination);
-                        if(mpf_context_termination_add(context,termination) == FALSE) {
-                                response-&gt;status_code = MPF_STATUS_CODE_FAILURE;
</del><ins>+                        case MPF_MODIFY_TERMINATION:
+                        {
+                                mpf_termination_modify(termination,mpf_request-&gt;descriptor);
</ins><span class="cx">                                 break;
</span><span class="cx">                         }
</span><del>-                        mpf_context_topology_apply(context,termination);
-                        if(context-&gt;termination_count == 1) {
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add Context&quot;);
-                                context-&gt;elem = apt_list_push_back(engine-&gt;contexts,context,context-&gt;pool);
</del><ins>+                        case MPF_SUBTRACT_TERMINATION:
+                        {
+                                if(mpf_context_termination_subtract(context,termination) == FALSE) {
+                                        mpf_response-&gt;status_code = MPF_STATUS_CODE_FAILURE;
+                                        break;
+                                }
+                                mpf_termination_subtract(termination);
+                                break;
</ins><span class="cx">                         }
</span><del>-                        break;
-                }
-                case MPF_COMMAND_SUBTRACT:
-                {
-                        mpf_context_topology_destroy(context,termination);
-                        if(mpf_context_termination_subtract(context,termination) == FALSE) {
-                                response-&gt;status_code = MPF_STATUS_CODE_FAILURE;
</del><ins>+                        case MPF_ADD_ASSOCIATION:
+                        {
+                                mpf_context_association_add(context,termination,mpf_request-&gt;assoc_termination);
</ins><span class="cx">                                 break;
</span><span class="cx">                         }
</span><del>-                        if(context-&gt;termination_count == 0) {
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Remove Context&quot;);
-                                apt_list_elem_remove(engine-&gt;contexts,context-&gt;elem);
-                                context-&gt;elem = NULL;
</del><ins>+                        case MPF_REMOVE_ASSOCIATION:
+                        {
+                                mpf_context_association_remove(context,termination,mpf_request-&gt;assoc_termination);
+                                break;
</ins><span class="cx">                         }
</span><del>-                        break;
-                }
-                case MPF_COMMAND_MODIFY:
-                {
-                        if(request-&gt;descriptor) {
-                                mpf_context_topology_destroy(context,termination);
-                                mpf_termination_modify(termination,request-&gt;descriptor);
-                                mpf_termination_validate(termination);
-                                mpf_context_topology_apply(context,termination);
</del><ins>+                        case MPF_RESET_ASSOCIATIONS:
+                        {
+                                mpf_context_associations_reset(context);
+                                break;
</ins><span class="cx">                         }
</span><del>-                        break;
</del><ins>+                        case MPF_APPLY_TOPOLOGY:
+                        {
+                                mpf_context_topology_apply(context);
+                                break;
+                        }
+                        case MPF_DESTROY_TOPOLOGY:
+                        {
+                                mpf_context_topology_destroy(context);
+                                break;
+                        }
+                        default:
+                        {
+                                mpf_response-&gt;status_code = MPF_STATUS_CODE_FAILURE;
+                        }
</ins><span class="cx">                 }
</span><del>-                default:
-                {
-                        response-&gt;status_code = MPF_STATUS_CODE_FAILURE;
-                }
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return apt_task_msg_parent_signal(engine-&gt;task,response_msg);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static void mpf_engine_main(mpf_timer_t *timer, void *data)
</del><ins>+static void mpf_engine_main(mpf_scheduler_t *scheduler, void *data)
</ins><span class="cx"> {
</span><span class="cx">         mpf_engine_t *engine = data;
</span><span class="cx">         apt_task_msg_t *msg;
</span><del>-        apt_list_elem_t *elem;
-        mpf_context_t *context;
</del><span class="cx"> 
</span><span class="cx">         /* process request queue */
</span><span class="cx">         apr_thread_mutex_lock(engine-&gt;request_queue_guard);
</span><span class="lines">@@ -273,24 +399,15 @@
</span><span class="cx">         }
</span><span class="cx">         apr_thread_mutex_unlock(engine-&gt;request_queue_guard);
</span><span class="cx"> 
</span><del>-        /* process contexts */
-        elem = apt_list_first_elem_get(engine-&gt;contexts);
-        while(elem) {
-                context = apt_list_elem_object_get(elem);
-                if(context) {
-                        mpf_context_process(context);
-                }
-                elem = apt_list_next_elem_get(engine-&gt;contexts,elem);
-        }
</del><ins>+        /* process factory of media contexts */
+        mpf_context_factory_process(engine-&gt;context_factory);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MPF_DECLARE(mpf_codec_manager_t*) mpf_engine_codec_manager_create(apr_pool_t *pool)
</span><span class="cx"> {
</span><del>-        mpf_codec_manager_t *codec_manager = mpf_codec_manager_create(3,pool);
</del><ins>+        mpf_codec_manager_t *codec_manager = mpf_codec_manager_create(4,pool);
</ins><span class="cx">         if(codec_manager) {
</span><span class="cx">                 mpf_codec_t *codec;
</span><del>-                codec = mpf_codec_lpcm_create(pool);
-                mpf_codec_manager_codec_register(codec_manager,codec);
</del><span class="cx"> 
</span><span class="cx">                 codec = mpf_codec_g711u_create(pool);
</span><span class="cx">                 mpf_codec_manager_codec_register(codec_manager,codec);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_file_termination_factoryc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,8 +23,9 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_file_termination_modify(mpf_termination_t *termination, void *descriptor)
</del><ins>+static apt_bool_t mpf_file_termination_add(mpf_termination_t *termination, void *descriptor)
</ins><span class="cx"> {
</span><ins>+        apt_bool_t status = TRUE;
</ins><span class="cx">         mpf_audio_stream_t *audio_stream = termination-&gt;audio_stream;
</span><span class="cx">         if(!audio_stream) {
</span><span class="cx">                 audio_stream = mpf_file_stream_create(termination,termination-&gt;pool);
</span><span class="lines">@@ -34,12 +35,36 @@
</span><span class="cx">                 termination-&gt;audio_stream = audio_stream;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return mpf_file_stream_modify(audio_stream,descriptor);
</del><ins>+        if(descriptor) {
+                status = mpf_file_stream_modify(audio_stream,descriptor);
+        }
+        return status;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static apt_bool_t mpf_file_termination_modify(mpf_termination_t *termination, void *descriptor)
+{
+        apt_bool_t status = TRUE;
+        mpf_audio_stream_t *audio_stream = termination-&gt;audio_stream;
+        if(!audio_stream) {
+                return FALSE;
+        }
+
+        if(descriptor) {
+                status = mpf_file_stream_modify(audio_stream,descriptor);
+        }
+        return status;
+}
+
+static apt_bool_t mpf_file_termination_subtract(mpf_termination_t *termination)
+{
+        return TRUE;
+}
+
</ins><span class="cx"> static const mpf_termination_vtable_t file_vtable = {
</span><span class="cx">         mpf_file_termination_destroy,
</span><ins>+        mpf_file_termination_add,
</ins><span class="cx">         mpf_file_termination_modify,
</span><ins>+        mpf_file_termination_subtract
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static mpf_termination_t* mpf_file_termination_create(
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_frame_bufferc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> mpf_frame_buffer_t* mpf_frame_buffer_create(apr_size_t frame_size, apr_size_t frame_count, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         apr_size_t i;
</span><ins>+        mpf_frame_t *frame;
</ins><span class="cx">         mpf_frame_buffer_t *buffer = apr_palloc(pool,sizeof(mpf_frame_buffer_t));
</span><span class="cx"> 
</span><span class="cx">         buffer-&gt;frame_size = frame_size;
</span><span class="lines">@@ -40,8 +41,10 @@
</span><span class="cx">         buffer-&gt;raw_data = apr_palloc(pool,buffer-&gt;frame_size*buffer-&gt;frame_count);
</span><span class="cx">         buffer-&gt;frames = apr_palloc(pool,sizeof(mpf_frame_t)*buffer-&gt;frame_count);
</span><span class="cx">         for(i=0; i&lt;buffer-&gt;frame_count; i++) {
</span><del>-                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;
</del><ins>+                frame = &amp;buffer-&gt;frames[i];
+                frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
+                frame-&gt;marker = MPF_MARKER_NONE;
+                frame-&gt;codec_frame.buffer = buffer-&gt;raw_data + i*buffer-&gt;frame_size;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         buffer-&gt;write_pos = buffer-&gt;read_pos = 0;
</span><span class="lines">@@ -102,6 +105,7 @@
</span><span class="cx">                 /* normal read */
</span><span class="cx">                 mpf_frame_t *src_media_frame = mpf_frame_buffer_frame_get(buffer,buffer-&gt;read_pos);
</span><span class="cx">                 media_frame-&gt;type = src_media_frame-&gt;type;
</span><ins>+                media_frame-&gt;marker = src_media_frame-&gt;marker;
</ins><span class="cx">                 if(media_frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) {
</span><span class="cx">                         media_frame-&gt;codec_frame.size = src_media_frame-&gt;codec_frame.size;
</span><span class="cx">                         memcpy(
</span><span class="lines">@@ -113,11 +117,13 @@
</span><span class="cx">                         media_frame-&gt;event_frame = src_media_frame-&gt;event_frame;
</span><span class="cx">                 }
</span><span class="cx">                 src_media_frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
</span><ins>+                src_media_frame-&gt;marker = MPF_MARKER_NONE;
</ins><span class="cx">                 buffer-&gt;read_pos ++;
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="cx">                 /* underflow */
</span><span class="cx">                 media_frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
</span><ins>+                media_frame-&gt;marker = MPF_MARKER_NONE;
</ins><span class="cx">         }
</span><span class="cx">         apr_thread_mutex_unlock(buffer-&gt;guard);
</span><span class="cx">         return TRUE;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_jitter_bufferc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,30 +16,56 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mpf_jitter_buffer.h&quot;
</span><span class="cx"> 
</span><ins>+#if ENABLE_JB_TRACE
+#define JB_TRACE printf
+#else
+static APR_INLINE void null_trace() {}
+#define JB_TRACE null_trace
+#endif
+
</ins><span class="cx"> struct mpf_jitter_buffer_t {
</span><ins>+        /* jitter buffer config */
</ins><span class="cx">         mpf_jb_config_t *config;
</span><ins>+        /* codec to be used to dissect payload */
+        mpf_codec_t     *codec;
</ins><span class="cx"> 
</span><ins>+        /* cyclic raw data */
</ins><span class="cx">         apr_byte_t      *raw_data;
</span><ins>+        /* frames (out of raw data) */
</ins><span class="cx">         mpf_frame_t     *frames;
</span><ins>+        /* number of frames */
</ins><span class="cx">         apr_size_t       frame_count;
</span><ins>+        /* frame timestamp units (samples) */
</ins><span class="cx">         apr_size_t       frame_ts;
</span><ins>+        /* frame size in bytes */
</ins><span class="cx">         apr_size_t       frame_size;
</span><span class="cx"> 
</span><ins>+        /* playout delay in timetsamp units */
</ins><span class="cx">         apr_size_t       playout_delay_ts;
</span><span class="cx"> 
</span><ins>+        /* write should be synchronized (offset calculated) */
</ins><span class="cx">         apr_byte_t       write_sync;
</span><ins>+        /* write timestamp offset */
</ins><span class="cx">         int              write_ts_offset;
</span><span class="cx">         
</span><ins>+        /* write pointer in timestamp units */
</ins><span class="cx">         apr_size_t       write_ts;
</span><ins>+        /* read pointer in timestamp units */
</ins><span class="cx">         apr_size_t       read_ts;
</span><span class="cx"> 
</span><del>-        apr_pool_t      *pool;
</del><ins>+        /* timestamp event starts at */
+        apr_size_t              event_write_base_ts;
+        /* the first (base) frame of the event */
+        mpf_named_event_frame_t event_write_base;
+        /* the last received update for the event */
+        const mpf_named_event_frame_t *event_write_update;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-mpf_jitter_buffer_t* mpf_jitter_buffer_create(mpf_jb_config_t *jb_config, mpf_codec_t *codec, apr_pool_t *pool)
</del><ins>+mpf_jitter_buffer_t* mpf_jitter_buffer_create(mpf_jb_config_t *jb_config, mpf_codec_descriptor_t *descriptor, mpf_codec_t *codec, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         size_t i;
</span><ins>+        mpf_frame_t *frame;
</ins><span class="cx">         mpf_jitter_buffer_t *jb = apr_palloc(pool,sizeof(mpf_jitter_buffer_t));
</span><span class="cx">         if(!jb_config) {
</span><span class="cx">                 /* create default jb config */
</span><span class="lines">@@ -62,24 +88,31 @@
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         jb-&gt;config = jb_config;
</span><ins>+        jb-&gt;codec = codec;
</ins><span class="cx"> 
</span><del>-        jb-&gt;frame_ts = mpf_codec_frame_samples_calculate(codec-&gt;descriptor);
-        jb-&gt;frame_size = mpf_codec_frame_size_calculate(codec-&gt;descriptor,codec-&gt;attribs);
</del><ins>+        jb-&gt;frame_ts = mpf_codec_frame_samples_calculate(descriptor);
+        jb-&gt;frame_size = mpf_codec_frame_size_calculate(descriptor,codec-&gt;attribs);
</ins><span class="cx">         jb-&gt;frame_count = jb-&gt;config-&gt;max_playout_delay / CODEC_FRAME_TIME_BASE;
</span><span class="cx">         jb-&gt;raw_data = apr_palloc(pool,jb-&gt;frame_size*jb-&gt;frame_count);
</span><span class="cx">         jb-&gt;frames = apr_palloc(pool,sizeof(mpf_frame_t)*jb-&gt;frame_count);
</span><span class="cx">         for(i=0; i&lt;jb-&gt;frame_count; i++) {
</span><del>-                jb-&gt;frames[i].type = MEDIA_FRAME_TYPE_NONE;
-                jb-&gt;frames[i].codec_frame.buffer = jb-&gt;raw_data + i*jb-&gt;frame_size;
</del><ins>+                frame = &amp;jb-&gt;frames[i];
+                frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
+                frame-&gt;marker = MPF_MARKER_NONE;
+                frame-&gt;codec_frame.buffer = jb-&gt;raw_data + i*jb-&gt;frame_size;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         jb-&gt;playout_delay_ts = jb-&gt;config-&gt;initial_playout_delay *
</span><del>-                codec-&gt;descriptor-&gt;channel_count * codec-&gt;descriptor-&gt;sampling_rate / 1000;
</del><ins>+                descriptor-&gt;channel_count * descriptor-&gt;sampling_rate / 1000;
</ins><span class="cx"> 
</span><span class="cx">         jb-&gt;write_sync = 1;
</span><span class="cx">         jb-&gt;write_ts_offset = 0;
</span><span class="cx">         jb-&gt;write_ts = jb-&gt;read_ts = 0;
</span><span class="cx"> 
</span><ins>+        jb-&gt;event_write_base_ts = 0;
+        memset(&amp;jb-&gt;event_write_base,0,sizeof(mpf_named_event_frame_t));
+        jb-&gt;event_write_update = NULL;
+
</ins><span class="cx">         return jb;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -92,6 +125,11 @@
</span><span class="cx">         jb-&gt;write_sync = 1;
</span><span class="cx">         jb-&gt;write_ts_offset = 0;
</span><span class="cx">         jb-&gt;write_ts = jb-&gt;read_ts;
</span><ins>+
+        jb-&gt;event_write_base_ts = 0;
+        memset(&amp;jb-&gt;event_write_base,0,sizeof(mpf_named_event_frame_t));
+        jb-&gt;event_write_update = NULL;
+
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -101,10 +139,8 @@
</span><span class="cx">         return &amp;jb-&gt;frames[index];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static APR_INLINE jb_result_t mpf_jitter_buffer_write_prepare(mpf_jitter_buffer_t *jb, apr_uint32_t ts, 
-                                                                                                apr_size_t *write_ts, apr_size_t *available_frame_count)
</del><ins>+static APR_INLINE jb_result_t mpf_jitter_buffer_write_prepare(mpf_jitter_buffer_t *jb, apr_uint32_t ts, apr_size_t *write_ts)
</ins><span class="cx"> {
</span><del>-        jb_result_t result = JB_OK;
</del><span class="cx">         if(jb-&gt;write_sync) {
</span><span class="cx">                 jb-&gt;write_ts_offset = ts - jb-&gt;write_ts;
</span><span class="cx">                 jb-&gt;write_sync = 0;
</span><span class="lines">@@ -115,40 +151,47 @@
</span><span class="cx">                 /* not frame alligned */
</span><span class="cx">                 return JB_DISCARD_NOT_ALLIGNED;
</span><span class="cx">         }
</span><ins>+        return JB_OK;
+}
</ins><span class="cx"> 
</span><del>-        if(*write_ts &gt;= jb-&gt;write_ts) {
-                if(*write_ts - jb-&gt;write_ts &gt; jb-&gt;frame_ts) {
</del><ins>+jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, void *buffer, apr_size_t size, apr_uint32_t ts)
+{
+        mpf_frame_t *media_frame;
+        apr_size_t write_ts;
+        apr_size_t available_frame_count;
+        jb_result_t result = mpf_jitter_buffer_write_prepare(jb,ts,&amp;write_ts);
+        if(result != JB_OK) {
+                return result;
+        }
+
+        if(write_ts &gt;= jb-&gt;write_ts) {
+                if(write_ts - jb-&gt;write_ts &gt; jb-&gt;frame_ts) {
</ins><span class="cx">                         /* gap */
</span><span class="cx">                 }
</span><span class="cx">                 /* normal write */
</span><span class="cx">         }
</span><span class="cx">         else {
</span><del>-                if(*write_ts &gt;= jb-&gt;read_ts) {
</del><ins>+                if(write_ts &gt;= jb-&gt;read_ts) {
</ins><span class="cx">                         /* backward write */
</span><span class="cx">                 }
</span><span class="cx">                 else {
</span><span class="cx">                         /* too late */
</span><del>-                        result = JB_DISCARD_TOO_LATE;
</del><ins>+                        JB_TRACE(&quot;JB write ts=%d too late\n&quot;,write_ts);
+                        return JB_DISCARD_TOO_LATE;
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        *available_frame_count = jb-&gt;frame_count - (*write_ts - jb-&gt;read_ts)/jb-&gt;frame_ts;
-        return result;
-}
-
-jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, mpf_codec_t *codec, void *buffer, apr_size_t size, apr_uint32_t ts)
-{
-        mpf_frame_t *media_frame;
-        apr_size_t write_ts;
-        apr_size_t available_frame_count = 0;
-        jb_result_t result = mpf_jitter_buffer_write_prepare(jb,ts,&amp;write_ts,&amp;available_frame_count);
-        if(result != JB_OK) {
-                return result;
</del><ins>+        available_frame_count = jb-&gt;frame_count - (write_ts - jb-&gt;read_ts)/jb-&gt;frame_ts;
+        if(available_frame_count &lt;= 0) {
+                /* too early */
+                JB_TRACE(&quot;JB write ts=%d too early\n&quot;,write_ts);
+                return JB_DISCARD_TOO_EARLY;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        JB_TRACE(&quot;JB write ts=%d size=%d\n&quot;,write_ts,size);
</ins><span class="cx">         while(available_frame_count &amp;&amp; size) {
</span><span class="cx">                 media_frame = mpf_jitter_buffer_frame_get(jb,write_ts);
</span><span class="cx">                 media_frame-&gt;codec_frame.size = jb-&gt;frame_size;
</span><del>-                if(mpf_codec_dissect(codec,&amp;buffer,&amp;size,&amp;media_frame-&gt;codec_frame) == FALSE) {
</del><ins>+                if(mpf_codec_dissect(jb-&gt;codec,&amp;buffer,&amp;size,&amp;media_frame-&gt;codec_frame) == FALSE) {
</ins><span class="cx">                         break;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -167,9 +210,84 @@
</span><span class="cx">         return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-jb_result_t mpf_jitter_buffer_write_named_event(mpf_jitter_buffer_t *jb, mpf_named_event_frame_t *named_event, apr_uint32_t ts)
</del><ins>+jb_result_t mpf_jitter_buffer_event_write(mpf_jitter_buffer_t *jb, const mpf_named_event_frame_t *named_event, apr_uint32_t ts, apr_byte_t marker)
</ins><span class="cx"> {
</span><del>-        return JB_OK;
</del><ins>+        mpf_frame_t *media_frame;
+        apr_size_t write_ts;
+        jb_result_t result = mpf_jitter_buffer_write_prepare(jb,ts,&amp;write_ts);
+        if(result != JB_OK) {
+                return result;
+        }
+
+        /* new event detection */
+        if(!marker) {
+                if(jb-&gt;event_write_base.event_id != named_event-&gt;event_id) {
+                        /* new event detected, marker is missing though */
+                        marker = 1;
+                }
+                else if(jb-&gt;event_write_base_ts != write_ts) {
+                        /* detect whether this is a new segment of the same event or new event with missing marker
+                        assuming a threshold which equals to 4 frames */
+                        if(write_ts &gt; jb-&gt;event_write_base_ts + jb-&gt;event_write_update-&gt;duration + 4*jb-&gt;frame_ts) {
+                                /* new event detected, marker is missing though */
+                                marker = 1;
+                        }
+                        else {
+                                /* new segment of the same long-lasting event detected */
+                                jb-&gt;event_write_base = *named_event;
+                                jb-&gt;event_write_update = &amp;jb-&gt;event_write_base;
+                                jb-&gt;event_write_base_ts = write_ts;
+                        }
+                }
+        }
+        if(marker) {
+                /* new event */
+                jb-&gt;event_write_base = *named_event;
+                jb-&gt;event_write_update = &amp;jb-&gt;event_write_base;
+                jb-&gt;event_write_base_ts = write_ts;
+        }
+        else {
+                /* an update */
+                if(named_event-&gt;duration &lt;= jb-&gt;event_write_update-&gt;duration) {
+                        /* ignore this update, it's either a retransmission or
+                        something from the past, which makes no sense now */
+                        return JB_OK;
+                }
+                /* calculate position in jitter buffer considering the last received event (update) */
+                write_ts += jb-&gt;event_write_update-&gt;duration;
+        }
+
+        if(write_ts &lt; jb-&gt;read_ts) {
+                /* too late */
+                JB_TRACE(&quot;JB write ts=%d event=%d duration=%d too late\n&quot;,
+                        write_ts,named_event-&gt;event_id,named_event-&gt;duration);
+                return JB_DISCARD_TOO_LATE;
+        }
+        else if( (write_ts - jb-&gt;read_ts)/jb-&gt;frame_ts &gt;= jb-&gt;frame_count) {
+                /* too early */
+                JB_TRACE(&quot;JB write ts=%d event=%d duration=%d too early\n&quot;,
+                        write_ts,named_event-&gt;event_id,named_event-&gt;duration);
+                return JB_DISCARD_TOO_EARLY;
+        }
+
+        JB_TRACE(&quot;JB write ts=%d event=%d duration=%d\n&quot;,
+                write_ts,named_event-&gt;event_id,named_event-&gt;duration);
+        media_frame = mpf_jitter_buffer_frame_get(jb,write_ts);
+        media_frame-&gt;event_frame = *named_event;
+        media_frame-&gt;type |= MEDIA_FRAME_TYPE_EVENT;
+        if(marker) {
+                media_frame-&gt;marker = MPF_MARKER_START_OF_EVENT;
+        }
+        else if(named_event-&gt;edge == 1) {
+                media_frame-&gt;marker = MPF_MARKER_END_OF_EVENT;
+        }
+        jb-&gt;event_write_update = &amp;media_frame-&gt;event_frame;
+
+        write_ts += jb-&gt;frame_ts;
+        if(write_ts &gt; jb-&gt;write_ts) {
+                jb-&gt;write_ts = write_ts;
+        }
+        return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> apt_bool_t mpf_jitter_buffer_read(mpf_jitter_buffer_t *jb, mpf_frame_t *media_frame)
</span><span class="lines">@@ -177,7 +295,9 @@
</span><span class="cx">         mpf_frame_t *src_media_frame = mpf_jitter_buffer_frame_get(jb,jb-&gt;read_ts);
</span><span class="cx">         if(jb-&gt;write_ts &gt; jb-&gt;read_ts) {
</span><span class="cx">                 /* normal read */
</span><ins>+                JB_TRACE(&quot;JB read ts=%d\n&quot;,        jb-&gt;read_ts);
</ins><span class="cx">                 media_frame-&gt;type = src_media_frame-&gt;type;
</span><ins>+                media_frame-&gt;marker = src_media_frame-&gt;marker;
</ins><span class="cx">                 if(media_frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) {
</span><span class="cx">                         media_frame-&gt;codec_frame.size = src_media_frame-&gt;codec_frame.size;
</span><span class="cx">                         memcpy(media_frame-&gt;codec_frame.buffer,src_media_frame-&gt;codec_frame.buffer,media_frame-&gt;codec_frame.size);
</span><span class="lines">@@ -188,10 +308,13 @@
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="cx">                 /* underflow */
</span><ins>+                JB_TRACE(&quot;JB read ts=%d underflow\n&quot;, jb-&gt;read_ts);
</ins><span class="cx">                 media_frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
</span><ins>+                media_frame-&gt;marker = MPF_MARKER_NONE;
</ins><span class="cx">                 jb-&gt;write_ts += jb-&gt;frame_ts;
</span><span class="cx">         }
</span><span class="cx">         src_media_frame-&gt;type = MEDIA_FRAME_TYPE_NONE;
</span><ins>+        src_media_frame-&gt;marker = MPF_MARKER_NONE;
</ins><span class="cx">         jb-&gt;read_ts += jb-&gt;frame_ts;
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_mixerc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_mixer.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_mixer.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_mixer.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,205 @@
</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;mpf_mixer.h&quot;
+#include &quot;mpf_encoder.h&quot;
+#include &quot;mpf_decoder.h&quot;
+#include &quot;mpf_resampler.h&quot;
+#include &quot;mpf_codec_manager.h&quot;
+#include &quot;apt_log.h&quot;
+
+typedef struct mpf_mixer_t mpf_mixer_t;
+
+/** MPF mixer derived from MPF object */
+struct mpf_mixer_t {
+        /** MPF mixer base */
+        mpf_object_t         base;
+        /** Array of audio sources */
+        mpf_audio_stream_t **source_arr;
+        /** Number of audio sources */
+        apr_size_t           source_count;
+        /** Audio sink */
+        mpf_audio_stream_t  *sink;
+
+        /** Frame to read from audio source */
+        mpf_frame_t          frame;
+        /** Mixed frame to write to audio sink */
+        mpf_frame_t          mix_frame;
+};
+
+static apt_bool_t mpf_frames_mix(mpf_frame_t *mix_frame, const mpf_frame_t *frame)
+{
+        apr_size_t i;
+        apr_int16_t *mix_buf = mix_frame-&gt;codec_frame.buffer;
+        const apr_int16_t *buf = frame-&gt;codec_frame.buffer;
+        apr_size_t samples = frame-&gt;codec_frame.size / sizeof(apr_int16_t);
+
+        if(mix_frame-&gt;codec_frame.size != frame-&gt;codec_frame.size) {
+                return FALSE;
+        }
+
+        if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) == MEDIA_FRAME_TYPE_AUDIO) {
+                for(i=0; i&lt;samples; i++) {
+                        /* overflow MUST be considered */
+                        mix_buf[i] = mix_buf[i] + buf[i];
+                }
+                mix_frame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+        }
+
+        return TRUE;
+}
+
+static apt_bool_t mpf_mixer_process(mpf_object_t *object)
+{
+        apr_size_t i;
+        mpf_audio_stream_t *source;
+        mpf_mixer_t *mixer = (mpf_mixer_t*) object;
+
+        mixer-&gt;mix_frame.type = MEDIA_FRAME_TYPE_NONE;
+        mixer-&gt;mix_frame.marker = MPF_MARKER_NONE;
+        memset(mixer-&gt;mix_frame.codec_frame.buffer,0,mixer-&gt;mix_frame.codec_frame.size);
+        for(i=0; i&lt;mixer-&gt;source_count; i++) {
+                source = mixer-&gt;source_arr[i];
+                if(source) {
+                        mixer-&gt;frame.type = MEDIA_FRAME_TYPE_NONE;
+                        mixer-&gt;frame.marker = MPF_MARKER_NONE;
+                        source-&gt;vtable-&gt;read_frame(source,&amp;mixer-&gt;frame);
+                        mpf_frames_mix(&amp;mixer-&gt;mix_frame,&amp;mixer-&gt;frame);
+                }
+        }
+        mixer-&gt;sink-&gt;vtable-&gt;write_frame(mixer-&gt;sink,&amp;mixer-&gt;mix_frame);
+        return TRUE;
+}
+
+static apt_bool_t mpf_mixer_destroy(mpf_object_t *object)
+{
+        apr_size_t i;
+        mpf_audio_stream_t *source;
+        mpf_mixer_t *mixer = (mpf_mixer_t*) object;
+
+        for(i=0; i&lt;mixer-&gt;source_count; i++)        {
+                source = mixer-&gt;source_arr[i];
+                if(source) {
+                        mpf_audio_stream_rx_close(source);
+                }
+        }
+        mpf_audio_stream_tx_close(mixer-&gt;sink);
+        return TRUE;
+}
+
+static void mpf_mixer_trace(mpf_object_t *object)
+{
+        mpf_mixer_t *mixer = (mpf_mixer_t*) object;
+        apr_size_t i;
+        mpf_audio_stream_t *source;
+        char buf[2048];
+        apr_size_t offset;
+
+        apt_text_stream_t output;
+        apt_text_stream_init(&amp;output,buf,sizeof(buf)-1);
+
+        for(i=0; i&lt;mixer-&gt;source_count; i++)        {
+                source = mixer-&gt;source_arr[i];
+                if(source) {
+                        mpf_audio_stream_trace(source,STREAM_DIRECTION_RECEIVE,&amp;output);
+                        if(apt_text_is_eos(&amp;output) == FALSE) {
+                                *output.pos++ = ';';
+                        }
+                }
+        }
+
+        offset = output.pos - output.text.buf;
+        output.pos += apr_snprintf(output.pos, output.text.length - offset,
+                &quot;-&gt;Mixer-&gt;&quot;);
+
+        mpf_audio_stream_trace(mixer-&gt;sink,STREAM_DIRECTION_SEND,&amp;output);
+
+        *output.pos = '\0';
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,output.text.buf);
+}
+
+MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
+                                                                mpf_audio_stream_t **source_arr, 
+                                                                apr_size_t source_count, 
+                                                                mpf_audio_stream_t *sink, 
+                                                                const mpf_codec_manager_t *codec_manager, 
+                                                                apr_pool_t *pool)
+{
+        apr_size_t i;
+        apr_size_t frame_size;
+        mpf_codec_descriptor_t *descriptor;
+        mpf_audio_stream_t *source;
+        mpf_mixer_t *mixer;
+        if(!source_arr || !source_count || !sink) {
+                return NULL;
+        }
+
+        mixer = apr_palloc(pool,sizeof(mpf_mixer_t));
+        mixer-&gt;source_arr = NULL;
+        mixer-&gt;source_count = 0;
+        mixer-&gt;sink = NULL;
+        mpf_object_init(&amp;mixer-&gt;base);
+        mixer-&gt;base.process = mpf_mixer_process;
+        mixer-&gt;base.destroy = mpf_mixer_destroy;
+        mixer-&gt;base.trace = mpf_mixer_trace;
+
+        if(mpf_audio_stream_tx_validate(sink,NULL,NULL,pool) == FALSE) {
+                return NULL;
+        }
+
+        descriptor = sink-&gt;tx_descriptor;
+        if(descriptor &amp;&amp; mpf_codec_lpcm_descriptor_match(descriptor) == FALSE) {
+                mpf_codec_t *codec = mpf_codec_manager_codec_get(codec_manager,descriptor,pool);
+                if(codec) {
+                        /* set encoder after mixer */
+                        mpf_audio_stream_t *encoder = mpf_encoder_create(sink,codec,pool);
+                        sink = encoder;
+                }
+        }
+        mixer-&gt;sink = sink;
+        mpf_audio_stream_tx_open(sink,NULL);
+
+        for(i=0; i&lt;source_count; i++)        {
+                source = source_arr[i];
+                if(!source) continue;
+
+                if(mpf_audio_stream_rx_validate(source,NULL,NULL,pool) == FALSE) {
+                        continue;
+                }
+
+                descriptor = source-&gt;rx_descriptor;
+                if(descriptor &amp;&amp; mpf_codec_lpcm_descriptor_match(descriptor) == FALSE) {
+                        mpf_codec_t *codec = mpf_codec_manager_codec_get(codec_manager,descriptor,pool);
+                        if(codec) {
+                                /* set decoder before mixer */
+                                mpf_audio_stream_t *decoder = mpf_decoder_create(source,codec,pool);
+                                source = decoder;
+                        }
+                }
+                source_arr[i] = source;
+                mpf_audio_stream_rx_open(source,NULL);
+        }
+        mixer-&gt;source_arr = source_arr;
+        mixer-&gt;source_count = source_count;
+
+        descriptor = sink-&gt;tx_descriptor;
+        frame_size = mpf_codec_linear_frame_size_calculate(descriptor-&gt;sampling_rate,descriptor-&gt;channel_count);
+        mixer-&gt;frame.codec_frame.size = frame_size;
+        mixer-&gt;frame.codec_frame.buffer = apr_palloc(pool,frame_size);
+        mixer-&gt;mix_frame.codec_frame.size = frame_size;
+        mixer-&gt;mix_frame.codec_frame.buffer = apr_palloc(pool,frame_size);
+        return &amp;mixer-&gt;base;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_multiplierc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_multiplier.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_multiplier.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_multiplier.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,182 @@
</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;mpf_multiplier.h&quot;
+#include &quot;mpf_encoder.h&quot;
+#include &quot;mpf_decoder.h&quot;
+#include &quot;mpf_resampler.h&quot;
+#include &quot;mpf_codec_manager.h&quot;
+#include &quot;apt_log.h&quot;
+
+typedef struct mpf_multiplier_t mpf_multiplier_t;
+
+/** MPF multiplier derived from MPF object */
+struct mpf_multiplier_t {
+        /** MPF multiplier base */
+        mpf_object_t         base;
+        /** Audio source */
+        mpf_audio_stream_t  *source;
+        /** Array of audio sinks */
+        mpf_audio_stream_t **sink_arr;
+        /** Number of audio sinks */
+        apr_size_t           sink_count;
+
+        /** Media frame used to read data from source and write it to sinks */
+        mpf_frame_t          frame;
+};
+
+static apt_bool_t mpf_multiplier_process(mpf_object_t *object)
+{
+        apr_size_t i;
+        mpf_audio_stream_t *sink;
+        mpf_multiplier_t *multiplier = (mpf_multiplier_t*) object;
+
+        multiplier-&gt;frame.type = MEDIA_FRAME_TYPE_NONE;
+        multiplier-&gt;frame.marker = MPF_MARKER_NONE;
+        multiplier-&gt;source-&gt;vtable-&gt;read_frame(multiplier-&gt;source,&amp;multiplier-&gt;frame);
+        
+        if((multiplier-&gt;frame.type &amp; MEDIA_FRAME_TYPE_AUDIO) == 0) {
+                memset(        multiplier-&gt;frame.codec_frame.buffer,
+                                0,
+                                multiplier-&gt;frame.codec_frame.size);
+        }
+
+        for(i=0; i&lt;multiplier-&gt;sink_count; i++)        {
+                sink = multiplier-&gt;sink_arr[i];
+                if(sink) {
+                        sink-&gt;vtable-&gt;write_frame(sink,&amp;multiplier-&gt;frame);
+                }
+        }
+        return TRUE;
+}
+
+static apt_bool_t mpf_multiplier_destroy(mpf_object_t *object)
+{
+        apr_size_t i;
+        mpf_audio_stream_t *sink;
+        mpf_multiplier_t *multiplier = (mpf_multiplier_t*) object;
+
+        mpf_audio_stream_rx_close(multiplier-&gt;source);
+        for(i=0; i&lt;multiplier-&gt;sink_count; i++)        {
+                sink = multiplier-&gt;sink_arr[i];
+                if(sink) {
+                        mpf_audio_stream_tx_close(sink);
+                }
+        }
+        return TRUE;
+}
+
+static void mpf_multiplier_trace(mpf_object_t *object)
+{
+        mpf_multiplier_t *multiplier = (mpf_multiplier_t*) object;
+        apr_size_t i;
+        mpf_audio_stream_t *sink;
+        char buf[2048];
+        apr_size_t offset;
+
+        apt_text_stream_t output;
+        apt_text_stream_init(&amp;output,buf,sizeof(buf)-1);
+
+        mpf_audio_stream_trace(multiplier-&gt;source,STREAM_DIRECTION_RECEIVE,&amp;output);
+        
+        offset = output.pos - output.text.buf;
+        output.pos += apr_snprintf(output.pos, output.text.length - offset,
+                &quot;-&gt;Multiplier-&gt;&quot;);
+
+        for(i=0; i&lt;multiplier-&gt;sink_count; i++)        {
+                sink = multiplier-&gt;sink_arr[i];
+                if(sink) {
+                        mpf_audio_stream_trace(sink,STREAM_DIRECTION_SEND,&amp;output);
+                        if(apt_text_is_eos(&amp;output) == FALSE) {
+                                *output.pos++ = ';';
+                        }
+                }
+        }
+
+        *output.pos = '\0';
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,output.text.buf);
+}
+
+MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
+                                                                mpf_audio_stream_t *source,
+                                                                mpf_audio_stream_t **sink_arr,
+                                                                apr_size_t sink_count,
+                                                                const mpf_codec_manager_t *codec_manager,
+                                                                apr_pool_t *pool)
+{
+        apr_size_t i;
+        apr_size_t frame_size;
+        mpf_codec_descriptor_t *descriptor;
+        mpf_audio_stream_t *sink;
+        mpf_multiplier_t *multiplier;
+        if(!source || !sink_arr || !sink_count) {
+                return NULL;
+        }
+
+        multiplier = apr_palloc(pool,sizeof(mpf_multiplier_t));
+        multiplier-&gt;source = NULL;
+        multiplier-&gt;sink_arr = NULL;
+        multiplier-&gt;sink_count = 0;
+        mpf_object_init(&amp;multiplier-&gt;base);
+        multiplier-&gt;base.process = mpf_multiplier_process;
+        multiplier-&gt;base.destroy = mpf_multiplier_destroy;
+        multiplier-&gt;base.trace = mpf_multiplier_trace;
+
+        if(mpf_audio_stream_rx_validate(source,NULL,NULL,pool) == FALSE) {
+                return NULL;
+        }
+
+        descriptor = source-&gt;rx_descriptor;
+        if(descriptor &amp;&amp; mpf_codec_lpcm_descriptor_match(descriptor) == FALSE) {
+                mpf_codec_t *codec = mpf_codec_manager_codec_get(codec_manager,descriptor,pool);
+                if(codec) {
+                        /* set decoder before bridge */
+                        mpf_audio_stream_t *decoder = mpf_decoder_create(source,codec,pool);
+                        source = decoder;
+                }
+        }
+        multiplier-&gt;source = source;
+        mpf_audio_stream_rx_open(source,NULL);
+        
+        for(i=0; i&lt;sink_count; i++)        {
+                sink = sink_arr[i];
+                if(!sink) continue;
+
+                if(mpf_audio_stream_tx_validate(sink,NULL,NULL,pool) == FALSE) {
+                        continue;
+                }
+
+                descriptor = sink-&gt;tx_descriptor;
+                if(descriptor &amp;&amp; mpf_codec_lpcm_descriptor_match(descriptor) == FALSE) {
+                        mpf_codec_t *codec = mpf_codec_manager_codec_get(codec_manager,descriptor,pool);
+                        if(codec) {
+                                /* set encoder after bridge */
+                                mpf_audio_stream_t *encoder = mpf_encoder_create(sink,codec,pool);
+                                sink = encoder;
+                        }
+                }
+                sink_arr[i] = sink;
+                mpf_audio_stream_tx_open(sink,NULL);
+        }
+        multiplier-&gt;sink_arr = sink_arr;
+        multiplier-&gt;sink_count = sink_count;
+        
+        descriptor = source-&gt;rx_descriptor;
+        frame_size = mpf_codec_linear_frame_size_calculate(descriptor-&gt;sampling_rate,descriptor-&gt;channel_count);
+        multiplier-&gt;frame.codec_frame.size = frame_size;
+        multiplier-&gt;frame.codec_frame.buffer = apr_palloc(pool,frame_size);
+        return &amp;multiplier-&gt;base;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_named_eventc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_named_event.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_named_event.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_named_event.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,74 @@
</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;mpf_named_event.h&quot;
+
+#define TEL_EVENT_NAME        &quot;telephone-event&quot;
+#define TEL_EVENT_NAME_LENGTH (sizeof(TEL_EVENT_NAME)-1)
+
+#define TEL_EVENT_FMTP        &quot;0-15&quot;
+#define TEL_EVENT_FMTP_LENGTH (sizeof(TEL_EVENT_FMTP)-1)
+
+
+MPF_DECLARE(mpf_codec_descriptor_t*) mpf_event_descriptor_create(apr_uint16_t sampling_rate, apr_pool_t *pool)
+{
+        mpf_codec_descriptor_t *descriptor = apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
+        mpf_codec_descriptor_init(descriptor);
+        descriptor-&gt;payload_type = 101;
+        descriptor-&gt;name.buf = TEL_EVENT_NAME;
+        descriptor-&gt;name.length = TEL_EVENT_NAME_LENGTH;
+        descriptor-&gt;sampling_rate = sampling_rate;
+        descriptor-&gt;channel_count = 1;
+        descriptor-&gt;format.buf = TEL_EVENT_FMTP;
+        descriptor-&gt;format.length = TEL_EVENT_FMTP_LENGTH;
+        return descriptor;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_event_descriptor_check(const mpf_codec_descriptor_t *descriptor)
+{
+        apt_str_t name;
+        name.buf = TEL_EVENT_NAME;
+        name.length = TEL_EVENT_NAME_LENGTH;
+        return apt_string_compare(&amp;descriptor-&gt;name,&amp;name);
+}
+
+MPF_DECLARE(apr_uint32_t) mpf_dtmf_char_to_event_id(const char dtmf_char)
+{
+        if ((dtmf_char &gt;= '0') &amp;&amp; (dtmf_char &lt;= '9'))
+                return dtmf_char - '0';
+        else if (dtmf_char == '*')
+                return 10;
+        else if (dtmf_char == '#')
+                return 11;
+        else if ((dtmf_char &gt;= 'A') &amp;&amp; (dtmf_char &lt;= 'D'))
+                return 12 + dtmf_char - 'A';
+
+        return 255; /* Invalid DTMF event */
+}
+
+MPF_DECLARE(char) mpf_event_id_to_dtmf_char(const apr_uint32_t event_id)
+{
+        if (event_id &lt;= 9)
+                return '0' + (char)event_id;
+        else if (event_id == 10)
+                return '*';
+        else if (event_id == 11)
+                return '#';
+        else if (event_id &lt;= 15)
+                return 'A' + (char)event_id - 12;
+
+        return 0; /* Not a DTMF event */
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_resamplerc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_resampler.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_resampler.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_resampler.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,26 @@
</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;mpf_resampler.h&quot;
+#include &quot;apt_log.h&quot;
+
+MPF_DECLARE(mpf_audio_stream_t*) mpf_resampler_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,
+                &quot;Currently resampling is not supported. &quot;
+                &quot;Try to configure and use the same sampling rate on both ends&quot;);
+        return NULL;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_rtp_attribsc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -38,17 +38,17 @@
</span><span class="cx">         return apt_string_table_id_find(mpf_rtp_attrib_table,RTP_ATTRIB_COUNT,attrib);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(const apt_str_t*) mpf_stream_mode_str_get(mpf_stream_mode_e direction)
</del><ins>+MPF_DECLARE(const apt_str_t*) mpf_rtp_direction_str_get(mpf_stream_direction_e direction)
</ins><span class="cx"> {
</span><span class="cx">         mpf_rtp_attrib_e attrib_id = RTP_ATTRIB_UNKNOWN;
</span><span class="cx">         switch(direction) {
</span><del>-                case STREAM_MODE_SEND:
</del><ins>+                case STREAM_DIRECTION_SEND:
</ins><span class="cx">                         attrib_id = RTP_ATTRIB_SENDONLY;
</span><span class="cx">                         break;
</span><del>-                case STREAM_MODE_RECEIVE:
</del><ins>+                case STREAM_DIRECTION_RECEIVE:
</ins><span class="cx">                         attrib_id = RTP_ATTRIB_RECVONLY;
</span><span class="cx">                         break;
</span><del>-                case STREAM_MODE_SEND_RECEIVE:
</del><ins>+                case STREAM_DIRECTION_DUPLEX:
</ins><span class="cx">                         attrib_id = RTP_ATTRIB_SENDRECV;
</span><span class="cx">                         break;
</span><span class="cx">                 default:
</span></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 (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,14 +15,33 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &lt;apr_network_io.h&gt;
</span><ins>+#include &quot;apt_net.h&quot;
</ins><span class="cx"> #include &quot;mpf_rtp_stream.h&quot;
</span><span class="cx"> #include &quot;mpf_termination.h&quot;
</span><span class="cx"> #include &quot;mpf_codec_manager.h&quot;
</span><ins>+#include &quot;mpf_timer_manager.h&quot;
</ins><span class="cx"> #include &quot;mpf_rtp_header.h&quot;
</span><ins>+#include &quot;mpf_rtcp_packet.h&quot;
</ins><span class="cx"> #include &quot;mpf_rtp_defs.h&quot;
</span><ins>+#include &quot;mpf_rtp_pt.h&quot;
</ins><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><ins>+/** Max size of RTP packet */
+#define MAX_RTP_PACKET_SIZE  1500
+/** Max size of RTCP packet */
+#define MAX_RTCP_PACKET_SIZE 1500
</ins><span class="cx"> 
</span><ins>+/* Reason strings used in RTCP BYE messages (informative only) */
+#define RTCP_BYE_SESSION_ENDED &quot;Session ended&quot;
+#define RTCP_BYE_TALKSPURT_ENDED &quot;Talskpurt ended&quot;
+
+#if ENABLE_RTP_PACKET_TRACE
+#define RTP_TRACE printf
+#else
+static APR_INLINE void null_trace() {}
+#define RTP_TRACE null_trace
+#endif
+
</ins><span class="cx"> /** RTP stream */
</span><span class="cx"> typedef struct mpf_rtp_stream_t mpf_rtp_stream_t;
</span><span class="cx"> struct mpf_rtp_stream_t {
</span><span class="lines">@@ -30,24 +49,31 @@
</span><span class="cx"> 
</span><span class="cx">         mpf_rtp_media_descriptor_t *local_media;
</span><span class="cx">         mpf_rtp_media_descriptor_t *remote_media;
</span><ins>+        mpf_media_state_e           state;
</ins><span class="cx"> 
</span><span class="cx">         rtp_transmitter_t           transmitter;
</span><span class="cx">         rtp_receiver_t              receiver;
</span><span class="cx"> 
</span><span class="cx">         mpf_rtp_config_t           *config;
</span><span class="cx"> 
</span><del>-        apr_socket_t               *socket;
-        apr_sockaddr_t             *local_sockaddr;
-        apr_sockaddr_t             *remote_sockaddr;
</del><ins>+        apr_socket_t               *rtp_socket;
+        apr_socket_t               *rtcp_socket;
+        apr_sockaddr_t             *rtp_l_sockaddr;
+        apr_sockaddr_t             *rtp_r_sockaddr;
+        apr_sockaddr_t             *rtcp_l_sockaddr;
+        apr_sockaddr_t             *rtcp_r_sockaddr;
+
+        mpf_timer_t                *rtcp_tx_timer;
+        mpf_timer_t                *rtcp_rx_timer;
</ins><span class="cx">         
</span><span class="cx">         apr_pool_t                 *pool;
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_rtp_stream_destroy(mpf_audio_stream_t *stream);
</span><del>-static apt_bool_t mpf_rtp_rx_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t mpf_rtp_rx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t mpf_rtp_rx_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t mpf_rtp_stream_receive(mpf_audio_stream_t *stream, mpf_frame_t *frame);
</span><del>-static apt_bool_t mpf_rtp_tx_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t mpf_rtp_tx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t mpf_rtp_tx_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t mpf_rtp_stream_transmit(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="lines">@@ -61,67 +87,102 @@
</span><span class="cx">         mpf_rtp_stream_transmit
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_rtp_socket_create(mpf_rtp_stream_t *stream, mpf_rtp_media_descriptor_t *local_media);
</del><ins>+static apt_bool_t mpf_rtp_socket_pair_create(mpf_rtp_stream_t *stream, mpf_rtp_media_descriptor_t *local_media);
+static void mpf_rtp_socket_pair_close(mpf_rtp_stream_t *stream);
</ins><span class="cx"> 
</span><ins>+static apt_bool_t mpf_rtcp_report_send(mpf_rtp_stream_t *stream);
+static apt_bool_t mpf_rtcp_bye_send(mpf_rtp_stream_t *stream, apt_str_t *reason);
+static void mpf_rtcp_tx_timer_proc(mpf_timer_t *timer, void *obj);
+static void mpf_rtcp_rx_timer_proc(mpf_timer_t *timer, void *obj);
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termination, mpf_rtp_config_t *config, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mpf_rtp_stream_t *rtp_stream = apr_palloc(pool,sizeof(mpf_rtp_stream_t));
</span><ins>+        mpf_stream_capabilities_t *capabilities = mpf_stream_capabilities_create(STREAM_DIRECTION_DUPLEX,pool);
+        mpf_audio_stream_t *audio_stream = mpf_audio_stream_create(rtp_stream,&amp;vtable,capabilities,pool);
+        if(!audio_stream) {
+                return NULL;
+        }
+
+        audio_stream-&gt;direction = STREAM_DIRECTION_NONE;
+        audio_stream-&gt;termination = termination;
+
+        rtp_stream-&gt;base = audio_stream;
</ins><span class="cx">         rtp_stream-&gt;pool = pool;
</span><span class="cx">         rtp_stream-&gt;config = config;
</span><span class="cx">         rtp_stream-&gt;local_media = NULL;
</span><span class="cx">         rtp_stream-&gt;remote_media = NULL;
</span><del>-        rtp_stream-&gt;socket = NULL;
-        rtp_stream-&gt;local_sockaddr = NULL;
-        rtp_stream-&gt;remote_sockaddr = NULL;
-        rtp_stream-&gt;base = mpf_audio_stream_create(rtp_stream,&amp;vtable,STREAM_MODE_NONE,pool);
-        rtp_stream-&gt;base-&gt;termination = termination;
</del><ins>+        rtp_stream-&gt;rtp_socket = NULL;
+        rtp_stream-&gt;rtcp_socket = NULL;
+        rtp_stream-&gt;rtp_l_sockaddr = NULL;
+        rtp_stream-&gt;rtp_r_sockaddr = NULL;
+        rtp_stream-&gt;rtcp_l_sockaddr = NULL;
+        rtp_stream-&gt;rtcp_r_sockaddr = NULL;
+        rtp_stream-&gt;rtcp_tx_timer = NULL;
+        rtp_stream-&gt;rtcp_rx_timer = NULL;
+        rtp_stream-&gt;state = MPF_MEDIA_DISABLED;
</ins><span class="cx">         rtp_receiver_init(&amp;rtp_stream-&gt;receiver);
</span><span class="cx">         rtp_transmitter_init(&amp;rtp_stream-&gt;transmitter);
</span><del>-        rtp_stream-&gt;transmitter.ssrc = (apr_uint32_t)apr_time_now();
</del><ins>+        rtp_stream-&gt;transmitter.sr_stat.ssrc = (apr_uint32_t)apr_time_now();
</ins><span class="cx"> 
</span><del>-        return rtp_stream-&gt;base;
</del><ins>+        if(config-&gt;rtcp == TRUE) {
+                if(config-&gt;rtcp_tx_interval) {
+                        rtp_stream-&gt;rtcp_tx_timer = mpf_timer_create(
+                                                                                termination-&gt;timer_manager,
+                                                                                mpf_rtcp_tx_timer_proc,
+                                                                                rtp_stream, pool);
+                }
+                if(config-&gt;rtcp_rx_resolution) {
+                        rtp_stream-&gt;rtcp_rx_timer = mpf_timer_create(
+                                                                                termination-&gt;timer_manager,
+                                                                                mpf_rtcp_rx_timer_proc,
+                                                                                rtp_stream, pool);
+                }
+        }
+
+        return audio_stream;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-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)
</del><ins>+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, mpf_stream_capabilities_t *capabilities)
</ins><span class="cx"> {
</span><span class="cx">         apt_bool_t status = TRUE;
</span><span class="cx">         if(!local_media) {
</span><span class="cx">                 /* local media is not specified, create the default one */
</span><span class="cx">                 local_media = apr_palloc(rtp_stream-&gt;pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                 mpf_rtp_media_descriptor_init(local_media);
</span><del>-                local_media-&gt;base.state = MPF_MEDIA_ENABLED;
-                local_media-&gt;mode = STREAM_MODE_SEND_RECEIVE;
</del><ins>+                local_media-&gt;state = MPF_MEDIA_ENABLED;
+                local_media-&gt;direction = STREAM_DIRECTION_DUPLEX;
</ins><span class="cx">         }
</span><span class="cx">         if(remote_media) {
</span><del>-                local_media-&gt;base.id = remote_media-&gt;base.id;
</del><ins>+                local_media-&gt;id = remote_media-&gt;id;
</ins><span class="cx">         }
</span><del>-        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;
</del><ins>+        if(local_media-&gt;ip.length == 0) {
+                local_media-&gt;ip = rtp_stream-&gt;config-&gt;ip;
+                local_media-&gt;ext_ip = rtp_stream-&gt;config-&gt;ext_ip;
</ins><span class="cx">         }
</span><del>-        if(local_media-&gt;base.port == 0) {
</del><ins>+        if(local_media-&gt;port == 0) {
</ins><span class="cx">                 /* RTP port management */
</span><span class="cx">                 apr_port_t first_port_in_search = rtp_stream-&gt;config-&gt;rtp_port_cur;
</span><span class="cx">                 apt_bool_t is_port_ok = FALSE;
</span><span class="cx"> 
</span><span class="cx">                 do {
</span><del>-                        local_media-&gt;base.port = rtp_stream-&gt;config-&gt;rtp_port_cur;
</del><ins>+                        local_media-&gt;port = rtp_stream-&gt;config-&gt;rtp_port_cur;
</ins><span class="cx">                         rtp_stream-&gt;config-&gt;rtp_port_cur += 2;
</span><span class="cx">                         if(rtp_stream-&gt;config-&gt;rtp_port_cur == rtp_stream-&gt;config-&gt;rtp_port_max) {
</span><span class="cx">                                 rtp_stream-&gt;config-&gt;rtp_port_cur = rtp_stream-&gt;config-&gt;rtp_port_min;
</span><span class="cx">                         }
</span><del>-                        if(mpf_rtp_socket_create(rtp_stream,local_media) == TRUE) {
</del><ins>+                        if(mpf_rtp_socket_pair_create(rtp_stream,local_media) == TRUE) {
</ins><span class="cx">                                 is_port_ok = TRUE;
</span><span class="cx">                         }
</span><span class="cx">                 } while((is_port_ok == FALSE) &amp;&amp; (first_port_in_search != rtp_stream-&gt;config-&gt;rtp_port_cur));
</span><span class="cx">                 if(is_port_ok == FALSE) {
</span><del>-                        local_media-&gt;base.state = MPF_MEDIA_DISABLED;
</del><ins>+                        local_media-&gt;state = MPF_MEDIA_DISABLED;
</ins><span class="cx">                         status = FALSE;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        else if(mpf_rtp_socket_create(rtp_stream,local_media) == FALSE) {
-                local_media-&gt;base.state = MPF_MEDIA_DISABLED;
</del><ins>+        else if(mpf_rtp_socket_pair_create(rtp_stream,local_media) == FALSE) {
+                local_media-&gt;state = MPF_MEDIA_DISABLED;
</ins><span class="cx">                 status = FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -141,20 +202,24 @@
</span><span class="cx">                                                                 &amp;rtp_stream-&gt;config-&gt;codec_list,
</span><span class="cx">                                                                 rtp_stream-&gt;pool);
</span><span class="cx">                 }
</span><ins>+                
+                if(capabilities) {
+                        mpf_codec_list_modify(&amp;local_media-&gt;codec_list,&amp;capabilities-&gt;codecs);
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         rtp_stream-&gt;local_media = local_media;
</span><span class="cx">         return status;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_rtp_stream_local_media_update(mpf_rtp_stream_t *rtp_stream, mpf_rtp_media_descriptor_t *media)
</del><ins>+static apt_bool_t mpf_rtp_stream_local_media_update(mpf_rtp_stream_t *rtp_stream, mpf_rtp_media_descriptor_t *media, mpf_stream_capabilities_t *capabilities)
</ins><span class="cx"> {
</span><span class="cx">         apt_bool_t status = TRUE;
</span><del>-        if(apt_string_compare(&amp;rtp_stream-&gt;local_media-&gt;base.ip,&amp;media-&gt;base.ip) == FALSE ||
-                rtp_stream-&gt;local_media-&gt;base.port != media-&gt;base.port) {
</del><ins>+        if(apt_string_compare(&amp;rtp_stream-&gt;local_media-&gt;ip,&amp;media-&gt;ip) == FALSE ||
+                rtp_stream-&gt;local_media-&gt;port != media-&gt;port) {
</ins><span class="cx"> 
</span><del>-                if(mpf_rtp_socket_create(rtp_stream,media) == FALSE) {
-                        media-&gt;base.state = MPF_MEDIA_DISABLED;
</del><ins>+                if(mpf_rtp_socket_pair_create(rtp_stream,media) == FALSE) {
+                        media-&gt;state = MPF_MEDIA_DISABLED;
</ins><span class="cx">                         status = FALSE;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -163,6 +228,9 @@
</span><span class="cx">                                                         rtp_stream-&gt;base-&gt;termination-&gt;codec_manager,
</span><span class="cx">                                                         &amp;media-&gt;codec_list,
</span><span class="cx">                                                         rtp_stream-&gt;pool);
</span><ins>+                if(capabilities) {
+                        mpf_codec_list_modify(&amp;media-&gt;codec_list,&amp;capabilities-&gt;codecs);
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         rtp_stream-&gt;local_media = media;
</span><span class="lines">@@ -172,20 +240,33 @@
</span><span class="cx"> static apt_bool_t mpf_rtp_stream_remote_media_update(mpf_rtp_stream_t *rtp_stream, mpf_rtp_media_descriptor_t *media)
</span><span class="cx"> {
</span><span class="cx">         apt_bool_t status = TRUE;
</span><del>-        if(!rtp_stream-&gt;remote_media || 
-                apt_string_compare(&amp;rtp_stream-&gt;remote_media-&gt;base.ip,&amp;media-&gt;base.ip) == FALSE ||
-                rtp_stream-&gt;remote_media-&gt;base.port != media-&gt;base.port) {
</del><ins>+        if(media-&gt;state == MPF_MEDIA_ENABLED) {
+                if(!rtp_stream-&gt;remote_media || 
+                        apt_string_compare(&amp;rtp_stream-&gt;remote_media-&gt;ip,&amp;media-&gt;ip) == FALSE ||
+                        rtp_stream-&gt;remote_media-&gt;port != media-&gt;port) {
</ins><span class="cx"> 
</span><del>-                rtp_stream-&gt;remote_sockaddr = NULL;
-                apr_sockaddr_info_get(
-                        &amp;rtp_stream-&gt;remote_sockaddr,
-                        media-&gt;base.ip.buf,
-                        APR_INET,
-                        media-&gt;base.port,
-                        0,
-                        rtp_stream-&gt;pool);
-                if(!rtp_stream-&gt;remote_sockaddr) {
-                        status = FALSE;
</del><ins>+                        /* update RTP port */
+                        rtp_stream-&gt;rtp_r_sockaddr = NULL;
+                        apr_sockaddr_info_get(
+                                &amp;rtp_stream-&gt;rtp_r_sockaddr,
+                                media-&gt;ip.buf,
+                                APR_INET,
+                                media-&gt;port,
+                                0,
+                                rtp_stream-&gt;pool);
+                        if(!rtp_stream-&gt;rtp_r_sockaddr) {
+                                status = FALSE;
+                        }
+
+                        /* update RTCP port */
+                        rtp_stream-&gt;rtcp_r_sockaddr = NULL;
+                        apr_sockaddr_info_get(
+                                &amp;rtp_stream-&gt;rtcp_r_sockaddr,
+                                media-&gt;ip.buf,
+                                APR_INET,
+                                media-&gt;port+1,
+                                0,
+                                rtp_stream-&gt;pool);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -195,36 +276,115 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_rtp_stream_media_negotiate(mpf_rtp_stream_t *rtp_stream)
</span><span class="cx"> {
</span><del>-        if(!rtp_stream-&gt;local_media || !rtp_stream-&gt;remote_media) {
</del><ins>+        mpf_rtp_media_descriptor_t *local_media = rtp_stream-&gt;local_media;
+        mpf_rtp_media_descriptor_t *remote_media = rtp_stream-&gt;remote_media;
+        if(!local_media || !remote_media) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        rtp_stream-&gt;local_media-&gt;base.id = rtp_stream-&gt;remote_media-&gt;base.id;
-        rtp_stream-&gt;local_media-&gt;base.state = rtp_stream-&gt;remote_media-&gt;base.state;
</del><ins>+        local_media-&gt;id = remote_media-&gt;id;
+        local_media-&gt;mid = remote_media-&gt;mid;
+        local_media-&gt;ptime = remote_media-&gt;ptime;
</ins><span class="cx"> 
</span><del>-        rtp_stream-&gt;local_media-&gt;mid = rtp_stream-&gt;remote_media-&gt;mid;
-        rtp_stream-&gt;local_media-&gt;ptime = rtp_stream-&gt;remote_media-&gt;ptime;
-        rtp_stream-&gt;local_media-&gt;mode = mpf_stream_mode_negotiate(rtp_stream-&gt;remote_media-&gt;mode);
</del><ins>+        if(rtp_stream-&gt;state == MPF_MEDIA_DISABLED &amp;&amp; remote_media-&gt;state == MPF_MEDIA_ENABLED) {
+                /* enable RTP/RTCP session */
+                rtp_stream-&gt;state = MPF_MEDIA_ENABLED;
+                if(rtp_stream-&gt;rtp_l_sockaddr) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Enable RTP Session %s:%hu&quot;,
+                                rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                                rtp_stream-&gt;rtp_l_sockaddr-&gt;port);
+                }
</ins><span class="cx"> 
</span><del>-        if(mpf_codec_list_is_empty(&amp;rtp_stream-&gt;remote_media-&gt;codec_list) == TRUE) {
-                /* no remote codecs available, initialize them according to the local codecs  */
-                mpf_codec_list_copy(&amp;rtp_stream-&gt;remote_media-&gt;codec_list,
-                                                        &amp;rtp_stream-&gt;local_media-&gt;codec_list,
-                                                        rtp_stream-&gt;pool);
</del><ins>+                if(rtp_stream-&gt;rtcp_tx_timer) {
+                        mpf_timer_set(rtp_stream-&gt;rtcp_tx_timer,rtp_stream-&gt;config-&gt;rtcp_tx_interval);
+                }
+                if(rtp_stream-&gt;rtcp_rx_timer) {
+                        mpf_timer_set(rtp_stream-&gt;rtcp_rx_timer,rtp_stream-&gt;config-&gt;rtcp_rx_resolution);
+                }
</ins><span class="cx">         }
</span><ins>+        else if(rtp_stream-&gt;state == MPF_MEDIA_ENABLED &amp;&amp; remote_media-&gt;state == MPF_MEDIA_DISABLED) {
+                /* disable RTP/RTCP session */
+                rtp_stream-&gt;state = MPF_MEDIA_DISABLED;
+                if(rtp_stream-&gt;rtp_l_sockaddr) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Disable RTP Session %s:%hu&quot;,
+                                rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                                rtp_stream-&gt;rtp_l_sockaddr-&gt;port);
+                }
</ins><span class="cx"> 
</span><del>-        /* intersect local and remote codecs */
-        if(rtp_stream-&gt;config-&gt;own_preferrence == TRUE) {
-                mpf_codec_list_intersect(&amp;rtp_stream-&gt;local_media-&gt;codec_list,&amp;rtp_stream-&gt;remote_media-&gt;codec_list);
</del><ins>+                if(rtp_stream-&gt;rtcp_tx_timer) {
+                        mpf_timer_kill(rtp_stream-&gt;rtcp_tx_timer);
+                }
+                if(rtp_stream-&gt;rtcp_rx_timer) {
+                        mpf_timer_kill(rtp_stream-&gt;rtcp_rx_timer);
+                }
+                if(rtp_stream-&gt;config-&gt;rtcp == TRUE &amp;&amp; rtp_stream-&gt;config-&gt;rtcp_bye_policy != RTCP_BYE_DISABLE) {
+                        apt_str_t reason = {RTCP_BYE_SESSION_ENDED, sizeof(RTCP_BYE_SESSION_ENDED)-1};
+                        mpf_rtcp_bye_send(rtp_stream,&amp;reason);
+                }
</ins><span class="cx">         }
</span><del>-        else {
-                mpf_codec_list_intersect(&amp;rtp_stream-&gt;remote_media-&gt;codec_list,&amp;rtp_stream-&gt;local_media-&gt;codec_list);
</del><ins>+
+        local_media-&gt;state = remote_media-&gt;state;
+        local_media-&gt;direction = mpf_stream_reverse_direction_get(remote_media-&gt;direction);
+        rtp_stream-&gt;base-&gt;direction = local_media-&gt;direction;
+
+        if(remote_media-&gt;state == MPF_MEDIA_ENABLED) {
+                if(mpf_codec_list_is_empty(&amp;remote_media-&gt;codec_list) == TRUE) {
+                        /* no remote codecs available, initialize them according to the local codecs  */
+                        mpf_codec_list_copy(&amp;remote_media-&gt;codec_list,
+                                                                &amp;local_media-&gt;codec_list,
+                                                                rtp_stream-&gt;pool);
+                }
+
+                /* intersect local and remote codecs */
+                if(rtp_stream-&gt;config-&gt;own_preferrence == TRUE) {
+                        mpf_codec_lists_intersect(
+                                &amp;local_media-&gt;codec_list,
+                                &amp;remote_media-&gt;codec_list);
+                }
+                else {
+                        mpf_codec_lists_intersect(
+                                &amp;remote_media-&gt;codec_list,
+                                &amp;local_media-&gt;codec_list);
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        rtp_stream-&gt;base-&gt;mode = rtp_stream-&gt;local_media-&gt;mode;
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+MPF_DECLARE(apt_bool_t) mpf_rtp_stream_add(mpf_audio_stream_t *stream)
+{
+        return TRUE;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_rtp_stream_remove(mpf_audio_stream_t *stream)
+{
+        mpf_rtp_stream_t *rtp_stream = stream-&gt;obj;
+        
+        if(rtp_stream-&gt;state == MPF_MEDIA_ENABLED) {
+                /* disable RTP/RTCP session */
+                rtp_stream-&gt;state = MPF_MEDIA_DISABLED;
+                if(rtp_stream-&gt;rtp_l_sockaddr) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove RTP Session %s:%hu&quot;,
+                                rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                                rtp_stream-&gt;rtp_l_sockaddr-&gt;port);
+                }
+
+                if(rtp_stream-&gt;rtcp_tx_timer) {
+                        mpf_timer_kill(rtp_stream-&gt;rtcp_tx_timer);
+                }
+                if(rtp_stream-&gt;rtcp_rx_timer) {
+                        mpf_timer_kill(rtp_stream-&gt;rtcp_rx_timer);
+                }
+                if(rtp_stream-&gt;config-&gt;rtcp == TRUE &amp;&amp; rtp_stream-&gt;config-&gt;rtcp_bye_policy != RTCP_BYE_DISABLE) {
+                        apt_str_t reason = {RTCP_BYE_SESSION_ENDED, sizeof(RTCP_BYE_SESSION_ENDED)-1};
+                        mpf_rtcp_bye_send(rtp_stream,&amp;reason);
+                }
+        }
+        
+        mpf_rtp_socket_pair_close(rtp_stream);
+        return TRUE;
+}
+
</ins><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_rtp_stream_modify(mpf_audio_stream_t *stream, mpf_rtp_stream_descriptor_t *descriptor)
</span><span class="cx"> {
</span><span class="cx">         apt_bool_t status = TRUE;
</span><span class="lines">@@ -235,11 +395,11 @@
</span><span class="cx"> 
</span><span class="cx">         if(!rtp_stream-&gt;local_media) {
</span><span class="cx">                 /* create local media */
</span><del>-                status = mpf_rtp_stream_local_media_create(rtp_stream,descriptor-&gt;local,descriptor-&gt;remote);
</del><ins>+                status = mpf_rtp_stream_local_media_create(rtp_stream,descriptor-&gt;local,descriptor-&gt;remote,descriptor-&gt;capabilities);
</ins><span class="cx">         }
</span><span class="cx">         else if(descriptor-&gt;local) {
</span><span class="cx">                 /* update local media */
</span><del>-                status = mpf_rtp_stream_local_media_update(rtp_stream,descriptor-&gt;local);
</del><ins>+                status = mpf_rtp_stream_local_media_update(rtp_stream,descriptor-&gt;local,descriptor-&gt;capabilities);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if(descriptor-&gt;remote &amp;&amp; status == TRUE) {
</span><span class="lines">@@ -250,21 +410,23 @@
</span><span class="cx">                 mpf_rtp_stream_media_negotiate(rtp_stream);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if((rtp_stream-&gt;base-&gt;mode &amp; STREAM_MODE_SEND) == STREAM_MODE_SEND) {
-                rtp_stream-&gt;base-&gt;tx_codec = mpf_codec_manager_codec_get(
-                                                                rtp_stream-&gt;base-&gt;termination-&gt;codec_manager,
-                                                                rtp_stream-&gt;remote_media-&gt;codec_list.preffered,
-                                                                rtp_stream-&gt;pool);
-                if(rtp_stream-&gt;base-&gt;tx_codec) {
</del><ins>+        if((rtp_stream-&gt;base-&gt;direction &amp; STREAM_DIRECTION_SEND) == STREAM_DIRECTION_SEND) {
+                mpf_codec_list_t *codec_list = &amp;rtp_stream-&gt;remote_media-&gt;codec_list;
+                rtp_stream-&gt;base-&gt;tx_descriptor = codec_list-&gt;primary_descriptor;
+                if(rtp_stream-&gt;base-&gt;tx_descriptor) {
</ins><span class="cx">                         rtp_stream-&gt;transmitter.samples_per_frame = 
</span><del>-                                (apr_uint32_t)mpf_codec_frame_samples_calculate(rtp_stream-&gt;base-&gt;tx_codec-&gt;descriptor);
</del><ins>+                                (apr_uint32_t)mpf_codec_frame_samples_calculate(rtp_stream-&gt;base-&gt;tx_descriptor);
</ins><span class="cx">                 }
</span><ins>+                if(codec_list-&gt;event_descriptor) {
+                        rtp_stream-&gt;base-&gt;tx_event_descriptor = codec_list-&gt;event_descriptor;
+                }
</ins><span class="cx">         }
</span><del>-        if((rtp_stream-&gt;base-&gt;mode &amp; STREAM_MODE_RECEIVE) == STREAM_MODE_RECEIVE) {
-                rtp_stream-&gt;base-&gt;rx_codec = mpf_codec_manager_codec_get(
-                                                                rtp_stream-&gt;base-&gt;termination-&gt;codec_manager,
-                                                                rtp_stream-&gt;local_media-&gt;codec_list.preffered,
-                                                                rtp_stream-&gt;pool);
</del><ins>+        if((rtp_stream-&gt;base-&gt;direction &amp; STREAM_DIRECTION_RECEIVE) == STREAM_DIRECTION_RECEIVE) {
+                mpf_codec_list_t *codec_list = &amp;rtp_stream-&gt;local_media-&gt;codec_list;
+                rtp_stream-&gt;base-&gt;rx_descriptor = codec_list-&gt;primary_descriptor;
+                if(codec_list-&gt;event_descriptor) {
+                        rtp_stream-&gt;base-&gt;rx_event_descriptor = codec_list-&gt;event_descriptor;
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(!descriptor-&gt;local) {
</span><span class="lines">@@ -273,35 +435,31 @@
</span><span class="cx">         return status;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> static apt_bool_t mpf_rtp_stream_destroy(mpf_audio_stream_t *stream)
</span><span class="cx"> {
</span><del>-        mpf_rtp_stream_t *rtp_stream = stream-&gt;obj;
-        if(rtp_stream-&gt;socket) {
-                apr_socket_close(rtp_stream-&gt;socket);
-                rtp_stream-&gt;socket = NULL;
-        }
-        
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_rtp_rx_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t mpf_rtp_rx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         mpf_rtp_stream_t *rtp_stream = stream-&gt;obj;
</span><span class="cx">         rtp_receiver_t *receiver = &amp;rtp_stream-&gt;receiver;
</span><del>-        if(!rtp_stream-&gt;socket || !rtp_stream-&gt;local_media) {
</del><ins>+        if(!rtp_stream-&gt;rtp_socket || !rtp_stream-&gt;rtp_l_sockaddr || !rtp_stream-&gt;rtp_r_sockaddr) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         receiver-&gt;jb = mpf_jitter_buffer_create(
</span><span class="cx">                                                 &amp;rtp_stream-&gt;config-&gt;jb_config,
</span><del>-                                                stream-&gt;rx_codec,
</del><ins>+                                                stream-&gt;rx_descriptor,
+                                                codec,
</ins><span class="cx">                                                 rtp_stream-&gt;pool);
</span><span class="cx"> 
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open RTP Receive %s:%hu &lt;- %s:%hu playout [%d ms]&quot;,
-                        rtp_stream-&gt;local_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;local_media-&gt;base.port,
-                        rtp_stream-&gt;remote_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;remote_media-&gt;base.port,
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open RTP Receiver %s:%hu &lt;- %s:%hu playout [%d ms]&quot;,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;port,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;port,
</ins><span class="cx">                         rtp_stream-&gt;config-&gt;jb_config.initial_playout_delay);
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -310,6 +468,11 @@
</span><span class="cx"> {
</span><span class="cx">         mpf_rtp_stream_t *rtp_stream = stream-&gt;obj;
</span><span class="cx">         rtp_receiver_t *receiver = &amp;rtp_stream-&gt;receiver;
</span><ins>+
+        if(!rtp_stream-&gt;rtp_l_sockaddr || !rtp_stream-&gt;rtp_r_sockaddr) {
+                return FALSE;
+        }
+
</ins><span class="cx">         receiver-&gt;stat.lost_packets = 0;
</span><span class="cx">         if(receiver-&gt;stat.received_packets) {
</span><span class="cx">                 apr_uint32_t expected_packets = receiver-&gt;history.seq_cycles + 
</span><span class="lines">@@ -320,14 +483,14 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         mpf_jitter_buffer_destroy(receiver-&gt;jb);
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close RTP Receive %s:%hu &lt;- %s:%hu [r:%lu l:%lu j:%lu]&quot;,
-                        rtp_stream-&gt;local_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;local_media-&gt;base.port,
-                        rtp_stream-&gt;remote_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;remote_media-&gt;base.port,
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close RTP Receiver %s:%hu &lt;- %s:%hu [r:%lu l:%lu j:%lu]&quot;,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;port,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;port,
</ins><span class="cx">                         receiver-&gt;stat.received_packets,
</span><span class="cx">                         receiver-&gt;stat.lost_packets,
</span><del>-                        receiver-&gt;stat.jitter);
</del><ins>+                        receiver-&gt;rr_stat.jitter);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -341,7 +504,7 @@
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE void rtp_rx_stat_init(rtp_receiver_t *receiver, rtp_header_t *header, apr_time_t *time)
</span><span class="cx"> {
</span><del>-        receiver-&gt;stat.ssrc = header-&gt;ssrc;
</del><ins>+        receiver-&gt;rr_stat.ssrc = header-&gt;ssrc;
</ins><span class="cx">         receiver-&gt;history.seq_num_base = receiver-&gt;history.seq_num_max = (apr_uint16_t)header-&gt;sequence;
</span><span class="cx">         receiver-&gt;history.ts_last = header-&gt;timestamp;
</span><span class="cx">         receiver-&gt;history.time_last = *time;
</span><span class="lines">@@ -385,6 +548,54 @@
</span><span class="cx">         return header;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static APR_INLINE void rtp_periodic_history_update(rtp_receiver_t *receiver)
+{
+        apr_uint32_t expected_packets;
+        apr_uint32_t expected_interval;
+        apr_uint32_t received_interval;
+        apr_uint32_t lost_interval;
+
+        /* calculate expected packets */
+        expected_packets = receiver-&gt;history.seq_cycles + 
+                receiver-&gt;history.seq_num_max - receiver-&gt;history.seq_num_base + 1;
+
+        /* calculate expected interval */
+        expected_interval = expected_packets - receiver-&gt;periodic_history.expected_prior;
+        /* update expected prior */
+        receiver-&gt;periodic_history.expected_prior = expected_packets;
+
+        /* calculate received interval */
+        received_interval = receiver-&gt;stat.received_packets - receiver-&gt;periodic_history.received_prior;
+        /* update received prior */
+        receiver-&gt;periodic_history.received_prior = receiver-&gt;stat.received_packets;
+        /* calculate lost interval */
+        if(expected_interval &gt; received_interval) {
+                lost_interval = expected_interval - received_interval;
+        }
+        else {
+                lost_interval = 0;
+        }
+
+        /* update lost fraction */
+        if(expected_interval == 0 || lost_interval == 0) {
+                receiver-&gt;rr_stat.fraction = 0;
+        }
+        else {
+                receiver-&gt;rr_stat.fraction = (lost_interval &lt;&lt; 8) / expected_interval;
+        }
+
+        if(expected_packets &gt; receiver-&gt;stat.received_packets) {
+                receiver-&gt;rr_stat.lost = expected_packets - receiver-&gt;stat.received_packets;
+        }
+        else {
+                receiver-&gt;rr_stat.lost = 0;
+        }
+
+        receiver-&gt;periodic_history.discarded_prior = receiver-&gt;stat.discarded_packets;
+        receiver-&gt;periodic_history.jitter_min = receiver-&gt;rr_stat.jitter;
+        receiver-&gt;periodic_history.jitter_max = receiver-&gt;rr_stat.jitter;
+}
+
</ins><span class="cx"> typedef enum {
</span><span class="cx">         RTP_SSRC_UPDATE,
</span><span class="cx">         RTP_SSRC_PROBATION,
</span><span class="lines">@@ -393,7 +604,7 @@
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE rtp_ssrc_result_e rtp_rx_ssrc_update(rtp_receiver_t *receiver, apr_uint32_t ssrc)
</span><span class="cx"> {
</span><del>-        if(receiver-&gt;stat.ssrc == ssrc) {
</del><ins>+        if(receiver-&gt;rr_stat.ssrc == ssrc) {
</ins><span class="cx">                 /* known ssrc */
</span><span class="cx">                 if(receiver-&gt;history.ssrc_probation) {
</span><span class="cx">                         /* reset the probation for new ssrc */
</span><span class="lines">@@ -405,7 +616,7 @@
</span><span class="cx">                 if(receiver-&gt;history.ssrc_new == ssrc) {
</span><span class="cx">                         if(--receiver-&gt;history.ssrc_probation == 0) {
</span><span class="cx">                                 /* restart with new ssrc */
</span><del>-                                receiver-&gt;stat.ssrc = ssrc;
</del><ins>+                                receiver-&gt;rr_stat.ssrc = ssrc;
</ins><span class="cx">                                 return RTP_SSRC_RESTART;
</span><span class="cx">                         }
</span><span class="cx">                         else {
</span><span class="lines">@@ -449,12 +660,6 @@
</span><span class="cx">         }
</span><span class="cx">         receiver-&gt;stat.received_packets++;
</span><span class="cx"> 
</span><del>-        if(receiver-&gt;stat.received_packets - receiver-&gt;periodic_history.received_prior &gt;= 50) {
-                receiver-&gt;periodic_history.received_prior = receiver-&gt;stat.received_packets;
-                receiver-&gt;periodic_history.discarded_prior = receiver-&gt;stat.discarded_packets;
-                receiver-&gt;periodic_history.jitter_min = receiver-&gt;stat.jitter;
-                receiver-&gt;periodic_history.jitter_max = receiver-&gt;stat.jitter;
-        }
</del><span class="cx">         return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -481,18 +686,16 @@
</span><span class="cx">                 return RTP_TS_DRIFT;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        receiver-&gt;stat.jitter += deviation - ((receiver-&gt;stat.jitter + 8) &gt;&gt; 4);
-#if PRINT_RTP_PACKET_STAT
-        printf(&quot;jitter=%d deviation=%d\n&quot;,receiver-&gt;stat.jitter,deviation);
-#endif
</del><ins>+        receiver-&gt;rr_stat.jitter += deviation - ((receiver-&gt;rr_stat.jitter + 8) &gt;&gt; 4);
+        RTP_TRACE(&quot;jitter=%d deviation=%d\n&quot;,receiver-&gt;rr_stat.jitter,deviation);
</ins><span class="cx">         receiver-&gt;history.time_last = *time;
</span><span class="cx">         receiver-&gt;history.ts_last = ts;
</span><span class="cx"> 
</span><del>-        if(receiver-&gt;stat.jitter &lt; receiver-&gt;periodic_history.jitter_min) {
-                receiver-&gt;periodic_history.jitter_min = receiver-&gt;stat.jitter;
</del><ins>+        if(receiver-&gt;rr_stat.jitter &lt; receiver-&gt;periodic_history.jitter_min) {
+                receiver-&gt;periodic_history.jitter_min = receiver-&gt;rr_stat.jitter;
</ins><span class="cx">         }
</span><del>-        if(receiver-&gt;stat.jitter &gt; receiver-&gt;periodic_history.jitter_max) {
-                receiver-&gt;periodic_history.jitter_max = receiver-&gt;stat.jitter;
</del><ins>+        if(receiver-&gt;rr_stat.jitter &gt; receiver-&gt;periodic_history.jitter_max) {
+                receiver-&gt;periodic_history.jitter_max = receiver-&gt;rr_stat.jitter;
</ins><span class="cx">         }
</span><span class="cx">         return RTP_TS_UPDATE;
</span><span class="cx"> }
</span><span class="lines">@@ -510,8 +713,10 @@
</span><span class="cx">         }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t rtp_rx_packet_receive(rtp_receiver_t *receiver, mpf_codec_t *codec, void *buffer, apr_size_t size)
</del><ins>+static apt_bool_t rtp_rx_packet_receive(mpf_rtp_stream_t *rtp_stream, void *buffer, apr_size_t size)
</ins><span class="cx"> {
</span><ins>+        rtp_receiver_t *receiver = &amp;rtp_stream-&gt;receiver;
+        mpf_codec_descriptor_t *descriptor = rtp_stream-&gt;base-&gt;rx_descriptor;
</ins><span class="cx">         apr_time_t time;
</span><span class="cx">         rtp_ssrc_result_e ssrc_result;
</span><span class="cx">         rtp_header_t *header = rtp_rx_header_skip(&amp;buffer,&amp;size);
</span><span class="lines">@@ -527,12 +732,10 @@
</span><span class="cx"> 
</span><span class="cx">         time = apr_time_now();
</span><span class="cx"> 
</span><del>-#if PRINT_RTP_PACKET_STAT
-        printf(&quot;RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u size=%lu\n&quot;,
</del><ins>+        RTP_TRACE(&quot;RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u size=%lu\n&quot;,
</ins><span class="cx">                                         (apr_uint32_t)apr_time_usec(time),
</span><del>-                                        header-&gt;ssrc, header-&gt;type, header-&gt;marker ? '*' : ' ',
</del><ins>+                                        header-&gt;ssrc, header-&gt;type, (header-&gt;marker == 1) ? '*' : ' ',
</ins><span class="cx">                                         header-&gt;timestamp, header-&gt;sequence, size);
</span><del>-#endif
</del><span class="cx">         if(!receiver-&gt;stat.received_packets) {
</span><span class="cx">                 /* initialization */
</span><span class="cx">                 rtp_rx_stat_init(receiver,header,&amp;time);
</span><span class="lines">@@ -550,28 +753,29 @@
</span><span class="cx"> 
</span><span class="cx">         rtp_rx_seq_update(receiver,(apr_uint16_t)header-&gt;sequence);
</span><span class="cx">         
</span><del>-        if(rtp_rx_ts_update(receiver,codec-&gt;descriptor,&amp;time,header-&gt;timestamp) == RTP_TS_DRIFT) {
-                rtp_rx_restart(receiver);
-                return FALSE;
-        }
</del><ins>+        if(header-&gt;type == descriptor-&gt;payload_type) {
+                /* codec */
+                if(rtp_rx_ts_update(receiver,descriptor,&amp;time,header-&gt;timestamp) == RTP_TS_DRIFT) {
+                        rtp_rx_restart(receiver);
+                        return FALSE;
+                }
</ins><span class="cx">         
</span><del>-        if(header-&gt;type == codec-&gt;descriptor-&gt;payload_type) {
-                /* codec */
-                if(mpf_jitter_buffer_write(receiver-&gt;jb,codec,buffer,size,header-&gt;timestamp) != JB_OK) {
</del><ins>+                if(mpf_jitter_buffer_write(receiver-&gt;jb,buffer,size,header-&gt;timestamp) != JB_OK) {
</ins><span class="cx">                         receiver-&gt;stat.discarded_packets++;
</span><span class="cx">                         rtp_rx_failure_threshold_check(receiver);
</span><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        else if(header-&gt;type == receiver-&gt;event_pt &amp;&amp; receiver-&gt;event_pt != 0) {
</del><ins>+        else if(rtp_stream-&gt;base-&gt;rx_event_descriptor &amp;&amp; 
+                header-&gt;type == rtp_stream-&gt;base-&gt;rx_event_descriptor-&gt;payload_type) {
</ins><span class="cx">                 /* named event */
</span><span class="cx">                 mpf_named_event_frame_t *named_event = (mpf_named_event_frame_t *)buffer;
</span><del>-                if(mpf_jitter_buffer_write_named_event(receiver-&gt;jb,named_event,header-&gt;timestamp) != JB_OK) {
</del><ins>+                named_event-&gt;duration = ntohs((apr_uint16_t)named_event-&gt;duration);
+                if(mpf_jitter_buffer_event_write(receiver-&gt;jb,named_event,header-&gt;timestamp,(apr_byte_t)header-&gt;marker) != JB_OK) {
</ins><span class="cx">                         receiver-&gt;stat.discarded_packets++;
</span><del>-                        rtp_rx_failure_threshold_check(receiver);
</del><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        else if(header-&gt;type == 13 || header-&gt;type == 19) {
-                /* CN packet*/
</del><ins>+        else if(header-&gt;type == RTP_PT_CN) {
+                /* CN packet */
</ins><span class="cx">                 receiver-&gt;stat.ignored_packets++;
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="lines">@@ -584,11 +788,11 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t rtp_rx_process(mpf_rtp_stream_t *rtp_stream)
</span><span class="cx"> {
</span><del>-        char buffer[1500];
</del><ins>+        char buffer[MAX_RTP_PACKET_SIZE];
</ins><span class="cx">         apr_size_t size = sizeof(buffer);
</span><span class="cx">         apr_size_t max_count = 5;
</span><del>-        while(max_count &amp;&amp; apr_socket_recvfrom(rtp_stream-&gt;remote_sockaddr,rtp_stream-&gt;socket,0,buffer,&amp;size) == APR_SUCCESS) {
-                rtp_rx_packet_receive(&amp;rtp_stream-&gt;receiver,rtp_stream-&gt;base-&gt;rx_codec,buffer,size);
</del><ins>+        while(max_count &amp;&amp; apr_socket_recv(rtp_stream-&gt;rtp_socket,buffer,&amp;size) == APR_SUCCESS) {
+                rtp_rx_packet_receive(rtp_stream,buffer,size);
</ins><span class="cx"> 
</span><span class="cx">                 size = sizeof(buffer);
</span><span class="cx">                 max_count--;
</span><span class="lines">@@ -605,18 +809,20 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-
-
-
-static apt_bool_t mpf_rtp_tx_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t mpf_rtp_tx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         apr_size_t frame_size;
</span><span class="cx">         mpf_rtp_stream_t *rtp_stream = stream-&gt;obj;
</span><span class="cx">         rtp_transmitter_t *transmitter = &amp;rtp_stream-&gt;transmitter;
</span><del>-        if(!rtp_stream-&gt;socket || !rtp_stream-&gt;remote_media) {
</del><ins>+
+        if(!rtp_stream-&gt;rtp_socket || !rtp_stream-&gt;rtp_l_sockaddr || !rtp_stream-&gt;rtp_r_sockaddr) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if(!codec) {
+                return FALSE;
+        }
+
</ins><span class="cx">         if(!transmitter-&gt;ptime) {
</span><span class="cx">                 if(rtp_stream-&gt;config &amp;&amp; rtp_stream-&gt;config-&gt;ptime) {
</span><span class="cx">                         transmitter-&gt;ptime = rtp_stream-&gt;config-&gt;ptime;
</span><span class="lines">@@ -629,59 +835,128 @@
</span><span class="cx">         transmitter-&gt;current_frames = 0;
</span><span class="cx"> 
</span><span class="cx">         frame_size = mpf_codec_frame_size_calculate(
</span><del>-                                                        stream-&gt;tx_codec-&gt;descriptor,
-                                                        stream-&gt;tx_codec-&gt;attribs);
</del><ins>+                                                        stream-&gt;tx_descriptor,
+                                                        codec-&gt;attribs);
</ins><span class="cx">         transmitter-&gt;packet_data = apr_palloc(
</span><span class="cx">                                                         rtp_stream-&gt;pool,
</span><span class="cx">                                                         sizeof(rtp_header_t) + transmitter-&gt;packet_frames * frame_size);
</span><span class="cx">         
</span><span class="cx">         transmitter-&gt;inactivity = 1;
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open RTP Transmit %s:%hu -&gt; %s:%hu&quot;,
-                        rtp_stream-&gt;local_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;local_media-&gt;base.port,
-                        rtp_stream-&gt;remote_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;remote_media-&gt;base.port);
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open RTP Transmitter %s:%hu -&gt; %s:%hu&quot;,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;port,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;port);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_rtp_tx_stream_close(mpf_audio_stream_t *stream)
</span><span class="cx"> {
</span><span class="cx">         mpf_rtp_stream_t *rtp_stream = stream-&gt;obj;
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close RTP Transmit %s:%hu -&gt; %s:%hu [s:%lu]&quot;,
-                        rtp_stream-&gt;local_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;local_media-&gt;base.port,
-                        rtp_stream-&gt;remote_media-&gt;base.ip.buf,
-                        rtp_stream-&gt;remote_media-&gt;base.port,
-                        rtp_stream-&gt;transmitter.stat.sent_packets);
</del><ins>+        if(!rtp_stream-&gt;rtp_l_sockaddr || !rtp_stream-&gt;rtp_r_sockaddr) {
+                return FALSE;
+        }
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close RTP Transmitter %s:%hu -&gt; %s:%hu [s:%lu o:%lu]&quot;,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;port,
+                        rtp_stream-&gt;rtp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtp_r_sockaddr-&gt;port,
+                        rtp_stream-&gt;transmitter.sr_stat.sent_packets,
+                        rtp_stream-&gt;transmitter.sr_stat.sent_octets);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-static APR_INLINE void rtp_header_prepare(rtp_transmitter_t *transmitter, apr_byte_t payload_type)
</del><ins>+static APR_INLINE void rtp_header_prepare(
+                                        rtp_transmitter_t *transmitter,
+                                        rtp_header_t *header,
+                                        apr_byte_t payload_type,
+                                        apr_byte_t marker,
+                                        apr_uint32_t timestamp)
</ins><span class="cx"> {
</span><del>-        rtp_header_t *header = (rtp_header_t*)transmitter-&gt;packet_data;
-
-#if PRINT_RTP_PACKET_STAT
-        printf(&quot;&gt; RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u\n&quot;,
-                (apr_uint32_t)apr_time_usec(apr_time_now()),
-                transmitter-&gt;ssrc, payload_type, transmitter-&gt;inactivity ? '*' : ' ',
-                transmitter-&gt;timestamp, transmitter-&gt;last_seq_num);
-#endif        
</del><span class="cx">         header-&gt;version = RTP_VERSION;
</span><span class="cx">         header-&gt;padding = 0;
</span><span class="cx">         header-&gt;extension = 0;
</span><span class="cx">         header-&gt;count = 0;
</span><del>-        header-&gt;marker = transmitter-&gt;inactivity;
</del><ins>+        header-&gt;marker = marker;
</ins><span class="cx">         header-&gt;type = payload_type;
</span><ins>+        header-&gt;timestamp = timestamp;
+        header-&gt;ssrc = htonl(transmitter-&gt;sr_stat.ssrc);
+}
+
+static APR_INLINE apt_bool_t mpf_rtp_data_send(mpf_rtp_stream_t *rtp_stream, rtp_transmitter_t *transmitter, const mpf_frame_t *frame)
+{
+        apt_bool_t status = TRUE;
+        memcpy(
+                transmitter-&gt;packet_data + transmitter-&gt;packet_size,
+                frame-&gt;codec_frame.buffer,
+                frame-&gt;codec_frame.size);
+        transmitter-&gt;packet_size += frame-&gt;codec_frame.size;
+
+        if(++transmitter-&gt;current_frames == transmitter-&gt;packet_frames) {
+                rtp_header_t *header = (rtp_header_t*)transmitter-&gt;packet_data;
+                header-&gt;sequence = htons(++transmitter-&gt;last_seq_num);
+                RTP_TRACE(&quot;&gt; RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u\n&quot;,
+                        (apr_uint32_t)apr_time_usec(apr_time_now()),
+                        transmitter-&gt;sr_stat.ssrc, header-&gt;type, 
+                        (header-&gt;marker == 1) ? '*' : ' ',
+                        header-&gt;timestamp, transmitter-&gt;last_seq_num);
+                header-&gt;timestamp = htonl(header-&gt;timestamp);
+                if(apr_socket_sendto(
+                                        rtp_stream-&gt;rtp_socket,
+                                        rtp_stream-&gt;rtp_r_sockaddr,
+                                        0,
+                                        transmitter-&gt;packet_data,
+                                        &amp;transmitter-&gt;packet_size) == APR_SUCCESS) {
+                        transmitter-&gt;sr_stat.sent_packets++;
+                        transmitter-&gt;sr_stat.sent_octets += transmitter-&gt;packet_size - sizeof(rtp_header_t);
+                }
+                else {
+                        status = FALSE;
+                }
+                transmitter-&gt;current_frames = 0;
+        }
+        return status;
+}
+
+static APR_INLINE apt_bool_t mpf_rtp_event_send(mpf_rtp_stream_t *rtp_stream, rtp_transmitter_t *transmitter, const mpf_frame_t *frame)
+{
+        char packet_data[20];
+        apr_size_t packet_size = sizeof(rtp_header_t) + sizeof(mpf_named_event_frame_t);
+        rtp_header_t *header = (rtp_header_t*) packet_data;
+        mpf_named_event_frame_t *named_event = (mpf_named_event_frame_t*)(header+1);
+        rtp_header_prepare(
+                transmitter,
+                header,
+                rtp_stream-&gt;base-&gt;tx_event_descriptor-&gt;payload_type,
+                (frame-&gt;marker == MPF_MARKER_START_OF_EVENT) ? 1 : 0,
+                transmitter-&gt;timestamp_base);
+
+        *named_event = frame-&gt;event_frame;
+        named_event-&gt;edge = (frame-&gt;marker == MPF_MARKER_END_OF_EVENT) ? 1 : 0;
+        
</ins><span class="cx">         header-&gt;sequence = htons(++transmitter-&gt;last_seq_num);
</span><del>-        header-&gt;timestamp = htonl(transmitter-&gt;timestamp);
-        header-&gt;ssrc = htonl(transmitter-&gt;ssrc);
</del><ins>+        RTP_TRACE(&quot;&gt; RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u event=%2u dur=%3u %c\n&quot;,
+                (apr_uint32_t)apr_time_usec(apr_time_now()),
+                transmitter-&gt;sr_stat.ssrc, 
+                header-&gt;type, (header-&gt;marker == 1) ? '*' : ' ',
+                header-&gt;timestamp, transmitter-&gt;last_seq_num,
+                named_event-&gt;event_id, named_event-&gt;duration,
+                (named_event-&gt;edge == 1) ? '*' : ' ');
</ins><span class="cx"> 
</span><del>-        if(transmitter-&gt;inactivity) {
-                transmitter-&gt;inactivity = 0;
</del><ins>+        header-&gt;timestamp = htonl(header-&gt;timestamp);
+        named_event-&gt;duration = htons((apr_uint16_t)named_event-&gt;duration);
+        if(apr_socket_sendto(
+                                rtp_stream-&gt;rtp_socket,
+                                rtp_stream-&gt;rtp_r_sockaddr,
+                                0,
+                                packet_data,
+                                &amp;packet_size) != APR_SUCCESS) {
+                return FALSE;
</ins><span class="cx">         }
</span><del>-
-        transmitter-&gt;packet_size = sizeof(rtp_header_t);
</del><ins>+        transmitter-&gt;sr_stat.sent_packets++;
+        transmitter-&gt;sr_stat.sent_octets += sizeof(mpf_named_event_frame_t);
+        return TRUE;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mpf_rtp_stream_transmit(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
</span><span class="lines">@@ -692,80 +967,433 @@
</span><span class="cx"> 
</span><span class="cx">         transmitter-&gt;timestamp += transmitter-&gt;samples_per_frame;
</span><span class="cx"> 
</span><del>-        if(transmitter-&gt;current_frames == 0) {
-                if(frame-&gt;type == MEDIA_FRAME_TYPE_NONE) {
-                        transmitter-&gt;inactivity = 1;
</del><ins>+        if(frame-&gt;type == MEDIA_FRAME_TYPE_NONE) {
+                if(!transmitter-&gt;inactivity) {
+                        if(transmitter-&gt;current_frames == 0) {
+                                /* set inactivity (ptime alligned) */
+                                transmitter-&gt;inactivity = 1;
+                                if(rtp_stream-&gt;config-&gt;rtcp == TRUE &amp;&amp; rtp_stream-&gt;config-&gt;rtcp_bye_policy == RTCP_BYE_PER_TALKSPURT) {
+                                        apt_str_t reason = {RTCP_BYE_TALKSPURT_ENDED, sizeof(RTCP_BYE_TALKSPURT_ENDED)-1};
+                                        mpf_rtcp_bye_send(rtp_stream,&amp;reason);
+                                }
+                        }
+                        else {
+                                /* ptime allignment */
+                                status = mpf_rtp_data_send(rtp_stream,transmitter,frame);
+                        }
</ins><span class="cx">                 }
</span><del>-                else {
-                        rtp_header_prepare(transmitter,stream-&gt;tx_codec-&gt;descriptor-&gt;payload_type);
-                }
</del><ins>+                return status;
</ins><span class="cx">         }
</span><del>-        
-        if(!transmitter-&gt;inactivity) {
-                memcpy(
-                        transmitter-&gt;packet_data + transmitter-&gt;packet_size,
-                        frame-&gt;codec_frame.buffer,
-                        frame-&gt;codec_frame.size);
-                transmitter-&gt;packet_size += frame-&gt;codec_frame.size;
</del><span class="cx"> 
</span><del>-                if(++transmitter-&gt;current_frames == transmitter-&gt;packet_frames) {
-                        if(apr_socket_sendto(
-                                                                rtp_stream-&gt;socket,
-                                                                rtp_stream-&gt;remote_sockaddr,
-                                                                0,
-                                                                transmitter-&gt;packet_data,
-                                                                &amp;transmitter-&gt;packet_size) == APR_SUCCESS) {
-                                transmitter-&gt;stat.sent_packets++;
</del><ins>+        if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT){
+                /* transmit event as soon as received */
+                if(stream-&gt;tx_event_descriptor) {
+                        if(frame-&gt;marker == MPF_MARKER_START_OF_EVENT) {
+                                /* store start time (base) of the event */
+                                transmitter-&gt;timestamp_base = transmitter-&gt;timestamp;
</ins><span class="cx">                         }
</span><del>-                        else {
-                                status = FALSE;
</del><ins>+                        else if(frame-&gt;marker == MPF_MARKER_NEW_SEGMENT) {
+                                /* update base in case of long-lasting events */
+                                transmitter-&gt;timestamp_base = transmitter-&gt;timestamp;
</ins><span class="cx">                         }
</span><del>-                        transmitter-&gt;current_frames = 0;
</del><ins>+
+                        status = mpf_rtp_event_send(rtp_stream,transmitter,frame);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_AUDIO) == MEDIA_FRAME_TYPE_AUDIO){
+                if(transmitter-&gt;current_frames == 0) {
+                        rtp_header_t *header = (rtp_header_t*)transmitter-&gt;packet_data;
+                        rtp_header_prepare(
+                                        transmitter,
+                                        header,
+                                        stream-&gt;tx_descriptor-&gt;payload_type,
+                                        transmitter-&gt;inactivity,
+                                        transmitter-&gt;timestamp);
+                        transmitter-&gt;packet_size = sizeof(rtp_header_t);
+                        if(transmitter-&gt;inactivity) {
+                                transmitter-&gt;inactivity = 0;
+                        }
+                }
+                status = mpf_rtp_data_send(rtp_stream,transmitter,frame);
+        }
+
</ins><span class="cx">         return status;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_rtp_socket_create(mpf_rtp_stream_t *stream, mpf_rtp_media_descriptor_t *local_media)
</del><ins>+static apr_socket_t* mpf_socket_create(apr_sockaddr_t **l_sockaddr, const char *ip, apr_port_t port, apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        if(stream-&gt;socket) {
-                apr_socket_close(stream-&gt;socket);
-                stream-&gt;socket = NULL;
-        }
-        
-        stream-&gt;local_sockaddr = NULL;
</del><ins>+        apr_socket_t *socket = NULL;
+        *l_sockaddr = NULL;
</ins><span class="cx">         apr_sockaddr_info_get(
</span><del>-                &amp;stream-&gt;local_sockaddr,
-                local_media-&gt;base.ip.buf,
</del><ins>+                l_sockaddr,
+                ip,
</ins><span class="cx">                 APR_INET,
</span><del>-                local_media-&gt;base.port,
</del><ins>+                port,
</ins><span class="cx">                 0,
</span><del>-                stream-&gt;pool);
-        if(!stream-&gt;local_sockaddr) {
-                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Failed to Get Sockaddr %s:%hu&quot;,
-                                local_media-&gt;base.ip.buf,
-                                local_media-&gt;base.port);
</del><ins>+                pool);
+        if(!*l_sockaddr) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Get Sockaddr %s:%hu&quot;,ip,port);
+                return NULL;
+        }
+        if(apr_socket_create(&amp;socket,(*l_sockaddr)-&gt;family,SOCK_DGRAM,0,pool) != APR_SUCCESS) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Socket %s:%hu&quot;, ip,port);
+                return NULL;
+        }
+        
+        apr_socket_opt_set(socket,APR_SO_NONBLOCK,1);
+        apr_socket_timeout_set(socket,0);
+        apr_socket_opt_set(socket,APR_SO_REUSEADDR,1);
+
+        if(apr_socket_bind(socket,*l_sockaddr) != APR_SUCCESS) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Bind Socket to %s:%hu&quot;, ip,port);
+                apr_socket_close(socket);
+                return NULL;
+        }
+        return socket;
+}
+
+static apt_bool_t mpf_rtp_socket_pair_create(mpf_rtp_stream_t *stream, mpf_rtp_media_descriptor_t *local_media)
+{
+        stream-&gt;rtp_socket = mpf_socket_create(&amp;stream-&gt;rtp_l_sockaddr,local_media-&gt;ip.buf,local_media-&gt;port,stream-&gt;pool);
+        if(!stream-&gt;rtp_socket) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create RTP Socket&quot;);
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        if(apr_socket_create(&amp;stream-&gt;socket,stream-&gt;local_sockaddr-&gt;family,SOCK_DGRAM,0,stream-&gt;pool) != APR_SUCCESS) {
-                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Failed to Create Socket %s:%hu&quot;,
-                                local_media-&gt;base.ip.buf,
-                                local_media-&gt;base.port);
</del><ins>+
+        stream-&gt;rtcp_socket = mpf_socket_create(&amp;stream-&gt;rtcp_l_sockaddr,local_media-&gt;ip.buf,local_media-&gt;port+1,stream-&gt;pool);
+        if(!stream-&gt;rtcp_socket) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create RTCP Socket&quot;);
+        }
+        return TRUE;
+}
+
+static void mpf_rtp_socket_pair_close(mpf_rtp_stream_t *stream)
+{
+        if(stream-&gt;rtp_socket) {
+                apr_socket_close(stream-&gt;rtp_socket);
+                stream-&gt;rtp_socket = NULL;
+        }
+        if(stream-&gt;rtcp_socket) {
+                apr_socket_close(stream-&gt;rtcp_socket);
+                stream-&gt;rtcp_socket = NULL;
+        }
+}
+
+
+
+static APR_INLINE void rtcp_sr_generate(mpf_rtp_stream_t *rtp_stream, rtcp_sr_stat_t *sr_stat)
+{
+        *sr_stat = rtp_stream-&gt;transmitter.sr_stat;
+        apt_ntp_time_get(&amp;sr_stat-&gt;ntp_sec, &amp;sr_stat-&gt;ntp_frac);
+        sr_stat-&gt;rtp_ts = rtp_stream-&gt;transmitter.timestamp;
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Generate RTCP SR [ssrc:%lu s:%lu o:%lu ts:%lu]&quot;,
+                                sr_stat-&gt;ssrc,
+                                sr_stat-&gt;sent_packets,
+                                sr_stat-&gt;sent_octets,
+                                sr_stat-&gt;rtp_ts);
+        rtcp_sr_hton(sr_stat);
+}
+
+static APR_INLINE void rtcp_rr_generate(mpf_rtp_stream_t *rtp_stream, rtcp_rr_stat_t *rr_stat)
+{
+        *rr_stat = rtp_stream-&gt;receiver.rr_stat;
+        rr_stat-&gt;last_seq =        rtp_stream-&gt;receiver.history.seq_num_max;
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Generate RTCP RR [ssrc:%lu last_seq:%lu j:%lu lost:%lu frac:%d]&quot;,
+                                rr_stat-&gt;ssrc,
+                                rr_stat-&gt;last_seq,
+                                rr_stat-&gt;jitter,
+                                rr_stat-&gt;lost,
+                                rr_stat-&gt;fraction);
+        rtcp_rr_hton(rr_stat);
+}
+
+/* Generate either RTCP SR or RTCP RR packet */
+static APR_INLINE apr_size_t rtcp_report_generate(mpf_rtp_stream_t *rtp_stream, rtcp_packet_t *rtcp_packet, apr_size_t length)
+{
+        apr_size_t offset = 0;
+        rtcp_header_init(&amp;rtcp_packet-&gt;header,RTCP_RR);
+        if(rtp_stream-&gt;base-&gt;direction &amp; STREAM_DIRECTION_SEND) {
+                rtcp_packet-&gt;header.pt = RTCP_SR;
+        }
+        if(rtp_stream-&gt;base-&gt;direction &amp; STREAM_DIRECTION_RECEIVE) {
+                rtcp_packet-&gt;header.count = 1;
+        }
+        offset += sizeof(rtcp_header_t);
+
+        if(rtcp_packet-&gt;header.pt == RTCP_SR) {
+                rtcp_sr_generate(rtp_stream,&amp;rtcp_packet-&gt;r.sr.sr_stat);
+                offset += sizeof(rtcp_sr_stat_t);
+                if(rtcp_packet-&gt;header.count) {
+                        rtcp_rr_generate(rtp_stream,rtcp_packet-&gt;r.sr.rr_stat);
+                        offset += sizeof(rtcp_rr_stat_t);
+                }
+        }
+        else if(rtcp_packet-&gt;header.pt == RTCP_RR) {
+                rtcp_packet-&gt;r.rr.ssrc = htonl(rtp_stream-&gt;transmitter.sr_stat.ssrc);
+                rtcp_rr_generate(rtp_stream,rtcp_packet-&gt;r.rr.rr_stat);
+                offset += sizeof(rtcp_packet-&gt;r.rr);
+        }
+        rtcp_header_length_set(&amp;rtcp_packet-&gt;header,offset);
+        return offset;
+}
+
+/* Generate RTCP SDES packet */
+static APR_INLINE apr_size_t rtcp_sdes_generate(mpf_rtp_stream_t *rtp_stream, rtcp_packet_t *rtcp_packet, apr_size_t length)
+{
+        rtcp_sdes_item_t *item;
+        apr_size_t offset = 0;
+        apr_size_t padding;
+        rtcp_header_init(&amp;rtcp_packet-&gt;header,RTCP_SDES);
+        offset += sizeof(rtcp_header_t);
+
+        rtcp_packet-&gt;header.count ++;
+        rtcp_packet-&gt;r.sdes.ssrc = htonl(rtp_stream-&gt;transmitter.sr_stat.ssrc);
+        offset += sizeof(apr_uint32_t);
+
+        /* insert SDES CNAME item */
+        item = &amp;rtcp_packet-&gt;r.sdes.item[0];
+        item-&gt;type = RTCP_SDES_CNAME;
+        item-&gt;length = (apr_byte_t)rtp_stream-&gt;local_media-&gt;ip.length;
+        memcpy(item-&gt;data,rtp_stream-&gt;local_media-&gt;ip.buf,item-&gt;length);
+        offset += sizeof(rtcp_sdes_item_t) - 1 + item-&gt;length;
+        
+        /* terminate with end marker and pad to next 4-octet boundary */
+        padding = 4 - (offset &amp; 0x3);
+        while(padding--) {
+                item = (rtcp_sdes_item_t*) ((char*)rtcp_packet + offset);
+                item-&gt;type = RTCP_SDES_END;
+                offset++;
+        }
+
+        rtcp_header_length_set(&amp;rtcp_packet-&gt;header,offset);
+        return offset;
+}
+
+/* Generate RTCP BYE packet */
+static APR_INLINE apr_size_t rtcp_bye_generate(mpf_rtp_stream_t *rtp_stream, rtcp_packet_t *rtcp_packet, apr_size_t length, apt_str_t *reason)
+{
+        apr_size_t offset = 0;
+        rtcp_header_init(&amp;rtcp_packet-&gt;header,RTCP_BYE);
+        offset += sizeof(rtcp_header_t);
+
+        rtcp_packet-&gt;r.bye.ssrc[0] = htonl(rtp_stream-&gt;transmitter.sr_stat.ssrc);
+        rtcp_packet-&gt;header.count++;
+        offset += rtcp_packet-&gt;header.count * sizeof(apr_uint32_t);
+
+        if(reason-&gt;length) {
+                apr_size_t padding;
+
+                memcpy(rtcp_packet-&gt;r.bye.data,reason-&gt;buf,reason-&gt;length);
+                rtcp_packet-&gt;r.bye.length = (apr_byte_t)reason-&gt;length;
+                offset += rtcp_packet-&gt;r.bye.length;
+        
+                /* terminate with end marker and pad to next 4-octet boundary */
+                padding = 4 - (reason-&gt;length &amp; 0x3);
+                if(padding) {
+                        char *end = rtcp_packet-&gt;r.bye.data + reason-&gt;length;
+                        memset(end,0,padding);
+                        offset += padding;
+                }
+        }
+
+        rtcp_header_length_set(&amp;rtcp_packet-&gt;header,offset);
+        return offset;
+}
+
+/* Send compound RTCP packet (SR/RR + SDES) */
+static apt_bool_t mpf_rtcp_report_send(mpf_rtp_stream_t *rtp_stream)
+{
+        char buffer[MAX_RTCP_PACKET_SIZE];
+        apr_size_t length = 0;
+        rtcp_packet_t *rtcp_packet;
+
+        if(!rtp_stream-&gt;rtcp_socket || !rtp_stream-&gt;rtcp_l_sockaddr || !rtp_stream-&gt;rtcp_r_sockaddr) {
+                /* session is not initialized */
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><ins>+
+        if(rtp_stream-&gt;base-&gt;direction != STREAM_DIRECTION_NONE) {
+                /* update periodic (prior) history */
+                rtp_periodic_history_update(&amp;rtp_stream-&gt;receiver);
+        }
+
+        rtcp_packet = (rtcp_packet_t*) (buffer + length);
+        length += rtcp_report_generate(rtp_stream,rtcp_packet,sizeof(buffer)-length);
+
+        rtcp_packet = (rtcp_packet_t*) (buffer + length);
+        length += rtcp_sdes_generate(rtp_stream,rtcp_packet,sizeof(buffer)-length);
</ins><span class="cx">         
</span><del>-        apr_socket_opt_set(stream-&gt;socket,APR_SO_NONBLOCK,1);
-        apr_socket_timeout_set(stream-&gt;socket,0);
-        apr_socket_opt_set(stream-&gt;socket,APR_SO_REUSEADDR,1);
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Send Compound RTCP Packet [%d bytes] %s:%hu -&gt; %s:%hu&quot;,
+                length,
+                rtp_stream-&gt;rtcp_l_sockaddr-&gt;hostname,
+                rtp_stream-&gt;rtcp_l_sockaddr-&gt;port,
+                rtp_stream-&gt;rtcp_r_sockaddr-&gt;hostname,
+                rtp_stream-&gt;rtcp_r_sockaddr-&gt;port);
+        if(apr_socket_sendto(
+                                rtp_stream-&gt;rtcp_socket,
+                                rtp_stream-&gt;rtcp_r_sockaddr,
+                                0,
+                                buffer,
+                                &amp;length) != APR_SUCCESS) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Send Compound RTCP Packet [%d bytes] %s:%hu -&gt; %s:%hu&quot;,
+                        length,
+                        rtp_stream-&gt;rtcp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtcp_l_sockaddr-&gt;port,
+                        rtp_stream-&gt;rtcp_r_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtcp_r_sockaddr-&gt;port);
+                return FALSE;
+        }
+        return TRUE;
+}
</ins><span class="cx"> 
</span><del>-        if(apr_socket_bind(stream-&gt;socket,stream-&gt;local_sockaddr) != APR_SUCCESS) {
-                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Failed to Bind Socket to %s:%hu&quot;,
-                                local_media-&gt;base.ip.buf,
-                                local_media-&gt;base.port);
-                apr_socket_close(stream-&gt;socket);
-                stream-&gt;socket = NULL;
</del><ins>+/* Send compound RTCP packet (SR/RR + SDES + BYE) */
+static apt_bool_t mpf_rtcp_bye_send(mpf_rtp_stream_t *rtp_stream, apt_str_t *reason)
+{
+        char buffer[MAX_RTCP_PACKET_SIZE];
+        apr_size_t length = 0;
+        rtcp_packet_t *rtcp_packet;
+
+        if(!rtp_stream-&gt;rtcp_socket || !rtp_stream-&gt;rtcp_l_sockaddr || !rtp_stream-&gt;rtcp_r_sockaddr) {
+                /* session is not initialized */
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><ins>+
+        if(rtp_stream-&gt;base-&gt;direction != STREAM_DIRECTION_NONE) {
+                /* update periodic (prior) history */
+                rtp_periodic_history_update(&amp;rtp_stream-&gt;receiver);
+        }
+
+        rtcp_packet = (rtcp_packet_t*) (buffer + length);
+        length += rtcp_report_generate(rtp_stream,rtcp_packet,sizeof(buffer)-length);
+
+        rtcp_packet = (rtcp_packet_t*) (buffer + length);
+        length += rtcp_sdes_generate(rtp_stream,rtcp_packet,sizeof(buffer)-length);
+
+        rtcp_packet = (rtcp_packet_t*) (buffer + length);
+        length += rtcp_bye_generate(rtp_stream,rtcp_packet,sizeof(buffer)-length,reason);
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Send Compound RTCP Packet [BYE] [%d bytes] %s:%hu -&gt; %s:%hu&quot;,
+                length,
+                rtp_stream-&gt;rtcp_l_sockaddr-&gt;hostname,
+                rtp_stream-&gt;rtcp_l_sockaddr-&gt;port,
+                rtp_stream-&gt;rtcp_r_sockaddr-&gt;hostname,
+                rtp_stream-&gt;rtcp_r_sockaddr-&gt;port);
+        if(apr_socket_sendto(
+                                rtp_stream-&gt;rtcp_socket,
+                                rtp_stream-&gt;rtcp_r_sockaddr,
+                                0,
+                                buffer,
+                                &amp;length) != APR_SUCCESS) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Send Compound RTCP Packet [BYE] [%d bytes] %s:%hu -&gt; %s:%hu&quot;,
+                        length,
+                        rtp_stream-&gt;rtcp_l_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtcp_l_sockaddr-&gt;port,
+                        rtp_stream-&gt;rtcp_r_sockaddr-&gt;hostname,
+                        rtp_stream-&gt;rtcp_r_sockaddr-&gt;port);
+                return FALSE;
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><ins>+
+static APR_INLINE void rtcp_sr_get(mpf_rtp_stream_t *rtp_stream, rtcp_sr_stat_t *sr_stat)
+{
+        rtcp_sr_ntoh(sr_stat);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Get RTCP SR [ssrc:%lu s:%lu o:%lu ts:%lu]&quot;,
+                                sr_stat-&gt;ssrc,
+                                sr_stat-&gt;sent_packets,
+                                sr_stat-&gt;sent_octets,
+                                sr_stat-&gt;rtp_ts);
+}
+
+static APR_INLINE void rtcp_rr_get(mpf_rtp_stream_t *rtp_stream, rtcp_rr_stat_t *rr_stat)
+{
+        rtcp_rr_ntoh(rr_stat);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Get RTCP RR [ssrc:%lu last_seq:%lu j:%lu lost:%lu frac:%d]&quot;,
+                                rr_stat-&gt;ssrc,
+                                rr_stat-&gt;last_seq,
+                                rr_stat-&gt;jitter,
+                                rr_stat-&gt;lost,
+                                rr_stat-&gt;fraction);
+}
+
+static apt_bool_t mpf_rtcp_compound_packet_receive(mpf_rtp_stream_t *rtp_stream, char *buffer, apr_size_t length)
+{
+        rtcp_packet_t *rtcp_packet = (rtcp_packet_t*) buffer;
+        rtcp_packet_t *rtcp_packet_end;
+
+        rtcp_packet_end = (rtcp_packet_t*)(buffer + length);
+
+        while(rtcp_packet &lt; rtcp_packet_end &amp;&amp; rtcp_packet-&gt;header.version == RTP_VERSION) {
+                rtcp_packet-&gt;header.length = ntohs((apr_uint16_t)rtcp_packet-&gt;header.length);
+                
+                if(rtcp_packet-&gt;header.pt == RTCP_SR) {
+                        /* RTCP SR */
+                        rtcp_sr_get(rtp_stream,&amp;rtcp_packet-&gt;r.sr.sr_stat);
+                        if(rtcp_packet-&gt;header.count) {
+                                rtcp_rr_get(rtp_stream,rtcp_packet-&gt;r.sr.rr_stat);
+                        }
+                }
+                else if(rtcp_packet-&gt;header.pt == RTCP_RR) {
+                        /* RTCP RR */
+                        rtcp_packet-&gt;r.rr.ssrc = ntohl(rtcp_packet-&gt;r.rr.ssrc);
+                        if(rtcp_packet-&gt;header.count) {
+                                rtcp_rr_get(rtp_stream,rtcp_packet-&gt;r.rr.rr_stat);
+                        }
+                }
+                else if(rtcp_packet-&gt;header.pt == RTCP_SDES) {
+                        /* RTCP SDES */
+                }
+                else if(rtcp_packet-&gt;header.pt == RTCP_BYE) {
+                        /* RTCP BYE */
+                }
+                else {
+                        /* unknown RTCP packet */
+                }
+
+                /* get next RTCP packet */
+                rtcp_packet = (rtcp_packet_t*)((apr_uint32_t*)rtcp_packet + rtcp_packet-&gt;header.length + 1);
+        }
+
+        if(rtcp_packet != rtcp_packet_end) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Malformed Compound RTCP Packet&quot;);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+static void mpf_rtcp_tx_timer_proc(mpf_timer_t *timer, void *obj)
+{
+        mpf_rtp_stream_t *rtp_stream = obj;
+
+        /* generate and send RTCP compound report (SR/RR + SDES) */
+        mpf_rtcp_report_send(rtp_stream);
+
+        /* re-schedule timer */
+        mpf_timer_set(timer,rtp_stream-&gt;config-&gt;rtcp_tx_interval);
+}
+
+static void mpf_rtcp_rx_timer_proc(mpf_timer_t *timer, void *obj)
+{
+        mpf_rtp_stream_t *rtp_stream = obj;
+        if(rtp_stream-&gt;rtcp_socket &amp;&amp; rtp_stream-&gt;rtcp_l_sockaddr &amp;&amp; rtp_stream-&gt;rtcp_r_sockaddr) {
+                char buffer[MAX_RTCP_PACKET_SIZE];
+                apr_size_t length = sizeof(buffer);
+                
+                if(apr_socket_recv(rtp_stream-&gt;rtcp_socket,buffer,&amp;length) == APR_SUCCESS) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Receive Compound RTCP Packet [%d bytes] %s:%hu &lt;- %s:%hu&quot;,
+                                        length,
+                                        rtp_stream-&gt;rtcp_l_sockaddr-&gt;hostname,
+                                        rtp_stream-&gt;rtcp_l_sockaddr-&gt;port,
+                                        rtp_stream-&gt;rtcp_r_sockaddr-&gt;hostname,
+                                        rtp_stream-&gt;rtcp_r_sockaddr-&gt;port);
+                        mpf_rtcp_compound_packet_receive(rtp_stream,buffer,length);
+                }
+        }
+
+        /* re-schedule timer */
+        mpf_timer_set(timer,rtp_stream-&gt;config-&gt;rtcp_rx_resolution);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_rtp_termination_factoryc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -30,8 +30,9 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mpf_rtp_termination_modify(mpf_termination_t *termination, void *descriptor)
</del><ins>+static apt_bool_t mpf_rtp_termination_add(mpf_termination_t *termination, void *descriptor)
</ins><span class="cx"> {
</span><ins>+        apt_bool_t status = TRUE;
</ins><span class="cx">         mpf_rtp_termination_descriptor_t *rtp_descriptor = descriptor;
</span><span class="cx">         mpf_audio_stream_t *audio_stream = termination-&gt;audio_stream;
</span><span class="cx">         if(!audio_stream) {
</span><span class="lines">@@ -43,12 +44,43 @@
</span><span class="cx">                 termination-&gt;audio_stream = audio_stream;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return mpf_rtp_stream_modify(audio_stream,&amp;rtp_descriptor-&gt;audio);
</del><ins>+        status = mpf_rtp_stream_add(audio_stream);
+        if(rtp_descriptor) {
+                status = mpf_rtp_stream_modify(audio_stream,&amp;rtp_descriptor-&gt;audio);
+        }
+        return status;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static apt_bool_t mpf_rtp_termination_modify(mpf_termination_t *termination, void *descriptor)
+{
+        apt_bool_t status = TRUE;
+        mpf_rtp_termination_descriptor_t *rtp_descriptor = descriptor;
+        mpf_audio_stream_t *audio_stream = termination-&gt;audio_stream;
+        if(!audio_stream) {
+                return FALSE;
+        }
+
+        if(rtp_descriptor) {
+                status = mpf_rtp_stream_modify(audio_stream,&amp;rtp_descriptor-&gt;audio);
+        }
+        return status;
+}
+
+static apt_bool_t mpf_rtp_termination_subtract(mpf_termination_t *termination)
+{
+        mpf_audio_stream_t *audio_stream = termination-&gt;audio_stream;
+        if(!audio_stream) {
+                return FALSE;
+        }
+        
+        return mpf_rtp_stream_remove(audio_stream);
+}
+
</ins><span class="cx"> static const mpf_termination_vtable_t rtp_vtable = {
</span><span class="cx">         mpf_rtp_termination_destroy,
</span><ins>+        mpf_rtp_termination_add,
</ins><span class="cx">         mpf_rtp_termination_modify,
</span><ins>+        mpf_rtp_termination_subtract
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> static mpf_termination_t* mpf_rtp_termination_create(mpf_termination_factory_t *termination_factory, void *obj, apr_pool_t *pool)
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_schedulerc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_scheduler.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_scheduler.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_scheduler.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,250 @@
</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;mpf_scheduler.h&quot;
+
+#ifdef WIN32
+#define ENABLE_MULTIMEDIA_TIMERS
+#endif
+
+#ifdef ENABLE_MULTIMEDIA_TIMERS
+
+#pragma warning(disable:4201)
+#include &lt;mmsystem.h&gt;
+#include &lt;windows.h&gt;
+
+#ifndef TIME_KILL_SYNCHRONOUS
+#define TIME_KILL_SYNCHRONOUS   0x0100
+#endif
+
+#else
+#include &lt;apr_thread_proc.h&gt;
+#endif
+
+
+struct mpf_scheduler_t {
+        apr_pool_t          *pool;
+        unsigned long        resolution; /* scheduler resolution */
+        unsigned long        rate; /* faster than real-time simulation */
+
+        unsigned long        media_resolution;
+        mpf_scheduler_proc_f media_proc;
+        void                *media_obj;
+        
+        unsigned long        timer_resolution;
+        unsigned long        timer_elapsed_time;
+        mpf_scheduler_proc_f timer_proc;
+        void                *timer_obj;
+
+#ifdef ENABLE_MULTIMEDIA_TIMERS
+        unsigned int         timer_id;
+#else
+        apr_thread_t        *thread;
+        apt_bool_t           running;
+#endif
+};
+
+static APR_INLINE void mpf_scheduler_init(mpf_scheduler_t *scheduler);
+
+/** Create scheduler */
+MPF_DECLARE(mpf_scheduler_t*) mpf_scheduler_create(unsigned long rate, apr_pool_t *pool)
+{
+        mpf_scheduler_t *scheduler = apr_palloc(pool,sizeof(mpf_scheduler_t));
+        mpf_scheduler_init(scheduler);
+        scheduler-&gt;pool = pool;
+        scheduler-&gt;resolution = 0;
+        if(rate == 0 || rate &gt; 10) {
+                /* rate shows how many times scheduler should be faster than real-time,
+                1 is the defualt and probably the only reasonable value, 
+                however, the rates up to 10 times faster should be acceptable */
+                rate = 1;
+        }
+        scheduler-&gt;rate = rate;
+
+        scheduler-&gt;media_resolution = 0;
+        scheduler-&gt;media_obj = NULL;
+        scheduler-&gt;media_proc = NULL;
+
+        scheduler-&gt;timer_resolution = 0;
+        scheduler-&gt;timer_elapsed_time = 0;
+        scheduler-&gt;timer_obj = NULL;
+        scheduler-&gt;timer_proc = NULL;
+        return scheduler;
+}
+
+/** Destroy scheduler */
+MPF_DECLARE(void) mpf_scheduler_destroy(mpf_scheduler_t *scheduler)
+{
+        /* nothing to destroy */
+}
+
+/** Set media processing clock */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_media_clock_set(
+                                                                mpf_scheduler_t *scheduler,
+                                                                unsigned long resolution,
+                                                                mpf_scheduler_proc_f proc,
+                                                                void *obj)
+{
+        scheduler-&gt;media_resolution = resolution / scheduler-&gt;rate;
+        scheduler-&gt;media_proc = proc;
+        scheduler-&gt;media_obj = obj;
+        return TRUE;
+}
+
+/** Set timer clock */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_timer_clock_set(
+                                                                mpf_scheduler_t *scheduler,
+                                                                unsigned long resolution,
+                                                                mpf_scheduler_proc_f proc,
+                                                                void *obj)
+{
+        scheduler-&gt;timer_resolution = resolution / scheduler-&gt;rate;
+        scheduler-&gt;timer_elapsed_time = 0;
+        scheduler-&gt;timer_proc = proc;
+        scheduler-&gt;timer_obj = obj;
+        return TRUE;
+}
+
+static APR_INLINE void mpf_scheduler_resolution_set(mpf_scheduler_t *scheduler)
+{
+        if(scheduler-&gt;media_resolution) {
+                scheduler-&gt;resolution = scheduler-&gt;media_resolution;
+        }
+        else if(scheduler-&gt;timer_resolution) {
+                scheduler-&gt;resolution = scheduler-&gt;timer_resolution;
+        }
+}
+
+
+
+#ifdef ENABLE_MULTIMEDIA_TIMERS
+
+static APR_INLINE void mpf_scheduler_init(mpf_scheduler_t *scheduler)
+{
+        scheduler-&gt;timer_id = 0;
+}
+
+static void CALLBACK mm_timer_proc(UINT uID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2)
+{
+        mpf_scheduler_t *scheduler = (mpf_scheduler_t*) dwUser;
+        if(scheduler-&gt;media_proc) {
+                scheduler-&gt;media_proc(scheduler,scheduler-&gt;media_obj);
+        }
+
+        if(scheduler-&gt;timer_proc) {
+                scheduler-&gt;timer_elapsed_time += scheduler-&gt;resolution;
+                if(scheduler-&gt;timer_elapsed_time &gt;= scheduler-&gt;timer_resolution) {
+                        scheduler-&gt;timer_elapsed_time = 0;
+                        scheduler-&gt;timer_proc(scheduler,scheduler-&gt;timer_obj);
+                }
+        }
+}
+
+/** Start scheduler */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_start(mpf_scheduler_t *scheduler)
+{
+        mpf_scheduler_resolution_set(scheduler);
+        scheduler-&gt;timer_id = timeSetEvent(
+                                        scheduler-&gt;resolution, 0, mm_timer_proc, (DWORD_PTR) scheduler, 
+                                        TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
+        return scheduler-&gt;timer_id ? TRUE : FALSE;
+}
+
+/** Stop scheduler */
+MPF_DECLARE(apt_bool_t) mpf_scheduler_stop(mpf_scheduler_t *scheduler)
+{
+        if(!scheduler) {
+                return FALSE;
+        }
+
+        timeKillEvent(scheduler-&gt;timer_id);
+        scheduler-&gt;timer_id = 0;
+        return TRUE;
+}
+
+#else
+
+static APR_INLINE void mpf_scheduler_init(mpf_scheduler_t *scheduler)
+{
+        scheduler-&gt;thread = NULL;
+        scheduler-&gt;running = FALSE;
+}
+
+static void* APR_THREAD_FUNC timer_thread_proc(apr_thread_t *thread, void *data)
+{
+        mpf_scheduler_t *scheduler = data;
+        apr_interval_time_t timeout = scheduler-&gt;resolution * 1000;
+        apr_interval_time_t time_drift = 0;
+        apr_time_t time_now, time_last;
+        
+        time_now = apr_time_now();
+        while(scheduler-&gt;running == TRUE) {
+                time_last = time_now;
+
+                if(scheduler-&gt;media_proc) {
+                        scheduler-&gt;media_proc(scheduler,scheduler-&gt;media_obj);
+                }
+
+                if(scheduler-&gt;timer_proc) {
+                        scheduler-&gt;timer_elapsed_time += scheduler-&gt;resolution;
+                        if(scheduler-&gt;timer_elapsed_time &gt;= scheduler-&gt;timer_resolution) {
+                                scheduler-&gt;timer_elapsed_time = 0;
+                                scheduler-&gt;timer_proc(scheduler,scheduler-&gt;timer_obj);
+                        }
+                }
+
+                if(timeout &gt; time_drift) {
+                        apr_sleep(timeout - time_drift);
+                }
+
+                time_now = apr_time_now();
+                time_drift += time_now - time_last - timeout;
+#if 0
+                printf(&quot;time_drift=%d\n&quot;,time_drift);
+#endif
+        }
+        
+        return NULL;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_scheduler_start(mpf_scheduler_t *scheduler)
+{
+        mpf_scheduler_resolution_set(scheduler);
+        
+        scheduler-&gt;running = TRUE;
+        if(apr_thread_create(&amp;scheduler-&gt;thread,NULL,timer_thread_proc,scheduler,scheduler-&gt;pool) != APR_SUCCESS) {
+                scheduler-&gt;running = FALSE;
+                return FALSE;
+        }
+        return TRUE;
+}
+
+MPF_DECLARE(apt_bool_t) mpf_scheduler_stop(mpf_scheduler_t *scheduler)
+{
+        if(!scheduler) {
+                return FALSE;
+        }
+
+        scheduler-&gt;running = FALSE;
+        if(scheduler-&gt;thread) {
+                apr_status_t s;
+                apr_thread_join(&amp;s,scheduler-&gt;thread);
+                scheduler-&gt;thread = NULL;
+        }
+        return TRUE;
+}
+
+#endif
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_streamc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_stream.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_stream.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_stream.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,158 @@
</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;mpf_stream.h&quot;
+
+/** Create stream capabilities */
+MPF_DECLARE(mpf_stream_capabilities_t*) mpf_stream_capabilities_create(mpf_stream_direction_e direction, apr_pool_t *pool)
+{
+        mpf_stream_capabilities_t *capabilities = (mpf_stream_capabilities_t*)apr_palloc(pool,sizeof(mpf_stream_capabilities_t));
+        capabilities-&gt;direction = direction;
+        mpf_codec_capabilities_init(&amp;capabilities-&gt;codecs,1,pool);
+        return capabilities;
+}
+
+/** Clone stream capabilities */
+MPF_DECLARE(mpf_stream_capabilities_t*) mpf_stream_capabilities_clone(const mpf_stream_capabilities_t *src_capabilities, apr_pool_t *pool)
+{
+        mpf_stream_capabilities_t *capabilities = (mpf_stream_capabilities_t*)apr_palloc(pool,sizeof(mpf_stream_capabilities_t));
+        capabilities-&gt;direction = src_capabilities-&gt;direction;
+        mpf_codec_capabilities_clone(&amp;capabilities-&gt;codecs,&amp;src_capabilities-&gt;codecs,pool);
+        return capabilities;
+}
+
+/** Merge stream capabilities */
+MPF_DECLARE(apt_bool_t) mpf_stream_capabilities_merge(mpf_stream_capabilities_t *capabilities, const mpf_stream_capabilities_t *src_capabilities, apr_pool_t *pool)
+{
+        capabilities-&gt;direction |= src_capabilities-&gt;direction;
+        return mpf_codec_capabilities_merge(&amp;capabilities-&gt;codecs,&amp;src_capabilities-&gt;codecs,pool);
+}
+
+
+
+/** Create audio stream */
+MPF_DECLARE(mpf_audio_stream_t*) mpf_audio_stream_create(void *obj, const mpf_audio_stream_vtable_t *vtable, const mpf_stream_capabilities_t *capabilities, apr_pool_t *pool)
+{
+        mpf_audio_stream_t *stream;
+        if(!vtable || !capabilities) {
+                return NULL;
+        }
+        
+        /* validate required fields */
+        if(capabilities-&gt;direction &amp; STREAM_DIRECTION_SEND) {
+                /* validate sink */
+                if(!vtable-&gt;write_frame) {
+                        return NULL;
+                }
+        }
+        if(capabilities-&gt;direction &amp; STREAM_DIRECTION_RECEIVE) {
+                /* validate source */
+                if(!vtable-&gt;read_frame) {
+                        return NULL;
+                }
+        }
+
+        stream = (mpf_audio_stream_t*)apr_palloc(pool,sizeof(mpf_audio_stream_t));
+        stream-&gt;obj = obj;
+        stream-&gt;vtable = vtable;
+        stream-&gt;termination = NULL;
+        stream-&gt;capabilities = capabilities;
+        stream-&gt;direction = capabilities-&gt;direction;
+        stream-&gt;rx_descriptor = NULL;
+        stream-&gt;rx_event_descriptor = NULL;
+        stream-&gt;tx_descriptor = NULL;
+        stream-&gt;tx_event_descriptor = NULL;
+        return stream;
+}
+
+/** Validate audio stream receiver */
+MPF_DECLARE(apt_bool_t) mpf_audio_stream_rx_validate(
+                                                                        mpf_audio_stream_t *stream,
+                                                                        const mpf_codec_descriptor_t *descriptor,
+                                                                        const mpf_codec_descriptor_t *event_descriptor,
+                                                                        apr_pool_t *pool)
+{
+        if(!stream-&gt;capabilities) {
+                return FALSE;
+        }
+
+        if(!stream-&gt;rx_descriptor) {
+                stream-&gt;rx_descriptor = mpf_codec_descriptor_create_by_capabilities(&amp;stream-&gt;capabilities-&gt;codecs,descriptor,pool);
+        }
+        if(!stream-&gt;rx_event_descriptor) {
+                if(stream-&gt;capabilities-&gt;codecs.allow_named_events == TRUE &amp;&amp; event_descriptor) {
+                        stream-&gt;rx_event_descriptor = apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
+                        *stream-&gt;rx_event_descriptor = *event_descriptor;
+                }
+        }
+
+        return stream-&gt;rx_descriptor ? TRUE : FALSE;
+}
+
+/** Validate audio stream transmitter */
+MPF_DECLARE(apt_bool_t) mpf_audio_stream_tx_validate(
+                                                                        mpf_audio_stream_t *stream,
+                                                                        const mpf_codec_descriptor_t *descriptor,
+                                                                        const mpf_codec_descriptor_t *event_descriptor,
+                                                                        apr_pool_t *pool)
+{
+        if(!stream-&gt;capabilities) {
+                return FALSE;
+        }
+
+        if(!stream-&gt;tx_descriptor) {
+                stream-&gt;tx_descriptor = mpf_codec_descriptor_create_by_capabilities(&amp;stream-&gt;capabilities-&gt;codecs,descriptor,pool);
+        }
+        if(!stream-&gt;tx_event_descriptor) {
+                if(stream-&gt;capabilities-&gt;codecs.allow_named_events == TRUE &amp;&amp; event_descriptor) {
+                        stream-&gt;tx_event_descriptor = apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
+                        *stream-&gt;tx_event_descriptor = *event_descriptor;
+                }
+        }
+        return stream-&gt;tx_descriptor ? TRUE : FALSE;
+}
+
+/** Trace media path */
+MPF_DECLARE(void) mpf_audio_stream_trace(mpf_audio_stream_t *stream, mpf_stream_direction_e direction, apt_text_stream_t *output)
+{
+        if(stream-&gt;vtable-&gt;trace) {
+                stream-&gt;vtable-&gt;trace(stream,direction,output);
+                return;
+        }
+
+        if(direction &amp; STREAM_DIRECTION_SEND) {
+                mpf_codec_descriptor_t *descriptor = stream-&gt;tx_descriptor;
+                if(descriptor) {
+                        apr_size_t offset = output-&gt;pos - output-&gt;text.buf;
+                        output-&gt;pos += apr_snprintf(output-&gt;pos, output-&gt;text.length - offset,
+                                &quot;[%s/%d/%d]-&gt;Sink&quot;,
+                                descriptor-&gt;name.buf,
+                                descriptor-&gt;sampling_rate,
+                                descriptor-&gt;channel_count);
+                }
+        }
+        if(direction &amp; STREAM_DIRECTION_RECEIVE) {
+                mpf_codec_descriptor_t *descriptor = stream-&gt;rx_descriptor;
+                if(descriptor) {
+                        apr_size_t offset = output-&gt;pos - output-&gt;text.buf;
+                        output-&gt;pos += apr_snprintf(output-&gt;pos, output-&gt;text.length - offset,
+                                &quot;Source-&gt;[%s/%d/%d]&quot;,
+                                descriptor-&gt;name.buf,
+                                descriptor-&gt;sampling_rate,
+                                descriptor-&gt;channel_count);
+                }
+        }
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_terminationc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx">         termination-&gt;event_handler_obj = NULL;
</span><span class="cx">         termination-&gt;event_handler = NULL;
</span><span class="cx">         termination-&gt;codec_manager = NULL;
</span><ins>+        termination-&gt;timer_manager = NULL;
</ins><span class="cx">         termination-&gt;termination_factory = termination_factory;
</span><span class="cx">         termination-&gt;vtable = vtable;
</span><span class="cx">         termination-&gt;slot = 0;
</span><span class="lines">@@ -46,19 +47,14 @@
</span><span class="cx">         return termination;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(apt_bool_t) mpf_termination_destroy(mpf_termination_t *termination)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_termination_add(mpf_termination_t *termination, void *descriptor)
</ins><span class="cx"> {
</span><del>-        if(termination-&gt;vtable &amp;&amp; termination-&gt;vtable-&gt;destroy) {
-                termination-&gt;vtable-&gt;destroy(termination);
</del><ins>+        if(termination-&gt;vtable &amp;&amp; termination-&gt;vtable-&gt;add) {
+                termination-&gt;vtable-&gt;add(termination,descriptor);
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(void*) mpf_termination_object_get(mpf_termination_t *termination)
-{
-        return termination-&gt;obj;
-}
-
</del><span class="cx"> MPF_DECLARE(apt_bool_t) mpf_termination_modify(mpf_termination_t *termination, void *descriptor)
</span><span class="cx"> {
</span><span class="cx">         if(termination-&gt;vtable &amp;&amp; termination-&gt;vtable-&gt;modify) {
</span><span class="lines">@@ -67,54 +63,10 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-MPF_DECLARE(apt_bool_t) mpf_termination_validate(mpf_termination_t *termination)
</del><ins>+MPF_DECLARE(apt_bool_t) mpf_termination_subtract(mpf_termination_t *termination)
</ins><span class="cx"> {
</span><del>-        mpf_audio_stream_t *audio_stream;
-        if(!termination) {
-                return FALSE;
</del><ins>+        if(termination-&gt;vtable &amp;&amp; termination-&gt;vtable-&gt;subtract) {
+                termination-&gt;vtable-&gt;subtract(termination);
</ins><span class="cx">         }
</span><del>-        audio_stream = termination-&gt;audio_stream;
-        if(audio_stream) {
-                if(!audio_stream-&gt;vtable) {
-                        return FALSE;
-                }
-                if((audio_stream-&gt;mode &amp; STREAM_MODE_RECEIVE) == STREAM_MODE_RECEIVE) {
-                        if(!audio_stream-&gt;rx_codec) {
-                                audio_stream-&gt;rx_codec = mpf_codec_manager_default_codec_get(
-                                                                                        termination-&gt;codec_manager,
-                                                                                        termination-&gt;pool);
-                        }
-                }
-                if((audio_stream-&gt;mode &amp; STREAM_MODE_SEND) == STREAM_MODE_SEND) {
-                        if(!audio_stream-&gt;tx_codec) {
-                                audio_stream-&gt;tx_codec = mpf_codec_manager_default_codec_get(
-                                                                                        termination-&gt;codec_manager,
-                                                                                        termination-&gt;pool);
-                        }
-                }
-        }
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><del>-
-
-/** Create MPF termination by termination factory */
-MPF_DECLARE(mpf_termination_t*) mpf_termination_create(
-                                                                                mpf_termination_factory_t *termination_factory,
-                                                                                void *obj,
-                                                                                apr_pool_t *pool)
-{
-        if(termination_factory &amp;&amp; termination_factory-&gt;create_termination) {
-                return termination_factory-&gt;create_termination(termination_factory,obj,pool);
-        }
-        return NULL;
-}
-
-/** Create raw MPF termination. */
-MPF_DECLARE(mpf_termination_t*) mpf_raw_termination_create(
-                                                                                void *obj,
-                                                                                mpf_audio_stream_t *audio_stream,
-                                                                                mpf_video_stream_t *video_stream,
-                                                                                apr_pool_t *pool)
-{
-        return mpf_termination_base_create(NULL,obj,NULL,audio_stream,video_stream,pool);
-}
</del></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_termination_factoryc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,66 @@
</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;mpf_termination_factory.h&quot;
+#include &quot;mpf_termination.h&quot;
+
+/** Create MPF termination from termination factory */
+MPF_DECLARE(mpf_termination_t*) mpf_termination_create(
+                                                                                mpf_termination_factory_t *termination_factory,
+                                                                                void *obj,
+                                                                                apr_pool_t *pool)
+{
+        if(termination_factory &amp;&amp; termination_factory-&gt;create_termination) {
+                return termination_factory-&gt;create_termination(termination_factory,obj,pool);
+        }
+        return NULL;
+}
+
+/** Create raw MPF termination. */
+MPF_DECLARE(mpf_termination_t*) mpf_raw_termination_create(
+                                                                                void *obj,
+                                                                                mpf_audio_stream_t *audio_stream,
+                                                                                mpf_video_stream_t *video_stream,
+                                                                                apr_pool_t *pool)
+{
+        return mpf_termination_base_create(NULL,obj,NULL,audio_stream,video_stream,pool);
+}
+
+MPF_DECLARE(apt_bool_t) mpf_termination_destroy(mpf_termination_t *termination)
+{
+        if(termination-&gt;vtable &amp;&amp; termination-&gt;vtable-&gt;destroy) {
+                termination-&gt;vtable-&gt;destroy(termination);
+        }
+        return TRUE;
+}
+
+/** Get associated object. */
+MPF_DECLARE(void*) mpf_termination_object_get(mpf_termination_t *termination)
+{
+        return termination-&gt;obj;
+}
+
+/** Get audio stream. */
+MPF_DECLARE(mpf_audio_stream_t*) mpf_termination_audio_stream_get(mpf_termination_t *termination)
+{
+        return termination-&gt;audio_stream;
+}
+
+/** Get video stream. */
+MPF_DECLARE(mpf_video_stream_t*) mpf_termination_video_stream_get(mpf_termination_t *termination)
+{
+        return termination-&gt;video_stream;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_timerc"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_timer.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmpfsrcmpf_timer_managerc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,188 @@
</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.
+ */
+
+#ifdef WIN32
+#pragma warning(disable: 4127)
+#endif
+#include &lt;apr_ring.h&gt; 
+#include &quot;mpf_timer_manager.h&quot;
+#include &quot;mpf_scheduler.h&quot;
+#include &quot;apt_log.h&quot;
+
+/** MPF timer manager */
+struct mpf_timer_manager_t {
+        /** Ring head */
+        APR_RING_HEAD(mpf_timer_head_t, mpf_timer_t) head;
+
+        /** Clock resolution */
+        apr_uint32_t  resolution;
+        /** Elapsed time */
+        apr_uint32_t  elapsed_time;
+};
+
+/** MPF timer */
+struct mpf_timer_t {
+        /** Ring entry */
+        APR_RING_ENTRY(mpf_timer_t) link;
+
+        /** Back pointer to manager */
+        mpf_timer_manager_t *manager;
+        /** Time next report is scheduled at */
+        apr_uint32_t         scheduled_time;
+
+        /** Timer proc */
+        mpf_timer_proc_f     proc;
+        /** Timer object */
+        void                *obj;
+};
+
+static void mpf_scheduler_proc(mpf_scheduler_t *scheduler, void *obj);
+
+/** Create timer manager */
+MPF_DECLARE(mpf_timer_manager_t*) mpf_timer_manager_create(mpf_scheduler_t *scheduler, apr_pool_t *pool)
+{
+        mpf_timer_manager_t *timer_manager = apr_palloc(pool,sizeof(mpf_timer_manager_t));
+        APR_RING_INIT(&amp;timer_manager-&gt;head, mpf_timer_t, link);
+        timer_manager-&gt;elapsed_time = 0;
+        timer_manager-&gt;resolution = 100; // 100 ms
+
+        mpf_scheduler_timer_clock_set(scheduler,timer_manager-&gt;resolution,mpf_scheduler_proc,timer_manager);
+        return timer_manager;
+}
+
+/** Destroy timer manager */
+MPF_DECLARE(void) mpf_timer_manager_destroy(mpf_timer_manager_t *timer_manager)
+{
+}
+
+
+/** Create timer */
+MPF_DECLARE(mpf_timer_t*) mpf_timer_create(mpf_timer_manager_t *timer_manager, mpf_timer_proc_f proc, void *obj, apr_pool_t *pool)
+{
+        mpf_timer_t *timer = apr_palloc(pool,sizeof(mpf_timer_t));
+        timer-&gt;manager = timer_manager;
+        timer-&gt;scheduled_time = 0;
+        timer-&gt;proc = proc;
+        timer-&gt;obj = obj;
+        return timer;
+}
+
+static APR_INLINE apt_bool_t mpf_timer_insert(mpf_timer_manager_t *manager, mpf_timer_t *timer)
+{
+        mpf_timer_t *it;
+        for(it = APR_RING_LAST(&amp;manager-&gt;head);
+                        it != APR_RING_SENTINEL(&amp;manager-&gt;head, mpf_timer_t, link);
+                                it = APR_RING_PREV(it, link)) {
+                
+                if(it-&gt;scheduled_time &lt;= timer-&gt;scheduled_time) {
+                        APR_RING_INSERT_AFTER(it,timer,link);
+                        return TRUE;
+                }
+        }
+        APR_RING_INSERT_HEAD(&amp;manager-&gt;head,timer,mpf_timer_t,link);
+        return TRUE;
+}
+
+/** Set one-shot timer */
+MPF_DECLARE(apt_bool_t) mpf_timer_set(mpf_timer_t *timer, apr_uint32_t timeout)
+
+{
+        mpf_timer_manager_t *manager = timer-&gt;manager;
+
+        if(timeout &lt;= 0 || !timer-&gt;proc) {
+                return FALSE;
+        }
+        
+        /* calculate time to elapse */
+        timer-&gt;scheduled_time = manager-&gt;elapsed_time + timeout;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Set Timer 0x%x [%d]&quot;,timer,timer-&gt;scheduled_time);
+
+        if(APR_RING_EMPTY(&amp;timer-&gt;manager-&gt;head, mpf_timer_t, link)) {
+                APR_RING_INSERT_TAIL(&amp;manager-&gt;head,timer,mpf_timer_t,link);
+                return TRUE;
+        }
+
+        /* insert new node (timer) to sorted by scheduled time list */
+        return mpf_timer_insert(manager,timer);
+}
+
+/** Kill timer */
+MPF_DECLARE(apt_bool_t) mpf_timer_kill(mpf_timer_t *timer)
+{
+        if(!timer-&gt;scheduled_time) {
+                return FALSE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Kill Timer 0x%x [%d]&quot;,timer,timer-&gt;scheduled_time);
+        /* remove node (timer) from the list */
+        APR_RING_REMOVE(timer,link);
+        timer-&gt;scheduled_time = 0;
+
+        if(APR_RING_EMPTY(&amp;timer-&gt;manager-&gt;head, mpf_timer_t, link)) {
+                /* reset elapsed time if no timers set */
+                timer-&gt;manager-&gt;elapsed_time = 0;
+        }
+        return TRUE;
+}
+
+static void mpf_timers_reschedule(mpf_timer_manager_t *manager)
+{
+        mpf_timer_t *it;
+        for(it = APR_RING_LAST(&amp;manager-&gt;head);
+                        it != APR_RING_SENTINEL(&amp;manager-&gt;head, mpf_timer_t, link);
+                                it = APR_RING_PREV(it, link)) {
+                
+                it-&gt;scheduled_time -= manager-&gt;elapsed_time;
+        }
+        manager-&gt;elapsed_time = 0;
+}
+
+static void mpf_scheduler_proc(mpf_scheduler_t *scheduler, void *obj)
+{
+        mpf_timer_manager_t *manager = obj;
+        mpf_timer_t *timer;
+
+        if(APR_RING_EMPTY(&amp;manager-&gt;head, mpf_timer_t, link)) {
+                /* just return, nothing to do */
+                return;
+        }
+
+        /* increment elapsed time */
+        manager-&gt;elapsed_time += manager-&gt;resolution;
+        if(manager-&gt;elapsed_time &gt;= 0xFFFF) {
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Reschedule Timers [%d]&quot;,manager-&gt;elapsed_time);
+                mpf_timers_reschedule(manager);
+        }
+
+        /* process timers */
+        do {
+                /* get first node (timer) */
+                timer = APR_RING_FIRST(&amp;manager-&gt;head);
+
+                if(timer-&gt;scheduled_time &gt; manager-&gt;elapsed_time) {
+                        /* scheduled time is not elapsed yet */
+                        break;
+                }
+                
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Timer Elapsed 0x%x [%d]&quot;,timer,timer-&gt;scheduled_time);
+                /* remove the elapsed timer from the list */
+                APR_RING_REMOVE(timer, link);
+                timer-&gt;scheduled_time = 0;
+                /* process the elapsed timer */
+                timer-&gt;proc(timer,timer-&gt;obj);
+        }
+        while(!APR_RING_EMPTY(&amp;manager-&gt;head, mpf_timer_t, link));
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -11,32 +11,31 @@
</span><span class="cx"> 
</span><span class="cx"> include_HEADERS          = include/mrcp.h \
</span><span class="cx">                            include/mrcp_types.h \
</span><ins>+                           message/include/mrcp_start_line.h \
</ins><span class="cx">                            message/include/mrcp_header_accessor.h \
</span><span class="cx">                            message/include/mrcp_generic_header.h \
</span><span class="cx">                            message/include/mrcp_message.h \
</span><del>-                           control/include/mrcp_state_machine.h \
</del><span class="cx">                            control/include/mrcp_resource.h \
</span><span class="cx">                            control/include/mrcp_resource_factory.h \
</span><ins>+                           control/include/mrcp_resource_loader.h \
</ins><span class="cx">                            control/include/mrcp_stream.h \
</span><span class="cx">                            resources/include/mrcp_synth_header.h \
</span><span class="cx">                            resources/include/mrcp_synth_resource.h \
</span><del>-                           resources/include/mrcp_synth_state_machine.h \
</del><span class="cx">                            resources/include/mrcp_recog_header.h \
</span><span class="cx">                            resources/include/mrcp_recog_resource.h \
</span><del>-                           resources/include/mrcp_recog_state_machine.h \
-                           resources/include/mrcp_default_factory.h
</del><ins>+                           resources/include/mrcp_recorder_header.h \
+                           resources/include/mrcp_recorder_resource.h
</ins><span class="cx"> 
</span><span class="cx"> libmrcp_la_SOURCES       = message/src/mrcp_header_accessor.c \
</span><span class="cx">                            message/src/mrcp_generic_header.c \
</span><ins>+                           message/src/mrcp_start_line.c \
</ins><span class="cx">                            message/src/mrcp_message.c \
</span><span class="cx">                            control/src/mrcp_resource_factory.c \
</span><ins>+                           control/src/mrcp_resource_loader.c \
</ins><span class="cx">                            control/src/mrcp_stream.c \
</span><span class="cx">                            resources/src/mrcp_synth_header.c \
</span><span class="cx">                            resources/src/mrcp_synth_resource.c \
</span><del>-                           resources/src/mrcp_synth_server_state_machine.c \
-                           resources/src/mrcp_synth_client_state_machine.c \
</del><span class="cx">                            resources/src/mrcp_recog_header.c \
</span><span class="cx">                            resources/src/mrcp_recog_resource.c \
</span><del>-                           resources/src/mrcp_recog_server_state_machine.c \
-                           resources/src/mrcp_recog_client_state_machine.c \
-                           resources/src/mrcp_default_factory.c
</del><ins>+                           resources/src/mrcp_recorder_header.c \
+                           resources/src/mrcp_recorder_resource.c
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_resourceh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -24,7 +24,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_types.h&quot;
</span><span class="cx"> #include &quot;mrcp_header_accessor.h&quot;
</span><del>-#include &quot;mrcp_state_machine.h&quot;
</del><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="lines">@@ -32,33 +31,48 @@
</span><span class="cx"> /** MRCP resource definition */
</span><span class="cx"> struct mrcp_resource_t {
</span><span class="cx">         /** MRCP resource identifier */
</span><del>-        mrcp_resource_id            id;
</del><ins>+        mrcp_resource_id id;
+        /** MRCP resource name */
+        apt_str_t        name;
</ins><span class="cx"> 
</span><del>-        /** Set resource specific data in a message by resource id */
-        apt_bool_t (*resourcify_message_by_id)(mrcp_resource_t *resource, mrcp_message_t *message);
-        /** Set resource specific data in a message by resource name */
-        apt_bool_t (*resourcify_message_by_name)(mrcp_resource_t *resource, mrcp_message_t *message);
</del><ins>+        /** Get string table of methods */
+        const apt_str_table_item_t* (*get_method_str_table)(mrcp_version_e version);
+        /** Number of methods */
+        apr_size_t       method_count;
</ins><span class="cx"> 
</span><del>-        /** Create client side state machine */
-        mrcp_state_machine_t* (*create_client_state_machine)(void *obj, mrcp_version_e version, apr_pool_t *pool);
-        /** Create server side state machine */
-        mrcp_state_machine_t* (*create_server_state_machine)(void *obj, mrcp_version_e version, apr_pool_t *pool);
</del><ins>+        /** Get string table of events */
+        const apt_str_table_item_t* (*get_event_str_table)(mrcp_version_e version);
+        /** Number of events */
+        apr_size_t       event_count;
+
+        /** Get vtable of resource header */
+        const mrcp_header_vtable_t* (*get_resource_header_vtable)(mrcp_version_e version);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Initialize MRCP resource */
</span><del>-static APR_INLINE void mrcp_resource_init(mrcp_resource_t *resource)
</del><ins>+static APR_INLINE mrcp_resource_t* mrcp_resource_create(apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        resource-&gt;resourcify_message_by_id = NULL;
-        resource-&gt;resourcify_message_by_name = NULL;
-        resource-&gt;create_client_state_machine = NULL;
-        resource-&gt;create_server_state_machine = NULL;
</del><ins>+        mrcp_resource_t *resource = (mrcp_resource_t*) apr_palloc(pool, sizeof(mrcp_resource_t));
+        resource-&gt;id = 0;
+        apt_string_reset(&amp;resource-&gt;name);
+        resource-&gt;method_count = 0;
+        resource-&gt;event_count = 0;
+        resource-&gt;get_method_str_table = NULL;
+        resource-&gt;get_event_str_table = NULL;
+        resource-&gt;get_resource_header_vtable = NULL;
+        return resource;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Validate MRCP resource */
</span><span class="cx"> static APR_INLINE apt_bool_t mrcp_resource_validate(mrcp_resource_t *resource)
</span><span class="cx"> {
</span><del>-        return (resource-&gt;resourcify_message_by_id &amp;&amp; 
-                resource-&gt;resourcify_message_by_name) ? TRUE : FALSE;
</del><ins>+        if(resource-&gt;method_count &amp;&amp; resource-&gt;event_count &amp;&amp;
+                resource-&gt;get_method_str_table &amp;&amp; resource-&gt;get_event_str_table &amp;&amp;
+                 resource-&gt;get_resource_header_vtable &amp;&amp;
+                 resource-&gt;name.buf &amp;&amp; resource-&gt;name.length) {
+                return TRUE;
+        }
+        return FALSE;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_resource_factoryh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,7 +22,6 @@
</span><span class="cx">  * @brief Aggregation of MRCP Resources
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &quot;apt_string_table.h&quot;
</del><span class="cx"> #include &quot;apt_text_stream.h&quot;
</span><span class="cx"> #include &quot;mrcp_types.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -34,29 +33,16 @@
</span><span class="cx"> /** Destroy MRCP resource factory */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_resource_factory_destroy(mrcp_resource_factory_t *resource_factory);
</span><span class="cx"> 
</span><del>-/** Set MRCP resource string table */
-MRCP_DECLARE(apt_bool_t) mrcp_resource_string_table_set(mrcp_resource_factory_t *resource_factory, const apt_str_table_item_t *string_table);
-
</del><span class="cx"> /** Register MRCP resource */
</span><del>-MRCP_DECLARE(apt_bool_t) mrcp_resource_register(mrcp_resource_factory_t *resource_factory, mrcp_resource_t *resource, mrcp_resource_id resource_id);
</del><ins>+MRCP_DECLARE(apt_bool_t) mrcp_resource_register(mrcp_resource_factory_t *resource_factory, mrcp_resource_t *resource);
</ins><span class="cx"> 
</span><span class="cx"> /** Get MRCP resource by resource id */
</span><span class="cx"> MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_get(mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id);
</span><span class="cx"> 
</span><del>-/** Get resource name associated with specified resource id */
-MRCP_DECLARE(const apt_str_t*) mrcp_resource_name_get(mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id);
</del><ins>+/** Find MRCP resource by resource name */
+MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_find(mrcp_resource_factory_t *resource_factory, const apt_str_t *name);
</ins><span class="cx"> 
</span><del>-/** Find resource id associated with specified resource name */
-MRCP_DECLARE(mrcp_resource_id) mrcp_resource_id_find(mrcp_resource_factory_t *resource_factory, const apt_str_t *resource_name);
</del><span class="cx"> 
</span><del>-
-/** Associate MRCP resource specific data by resource identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resourcify_by_id(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message);
-
-/** Associate MRCP resource specific data by resource name */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resourcify_by_name(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message);
-
-
</del><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MRCP_RESOURCE_FACTORY_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_resource_loaderh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,51 @@
</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 __MRCP_RESOURCE_LOADER_H__
+#define __MRCP_RESOURCE_LOADER_H__
+
+/**
+ * @file mrcp_resource_loader.h
+ * @brief MRCP Resource Loader
+ */ 
+
+#include &quot;apt_string.h&quot;
+#include &quot;mrcp_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque resource loader declaration */
+typedef struct mrcp_resource_loader_t mrcp_resource_loader_t;
+
+
+/** Create MRCP resource loader */
+MRCP_DECLARE(mrcp_resource_loader_t*) mrcp_resource_loader_create(apt_bool_t load_all_resources, apr_pool_t *pool);
+
+/** Load all MRCP resources */
+MRCP_DECLARE(apt_bool_t) mrcp_resources_load(mrcp_resource_loader_t *loader);
+
+/** Load MRCP resource by resource name */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_load(mrcp_resource_loader_t *loader, const apt_str_t *name);
+
+/** Load MRCP resource by resource identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_load_by_id(mrcp_resource_loader_t *loader, mrcp_resource_id id);
+
+/** Get MRCP resource factory */
+MRCP_DECLARE(mrcp_resource_factory_t*) mrcp_resource_factory_get(mrcp_resource_loader_t *loader);
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_RESOURCE_LOADER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolincludemrcp_state_machineh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/include/mrcp_state_machine.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolsrcmrcp_resource_factoryc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -14,6 +14,7 @@
</span><span class="cx">  * limitations under the License.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#include &lt;apr_hash.h&gt;
</ins><span class="cx"> #include &quot;mrcp_resource_factory.h&quot;
</span><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_resource.h&quot;
</span><span class="lines">@@ -21,12 +22,12 @@
</span><span class="cx"> 
</span><span class="cx"> /** Resource factory definition (aggregation of resources) */
</span><span class="cx"> struct mrcp_resource_factory_t {
</span><del>-        /** Array of MRCP resources */
-        mrcp_resource_t           **resource_array;
</del><ins>+        /** Array of MRCP resources (reference by id) */
+        mrcp_resource_t **resource_array;
</ins><span class="cx">         /** Number of MRCP resources */
</span><del>-        apr_size_t                  resource_count;
-        /** String table of MRCP resource names */
-        const apt_str_table_item_t *string_table;
</del><ins>+        apr_size_t        resource_count;
+        /** Hash of MRCP resources (reference by name) */
+        apr_hash_t       *resource_hash;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Create MRCP resource factory */
</span><span class="lines">@@ -44,8 +45,7 @@
</span><span class="cx">         for(i=0; i&lt;resource_count; i++) {
</span><span class="cx">                 resource_factory-&gt;resource_array[i] = NULL;
</span><span class="cx">         }
</span><del>-        resource_factory-&gt;string_table = NULL;
-        
</del><ins>+        resource_factory-&gt;resource_hash = apr_hash_make(pool);
</ins><span class="cx">         return resource_factory;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -59,30 +59,23 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Set MRCP resource string table */
-MRCP_DECLARE(apt_bool_t) mrcp_resource_string_table_set(mrcp_resource_factory_t *resource_factory, const apt_str_table_item_t *string_table)
-{
-        resource_factory-&gt;string_table = string_table;
-        return TRUE;
-}
-
</del><span class="cx"> /** Register MRCP resource */
</span><del>-MRCP_DECLARE(apt_bool_t) mrcp_resource_register(mrcp_resource_factory_t *resource_factory, mrcp_resource_t *resource, mrcp_resource_id resource_id)
</del><ins>+MRCP_DECLARE(apt_bool_t) mrcp_resource_register(mrcp_resource_factory_t *resource_factory, mrcp_resource_t *resource)
</ins><span class="cx"> {        
</span><del>-        if(!resource || resource_id &gt;= resource_factory-&gt;resource_count) {
</del><ins>+        if(!resource || resource-&gt;id &gt;= resource_factory-&gt;resource_count) {
</ins><span class="cx">                 /* invalid params */
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        if(resource_factory-&gt;resource_array[resource_id]) {
</del><ins>+        if(resource_factory-&gt;resource_array[resource-&gt;id]) {
</ins><span class="cx">                 /* resource with specified id already exists */
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        resource-&gt;id = resource_id;
</del><span class="cx">         if(mrcp_resource_validate(resource) != TRUE) {
</span><span class="cx">                 /* invalid resource */
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         resource_factory-&gt;resource_array[resource-&gt;id] = resource;
</span><ins>+        apr_hash_set(resource_factory-&gt;resource_hash,resource-&gt;name.buf,resource-&gt;name.length,resource);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -95,57 +88,12 @@
</span><span class="cx">         return resource_factory-&gt;resource_array[resource_id];
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
-/** Set header accessor interface */
-static APR_INLINE void mrcp_generic_header_accessor_set(mrcp_message_t *message)
</del><ins>+/** Find MRCP resource by resource name */
+MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_find(mrcp_resource_factory_t *resource_factory, const apt_str_t *name)
</ins><span class="cx"> {
</span><del>-        message-&gt;header.generic_header_accessor.vtable = mrcp_generic_header_vtable_get(message-&gt;start_line.version);
-}
-
-/** Associate MRCP resource specific data by resource identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resourcify_by_id(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message)
-{
-        mrcp_resource_t *resource;
-        const apt_str_t *name;
-        resource = mrcp_resource_get(resource_factory,message-&gt;channel_id.resource_id);
-        if(!resource) {
-                return FALSE;
</del><ins>+        if(!name-&gt;buf || !name-&gt;length) {
+                return NULL;
</ins><span class="cx">         }
</span><del>-        name = mrcp_resource_name_get(resource_factory,resource-&gt;id);
-        if(!name) {
-                return FALSE;
-        }
-        /* associate resource_name and resource_id */
-        message-&gt;channel_id.resource_name = *name;
</del><span class="cx"> 
</span><del>-        mrcp_generic_header_accessor_set(message);
-        return resource-&gt;resourcify_message_by_id(resource,message);
</del><ins>+        return apr_hash_get(resource_factory-&gt;resource_hash,name-&gt;buf,name-&gt;length);
</ins><span class="cx"> }
</span><del>-
-/** Associate MRCP resource specific data by resource name */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resourcify_by_name(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message)
-{
-        mrcp_resource_t *resource;
-        /* associate resource_name and resource_id */
-        const apt_str_t *name = &amp;message-&gt;channel_id.resource_name;
-        message-&gt;channel_id.resource_id = mrcp_resource_id_find(resource_factory,name);
-        resource = mrcp_resource_get(resource_factory,message-&gt;channel_id.resource_id);
-        if(!resource) {
-                return FALSE;
-        }
-
-        mrcp_generic_header_accessor_set(message);
-        return resource-&gt;resourcify_message_by_name(resource,message);
-}
-
-/** Get resource name associated with specified resource id */
-MRCP_DECLARE(const apt_str_t*) mrcp_resource_name_get(mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id)
-{
-        return apt_string_table_str_get(resource_factory-&gt;string_table,resource_factory-&gt;resource_count,resource_id);
-}
-
-/** Find resource id associated with specified resource name */
-MRCP_DECLARE(mrcp_resource_id) mrcp_resource_id_find(mrcp_resource_factory_t *resource_factory, const apt_str_t *resource_name)
-{
-        return apt_string_table_id_find(resource_factory-&gt;string_table,resource_factory-&gt;resource_count,resource_name);
-}
</del></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolsrcmrcp_resource_loaderc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,133 @@
</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;mrcp_resource_loader.h&quot;
+#include &quot;mrcp_resource_factory.h&quot;
+#include &quot;mrcp_resource.h&quot;
+#include &quot;mrcp_synth_resource.h&quot;
+#include &quot;mrcp_recog_resource.h&quot;
+#include &quot;mrcp_recorder_resource.h&quot;
+#include &quot;apt_log.h&quot;
+
+/** Resource loader */
+struct mrcp_resource_loader_t {
+        mrcp_resource_factory_t *factory;
+        apr_pool_t              *pool;
+};
+
+/** String table of MRCPv2 resources (mrcp_resource_types_e) */
+static const apt_str_table_item_t mrcp_resource_string_table[] = {
+        {{&quot;speechsynth&quot;,11},6},
+        {{&quot;speechrecog&quot;,11},6},
+        {{&quot;recorder&quot;,    8},0}
+};
+
+static mrcp_resource_t* mrcp_resource_create_by_id(mrcp_resource_id id, apr_pool_t *pool);
+
+/** Create default MRCP resource factory */
+MRCP_DECLARE(mrcp_resource_loader_t*) mrcp_resource_loader_create(apt_bool_t load_all_resources, apr_pool_t *pool)
+{
+        mrcp_resource_loader_t *loader;
+        mrcp_resource_factory_t *resource_factory;
+        resource_factory = mrcp_resource_factory_create(MRCP_RESOURCE_TYPE_COUNT,pool);
+        if(!resource_factory) {
+                return NULL;
+        }
+        
+        loader = apr_palloc(pool,sizeof(mrcp_resource_loader_t));
+        loader-&gt;factory = resource_factory;
+        loader-&gt;pool = pool;
+
+        if(load_all_resources == TRUE) {
+                mrcp_resources_load(loader);
+        }
+
+        return loader;
+}
+
+/** Load all MRCP resources */
+MRCP_DECLARE(apt_bool_t) mrcp_resources_load(mrcp_resource_loader_t *loader)
+{
+        mrcp_resource_id id;
+        for(id=0; id&lt;MRCP_RESOURCE_TYPE_COUNT; id++) {
+                mrcp_resource_load_by_id(loader,id);
+        }
+        return TRUE;
+}
+
+/** Load MRCP resource by resource name */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_load(mrcp_resource_loader_t *loader, const apt_str_t *name)
+{
+        mrcp_resource_id id = apt_string_table_id_find(
+                                                        mrcp_resource_string_table,
+                                                        MRCP_RESOURCE_TYPE_COUNT,
+                                                        name);
+
+        mrcp_resource_t *resource = mrcp_resource_create_by_id(id,loader-&gt;pool);
+        if(!resource) {
+                apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Failed to Load Resource [%d]&quot;,id);
+                return FALSE;
+        }
+
+        apt_string_copy(&amp;resource-&gt;name,name,loader-&gt;pool);
+        apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Register Resource [%s]&quot;,name-&gt;buf);
+        return mrcp_resource_register(loader-&gt;factory,resource);
+}
+
+/** Load MRCP resource by resource identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_load_by_id(mrcp_resource_loader_t *loader, mrcp_resource_id id)
+{
+        const apt_str_t *name = apt_string_table_str_get(
+                                                                mrcp_resource_string_table,
+                                                                MRCP_RESOURCE_TYPE_COUNT,
+                                                                id);
+        mrcp_resource_t *resource = mrcp_resource_create_by_id(id,loader-&gt;pool);
+        if(!resource || !name) {
+                apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Failed to Load Resource [%d]&quot;,id);
+                return FALSE;
+        }
+
+        resource-&gt;name = *name;
+        apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Register Resource [%s]&quot;,resource-&gt;name.buf);
+        return mrcp_resource_register(loader-&gt;factory,resource);
+}
+
+/** Get MRCP resource factory */
+MRCP_DECLARE(mrcp_resource_factory_t*) mrcp_resource_factory_get(mrcp_resource_loader_t *loader)
+{
+        return loader-&gt;factory;
+}
+
+static mrcp_resource_t* mrcp_resource_create_by_id(mrcp_resource_id id, apr_pool_t *pool)
+{
+        mrcp_resource_t *resource = NULL;
+        switch(id) {
+                case MRCP_SYNTHESIZER_RESOURCE:
+                        resource = mrcp_synth_resource_create(pool);
+                        break;
+                case MRCP_RECOGNIZER_RESOURCE:
+                        resource = mrcp_recog_resource_create(pool);
+                        break;
+                case MRCP_RECORDER_RESOURCE:
+                        resource = mrcp_recorder_resource_create(pool);
+                        break;
+        }
+        
+        if(resource) {
+                resource-&gt;id = id;
+        }
+        return resource;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpcontrolsrcmrcp_streamc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -121,6 +121,8 @@
</span><span class="cx"> /** Parse MRCP message (excluding message body) */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_message_parse(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream)
</span><span class="cx"> {
</span><ins>+        mrcp_resource_t *resource;
+
</ins><span class="cx">         /* parse start-line */
</span><span class="cx">         if(mrcp_start_line_parse(&amp;message-&gt;start_line,stream,message-&gt;pool) == FALSE) {
</span><span class="cx">                 return FALSE;
</span><span class="lines">@@ -130,10 +132,16 @@
</span><span class="cx">                 mrcp_channel_id_parse(&amp;message-&gt;channel_id,stream,message-&gt;pool);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(mrcp_message_resourcify_by_name(resource_factory,message) == FALSE) {
</del><ins>+        /* find resource */
+        resource = mrcp_resource_find(resource_factory,&amp;message-&gt;channel_id.resource_name);
+        if(!resource) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if(mrcp_message_resource_set(message,resource) == FALSE) {
+                return FALSE;
+        }
+
</ins><span class="cx">         /* parse header */
</span><span class="cx">         if(mrcp_message_header_parse(&amp;message-&gt;header,stream,message-&gt;pool) == FALSE) {
</span><span class="cx">                 return FALSE;
</span><span class="lines">@@ -145,11 +153,6 @@
</span><span class="cx"> /** Generate MRCP message (excluding message body) */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_message_generate(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream)
</span><span class="cx"> {
</span><del>-        /* initialize resource specific data */
-        if(mrcp_message_resourcify_by_id(resource_factory,message) == FALSE) {
-                return FALSE;
-        }
-
</del><span class="cx">         /* validate message */
</span><span class="cx">         if(mrcp_message_validate(message) == FALSE) {
</span><span class="cx">                 return FALSE;
</span><span class="lines">@@ -170,7 +173,10 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         /* finalize start-line generation */
</span><del>-        mrcp_start_line_finalize(&amp;message-&gt;start_line,message-&gt;body.length,stream);
</del><ins>+        if(mrcp_start_line_finalize(&amp;message-&gt;start_line,message-&gt;body.length,stream) == FALSE) {
+                return FALSE;
+        }
+
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpincludemrcp_typesh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/include/mrcp_types.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/include/mrcp_types.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/include/mrcp_types.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -31,22 +31,39 @@
</span><span class="cx">         
</span><span class="cx">         MRCP_VERSION_UNKNOWN = 0,  /**&lt; Unknown version */
</span><span class="cx">         MRCP_VERSION_1 = 1,        /**&lt; MRCPv1 (RFC4463) */
</span><del>-        MRCP_VERSION_2 = 2         /**&lt; MRCPv2 (draft-ietf-speechsc-mrcpv2-15) */
</del><ins>+        MRCP_VERSION_2 = 2         /**&lt; MRCPv2 (draft-ietf-speechsc-mrcpv2-20) */
</ins><span class="cx"> } mrcp_version_e;
</span><span class="cx"> 
</span><span class="cx"> /** Enumeration of MRCP resource types */
</span><span class="cx"> typedef enum {
</span><span class="cx">         MRCP_SYNTHESIZER_RESOURCE, /**&lt; Synthesizer resource */
</span><span class="cx">         MRCP_RECOGNIZER_RESOURCE,  /**&lt; Recognizer resource */
</span><ins>+        MRCP_RECORDER_RESOURCE,    /**&lt; Recorder resource */
</ins><span class="cx"> 
</span><span class="cx">         MRCP_RESOURCE_TYPE_COUNT   /**&lt; Number of resources */
</span><span class="cx"> } mrcp_resource_type_e;
</span><span class="cx"> 
</span><del>-/** Message identifier used in request/response/event messages. */
-typedef apr_size_t  mrcp_request_id;
-/** Method identifier associated with method name. */
</del><ins>+/* MRCPv2 specifies request-id as 32bit unsigned integer,
+ * while MRCPv1 doesn't limit this value (1 * DIGIT).
+ * Some MRCPv1 clients use too long request-id. 
+ * To support them #define TOO_LONG_MRCP_REQUEST_ID
+ */
+#ifdef TOO_LONG_MRCP_REQUEST_ID
+/** MRCP request identifier */
+typedef apr_uint64_t  mrcp_request_id;
+/** Format to log MRCP request identifier */
+#define MRCP_REQUEST_ID_FMT    APR_UINT64_T_FMT
+#else 
+/** MRCP request identifier */
+typedef apr_uint32_t  mrcp_request_id;
+/** Format to log MRCP request identifier */
+#define MRCP_REQUEST_ID_FMT    &quot;d&quot;
+#endif
+
+
+/** Method identifier associated with method name */
</ins><span class="cx"> typedef apr_size_t mrcp_method_id;
</span><del>-/** Resource identifier associated with resource name. */
</del><ins>+/** Resource identifier associated with resource name */
</ins><span class="cx"> typedef apr_size_t mrcp_resource_id;
</span><span class="cx"> 
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmessageincludemrcp_messageh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,100 +23,22 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_types.h&quot;
</span><ins>+#include &quot;mrcp_start_line.h&quot;
</ins><span class="cx"> #include &quot;mrcp_header_accessor.h&quot;
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** Request-states used in MRCP response message */
-typedef enum {
-        /** The request was processed to completion and there will be no        
-            more events from that resource to the client with that request-id */
-        MRCP_REQUEST_STATE_COMPLETE,
-        /** The job has been placed on a queue and will be processed in first-in-first-out order */
-        MRCP_REQUEST_STATE_INPROGRESS,
-        /** Indicate that further event messages will be delivered with that request-id */
-        MRCP_REQUEST_STATE_PENDING,
-        
-        /** Number of request states */
-        MRCP_REQUEST_STATE_COUNT,
-        /** Unknown request state */
-        MRCP_REQUEST_STATE_UNKNOWN = MRCP_REQUEST_STATE_COUNT
-} mrcp_request_state_e;
-
-/** Status codes */
-typedef enum {
-        MRCP_STATUS_CODE_UNKNOWN                   = 0,
-        /* success codes (2xx) */
-        MRCP_STATUS_CODE_SUCCESS                   = 200,
-        MRCP_STATUS_CODE_SUCCESS_WITH_IGNORE       = 201,
-        /* failure codes (4xx) */
-        MRCP_STATUS_CODE_METHOD_NOT_ALLOWED        = 401,
-        MRCP_STATUS_CODE_METHOD_NOT_VALID          = 402,
-        MRCP_STATUS_CODE_UNSUPPORTED_PARAM         = 403,
-        MRCP_STATUS_CODE_ILLEGAL_PARAM_VALUE       = 404,
-        MRCP_STATUS_CODE_NOT_FOUND                 = 405,
-        MRCP_STATUS_CODE_MISSING_PARAM             = 406,
-        MRCP_STATUS_CODE_METHOD_FAILED             = 407,
-        MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE      = 408,
-        MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE   = 409,
-        MRCP_STATUS_CODE_RESOURCE_SPECIFIC_FAILURE = 421
-} mrcp_status_code_e;
-
-/** MRCP message types */
-typedef enum {
-        MRCP_MESSAGE_TYPE_UNKNOWN,
-        MRCP_MESSAGE_TYPE_REQUEST,
-        MRCP_MESSAGE_TYPE_RESPONSE,
-        MRCP_MESSAGE_TYPE_EVENT
-} mrcp_message_type_e;
-
-
-/** MRCP start-line declaration */
-typedef struct mrcp_start_line_t mrcp_start_line_t;
</del><span class="cx"> /** MRCP channel-id declaration */
</span><span class="cx"> typedef struct mrcp_channel_id mrcp_channel_id;
</span><span class="cx"> /** MRCP message header declaration */
</span><span class="cx"> typedef struct mrcp_message_header_t mrcp_message_header_t;
</span><span class="cx"> 
</span><del>-
-/** Start-line of MRCP message */
-struct mrcp_start_line_t {
-        /** MRCP message type */
-        mrcp_message_type_e  message_type;
-        /** Version of protocol in use */
-        mrcp_version_e       version;
-        /** Specify the length of the message, including the start-line (v2) */
-        size_t               length;
-        /** Unique identifier among client and server */
-        mrcp_request_id      request_id;
-        /** MRCP method name */
-        apt_str_t            method_name;
-        /** MRCP method id (associated with method name) */
-        mrcp_method_id       method_id;
-        /** Success or failure or other status of the request */
-        mrcp_status_code_e   status_code;
-        /** The state of the job initiated by the request */
-        mrcp_request_state_e request_state;
-};
-
-/** Initialize MRCP start-line */
-MRCP_DECLARE(void) mrcp_start_line_init(mrcp_start_line_t *start_line);
-/** Parse MRCP start-line */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool);
-/** Generate MRCP start-line */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream);
-/** Finalize MRCP start-line generation */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_finalize(mrcp_start_line_t *start_line, apr_size_t content_length, apt_text_stream_t *text_stream);
-
-
</del><span class="cx"> /** MRCP channel-identifier */
</span><span class="cx"> struct mrcp_channel_id {
</span><span class="cx">         /** Unambiguous string identifying the MRCP session */
</span><span class="cx">         apt_str_t        session_id;
</span><span class="cx">         /** MRCP resource name */
</span><span class="cx">         apt_str_t        resource_name;
</span><del>-        /** MRCP resource id (associated with resource name) */
-        mrcp_resource_id resource_id;
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Initialize MRCP channel-identifier */
</span><span class="lines">@@ -172,34 +94,33 @@
</span><span class="cx"> /** MRCP message */
</span><span class="cx"> struct mrcp_message_t {
</span><span class="cx">         /** Start-line of MRCP message */
</span><del>-        mrcp_start_line_t      start_line;
</del><ins>+        mrcp_start_line_t     start_line;
</ins><span class="cx">         /** Channel-identifier of MRCP message */
</span><del>-        mrcp_channel_id        channel_id;
</del><ins>+        mrcp_channel_id       channel_id;
</ins><span class="cx">         /** Header of MRCP message */
</span><del>-        mrcp_message_header_t  header;
</del><ins>+        mrcp_message_header_t header;
</ins><span class="cx">         /** Body of MRCP message */
</span><del>-        apt_str_t              body;
</del><ins>+        apt_str_t             body;
</ins><span class="cx"> 
</span><ins>+        /** Associated MRCP resource */
+        mrcp_resource_t      *resource;
</ins><span class="cx">         /** Memory pool MRCP message is allocated from */
</span><del>-        apr_pool_t            *pool;
</del><ins>+        apr_pool_t           *pool;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Create MRCP message */
</span><span class="cx"> MRCP_DECLARE(mrcp_message_t*) mrcp_message_create(apr_pool_t *pool);
</span><span class="cx"> 
</span><del>-/** Initialize MRCP message */
-MRCP_DECLARE(void) mrcp_message_init(mrcp_message_t *message, apr_pool_t *pool);
-
-/** Initialize MRCP response/event message by request message */
-MRCP_DECLARE(void) mrcp_message_init_by_request(mrcp_message_t *message, const mrcp_message_t *request_message);
-
</del><span class="cx"> /** Create MRCP request message */
</span><del>-MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_id resource_id, mrcp_method_id method_id, apr_pool_t *pool);
</del><ins>+MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_t *resource, mrcp_version_e version, mrcp_method_id method_id, apr_pool_t *pool);
</ins><span class="cx"> /** Create MRCP response message */
</span><span class="cx"> MRCP_DECLARE(mrcp_message_t*) mrcp_response_create(const mrcp_message_t *request_message, apr_pool_t *pool);
</span><span class="cx"> /** Create MRCP event message */
</span><span class="cx"> MRCP_DECLARE(mrcp_message_t*) mrcp_event_create(const mrcp_message_t *request_message, mrcp_method_id event_id, apr_pool_t *pool);
</span><span class="cx"> 
</span><ins>+/** Associate MRCP resource specific data by resource name */
+MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, mrcp_resource_t *resource);
+
</ins><span class="cx"> /** Validate MRCP message */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_message_validate(mrcp_message_t *message);
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmessageincludemrcp_start_lineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,114 @@
</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 __MRCP_START_LINE_H__
+#define __MRCP_START_LINE_H__
+
+/**
+ * @file mrcp_start_line.h
+ * @brief MRCP Start Line Definition
+ */ 
+
+#include &quot;mrcp_types.h&quot;
+#include &quot;apt_text_stream.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Request-states used in MRCP response message */
+typedef enum {
+        /** The request was processed to completion and there will be no        
+            more events from that resource to the client with that request-id */
+        MRCP_REQUEST_STATE_COMPLETE,
+        /** The job has been placed on a queue and will be processed in first-in-first-out order */
+        MRCP_REQUEST_STATE_INPROGRESS,
+        /** Indicate that further event messages will be delivered with that request-id */
+        MRCP_REQUEST_STATE_PENDING,
+        
+        /** Number of request states */
+        MRCP_REQUEST_STATE_COUNT,
+        /** Unknown request state */
+        MRCP_REQUEST_STATE_UNKNOWN = MRCP_REQUEST_STATE_COUNT
+} mrcp_request_state_e;
+
+/** Status codes */
+typedef enum {
+        MRCP_STATUS_CODE_UNKNOWN                   = 0,
+        /* success codes (2xx) */
+        MRCP_STATUS_CODE_SUCCESS                   = 200,
+        MRCP_STATUS_CODE_SUCCESS_WITH_IGNORE       = 201,
+        /* failure codes (4xx) */
+        MRCP_STATUS_CODE_METHOD_NOT_ALLOWED        = 401,
+        MRCP_STATUS_CODE_METHOD_NOT_VALID          = 402,
+        MRCP_STATUS_CODE_UNSUPPORTED_PARAM         = 403,
+        MRCP_STATUS_CODE_ILLEGAL_PARAM_VALUE       = 404,
+        MRCP_STATUS_CODE_NOT_FOUND                 = 405,
+        MRCP_STATUS_CODE_MISSING_PARAM             = 406,
+        MRCP_STATUS_CODE_METHOD_FAILED             = 407,
+        MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE      = 408,
+        MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE   = 409,
+        MRCP_STATUS_CODE_RESOURCE_SPECIFIC_FAILURE = 421
+} mrcp_status_code_e;
+
+/** MRCP message types */
+typedef enum {
+        MRCP_MESSAGE_TYPE_UNKNOWN,
+        MRCP_MESSAGE_TYPE_REQUEST,
+        MRCP_MESSAGE_TYPE_RESPONSE,
+        MRCP_MESSAGE_TYPE_EVENT
+} mrcp_message_type_e;
+
+
+/** MRCP start-line declaration */
+typedef struct mrcp_start_line_t mrcp_start_line_t;
+
+/** Start-line of MRCP message */
+struct mrcp_start_line_t {
+        /** MRCP message type */
+        mrcp_message_type_e  message_type;
+        /** Version of protocol in use */
+        mrcp_version_e       version;
+        /** Specify the length of the message, including the start-line (v2) */
+        apr_size_t           length;
+        /** Unique identifier among client and server */
+        mrcp_request_id      request_id;
+        /** MRCP method name */
+        apt_str_t            method_name;
+        /** MRCP method id (associated with method name) */
+        mrcp_method_id       method_id;
+        /** Success or failure or other status of the request */
+        mrcp_status_code_e   status_code;
+        /** The state of the job initiated by the request */
+        mrcp_request_state_e request_state;
+};
+
+/** Initialize MRCP start-line */
+MRCP_DECLARE(void) mrcp_start_line_init(mrcp_start_line_t *start_line);
+/** Parse MRCP start-line */
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool);
+/** Generate MRCP start-line */
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream);
+/** Finalize MRCP start-line generation */
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_finalize(mrcp_start_line_t *start_line, apr_size_t content_length, apt_text_stream_t *text_stream);
+
+/** Parse MRCP request-id */
+MRCP_DECLARE(mrcp_request_id) mrcp_request_id_parse(const apt_str_t *field);
+/** Generate MRCP request-id */
+MRCP_DECLARE(apt_bool_t) mrcp_request_id_generate(mrcp_request_id request_id, apt_text_stream_t *stream);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_START_LINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_generic_headerc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,6 +15,7 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><ins>+#include &quot;mrcp_start_line.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> /** String table of mrcp generic-header fields (mrcp_generic_header_id) */
</span><span class="cx"> static const apt_str_table_item_t generic_header_string_table[] = {
</span><span class="lines">@@ -36,7 +37,6 @@
</span><span class="cx">         {{&quot;Set-Cookie2&quot;,               11},10}
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> /** Parse mrcp request-id list */
</span><span class="cx"> static apt_bool_t mrcp_request_id_list_parse(mrcp_request_id_list_t *request_id_list, const apt_str_t *value)
</span><span class="cx"> {
</span><span class="lines">@@ -49,7 +49,7 @@
</span><span class="cx">                 if(apt_text_field_read(&amp;stream,',',TRUE,&amp;field) == FALSE) {
</span><span class="cx">                         break;
</span><span class="cx">                 }
</span><del>-                request_id_list-&gt;ids[request_id_list-&gt;count] = apt_size_value_parse(&amp;field);
</del><ins>+                request_id_list-&gt;ids[request_id_list-&gt;count] = mrcp_request_id_parse(&amp;field);
</ins><span class="cx">                 request_id_list-&gt;count++;
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx"> {
</span><span class="cx">         size_t i;
</span><span class="cx">         for(i=0; i&lt;request_id_list-&gt;count; i++) {
</span><del>-                apt_size_value_generate(request_id_list-&gt;ids[i],stream);
</del><ins>+                mrcp_request_id_generate(request_id_list-&gt;ids[i],stream);
</ins><span class="cx">                 if(i &lt; request_id_list-&gt;count-1) {
</span><span class="cx">                         *stream-&gt;pos++ = ',';
</span><span class="cx">                 }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_header_accessorc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -79,6 +79,10 @@
</span><span class="cx"> 
</span><span class="cx"> MRCP_DECLARE(void) mrcp_header_property_add(mrcp_header_accessor_t *accessor, apr_size_t id)
</span><span class="cx"> {
</span><ins>+        if(!accessor-&gt;vtable) {
+                return;
+        }
+
</ins><span class="cx">         if(id &lt; accessor-&gt;vtable-&gt;field_count) {
</span><span class="cx">                 char *prop = &amp;accessor-&gt;properties[id];
</span><span class="cx">                 if((*prop &amp; MRCP_HEADER_FIELD_NAME) != MRCP_HEADER_FIELD_NAME) {
</span><span class="lines">@@ -90,6 +94,10 @@
</span><span class="cx"> 
</span><span class="cx"> MRCP_DECLARE(void) mrcp_header_name_property_add(mrcp_header_accessor_t *accessor, apr_size_t id)
</span><span class="cx"> {
</span><ins>+        if(!accessor-&gt;vtable) {
+                return;
+        }
+
</ins><span class="cx">         if(id &lt; accessor-&gt;vtable-&gt;field_count) {
</span><span class="cx">                 char *prop = &amp;accessor-&gt;properties[id];
</span><span class="cx">                 if((*prop &amp; MRCP_HEADER_FIELD_NAME) != MRCP_HEADER_FIELD_NAME) {
</span><span class="lines">@@ -102,6 +110,10 @@
</span><span class="cx"> 
</span><span class="cx"> MRCP_DECLARE(void) mrcp_header_property_remove(mrcp_header_accessor_t *accessor, apr_size_t id)
</span><span class="cx"> {
</span><ins>+        if(!accessor-&gt;vtable) {
+                return;
+        }
+
</ins><span class="cx">         if(id &lt; accessor-&gt;vtable-&gt;field_count) {
</span><span class="cx">                 char *prop = &amp;accessor-&gt;properties[id];
</span><span class="cx">                 if((*prop &amp; MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
</span><span class="lines">@@ -113,6 +125,10 @@
</span><span class="cx"> 
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_header_property_check(mrcp_header_accessor_t *accessor, apr_size_t id)
</span><span class="cx"> {
</span><ins>+        if(!accessor-&gt;vtable) {
+                return FALSE;
+        }
+
</ins><span class="cx">         if((id &lt; accessor-&gt;vtable-&gt;field_count) &amp;&amp; accessor-&gt;properties) {
</span><span class="cx">                 if((accessor-&gt;properties[id] &amp; MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
</span><span class="cx">                         return TRUE;
</span><span class="lines">@@ -161,13 +177,15 @@
</span><span class="cx">         for(i=0, j=0; i&lt;parent-&gt;vtable-&gt;field_count &amp;&amp; j &lt; parent-&gt;counter; i++) {
</span><span class="cx">                 if((parent-&gt;properties[i] &amp; MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
</span><span class="cx">                         j++;
</span><del>-                        if((parent-&gt;properties[i] &amp; MRCP_HEADER_FIELD_VALUE) == MRCP_HEADER_FIELD_VALUE) {
-                                accessor-&gt;vtable-&gt;duplicate_field(accessor,parent,i,pool);
-                                mrcp_header_property_add(accessor,i);
</del><ins>+                        if((accessor-&gt;properties[i] &amp; MRCP_HEADER_FIELD_NAME) != MRCP_HEADER_FIELD_NAME) {
+                                if((parent-&gt;properties[i] &amp; MRCP_HEADER_FIELD_VALUE) == MRCP_HEADER_FIELD_VALUE) {
+                                        accessor-&gt;vtable-&gt;duplicate_field(accessor,parent,i,pool);
+                                        mrcp_header_property_add(accessor,i);
+                                }
+                                else {
+                                        mrcp_header_name_property_add(accessor,i);
+                                }
</ins><span class="cx">                         }
</span><del>-                        else {
-                                mrcp_header_name_property_add(accessor,i);
-                        }
</del><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_messagec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,426 +16,17 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><ins>+#include &quot;mrcp_resource.h&quot;
</ins><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><del>-/** Protocol name used in version string */
-#define MRCP_NAME               &quot;MRCP&quot;
-#define MRCP_NAME_LENGTH        (sizeof(MRCP_NAME)-1)
-
</del><span class="cx"> #define MRCP_CHANNEL_ID         &quot;Channel-Identifier&quot;
</span><span class="cx"> #define MRCP_CHANNEL_ID_LENGTH  (sizeof(MRCP_CHANNEL_ID)-1)
</span><span class="cx"> 
</span><del>-/** Separators used in MRCP version string parse/generate */
-#define MRCP_NAME_VERSION_SEPARATOR        '/'
-#define MRCP_VERSION_MAJOR_MINOR_SEPARATOR '.'
-
-#define MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT 4
-
-
-/** String table of MRCP request-states (mrcp_request_state_t) */
-static const apt_str_table_item_t mrcp_request_state_string_table[] = {
-        {{&quot;COMPLETE&quot;,    8},0},
-        {{&quot;IN-PROGRESS&quot;,11},0},
-        {{&quot;PENDING&quot;,     7},0}
-};
-
-
-/** Parse MRCP version */
-static mrcp_version_e mrcp_version_parse(const apt_str_t *field)
-{
-        mrcp_version_e version = MRCP_VERSION_UNKNOWN;
-        const char *pos;
-        if(field-&gt;length &lt;= MRCP_NAME_LENGTH || strncasecmp(field-&gt;buf,MRCP_NAME,MRCP_NAME_LENGTH) != 0) {
-                /* unexpected protocol name */
-                return version;
-        }
-
-        pos = field-&gt;buf + MRCP_NAME_LENGTH;
-        if(*pos == MRCP_NAME_VERSION_SEPARATOR) {
-                pos++;
-                switch(*pos) {
-                        case '1': version = MRCP_VERSION_1; break;
-                        case '2': version = MRCP_VERSION_2; break;
-                        default: ;
-                }
-        }
-        return version;
-}
-
-/** Generate MRCP version */
-static apt_bool_t mrcp_version_generate(mrcp_version_e version, apt_text_stream_t *stream)
-{
-        memcpy(stream-&gt;pos,MRCP_NAME,MRCP_NAME_LENGTH);
-        stream-&gt;pos += MRCP_NAME_LENGTH;
-        *stream-&gt;pos++ = MRCP_NAME_VERSION_SEPARATOR;
-        apt_size_value_generate(version,stream);
-        *stream-&gt;pos++ = MRCP_VERSION_MAJOR_MINOR_SEPARATOR;
-        *stream-&gt;pos++ = '0';
-        return TRUE;
-}
-
-/** Parse MRCP request-state used in MRCP response and event */
-static APR_INLINE mrcp_request_state_e mrcp_request_state_parse(const apt_str_t *request_state_str)
-{
-        return apt_string_table_id_find(mrcp_request_state_string_table,MRCP_REQUEST_STATE_COUNT,request_state_str);
-}
-
-/** Generate MRCP request-state used in MRCP response and event */
-static apt_bool_t mrcp_request_state_generate(mrcp_request_state_e request_state, apt_text_stream_t *stream)
-{
-        const apt_str_t *name;
-        name = apt_string_table_str_get(mrcp_request_state_string_table,MRCP_REQUEST_STATE_COUNT,request_state);
-        if(request_state &lt; MRCP_REQUEST_STATE_COUNT) {
-                memcpy(stream-&gt;pos,name-&gt;buf,name-&gt;length);
-                stream-&gt;pos += name-&gt;length;
-        }
-        return TRUE;
-}
-
-
-/** Parse MRCP request-id */
-static APR_INLINE mrcp_request_id mrcp_request_id_parse(const apt_str_t *field)
-{
-        return apt_size_value_parse(field);
-}
-
-/** Generate MRCP request-id */
-static APR_INLINE apt_bool_t mrcp_request_id_generate(mrcp_request_id request_id, apt_text_stream_t *stream)
-{
-        return apt_size_value_generate(request_id,stream);
-}
-
-/** Parse MRCP status-code */
-static APR_INLINE mrcp_status_code_e mrcp_status_code_parse(const apt_str_t *field)
-{
-        return apt_size_value_parse(field);
-}
-
-/** Generate MRCP status-code */
-static APR_INLINE size_t  mrcp_status_code_generate(mrcp_status_code_e status_code, apt_text_stream_t *stream)
-{
-        return apt_size_value_generate(status_code,stream);
-}
-
-
-/** Parse MRCP request-line */
-static apt_bool_t mrcp_request_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
-{
-        apt_str_t field;
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in request-line&quot;);
-                return FALSE;
-        }
-        start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
-
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse mrcp-version in request-line&quot;);
-                return FALSE;
-        }
-
-        start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
-        if(start_line-&gt;request_state == MRCP_REQUEST_STATE_UNKNOWN) {
-                /* request-line */
-                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_REQUEST;
-        }
-        else {
-                /* event line */
-                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_EVENT;
-
-                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse mrcp-version in request-line&quot;);
-                        return FALSE;
-                }
-        }
-
-        start_line-&gt;version = mrcp_version_parse(&amp;field);
-        if(start_line-&gt;version == MRCP_VERSION_UNKNOWN) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown mrcp-version&quot;);
-                return FALSE;
-        }
-        return TRUE;
-}
-
-/** Generate MRCP request-line */
-static apt_bool_t mrcp_request_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
-{
-        memcpy(stream-&gt;pos,start_line-&gt;method_name.buf,start_line-&gt;method_name.length);
-        stream-&gt;pos += start_line-&gt;method_name.length;
-        *stream-&gt;pos++ = APT_TOKEN_SP;
-
-        mrcp_request_id_generate(start_line-&gt;request_id,stream);
-        *stream-&gt;pos++ = APT_TOKEN_SP;
-
-        if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_REQUEST) {
-                if(start_line-&gt;status_code != MRCP_STATUS_CODE_UNKNOWN) {
-                        mrcp_status_code_generate(start_line-&gt;status_code,stream);
-                        *stream-&gt;pos++ = APT_TOKEN_SP;
-                }
-        }
-        else if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_EVENT) {
-                mrcp_request_state_generate(start_line-&gt;request_state,stream);
-                *stream-&gt;pos++ = APT_TOKEN_SP;
-        }
-
-        mrcp_version_generate(start_line-&gt;version,stream);
-        return TRUE;
-}
-
-/** Parse MRCP response-line */
-static apt_bool_t mrcp_response_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
-{
-        apt_str_t field;
-        start_line-&gt;length = 0;
-        if(start_line-&gt;version == MRCP_VERSION_2) {
-                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse message-length in response-line&quot;);
-                        return FALSE;
-                }
-                start_line-&gt;length = apt_size_value_parse(&amp;field);
-        }
-
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in response-line&quot;);
-                return FALSE;
-        }
-        start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
-
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse status-code in response-line&quot;);
-                return FALSE;
-        }
-        start_line-&gt;status_code = mrcp_status_code_parse(&amp;field);
-
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-state in response-line&quot;);
-                return FALSE;
-        }
-        start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
-        return TRUE;
-}
-
-/** Generate MRCP response-line */
-static apt_bool_t mrcp_response_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
-{
-        mrcp_version_generate(start_line-&gt;version,stream);
-        *stream-&gt;pos++ = APT_TOKEN_SP;
-
-        mrcp_request_id_generate(start_line-&gt;request_id,stream);
-        *stream-&gt;pos++ = APT_TOKEN_SP;
-
-        mrcp_status_code_generate(start_line-&gt;status_code,stream);
-        *stream-&gt;pos++ = APT_TOKEN_SP;
-
-        mrcp_request_state_generate(start_line-&gt;request_state,stream);
-        return TRUE;
-}
-
-/** Parse MRCP v2 start-line */
-static apt_bool_t mrcp_v2_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream, apr_pool_t *pool)
-{
-        apt_str_t field;
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse message-length in v2 start-line&quot;);
-                return FALSE;
-        }
-        start_line-&gt;length = apt_size_value_parse(&amp;field);
-
-        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in v2 start-line&quot;);
-                return FALSE;
-        }
-        start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
-        if(start_line-&gt;request_id == 0 &amp;&amp; *field.buf != '0') {
-                /* parsing MRCP v2 request or event */
-                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_REQUEST;
-                apt_string_copy(&amp;start_line-&gt;method_name,&amp;field,pool);
-
-                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in v2 start-line&quot;);
-                        return FALSE;
-                }
-                start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
-
-                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == TRUE) {
-                        /* parsing MRCP v2 event */
-                        start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
-                        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_EVENT;
-                }
-        }
-        else {
-                /* parsing MRCP v2 response */
-                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_RESPONSE;
-
-                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse status-code in v2 start-line&quot;);
-                        return FALSE;
-                }
-                start_line-&gt;status_code = mrcp_status_code_parse(&amp;field);
-
-                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-state in v2 start-line&quot;);
-                        return FALSE;
-                }
-                start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
-        }
-
-        return TRUE;
-}
-
-/** Generate MRCP v2 start-line */
-static apt_bool_t mrcp_v2_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
-{
-        char *pos = stream-&gt;pos;
-        mrcp_version_generate(start_line-&gt;version,stream);
-        *stream-&gt;pos++ = APT_TOKEN_SP;
-
-        start_line-&gt;length = stream-&gt;pos - pos; /* length is temrorary used to store offset */
-        /* reserving MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT space for start_line-&gt;length */
-        memset(stream-&gt;pos,APT_TOKEN_SP,MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT+1);
-        stream-&gt;pos += MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT+1;
-
-        if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
-                mrcp_request_id_generate(start_line-&gt;request_id,stream);
-                *stream-&gt;pos++ = APT_TOKEN_SP;
-
-                mrcp_status_code_generate(start_line-&gt;status_code,stream);
-                *stream-&gt;pos++ = APT_TOKEN_SP;
-
-                mrcp_request_state_generate(start_line-&gt;request_state,stream);
-                *stream-&gt;pos++ = APT_TOKEN_SP;
-        }
-        else {
-                memcpy(stream-&gt;pos,start_line-&gt;method_name.buf,start_line-&gt;method_name.length);
-                stream-&gt;pos += start_line-&gt;method_name.length;
-                *stream-&gt;pos++ = APT_TOKEN_SP;
-
-                mrcp_request_id_generate(start_line-&gt;request_id,stream);
-                if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_EVENT) {
-                        *stream-&gt;pos++ = APT_TOKEN_SP;
-                        mrcp_request_state_generate(start_line-&gt;request_state,stream);
-                }
-        }
-        return TRUE;
-}
-
-/** Initialize MRCP start-line */
-MRCP_DECLARE(void) mrcp_start_line_init(mrcp_start_line_t *start_line)
-{
-        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
-        start_line-&gt;version = MRCP_VERSION_UNKNOWN;
-        start_line-&gt;length = 0;
-        start_line-&gt;request_id = 0;
-        apt_string_reset(&amp;start_line-&gt;method_name);
-        start_line-&gt;status_code = MRCP_STATUS_CODE_UNKNOWN;
-        start_line-&gt;request_state = MRCP_REQUEST_STATE_UNKNOWN;
-}
-
-/** Parse MRCP start-line */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool)
-{
-        apt_text_stream_t line;
-        apt_str_t field;
-        apt_bool_t status = TRUE;
-        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
-        if(apt_text_line_read(text_stream,&amp;line.text) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse MRCP start-line&quot;);
-                return FALSE;
-        }
-        line.pos = line.text.buf;
-
-        if(apt_text_field_read(&amp;line,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot read the first field in start-line&quot;);
-                return FALSE;
-        }
-
-        if(field.buf == strstr(field.buf,MRCP_NAME)) {
-                start_line-&gt;version = mrcp_version_parse(&amp;field);
-
-                if(start_line-&gt;version == MRCP_VERSION_1) {
-                        /* parsing MRCP v1 response */
-                        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_RESPONSE;
-                        status = mrcp_response_line_parse(start_line,&amp;line);
-                }
-                else if(start_line-&gt;version == MRCP_VERSION_2) {
-                        /* parsing MRCP v2 start-line (request/response/event) */
-                        status = mrcp_v2_start_line_parse(start_line,&amp;line,pool);
-                }
-                else {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown MRCP version&quot;);
-                        return FALSE;
-                }
-        }
-        else {
-                /* parsing MRCP v1 request or event */
-                apt_string_copy(&amp;start_line-&gt;method_name,&amp;field,pool);
-                status = mrcp_request_line_parse(start_line,&amp;line);
-        }
-        return status;
-}
-
-/** Generate MRCP start-line */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream)
-{
-        apt_bool_t status = FALSE;
-        if(start_line-&gt;version == MRCP_VERSION_1) {
-                switch(start_line-&gt;message_type) {
-                        case MRCP_MESSAGE_TYPE_REQUEST:
-                                status = mrcp_request_line_generate(start_line,text_stream);
-                                break;
-                        case MRCP_MESSAGE_TYPE_RESPONSE:
-                                status = mrcp_response_line_generate(start_line,text_stream);
-                                break;
-                        case MRCP_MESSAGE_TYPE_EVENT:
-                                status = mrcp_request_line_generate(start_line,text_stream);
-                                break;
-                        default:
-                                break;
-                }
-        }
-        else if(start_line-&gt;version == MRCP_VERSION_2) {
-                status = mrcp_v2_start_line_generate(start_line,text_stream);
-        }
-
-        if(status == TRUE) {
-                apt_text_eol_insert(text_stream);
-        }
-        
-        return status;
-}
-
-/** Finalize MRCP start-line generation */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_finalize(mrcp_start_line_t *start_line, apr_size_t content_length, apt_text_stream_t *text_stream)
-{
-        apr_size_t length = text_stream-&gt;pos - text_stream-&gt;text.buf + content_length;
-        if(start_line-&gt;version == MRCP_VERSION_2) {
-                /* message-length includes the number of bytes that specify the message-length in the header */
-                /* too comlex to generate!!! see the discussion */
-                /* http://www1.ietf.org/mail-archive/web/speechsc/current/msg01734.html */
-                apt_str_t field;
-                field.buf = text_stream-&gt;text.buf + start_line-&gt;length; /* length is temrorary used to store offset */
-                length -= MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT;
-                apt_var_length_value_generate(&amp;length,MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT,&amp;field);
-                field.buf[field.length] = APT_TOKEN_SP;
-                start_line-&gt;length += field.length;
-
-                field.length = MRCP_MESSAGE_LENGTH_MAX_DIGITS_COUNT - field.length;
-                if(field.length) {
-                        memmove(text_stream-&gt;text.buf+field.length,text_stream-&gt;text.buf,start_line-&gt;length);
-                        text_stream-&gt;text.buf += field.length;
-                        text_stream-&gt;text.length -= field.length;
-                }
-        }
-
-        start_line-&gt;length = length;
-        return TRUE;
-}
-
</del><span class="cx"> /** Initialize MRCP channel-identifier */
</span><span class="cx"> MRCP_DECLARE(void) mrcp_channel_id_init(mrcp_channel_id *channel_id)
</span><span class="cx"> {
</span><span class="cx">         apt_string_reset(&amp;channel_id-&gt;session_id);
</span><span class="cx">         apt_string_reset(&amp;channel_id-&gt;resource_name);
</span><del>-        channel_id-&gt;resource_id = 0;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Parse MRCP channel-identifier */
</span><span class="lines">@@ -599,43 +190,113 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-
-/** Create MRCP message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_message_create(apr_pool_t *pool)
-{
-        mrcp_message_t *message = apr_palloc(pool,sizeof(mrcp_message_t));
-        mrcp_message_init(message,pool);
-        return message;
-}
-
</del><span class="cx"> /** Initialize MRCP message */
</span><del>-MRCP_DECLARE(void) mrcp_message_init(mrcp_message_t *message, apr_pool_t *pool)
</del><ins>+static void mrcp_message_init(mrcp_message_t *message, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         mrcp_start_line_init(&amp;message-&gt;start_line);
</span><span class="cx">         mrcp_channel_id_init(&amp;message-&gt;channel_id);
</span><span class="cx">         mrcp_message_header_init(&amp;message-&gt;header);
</span><span class="cx">         apt_string_reset(&amp;message-&gt;body);
</span><ins>+        message-&gt;resource = NULL;
</ins><span class="cx">         message-&gt;pool = pool;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Initialize response/event message by request message */
-MRCP_DECLARE(void) mrcp_message_init_by_request(mrcp_message_t *message, const mrcp_message_t *request_message)
</del><ins>+/** Set header accessor interface */
+static APR_INLINE void mrcp_generic_header_accessor_set(mrcp_message_t *message)
</ins><span class="cx"> {
</span><del>-        message-&gt;channel_id = request_message-&gt;channel_id;
-        message-&gt;start_line.request_id = request_message-&gt;start_line.request_id;
-        message-&gt;start_line.version = request_message-&gt;start_line.version;
-        message-&gt;start_line.method_id = request_message-&gt;start_line.method_id;
-        message-&gt;header.generic_header_accessor.vtable = request_message-&gt;header.generic_header_accessor.vtable;
-        message-&gt;header.resource_header_accessor.vtable = request_message-&gt;header.resource_header_accessor.vtable;
</del><ins>+        message-&gt;header.generic_header_accessor.vtable = mrcp_generic_header_vtable_get(message-&gt;start_line.version);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Associate MRCP resource specific data by resource identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set_by_id(mrcp_message_t *message, mrcp_resource_t *resource)
+{
+        if(!resource) {
+                return FALSE;
+        }
+        message-&gt;resource = resource;
+        
+        message-&gt;channel_id.resource_name = resource-&gt;name;
+
+        mrcp_generic_header_accessor_set(message);
+        message-&gt;header.resource_header_accessor.vtable = 
+                resource-&gt;get_resource_header_vtable(message-&gt;start_line.version);
+
+        /* associate method_name and method_id */
+        if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
+                const apt_str_t *name = apt_string_table_str_get(
+                        resource-&gt;get_method_str_table(message-&gt;start_line.version),
+                        resource-&gt;method_count,
+                        message-&gt;start_line.method_id);
+                if(!name) {
+                        return FALSE;
+                }
+                message-&gt;start_line.method_name = *name;
+        }
+        else if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
+                const apt_str_t *name = apt_string_table_str_get(
+                        resource-&gt;get_event_str_table(message-&gt;start_line.version),
+                        resource-&gt;event_count,
+                        message-&gt;start_line.method_id);
+                if(!name) {
+                        return FALSE;
+                }
+                message-&gt;start_line.method_name = *name;
+        }
+
+        return TRUE;
+}
+
+/** Associate MRCP resource specific data by resource name */
+MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, mrcp_resource_t *resource)
+{
+        if(!resource) {
+                return FALSE;
+        }
+        message-&gt;resource = resource;
+
+        mrcp_generic_header_accessor_set(message);
+        message-&gt;header.resource_header_accessor.vtable = 
+                resource-&gt;get_resource_header_vtable(message-&gt;start_line.version);
+        
+        /* associate method_name and method_id */
+        if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
+                message-&gt;start_line.method_id = apt_string_table_id_find(
+                        resource-&gt;get_method_str_table(message-&gt;start_line.version),
+                        resource-&gt;method_count,
+                        &amp;message-&gt;start_line.method_name);
+                if(message-&gt;start_line.method_id &gt;= resource-&gt;method_count) {
+                        return FALSE;
+                }
+        }
+        else if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
+                message-&gt;start_line.method_id = apt_string_table_id_find(
+                        resource-&gt;get_event_str_table(message-&gt;start_line.version),
+                        resource-&gt;event_count,
+                        &amp;message-&gt;start_line.method_name);
+                if(message-&gt;start_line.method_id &gt;= resource-&gt;event_count) {
+                        return FALSE;
+                }
+        }
+
+        return TRUE;
+}
+
+/** Create MRCP message */
+MRCP_DECLARE(mrcp_message_t*) mrcp_message_create(apr_pool_t *pool)
+{
+        mrcp_message_t *message = apr_palloc(pool,sizeof(mrcp_message_t));
+        mrcp_message_init(message,pool);
+        return message;
+}
+
</ins><span class="cx"> /** Create MRCP request message */
</span><del>-MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_id resource_id, mrcp_method_id method_id, apr_pool_t *pool)
</del><ins>+MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_t *resource, mrcp_version_e version, mrcp_method_id method_id, apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         mrcp_message_t *request_message = mrcp_message_create(pool);
</span><span class="cx">         request_message-&gt;start_line.message_type = MRCP_MESSAGE_TYPE_REQUEST;
</span><ins>+        request_message-&gt;start_line.version = version;
</ins><span class="cx">         request_message-&gt;start_line.method_id = method_id;
</span><del>-        request_message-&gt;channel_id.resource_id = resource_id;
</del><ins>+        mrcp_message_resource_set_by_id(request_message,resource);
</ins><span class="cx">         return request_message;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -643,12 +304,16 @@
</span><span class="cx"> MRCP_DECLARE(mrcp_message_t*) mrcp_response_create(const mrcp_message_t *request_message, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mrcp_message_t *response_message = mrcp_message_create(pool);
</span><del>-        if(request_message) {
-                mrcp_message_init_by_request(response_message,request_message);
-        }
</del><span class="cx">         response_message-&gt;start_line.message_type = MRCP_MESSAGE_TYPE_RESPONSE;
</span><span class="cx">         response_message-&gt;start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
</span><span class="cx">         response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_SUCCESS;
</span><ins>+        if(request_message) {
+                response_message-&gt;channel_id = request_message-&gt;channel_id;
+                response_message-&gt;start_line.request_id = request_message-&gt;start_line.request_id;
+                response_message-&gt;start_line.version = request_message-&gt;start_line.version;
+                response_message-&gt;start_line.method_id = request_message-&gt;start_line.method_id;
+                mrcp_message_resource_set_by_id(response_message,request_message-&gt;resource);
+        }
</ins><span class="cx">         return response_message;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -656,11 +321,14 @@
</span><span class="cx"> MRCP_DECLARE(mrcp_message_t*) mrcp_event_create(const mrcp_message_t *request_message, mrcp_method_id event_id, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mrcp_message_t *event_message = mrcp_message_create(pool);
</span><del>-        if(request_message) {
-                mrcp_message_init_by_request(event_message,request_message);
-        }
</del><span class="cx">         event_message-&gt;start_line.message_type = MRCP_MESSAGE_TYPE_EVENT;
</span><span class="cx">         event_message-&gt;start_line.method_id = event_id;
</span><ins>+        if(request_message) {
+                event_message-&gt;channel_id = request_message-&gt;channel_id;
+                event_message-&gt;start_line.request_id = request_message-&gt;start_line.request_id;
+                event_message-&gt;start_line.version = request_message-&gt;start_line.version;
+                mrcp_message_resource_set_by_id(event_message,request_message-&gt;resource);
+        }
</ins><span class="cx">         return event_message;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmessagesrcmrcp_start_linec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,444 @@
</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 &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
+#include &quot;mrcp_start_line.h&quot;
+#include &quot;apt_string_table.h&quot;
+#include &quot;apt_log.h&quot;
+
+/** Protocol name used in version string */
+#define MRCP_NAME               &quot;MRCP&quot;
+#define MRCP_NAME_LENGTH        (sizeof(MRCP_NAME)-1)
+
+/** Separators used in MRCP version string parse/generate */
+#define MRCP_NAME_VERSION_SEPARATOR        '/'
+#define MRCP_VERSION_MAJOR_MINOR_SEPARATOR '.'
+
+/** Max number of digits message length consists of */
+#define MAX_DIGIT_COUNT 6
+
+
+/** String table of MRCP request-states (mrcp_request_state_t) */
+static const apt_str_table_item_t mrcp_request_state_string_table[] = {
+        {{&quot;COMPLETE&quot;,    8},0},
+        {{&quot;IN-PROGRESS&quot;,11},0},
+        {{&quot;PENDING&quot;,     7},0}
+};
+
+
+/** Parse MRCP version */
+static mrcp_version_e mrcp_version_parse(const apt_str_t *field)
+{
+        mrcp_version_e version = MRCP_VERSION_UNKNOWN;
+        const char *pos;
+        if(field-&gt;length &lt;= MRCP_NAME_LENGTH || strncasecmp(field-&gt;buf,MRCP_NAME,MRCP_NAME_LENGTH) != 0) {
+                /* unexpected protocol name */
+                return version;
+        }
+
+        pos = field-&gt;buf + MRCP_NAME_LENGTH;
+        if(*pos == MRCP_NAME_VERSION_SEPARATOR) {
+                pos++;
+                switch(*pos) {
+                        case '1': version = MRCP_VERSION_1; break;
+                        case '2': version = MRCP_VERSION_2; break;
+                        default: ;
+                }
+        }
+        return version;
+}
+
+/** Generate MRCP version */
+static apt_bool_t mrcp_version_generate(mrcp_version_e version, apt_text_stream_t *stream)
+{
+        memcpy(stream-&gt;pos,MRCP_NAME,MRCP_NAME_LENGTH);
+        stream-&gt;pos += MRCP_NAME_LENGTH;
+        *stream-&gt;pos++ = MRCP_NAME_VERSION_SEPARATOR;
+        apt_size_value_generate(version,stream);
+        *stream-&gt;pos++ = MRCP_VERSION_MAJOR_MINOR_SEPARATOR;
+        *stream-&gt;pos++ = '0';
+        return TRUE;
+}
+
+/** Parse MRCP request-state used in MRCP response and event */
+static APR_INLINE mrcp_request_state_e mrcp_request_state_parse(const apt_str_t *request_state_str)
+{
+        return apt_string_table_id_find(mrcp_request_state_string_table,MRCP_REQUEST_STATE_COUNT,request_state_str);
+}
+
+/** Generate MRCP request-state used in MRCP response and event */
+static apt_bool_t mrcp_request_state_generate(mrcp_request_state_e request_state, apt_text_stream_t *stream)
+{
+        const apt_str_t *name;
+        name = apt_string_table_str_get(mrcp_request_state_string_table,MRCP_REQUEST_STATE_COUNT,request_state);
+        if(request_state &lt; MRCP_REQUEST_STATE_COUNT) {
+                memcpy(stream-&gt;pos,name-&gt;buf,name-&gt;length);
+                stream-&gt;pos += name-&gt;length;
+        }
+        return TRUE;
+}
+
+
+/** Parse MRCP status-code */
+static APR_INLINE mrcp_status_code_e mrcp_status_code_parse(const apt_str_t *field)
+{
+        return apt_size_value_parse(field);
+}
+
+/** Generate MRCP status-code */
+static APR_INLINE size_t  mrcp_status_code_generate(mrcp_status_code_e status_code, apt_text_stream_t *stream)
+{
+        return apt_size_value_generate(status_code,stream);
+}
+
+
+/** Parse MRCP request-line */
+static apt_bool_t mrcp_request_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
+{
+        apt_str_t field;
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in request-line&quot;);
+                return FALSE;
+        }
+        start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
+
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse mrcp-version in request-line&quot;);
+                return FALSE;
+        }
+
+        start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
+        if(start_line-&gt;request_state == MRCP_REQUEST_STATE_UNKNOWN) {
+                /* request-line */
+                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_REQUEST;
+        }
+        else {
+                /* event line */
+                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_EVENT;
+
+                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse mrcp-version in request-line&quot;);
+                        return FALSE;
+                }
+        }
+
+        start_line-&gt;version = mrcp_version_parse(&amp;field);
+        if(start_line-&gt;version == MRCP_VERSION_UNKNOWN) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown mrcp-version&quot;);
+                return FALSE;
+        }
+        return TRUE;
+}
+
+/** Generate MRCP request-line */
+static apt_bool_t mrcp_request_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
+{
+        memcpy(stream-&gt;pos,start_line-&gt;method_name.buf,start_line-&gt;method_name.length);
+        stream-&gt;pos += start_line-&gt;method_name.length;
+        *stream-&gt;pos++ = APT_TOKEN_SP;
+
+        mrcp_request_id_generate(start_line-&gt;request_id,stream);
+        *stream-&gt;pos++ = APT_TOKEN_SP;
+
+        if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_REQUEST) {
+                if(start_line-&gt;status_code != MRCP_STATUS_CODE_UNKNOWN) {
+                        mrcp_status_code_generate(start_line-&gt;status_code,stream);
+                        *stream-&gt;pos++ = APT_TOKEN_SP;
+                }
+        }
+        else if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_EVENT) {
+                mrcp_request_state_generate(start_line-&gt;request_state,stream);
+                *stream-&gt;pos++ = APT_TOKEN_SP;
+        }
+
+        mrcp_version_generate(start_line-&gt;version,stream);
+        return TRUE;
+}
+
+/** Parse MRCP response-line */
+static apt_bool_t mrcp_response_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
+{
+        apt_str_t field;
+        start_line-&gt;length = 0;
+        if(start_line-&gt;version == MRCP_VERSION_2) {
+                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse message-length in response-line&quot;);
+                        return FALSE;
+                }
+                start_line-&gt;length = apt_size_value_parse(&amp;field);
+        }
+
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in response-line&quot;);
+                return FALSE;
+        }
+        start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
+
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse status-code in response-line&quot;);
+                return FALSE;
+        }
+        start_line-&gt;status_code = mrcp_status_code_parse(&amp;field);
+
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-state in response-line&quot;);
+                return FALSE;
+        }
+        start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
+        return TRUE;
+}
+
+/** Generate MRCP response-line */
+static apt_bool_t mrcp_response_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
+{
+        mrcp_version_generate(start_line-&gt;version,stream);
+        *stream-&gt;pos++ = APT_TOKEN_SP;
+
+        mrcp_request_id_generate(start_line-&gt;request_id,stream);
+        *stream-&gt;pos++ = APT_TOKEN_SP;
+
+        mrcp_status_code_generate(start_line-&gt;status_code,stream);
+        *stream-&gt;pos++ = APT_TOKEN_SP;
+
+        mrcp_request_state_generate(start_line-&gt;request_state,stream);
+        return TRUE;
+}
+
+/** Parse MRCP v2 start-line */
+static apt_bool_t mrcp_v2_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *stream, apr_pool_t *pool)
+{
+        apt_str_t field;
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse message-length in v2 start-line&quot;);
+                return FALSE;
+        }
+        start_line-&gt;length = apt_size_value_parse(&amp;field);
+
+        if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in v2 start-line&quot;);
+                return FALSE;
+        }
+        start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
+        if(start_line-&gt;request_id == 0 &amp;&amp; *field.buf != '0') {
+                /* parsing MRCP v2 request or event */
+                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_REQUEST;
+                apt_string_copy(&amp;start_line-&gt;method_name,&amp;field,pool);
+
+                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-id in v2 start-line&quot;);
+                        return FALSE;
+                }
+                start_line-&gt;request_id = mrcp_request_id_parse(&amp;field);
+
+                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == TRUE) {
+                        /* parsing MRCP v2 event */
+                        start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
+                        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_EVENT;
+                }
+        }
+        else {
+                /* parsing MRCP v2 response */
+                start_line-&gt;message_type = MRCP_MESSAGE_TYPE_RESPONSE;
+
+                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse status-code in v2 start-line&quot;);
+                        return FALSE;
+                }
+                start_line-&gt;status_code = mrcp_status_code_parse(&amp;field);
+
+                if(apt_text_field_read(stream,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse request-state in v2 start-line&quot;);
+                        return FALSE;
+                }
+                start_line-&gt;request_state = mrcp_request_state_parse(&amp;field);
+        }
+
+        return TRUE;
+}
+
+/** Generate MRCP v2 start-line */
+static apt_bool_t mrcp_v2_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *stream)
+{
+        char *pos = stream-&gt;pos;
+        mrcp_version_generate(start_line-&gt;version,stream);
+        *stream-&gt;pos++ = APT_TOKEN_SP;
+
+        start_line-&gt;length = stream-&gt;pos - pos; /* length is temporary used to store offset */
+        /* reserving MAX_DIGIT_COUNT space for start_line-&gt;length */
+        memset(stream-&gt;pos,APT_TOKEN_SP,MAX_DIGIT_COUNT+1);
+        stream-&gt;pos += MAX_DIGIT_COUNT+1;
+
+        if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
+                mrcp_request_id_generate(start_line-&gt;request_id,stream);
+                *stream-&gt;pos++ = APT_TOKEN_SP;
+
+                mrcp_status_code_generate(start_line-&gt;status_code,stream);
+                *stream-&gt;pos++ = APT_TOKEN_SP;
+
+                mrcp_request_state_generate(start_line-&gt;request_state,stream);
+        }
+        else {
+                memcpy(stream-&gt;pos,start_line-&gt;method_name.buf,start_line-&gt;method_name.length);
+                stream-&gt;pos += start_line-&gt;method_name.length;
+                *stream-&gt;pos++ = APT_TOKEN_SP;
+
+                mrcp_request_id_generate(start_line-&gt;request_id,stream);
+                if(start_line-&gt;message_type == MRCP_MESSAGE_TYPE_EVENT) {
+                        *stream-&gt;pos++ = APT_TOKEN_SP;
+                        mrcp_request_state_generate(start_line-&gt;request_state,stream);
+                }
+        }
+        return TRUE;
+}
+
+/** Initialize MRCP start-line */
+MRCP_DECLARE(void) mrcp_start_line_init(mrcp_start_line_t *start_line)
+{
+        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
+        start_line-&gt;version = MRCP_VERSION_UNKNOWN;
+        start_line-&gt;length = 0;
+        start_line-&gt;request_id = 0;
+        apt_string_reset(&amp;start_line-&gt;method_name);
+        start_line-&gt;status_code = MRCP_STATUS_CODE_UNKNOWN;
+        start_line-&gt;request_state = MRCP_REQUEST_STATE_UNKNOWN;
+}
+
+/** Parse MRCP start-line */
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool)
+{
+        apt_text_stream_t line;
+        apt_str_t field;
+        apt_bool_t status = TRUE;
+        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
+        if(apt_text_line_read(text_stream,&amp;line.text) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot parse MRCP start-line&quot;);
+                return FALSE;
+        }
+        line.pos = line.text.buf;
+
+        if(apt_text_field_read(&amp;line,APT_TOKEN_SP,TRUE,&amp;field) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot read the first field in start-line&quot;);
+                return FALSE;
+        }
+
+        if(field.buf == strstr(field.buf,MRCP_NAME)) {
+                start_line-&gt;version = mrcp_version_parse(&amp;field);
+
+                if(start_line-&gt;version == MRCP_VERSION_1) {
+                        /* parsing MRCP v1 response */
+                        start_line-&gt;message_type = MRCP_MESSAGE_TYPE_RESPONSE;
+                        status = mrcp_response_line_parse(start_line,&amp;line);
+                }
+                else if(start_line-&gt;version == MRCP_VERSION_2) {
+                        /* parsing MRCP v2 start-line (request/response/event) */
+                        status = mrcp_v2_start_line_parse(start_line,&amp;line,pool);
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown MRCP version&quot;);
+                        return FALSE;
+                }
+        }
+        else {
+                /* parsing MRCP v1 request or event */
+                apt_string_copy(&amp;start_line-&gt;method_name,&amp;field,pool);
+                status = mrcp_request_line_parse(start_line,&amp;line);
+        }
+        return status;
+}
+
+/** Generate MRCP start-line */
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream)
+{
+        apt_bool_t status = FALSE;
+        if(start_line-&gt;version == MRCP_VERSION_1) {
+                switch(start_line-&gt;message_type) {
+                        case MRCP_MESSAGE_TYPE_REQUEST:
+                                status = mrcp_request_line_generate(start_line,text_stream);
+                                break;
+                        case MRCP_MESSAGE_TYPE_RESPONSE:
+                                status = mrcp_response_line_generate(start_line,text_stream);
+                                break;
+                        case MRCP_MESSAGE_TYPE_EVENT:
+                                status = mrcp_request_line_generate(start_line,text_stream);
+                                break;
+                        default:
+                                break;
+                }
+        }
+        else if(start_line-&gt;version == MRCP_VERSION_2) {
+                status = mrcp_v2_start_line_generate(start_line,text_stream);
+        }
+
+        if(status == TRUE) {
+                apt_text_eol_insert(text_stream);
+        }
+        
+        return status;
+}
+
+/** Finalize MRCP start-line generation */
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_finalize(mrcp_start_line_t *start_line, apr_size_t content_length, apt_text_stream_t *text_stream)
+{
+        apr_size_t length = text_stream-&gt;pos - text_stream-&gt;text.buf + content_length;
+        if(start_line-&gt;version == MRCP_VERSION_2) {
+                /* message-length includes the number of bytes that specify the message-length in the header */
+                /* too comlex to generate!!! see the discussion */
+                /* http://www1.ietf.org/mail-archive/web/speechsc/current/msg01734.html */
+                apt_str_t field;
+                field.buf = text_stream-&gt;text.buf + start_line-&gt;length; /* length is temporary used to store offset */
+                length -= MAX_DIGIT_COUNT;
+                if(apt_var_length_value_generate(&amp;length,MAX_DIGIT_COUNT,&amp;field) == FALSE) {
+                        return FALSE;
+                }
+                field.buf[field.length] = APT_TOKEN_SP;
+                start_line-&gt;length += field.length;
+
+                field.length = MAX_DIGIT_COUNT - field.length;
+                if(field.length) {
+                        memmove(text_stream-&gt;text.buf+field.length,text_stream-&gt;text.buf,start_line-&gt;length);
+                        text_stream-&gt;text.buf += field.length;
+                        text_stream-&gt;text.length -= field.length;
+                }
+        }
+
+        start_line-&gt;length = length;
+        return TRUE;
+}
+
+/** Parse MRCP request-id */
+MRCP_DECLARE(mrcp_request_id) mrcp_request_id_parse(const apt_str_t *field)
+{
+        if(field-&gt;buf) {
+#ifdef TOO_LONG_MRCP_REQUEST_ID
+                return apr_atoi64(field-&gt;buf);
+#else
+                return atol(field-&gt;buf);
+#endif
+        }
+        return 0;
+}
+
+/** Generate MRCP request-id */
+MRCP_DECLARE(apt_bool_t) mrcp_request_id_generate(mrcp_request_id request_id, apt_text_stream_t *stream)
+{
+        int length = sprintf(stream-&gt;pos, &quot;%&quot;MRCP_REQUEST_ID_FMT, request_id);
+        if(length &lt;= 0) {
+                return FALSE;
+        }
+        stream-&gt;pos += length;
+        return TRUE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpmrcpvcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/mrcp.vcproj (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/mrcp.vcproj        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/mrcp.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -159,6 +159,10 @@
</span><span class="cx">                                         RelativePath=&quot;.\message\include\mrcp_message.h&quot;
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><ins>+                                &lt;File
+                                        RelativePath=&quot;.\message\include\mrcp_start_line.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="lines">@@ -176,6 +180,10 @@
</span><span class="cx">                                         RelativePath=&quot;.\message\src\mrcp_message.c&quot;
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><ins>+                                &lt;File
+                                        RelativePath=&quot;.\message\src\mrcp_start_line.c&quot;
+                                        &gt;
+                                &lt;/File&gt;
</ins><span class="cx">                         &lt;/Filter&gt;
</span><span class="cx">                 &lt;/Filter&gt;
</span><span class="cx">                 &lt;Filter
</span><span class="lines">@@ -194,7 +202,7 @@
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\control\include\mrcp_state_machine.h&quot;
</del><ins>+                                        RelativePath=&quot;.\control\include\mrcp_resource_loader.h&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><span class="lines">@@ -211,6 +219,10 @@
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><ins>+                                        RelativePath=&quot;.\control\src\mrcp_resource_loader.c&quot;
+                                        &gt;
+                                &lt;/File&gt;
+                                &lt;File
</ins><span class="cx">                                         RelativePath=&quot;.\control\src\mrcp_stream.c&quot;
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="lines">@@ -224,19 +236,19 @@
</span><span class="cx">                                 Filter=&quot;h;hpp;hxx;hm;inl;inc;xsd&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\resources\include\mrcp_default_factory.h&quot;
</del><ins>+                                        RelativePath=&quot;.\resources\include\mrcp_recog_header.h&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\resources\include\mrcp_recog_header.h&quot;
</del><ins>+                                        RelativePath=&quot;.\resources\include\mrcp_recog_resource.h&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\resources\include\mrcp_recog_resource.h&quot;
</del><ins>+                                        RelativePath=&quot;.\resources\include\mrcp_recorder_header.h&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\resources\include\mrcp_recog_state_machine.h&quot;
</del><ins>+                                        RelativePath=&quot;.\resources\include\mrcp_recorder_resource.h&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><span class="lines">@@ -247,24 +259,12 @@
</span><span class="cx">                                         RelativePath=&quot;.\resources\include\mrcp_synth_resource.h&quot;
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><del>-                                &lt;File
-                                        RelativePath=&quot;.\resources\include\mrcp_synth_state_machine.h&quot;
-                                        &gt;
-                                &lt;/File&gt;
</del><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><del>-                                        RelativePath=&quot;.\resources\src\mrcp_default_factory.c&quot;
-                                        &gt;
-                                &lt;/File&gt;
-                                &lt;File
-                                        RelativePath=&quot;.\resources\src\mrcp_recog_client_state_machine.c&quot;
-                                        &gt;
-                                &lt;/File&gt;
-                                &lt;File
</del><span class="cx">                                         RelativePath=&quot;.\resources\src\mrcp_recog_header.c&quot;
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="lines">@@ -273,11 +273,11 @@
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\resources\src\mrcp_recog_server_state_machine.c&quot;
</del><ins>+                                        RelativePath=&quot;.\resources\src\mrcp_recorder_header.c&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><del>-                                        RelativePath=&quot;.\resources\src\mrcp_synth_client_state_machine.c&quot;
</del><ins>+                                        RelativePath=&quot;.\resources\src\mrcp_recorder_resource.c&quot;
</ins><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><span class="cx">                                 &lt;File
</span><span class="lines">@@ -288,10 +288,6 @@
</span><span class="cx">                                         RelativePath=&quot;.\resources\src\mrcp_synth_resource.c&quot;
</span><span class="cx">                                         &gt;
</span><span class="cx">                                 &lt;/File&gt;
</span><del>-                                &lt;File
-                                        RelativePath=&quot;.\resources\src\mrcp_synth_server_state_machine.c&quot;
-                                        &gt;
-                                &lt;/File&gt;
</del><span class="cx">                         &lt;/Filter&gt;
</span><span class="cx">                 &lt;/Filter&gt;
</span><span class="cx">         &lt;/Files&gt;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_default_factoryh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_default_factory.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recog_headerh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -206,7 +206,7 @@
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> /** Get recognizer header vtable */
</span><del>-MRCP_DECLARE(const mrcp_header_vtable_t*) mrcp_recog_header_vtable_get(mrcp_version_e version);
</del><ins>+const mrcp_header_vtable_t* mrcp_recog_header_vtable_get(mrcp_version_e version);
</ins><span class="cx"> 
</span><span class="cx"> /** Get recognizer completion cause string */
</span><span class="cx"> MRCP_DECLARE(const apt_str_t*) mrcp_recog_completion_cause_get(mrcp_recog_completion_cause_e completion_cause, mrcp_version_e version);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recog_state_machineh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_state_machine.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recorder_headerh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,136 @@
</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 __MRCP_RECORDER_HEADER_H__
+#define __MRCP_RECORDER_HEADER_H__
+
+/**
+ * @file mrcp_recorder_header.h
+ * @brief MRCP Recorder Header
+ */ 
+
+#include &quot;mrcp_types.h&quot;
+#include &quot;mrcp_header_accessor.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** MRCP recorder header fields */
+typedef enum {
+        RECORDER_HEADER_SENSITIVITY_LEVEL,
+        RECORDER_HEADER_NO_INPUT_TIMEOUT,
+        RECORDER_HEADER_COMPLETION_CAUSE,
+        RECORDER_HEADER_COMPLETION_REASON,
+        RECORDER_HEADER_FAILED_URI,
+        RECORDER_HEADER_FAILED_URI_CAUSE,
+        RECORDER_HEADER_RECORD_URI,
+        RECORDER_HEADER_MEDIA_TYPE,
+        RECORDER_HEADER_MAX_TIME,
+        RECORDER_HEADER_TRIM_LENGTH,
+        RECORDER_HEADER_FINAL_SILENCE,
+        RECORDER_HEADER_CAPTURE_ON_SPEECH,
+        RECORDER_HEADER_VER_BUFFER_UTTERANCE,
+        RECORDER_HEADER_START_INPUT_TIMERS,
+        RECORDER_HEADER_NEW_AUDIO_CHANNEL,
+
+        RECORDER_HEADER_COUNT
+} mrcp_recorder_header_id;
+
+
+/** MRCP recorder completion-cause  */
+typedef enum {
+        RECORDER_COMPLETION_CAUSE_SUCCESS_SILENCE         = 0,
+        RECORDER_COMPLETION_CAUSE_SUCCESS_MAXTIME         = 1,
+        RECORDER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT        = 2,
+        RECORDER_COMPLETION_CAUSE_URI_FAILURE             = 3,
+        RECORDER_COMPLETION_CAUSE_ERROR                   = 4,
+
+        RECORDER_COMPLETION_CAUSE_COUNT                   = 5,
+        RECORDER_COMPLETION_CAUSE_UNKNOWN                 = RECORDER_COMPLETION_CAUSE_COUNT
+} mrcp_recorder_completion_cause_e;
+
+
+
+/** MRCP recorder-header declaration */
+typedef struct mrcp_recorder_header_t mrcp_recorder_header_t;
+
+/** MRCP recorder-header */
+struct mrcp_recorder_header_t {
+        /** To filter out background noise and not mistake it for speech */
+        float                            sensitivity_level;
+        /** When recording is started and there is no speech detected for a
+        certain period of time, the recorder can send a RECORD-COMPLETE event */
+        apr_size_t                       no_input_timeout;
+        /** MUST be part of a RECORD-COMPLETE event coming from the 
+        recorder resource to the client */
+        mrcp_recorder_completion_cause_e completion_cause;
+        /** MAY be specified in a RECORD-COMPLETE event coming from
+        the recorder resource to the client */
+        apt_str_t                        completion_reason;
+        /** When a recorder method needs to post the audio to a URI and access to
+        the URI fails, the server MUST provide the failed URI in this header
+        in the method response */
+        apt_str_t                        failed_uri;
+        /** When a recorder method needs to post the audio to a URI and access to
+        the URI fails, the server MUST provide the URI specific or protocol
+        specific response code through this header in the method response */
+        apt_str_t                        failed_uri_cause;
+        /** When a recorder method contains this header the server must capture
+        the audio and store it */
+        apt_str_t                        record_uri;
+        /** A RECORD method MUST contain this header, which specifies to the
+        server the Media Type of the captured audio or video */
+        apt_str_t                        media_type;
+        /** When recording is started this specifies the maximum length of the
+        recording in milliseconds, calculated from the time the actual
+        capture and store begins and is not necessarily the time the RECORD
+        method is received */
+        apr_size_t                       max_time;
+        /** This header MAY be sent on a STOP method and specifies the length of
+        audio to be trimmed from the end of the recording after the stop */
+        apr_size_t                       trim_length;
+        /**  When recorder is started and the actual capture begins, this header
+        specifies the length of silence in the audio that is to be
+        interpreted as the end of the recording*/
+        apr_size_t                       final_silence;
+        /** f false, the recorder MUST start capturing immediately when started.
+        If true, the recorder MUST wait for the endpointing functionality to
+        detect speech before it starts capturing */
+        apt_bool_t                       capture_on_speech;
+        /** Tells the server to buffer the utterance associated with this 
+        recording request into the verification buffer */
+        apt_bool_t                       ver_buffer_utterance;
+        /** MAY be sent as part of the RECORD request. A value of false tells the 
+        recorder resource to start the operation, but not to start the no-input 
+        timer until the client sends a START-INPUT-TIMERS */
+        apt_bool_t                       start_input_timers;
+        /** MAY be specified in a RECORD request and allows the
+        client to tell the server that, from this point on, further input
+        audio comes from a different audio source */
+        apt_bool_t                       new_audio_channel;
+};
+
+
+/** Get recorder header vtable */
+const mrcp_header_vtable_t* mrcp_recorder_header_vtable_get(mrcp_version_e version);
+
+/** Get recorder completion cause string */
+MRCP_DECLARE(const apt_str_t*) mrcp_recorder_completion_cause_get(
+                                                                        mrcp_recorder_completion_cause_e completion_cause, 
+                                                                        mrcp_version_e version);
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_RECORDER_HEADER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_recorder_resourceh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,53 @@
</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 __MRCP_RECORDER_RESOURCE_H__
+#define __MRCP_RECORDER_RESOURCE_H__
+
+/**
+ * @file mrcp_recorder_resource.h
+ * @brief MRCP Recorder Resource
+ */ 
+
+#include &quot;mrcp_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** MRCP recorder methods */
+typedef enum {
+        RECORDER_SET_PARAMS,
+        RECORDER_GET_PARAMS,
+        RECORDER_RECORD,
+        RECORDER_STOP,
+        RECORDER_START_INPUT_TIMERS,
+
+        RECORDER_METHOD_COUNT
+} mrcp_recorder_method_id;
+
+/** MRCP recorder events */
+typedef enum {
+        RECORDER_START_OF_INPUT,
+        RECORDER_RECORD_COMPLETE,
+
+        RECORDER_EVENT_COUNT
+} mrcp_recorder_event_id;
+
+/** Create MRCP recorder resource */
+MRCP_DECLARE(mrcp_resource_t*) mrcp_recorder_resource_create(apr_pool_t *pool);
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_RECORDER_RESOURCE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_synth_headerh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -291,7 +291,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Get synthesizer header vtable */
</span><del>-MRCP_DECLARE(const mrcp_header_vtable_t*) mrcp_synth_header_vtable_get(mrcp_version_e version);
</del><ins>+const mrcp_header_vtable_t* mrcp_synth_header_vtable_get(mrcp_version_e version);
</ins><span class="cx"> 
</span><span class="cx"> /** Get synthesizer completion cause string */
</span><span class="cx"> MRCP_DECLARE(const apt_str_t*) mrcp_synth_completion_cause_get(mrcp_synth_completion_cause_e completion_cause, mrcp_version_e version);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcesincludemrcp_synth_state_machineh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_state_machine.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_default_factoryc"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_default_factory.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_client_state_machinec"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_client_state_machine.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_headerc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -638,7 +638,7 @@
</span><span class="cx">         RECOGNIZER_HEADER_COUNT
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-MRCP_DECLARE(const mrcp_header_vtable_t*) mrcp_recog_header_vtable_get(mrcp_version_e version)
</del><ins>+const mrcp_header_vtable_t* mrcp_recog_header_vtable_get(mrcp_version_e version)
</ins><span class="cx"> {
</span><span class="cx">         if(version == MRCP_VERSION_1) {
</span><span class="cx">                 return &amp;v1_vtable;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_resourcec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,9 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_recog_resource.h&quot;
</span><span class="cx"> #include &quot;mrcp_recog_header.h&quot;
</span><del>-#include &quot;mrcp_recog_state_machine.h&quot;
</del><span class="cx"> #include &quot;mrcp_resource.h&quot;
</span><del>-#include &quot;mrcp_message.h&quot;
</del><span class="cx"> 
</span><span class="cx"> /** String table of MRCP recognizer methods (mrcp_recognizer_method_id) */
</span><span class="cx"> static const apt_str_table_item_t v1_recog_method_string_table[] = {
</span><span class="lines">@@ -71,73 +69,15 @@
</span><span class="cx">         return v2_recog_event_string_table;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Set resource specifica data */
-static apt_bool_t recog_message_resourcify_by_id(mrcp_resource_t *resource, mrcp_message_t *message)
-{
-        /* associate method_name and method_id */
-        if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
-                const apt_str_t *name = apt_string_table_str_get(
-                        recog_method_string_table_get(message-&gt;start_line.version),
-                        RECOGNIZER_METHOD_COUNT,
-                        message-&gt;start_line.method_id);
-                if(!name) {
-                        return FALSE;
-                }
-                message-&gt;start_line.method_name = *name;
-        }
-        else if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
-                const apt_str_t *name = apt_string_table_str_get(
-                        recog_event_string_table_get(message-&gt;start_line.version),
-                        RECOGNIZER_EVENT_COUNT,
-                        message-&gt;start_line.method_id);
-                if(!name) {
-                        return FALSE;
-                }
-                message-&gt;start_line.method_name = *name;
-        }
-
-        message-&gt;header.resource_header_accessor.vtable = mrcp_recog_header_vtable_get(message-&gt;start_line.version);
-        return TRUE;
-}
-
-/** Set resource specifica data */
-static apt_bool_t recog_message_resourcify_by_name(mrcp_resource_t *resource, mrcp_message_t *message)
-{
-        /* associate method_name and method_id */
-        if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
-                message-&gt;start_line.method_id = apt_string_table_id_find(
-                        recog_method_string_table_get(message-&gt;start_line.version),
-                        RECOGNIZER_METHOD_COUNT,
-                        &amp;message-&gt;start_line.method_name);
-                if(message-&gt;start_line.method_id &gt;= RECOGNIZER_METHOD_COUNT) {
-                        return FALSE;
-                }
-        }
-        else if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
-                message-&gt;start_line.method_id = apt_string_table_id_find(
-                        recog_event_string_table_get(message-&gt;start_line.version),
-                        RECOGNIZER_EVENT_COUNT,
-                        &amp;message-&gt;start_line.method_name);
-                if(message-&gt;start_line.method_id &gt;= RECOGNIZER_EVENT_COUNT) {
-                        return FALSE;
-                }
-        }
-
-        message-&gt;header.resource_header_accessor.vtable = mrcp_recog_header_vtable_get(message-&gt;start_line.version);
-        return TRUE;
-}
-
-
</del><span class="cx"> /** Create MRCP recognizer resource */
</span><span class="cx"> MRCP_DECLARE(mrcp_resource_t*) mrcp_recog_resource_create(apr_pool_t *pool)
</span><span class="cx"> {
</span><del>-        mrcp_resource_t *resource = apr_palloc(pool,sizeof(mrcp_resource_t));
-        mrcp_resource_init(resource);
</del><ins>+        mrcp_resource_t *resource = mrcp_resource_create(pool);
</ins><span class="cx"> 
</span><del>-        resource-&gt;resourcify_message_by_id = recog_message_resourcify_by_id;
-        resource-&gt;resourcify_message_by_name = recog_message_resourcify_by_name;
-
-        resource-&gt;create_client_state_machine = mrcp_recog_client_state_machine_create;
-        resource-&gt;create_server_state_machine = mrcp_recog_server_state_machine_create;
</del><ins>+        resource-&gt;method_count = RECOGNIZER_METHOD_COUNT;
+        resource-&gt;event_count = RECOGNIZER_EVENT_COUNT;
+        resource-&gt;get_method_str_table = recog_method_string_table_get;
+        resource-&gt;get_event_str_table = recog_event_string_table_get;
+        resource-&gt;get_resource_header_vtable = mrcp_recog_header_vtable_get;
</ins><span class="cx">         return resource;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recog_server_state_machinec"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_server_state_machine.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recorder_headerc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,299 @@
</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 &lt;stdio.h&gt;
+#include &quot;mrcp_recorder_header.h&quot;
+
+/** String table of recorder headers (mrcp_recorder_header_id) */
+static const apt_str_table_item_t recorder_header_string_table[] = {
+        {{&quot;Sensitivity-Level&quot;,    17},3},
+        {{&quot;No-Input-Timeout&quot;,     16},2},
+        {{&quot;Completion-Cause&quot;,     16},16},
+        {{&quot;Completion-Reason&quot;,    17},11},
+        {{&quot;Failed-Uri&quot;,           10},10},
+        {{&quot;Failed-Uri-Cause&quot;,     16},16},
+        {{&quot;Record-Uri&quot;,           10},0},
+        {{&quot;Media-Type&quot;,           10},2},
+        {{&quot;Max-Time&quot;,              8},2},
+        {{&quot;Trim-Length&quot;,          11},0},
+        {{&quot;Final-Silence&quot;,        13},1},
+        {{&quot;Capture-On-Speech&quot;,    17},2},
+        {{&quot;Ver-Buffer-Utterance&quot;, 20},0},
+        {{&quot;Start-Input-Timers&quot;,   18},1},
+        {{&quot;New-Audio-Channel&quot;,    17},2}
+};
+
+/** String table of recorder completion-cause fields (mrcp_recorder_completion_cause_e) */
+static const apt_str_table_item_t completion_cause_string_table[] = {
+        {{&quot;success-silence&quot;,  15},8},
+        {{&quot;success-maxtime&quot;,  15},8},
+        {{&quot;no-input-timeout&quot;, 16},0},
+        {{&quot;uri-failure&quot;,      11},0},
+        {{&quot;error&quot;,             5},0}
+};
+
+/** Generate MRCP recorder completion-cause */
+static apt_bool_t mrcp_completion_cause_generate(
+                                                mrcp_recorder_completion_cause_e completion_cause, 
+                                                const apt_str_t *name, 
+                                                apt_text_stream_t *stream)
+{
+        int length = sprintf(stream-&gt;pos,&quot;%03&quot;APR_SIZE_T_FMT&quot; &quot;,completion_cause);
+        if(length &lt;= 0) {
+                return FALSE;
+        }
+        stream-&gt;pos += length;
+
+        if(name) {
+                memcpy(stream-&gt;pos,name-&gt;buf,name-&gt;length);
+                stream-&gt;pos += name-&gt;length;
+        }
+        return TRUE;
+}
+
+
+/** Initialize recorder header */
+static void mrcp_recorder_header_init(mrcp_recorder_header_t *recorder_header)
+{
+        recorder_header-&gt;sensitivity_level = 0.0;
+        recorder_header-&gt;no_input_timeout = 0;
+        recorder_header-&gt;completion_cause = RECORDER_COMPLETION_CAUSE_COUNT;
+        apt_string_reset(&amp;recorder_header-&gt;completion_reason);
+        apt_string_reset(&amp;recorder_header-&gt;failed_uri);
+        apt_string_reset(&amp;recorder_header-&gt;failed_uri_cause);
+        apt_string_reset(&amp;recorder_header-&gt;record_uri);
+        apt_string_reset(&amp;recorder_header-&gt;media_type);
+        recorder_header-&gt;max_time = 0;
+        recorder_header-&gt;trim_length = 0;
+        recorder_header-&gt;final_silence = 0;
+        recorder_header-&gt;capture_on_speech = FALSE;
+        recorder_header-&gt;ver_buffer_utterance = FALSE;
+        recorder_header-&gt;start_input_timers = FALSE;
+        recorder_header-&gt;new_audio_channel = FALSE;
+}
+
+/** Allocate MRCP recorder header */
+static void* mrcp_recorder_header_allocate(mrcp_header_accessor_t *accessor, apr_pool_t *pool)
+{
+        mrcp_recorder_header_t *recorder_header = apr_palloc(pool,sizeof(mrcp_recorder_header_t));
+        mrcp_recorder_header_init(recorder_header);
+        accessor-&gt;data = recorder_header;
+        return accessor-&gt;data;
+}
+
+/** Parse MRCP recorder header */
+static apt_bool_t mrcp_recorder_header_parse(mrcp_header_accessor_t *accessor, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
+{
+        apt_bool_t status = TRUE;
+        mrcp_recorder_header_t *recorder_header = accessor-&gt;data;
+        switch(id) {
+                case RECORDER_HEADER_SENSITIVITY_LEVEL:
+                        recorder_header-&gt;sensitivity_level = apt_float_value_parse(value);
+                        break;
+                case RECORDER_HEADER_NO_INPUT_TIMEOUT:
+                        recorder_header-&gt;no_input_timeout = apt_size_value_parse(value);
+                        break;
+                case RECORDER_HEADER_COMPLETION_CAUSE:
+                        recorder_header-&gt;completion_cause = apt_size_value_parse(value);
+                        break;
+                case RECORDER_HEADER_COMPLETION_REASON:
+                        apt_string_copy(&amp;recorder_header-&gt;completion_reason,value,pool);
+                        break;
+                case RECORDER_HEADER_FAILED_URI:
+                        apt_string_copy(&amp;recorder_header-&gt;failed_uri,value,pool);
+                        break;
+                case RECORDER_HEADER_FAILED_URI_CAUSE:
+                        apt_string_copy(&amp;recorder_header-&gt;failed_uri_cause,value,pool);
+                        break;
+                case RECORDER_HEADER_RECORD_URI:
+                        apt_string_copy(&amp;recorder_header-&gt;record_uri,value,pool);
+                        break;
+                case RECORDER_HEADER_MEDIA_TYPE:
+                        apt_string_copy(&amp;recorder_header-&gt;media_type,value,pool);
+                        break;
+                case RECORDER_HEADER_MAX_TIME:
+                        recorder_header-&gt;max_time = apt_size_value_parse(value);
+                        break;
+                case RECORDER_HEADER_TRIM_LENGTH:
+                        recorder_header-&gt;trim_length = apt_size_value_parse(value);
+                        break;
+                case RECORDER_HEADER_FINAL_SILENCE:
+                        recorder_header-&gt;final_silence = apt_size_value_parse(value);
+                        break;
+                case RECORDER_HEADER_CAPTURE_ON_SPEECH:
+                        apt_boolean_value_parse(value,&amp;recorder_header-&gt;capture_on_speech);
+                        break;
+                case RECORDER_HEADER_VER_BUFFER_UTTERANCE:
+                        apt_boolean_value_parse(value,&amp;recorder_header-&gt;ver_buffer_utterance);
+                        break;
+                case RECORDER_HEADER_START_INPUT_TIMERS:
+                        apt_boolean_value_parse(value,&amp;recorder_header-&gt;start_input_timers);
+                        break;
+                case RECORDER_HEADER_NEW_AUDIO_CHANNEL:
+                        apt_boolean_value_parse(value,&amp;recorder_header-&gt;new_audio_channel);
+                        break;
+                default:
+                        status = FALSE;
+        }
+        return status;
+}
+
+/** Generate MRCP recorder header */
+static apt_bool_t mrcp_recorder_header_generate(mrcp_header_accessor_t *accessor, apr_size_t id, apt_text_stream_t *value)
+{
+        mrcp_recorder_header_t *recorder_header = accessor-&gt;data;
+        switch(id) {
+                case RECORDER_HEADER_SENSITIVITY_LEVEL:
+                        apt_float_value_generate(recorder_header-&gt;sensitivity_level,value);
+                        break;
+                case RECORDER_HEADER_NO_INPUT_TIMEOUT:
+                        apt_size_value_generate(recorder_header-&gt;no_input_timeout,value);
+                        break;
+                case RECORDER_HEADER_COMPLETION_CAUSE:
+                {
+                        const apt_str_t *name = apt_string_table_str_get(
+                                completion_cause_string_table,
+                                RECORDER_COMPLETION_CAUSE_COUNT,
+                                recorder_header-&gt;completion_cause);
+                        mrcp_completion_cause_generate(recorder_header-&gt;completion_cause,name,value);
+                        break;
+                }
+                case RECORDER_HEADER_COMPLETION_REASON:
+                        apt_string_value_generate(&amp;recorder_header-&gt;completion_reason,value);
+                        break;
+                case RECORDER_HEADER_FAILED_URI:
+                        apt_string_value_generate(&amp;recorder_header-&gt;failed_uri,value);
+                        break;
+                case RECORDER_HEADER_FAILED_URI_CAUSE:
+                        apt_string_value_generate(&amp;recorder_header-&gt;failed_uri_cause,value);
+                        break;
+                case RECORDER_HEADER_RECORD_URI:
+                        apt_string_value_generate(&amp;recorder_header-&gt;record_uri,value);
+                        break;
+                case RECORDER_HEADER_MEDIA_TYPE:
+                        apt_string_value_generate(&amp;recorder_header-&gt;media_type,value);
+                        break;
+                case RECORDER_HEADER_MAX_TIME:
+                        apt_size_value_generate(recorder_header-&gt;max_time,value);
+                        break;
+                case RECORDER_HEADER_TRIM_LENGTH:
+                        apt_size_value_generate(recorder_header-&gt;trim_length,value);
+                        break;
+                case RECORDER_HEADER_FINAL_SILENCE:
+                        apt_size_value_generate(recorder_header-&gt;final_silence,value);
+                        break;
+                case RECORDER_HEADER_CAPTURE_ON_SPEECH:
+                        apt_boolean_value_generate(recorder_header-&gt;capture_on_speech,value);
+                        break;
+                case RECORDER_HEADER_VER_BUFFER_UTTERANCE:
+                        apt_boolean_value_generate(recorder_header-&gt;ver_buffer_utterance,value);
+                        break;
+                case RECORDER_HEADER_START_INPUT_TIMERS:
+                        apt_boolean_value_generate(recorder_header-&gt;start_input_timers,value);
+                        break;
+                case RECORDER_HEADER_NEW_AUDIO_CHANNEL:
+                        apt_boolean_value_generate(recorder_header-&gt;new_audio_channel,value);
+                        break;
+                default:
+                        break;
+        }
+        return TRUE;
+}
+
+/** Duplicate MRCP recorder header */
+static apt_bool_t mrcp_recorder_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, apr_pool_t *pool)
+{
+        mrcp_recorder_header_t *recorder_header = accessor-&gt;data;
+        const mrcp_recorder_header_t *src_recorder_header = src-&gt;data;
+        apt_bool_t status = TRUE;
+
+        if(!recorder_header || !src_recorder_header) {
+                return FALSE;
+        }
+        
+        switch(id) {
+                case RECORDER_HEADER_SENSITIVITY_LEVEL:
+                        recorder_header-&gt;sensitivity_level = src_recorder_header-&gt;sensitivity_level;
+                        break;
+                case RECORDER_HEADER_NO_INPUT_TIMEOUT:
+                        recorder_header-&gt;no_input_timeout = src_recorder_header-&gt;no_input_timeout;
+                        break;
+                case RECORDER_HEADER_COMPLETION_CAUSE:
+                        recorder_header-&gt;completion_cause = src_recorder_header-&gt;completion_cause;
+                        break;
+                case RECORDER_HEADER_COMPLETION_REASON:
+                        apt_string_copy(&amp;recorder_header-&gt;completion_reason,&amp;src_recorder_header-&gt;completion_reason,pool);
+                        break;
+                case RECORDER_HEADER_FAILED_URI:
+                        apt_string_copy(&amp;recorder_header-&gt;failed_uri,&amp;src_recorder_header-&gt;failed_uri,pool);
+                        break;
+                case RECORDER_HEADER_FAILED_URI_CAUSE:
+                        apt_string_copy(&amp;recorder_header-&gt;failed_uri_cause,&amp;src_recorder_header-&gt;failed_uri_cause,pool);
+                        break;
+                case RECORDER_HEADER_RECORD_URI:
+                        apt_string_copy(&amp;recorder_header-&gt;record_uri,&amp;src_recorder_header-&gt;record_uri,pool);
+                        break;
+                case RECORDER_HEADER_MEDIA_TYPE:
+                        apt_string_copy(&amp;recorder_header-&gt;media_type,&amp;src_recorder_header-&gt;media_type,pool);
+                        break;
+                case RECORDER_HEADER_MAX_TIME:
+                        recorder_header-&gt;max_time = src_recorder_header-&gt;max_time;
+                        break;
+                case RECORDER_HEADER_TRIM_LENGTH:
+                        recorder_header-&gt;trim_length = src_recorder_header-&gt;trim_length;
+                        break;
+                case RECORDER_HEADER_FINAL_SILENCE:
+                        recorder_header-&gt;final_silence = src_recorder_header-&gt;final_silence;
+                        break;
+                case RECORDER_HEADER_CAPTURE_ON_SPEECH:
+                        recorder_header-&gt;capture_on_speech = src_recorder_header-&gt;capture_on_speech;
+                        break;
+                case RECORDER_HEADER_VER_BUFFER_UTTERANCE:
+                        recorder_header-&gt;ver_buffer_utterance = src_recorder_header-&gt;ver_buffer_utterance;
+                        break;
+                case RECORDER_HEADER_START_INPUT_TIMERS:
+                        recorder_header-&gt;start_input_timers = src_recorder_header-&gt;start_input_timers;
+                        break;
+                case RECORDER_HEADER_NEW_AUDIO_CHANNEL:
+                        recorder_header-&gt;new_audio_channel = src_recorder_header-&gt;new_audio_channel;
+                        break;
+                default:
+                        status = FALSE;
+        }
+        return status;
+}
+
+static const mrcp_header_vtable_t vtable = {
+        mrcp_recorder_header_allocate,
+        NULL, /* nothing to destroy */
+        mrcp_recorder_header_parse,
+        mrcp_recorder_header_generate,
+        mrcp_recorder_header_duplicate,
+        recorder_header_string_table,
+        RECORDER_HEADER_COUNT
+};
+
+const mrcp_header_vtable_t* mrcp_recorder_header_vtable_get(mrcp_version_e version)
+{
+        return &amp;vtable;
+}
+
+MRCP_DECLARE(const apt_str_t*) mrcp_recorder_completion_cause_get(
+                                                                        mrcp_recorder_completion_cause_e completion_cause, 
+                                                                        mrcp_version_e version)
+{
+        return apt_string_table_str_get(completion_cause_string_table,RECORDER_COMPLETION_CAUSE_COUNT,completion_cause);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_recorder_resourcec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,57 @@
</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;mrcp_recorder_resource.h&quot;
+#include &quot;mrcp_recorder_header.h&quot;
+#include &quot;mrcp_resource.h&quot;
+
+/** String table of MRCP recorder methods (mrcp_recorder_method_id) */
+static const apt_str_table_item_t recorder_method_string_table[] = {
+        {{&quot;SET-PARAMS&quot;,         10},10},
+        {{&quot;GET-PARAMS&quot;,         10},0},
+        {{&quot;RECORD&quot;,              6},0},
+        {{&quot;STOP&quot;,                4},2},
+        {{&quot;START-INPUT-TIMERS&quot;, 18},2}
+};
+
+/** String table of MRCP recorder events (mrcp_recorder_event_id) */
+static const apt_str_table_item_t recorder_event_string_table[] = {
+        {{&quot;START-OF-INPUT&quot;,     14},0},
+        {{&quot;RECORD-COMPLETE&quot;,    15},0}
+};
+
+static APR_INLINE const apt_str_table_item_t* recorder_method_string_table_get(mrcp_version_e version)
+{
+        return recorder_method_string_table;
+}
+
+static APR_INLINE const apt_str_table_item_t* recorder_event_string_table_get(mrcp_version_e version)
+{
+        return recorder_event_string_table;
+}
+
+/** Create MRCP recorder resource */
+MRCP_DECLARE(mrcp_resource_t*) mrcp_recorder_resource_create(apr_pool_t *pool)
+{
+        mrcp_resource_t *resource = mrcp_resource_create(pool);
+
+        resource-&gt;method_count = RECORDER_METHOD_COUNT;
+        resource-&gt;event_count = RECORDER_EVENT_COUNT;
+        resource-&gt;get_method_str_table = recorder_method_string_table_get;
+        resource-&gt;get_event_str_table = recorder_event_string_table_get;
+        resource-&gt;get_resource_header_vtable = mrcp_recorder_header_vtable_get;
+        return resource;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_client_state_machinec"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_client_state_machine.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_headerc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -548,7 +548,7 @@
</span><span class="cx">         SYNTHESIZER_HEADER_COUNT
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-MRCP_DECLARE(const mrcp_header_vtable_t*) mrcp_synth_header_vtable_get(mrcp_version_e version)
</del><ins>+const mrcp_header_vtable_t* mrcp_synth_header_vtable_get(mrcp_version_e version)
</ins><span class="cx"> {
</span><span class="cx">         return &amp;vtable;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_resourcec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,9 +16,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_synth_resource.h&quot;
</span><span class="cx"> #include &quot;mrcp_synth_header.h&quot;
</span><del>-#include &quot;mrcp_synth_state_machine.h&quot;
</del><span class="cx"> #include &quot;mrcp_resource.h&quot;
</span><del>-#include &quot;mrcp_message.h&quot;
</del><span class="cx"> 
</span><span class="cx"> /** String table of MRCP synthesizer methods (mrcp_synthesizer_method_id) */
</span><span class="cx"> static const apt_str_table_item_t synth_method_string_table[] = {
</span><span class="lines">@@ -39,75 +37,25 @@
</span><span class="cx">         {{&quot;SPEAK-COMPLETE&quot;,14},3}
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-/** Set resource specifica data */
-static apt_bool_t synth_message_resourcify_by_id(mrcp_resource_t *resource, mrcp_message_t *message)
</del><ins>+static APR_INLINE const apt_str_table_item_t* synth_method_string_table_get(mrcp_version_e version)
</ins><span class="cx"> {
</span><del>-        /* associate method_name and method_id */
-        if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
-                const apt_str_t *name = apt_string_table_str_get(
-                        synth_method_string_table,
-                        SYNTHESIZER_METHOD_COUNT,
-                        message-&gt;start_line.method_id);
-                if(!name) {
-                        return FALSE;
-                }
-                message-&gt;start_line.method_name = *name;
-        }
-        else if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
-                const apt_str_t *name = apt_string_table_str_get(
-                        synth_event_string_table,
-                        SYNTHESIZER_EVENT_COUNT,
-                        message-&gt;start_line.method_id);
-                if(!name) {
-                        return FALSE;
-                }
-                message-&gt;start_line.method_name = *name;
-        }
-
-        message-&gt;header.resource_header_accessor.vtable = 
-                mrcp_synth_header_vtable_get(message-&gt;start_line.version);
-        return TRUE;
</del><ins>+        return synth_method_string_table;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Set resource specifica data */
-static apt_bool_t synth_message_resourcify_by_name(mrcp_resource_t *resource, mrcp_message_t *message)
</del><ins>+static APR_INLINE const apt_str_table_item_t* synth_event_string_table_get(mrcp_version_e version)
</ins><span class="cx"> {
</span><del>-        /* associate method_name and method_id */
-        if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
-                message-&gt;start_line.method_id = apt_string_table_id_find(
-                        synth_method_string_table,
-                        SYNTHESIZER_METHOD_COUNT,
-                        &amp;message-&gt;start_line.method_name);
-                if(message-&gt;start_line.method_id &gt;= SYNTHESIZER_METHOD_COUNT) {
-                        return FALSE;
-                }
-        }
-        else if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
-                message-&gt;start_line.method_id = apt_string_table_id_find(
-                        synth_event_string_table,
-                        SYNTHESIZER_EVENT_COUNT,
-                        &amp;message-&gt;start_line.method_name);
-                if(message-&gt;start_line.method_id &gt;= SYNTHESIZER_EVENT_COUNT) {
-                        return FALSE;
-                }
-        }
-
-        message-&gt;header.resource_header_accessor.vtable = 
-                mrcp_synth_header_vtable_get(message-&gt;start_line.version);
-        return TRUE;
</del><ins>+        return synth_event_string_table;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-
</del><span class="cx"> /** Create MRCP synthesizer resource */
</span><span class="cx"> MRCP_DECLARE(mrcp_resource_t*) mrcp_synth_resource_create(apr_pool_t *pool)
</span><span class="cx"> {
</span><del>-        mrcp_resource_t *resource = apr_palloc(pool,sizeof(mrcp_resource_t));
-        mrcp_resource_init(resource);
</del><ins>+        mrcp_resource_t *resource = mrcp_resource_create(pool);
</ins><span class="cx"> 
</span><del>-        resource-&gt;resourcify_message_by_id = synth_message_resourcify_by_id;
-        resource-&gt;resourcify_message_by_name = synth_message_resourcify_by_name;
-
-        resource-&gt;create_client_state_machine = mrcp_synth_client_state_machine_create;
-        resource-&gt;create_server_state_machine = mrcp_synth_server_state_machine_create;
</del><ins>+        resource-&gt;method_count = SYNTHESIZER_METHOD_COUNT;
+        resource-&gt;event_count = SYNTHESIZER_EVENT_COUNT;
+        resource-&gt;get_method_str_table = synth_method_string_table_get;
+        resource-&gt;get_event_str_table = synth_event_string_table_get;
+        resource-&gt;get_resource_header_vtable = mrcp_synth_header_vtable_get;
</ins><span class="cx">         return resource;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpresourcessrcmrcp_synth_server_state_machinec"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_server_state_machine.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpclientincludemrcp_applicationh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -174,11 +174,30 @@
</span><span class="cx"> MRCP_DECLARE(mrcp_session_t*) mrcp_application_session_create(mrcp_application_t *application, const char *profile, void *obj);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Get memory pool the session object is created out of.
+ * @param session the session to get pool from
+ */
+MRCP_DECLARE(apr_pool_t*) mrcp_application_session_pool_get(mrcp_session_t *session);
+
+/**
+ * Get session identifier.
+ * @param session the session to get identifier of
+ */
+MRCP_DECLARE(const apt_str_t*) mrcp_application_session_id_get(mrcp_session_t *session);
+
+/**
</ins><span class="cx">  * Get external object associated with the session.
</span><span class="cx">  * @param session the session to get object from
</span><span class="cx">  */
</span><span class="cx"> MRCP_DECLARE(void*) mrcp_application_session_object_get(mrcp_session_t *session);
</span><span class="cx"> 
</span><ins>+/**
+ * Set (associate) external object to the session.
+ * @param session the session to set object for
+ * @param obj the object to set
+ */
+MRCP_DECLARE(void) mrcp_application_session_object_set(mrcp_session_t *session, void *obj);
+
</ins><span class="cx"> /** 
</span><span class="cx">  * Send session update request.
</span><span class="cx">  * @param session the session to update
</span><span class="lines">@@ -225,6 +244,18 @@
</span><span class="cx">  */
</span><span class="cx"> MRCP_DECLARE(mpf_rtp_termination_descriptor_t*) mrcp_application_rtp_descriptor_get(mrcp_channel_t *channel);
</span><span class="cx"> 
</span><ins>+/**
+ * Get codec descriptor of source stream.
+ * @param channel the channel to get descriptor from
+ */
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_source_descriptor_get(mrcp_channel_t *channel);
+
+/**
+ * Get codec descriptor of sink stream.
+ * @param channel the channel to get descriptor from
+ */
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_sink_descriptor_get(mrcp_channel_t *channel);
+
</ins><span class="cx"> /** 
</span><span class="cx">  * Send channel add request.
</span><span class="cx">  * @param session the session to create channel for
</span><span class="lines">@@ -268,23 +299,38 @@
</span><span class="cx">  */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_application_message_dispatch(const mrcp_app_message_dispatcher_t *dispatcher, const mrcp_app_message_t *app_message);
</span><span class="cx"> 
</span><del>-
-/** Create source media termination
- * @param session the session to create channel for
</del><ins>+/** 
+ * Create audio termination
+ * @param session the session to create termination for
</ins><span class="cx">  * @param stream_vtable the virtual table of audio stream
</span><ins>+ * @param capabilities the capabilities of the stream
+ * @param obj the external object
+ */
+MRCP_DECLARE(mpf_termination_t*) mrcp_application_audio_termination_create(
+                                                                                mrcp_session_t *session,
+                                                                                const mpf_audio_stream_vtable_t *stream_vtable,
+                                                                                mpf_stream_capabilities_t *capabilities,
+                                                                                void *obj);
+/** 
+ * Create source media termination
+ * @param session the session to create termination for
+ * @param stream_vtable the virtual table of audio stream
</ins><span class="cx">  * @param codec_descriptor the descriptor of audio stream (NULL by default)
</span><span class="cx">  * @param obj the external object
</span><ins>+ * @deprecated @see mrcp_application_audio_termination_create()
</ins><span class="cx">  */
</span><span class="cx"> MRCP_DECLARE(mpf_termination_t*) mrcp_application_source_termination_create(
</span><span class="cx">                                                                                 mrcp_session_t *session,
</span><span class="cx">                                                                                 const mpf_audio_stream_vtable_t *stream_vtable,
</span><span class="cx">                                                                                 mpf_codec_descriptor_t *codec_descriptor,
</span><span class="cx">                                                                                 void *obj);
</span><del>-/** Create sink media termination
- * @param session the session to create channel for
</del><ins>+/** 
+ * Create sink media termination
+ * @param session the session to create termination for
</ins><span class="cx">  * @param stream_vtable the virtual table of audio stream
</span><span class="cx">  * @param codec_descriptor the descriptor of audio stream (NULL by default)
</span><span class="cx">  * @param obj the external object
</span><ins>+ * @deprecated @see mrcp_application_audio_termination_create()
</ins><span class="cx">  */
</span><span class="cx"> MRCP_DECLARE(mpf_termination_t*) mrcp_application_sink_termination_create(
</span><span class="cx">                                                                                 mrcp_session_t *session,
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpclientincludemrcp_client_sessionh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -25,7 +25,7 @@
</span><span class="cx"> #include &quot;mrcp_client_types.h&quot;
</span><span class="cx"> #include &quot;mrcp_application.h&quot;
</span><span class="cx"> #include &quot;mrcp_session.h&quot;
</span><del>-#include &quot;mpf_message.h&quot;
</del><ins>+#include &quot;mpf_engine.h&quot;
</ins><span class="cx"> #include &quot;apt_task_msg.h&quot;
</span><span class="cx"> #include &quot;apt_obj_list.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -37,47 +37,59 @@
</span><span class="cx"> /** MRCP client session declaration */
</span><span class="cx"> typedef struct mrcp_client_session_t mrcp_client_session_t;
</span><span class="cx"> 
</span><ins>+/** Client session states */
+typedef enum {
+        SESSION_STATE_NONE,
+        SESSION_STATE_GENERATING_OFFER,
+        SESSION_STATE_PROCESSING_ANSWER,
+        SESSION_STATE_TERMINATING,
+        SESSION_STATE_DISCOVERING
+} mrcp_client_session_state_e;
+
</ins><span class="cx"> /** MRCP client session */
</span><span class="cx"> struct mrcp_client_session_t {
</span><span class="cx">         /** Session base */
</span><del>-        mrcp_session_t             base;
</del><ins>+        mrcp_session_t              base;
</ins><span class="cx">         /** Application session belongs to */
</span><del>-        mrcp_application_t        *application;
</del><ins>+        mrcp_application_t         *application;
</ins><span class="cx">         /** External object associated with session */
</span><del>-        void                      *app_obj;
</del><ins>+        void                       *app_obj;
</ins><span class="cx">         /** Profile to use */
</span><del>-        mrcp_profile_t            *profile;
</del><ins>+        mrcp_profile_t             *profile;
</ins><span class="cx"> 
</span><span class="cx">         /** Media context */
</span><del>-        mpf_context_t             *context;
</del><ins>+        mpf_context_t              *context;
</ins><span class="cx">         /** Codec manager */
</span><del>-        const mpf_codec_manager_t *codec_manager;
</del><ins>+        const mpf_codec_manager_t  *codec_manager;
</ins><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx">         /** RTP termination array (mrcp_termination_slot_t) */
</span><del>-        apr_array_header_t        *terminations;
</del><ins>+        apr_array_header_t         *terminations;
</ins><span class="cx">         /** MRCP control channel array (mrcp_channel_t*) */
</span><del>-        apr_array_header_t        *channels;
</del><ins>+        apr_array_header_t         *channels;
</ins><span class="cx"> 
</span><span class="cx">         /** Indicates whether session is already added to session table */
</span><del>-        apt_bool_t                 registered;
</del><ins>+        apt_bool_t                  registered;
</ins><span class="cx"> 
</span><span class="cx">         /** In-progress offer */
</span><del>-        mrcp_session_descriptor_t *offer;
</del><ins>+        mrcp_session_descriptor_t  *offer;
</ins><span class="cx">         /** In-progress answer */
</span><del>-        mrcp_session_descriptor_t *answer;
</del><ins>+        mrcp_session_descriptor_t  *answer;
</ins><span class="cx"> 
</span><span class="cx">         /** MRCP application active request */
</span><del>-        const mrcp_app_message_t  *active_request;
</del><ins>+        const mrcp_app_message_t   *active_request;
</ins><span class="cx">         /** MRCP application request queue */
</span><del>-        apt_obj_list_t            *request_queue;
</del><ins>+        apt_obj_list_t             *request_queue;
</ins><span class="cx"> 
</span><del>-        /** Number of in-progress offer requests (flags) */
-        apr_size_t                 offer_flag_count;
-        /** Number of in-progress answer requests (flags) */
-        apr_size_t                 answer_flag_count;
-        /** Number of in-progress terminate requests (flags) */
-        apr_size_t                 terminate_flag_count;
</del><ins>+        /** MPF task message, which construction is in progress */
+        mpf_task_msg_t             *mpf_task_msg;
+
+        /** Session state */
+        mrcp_client_session_state_e state;
+        /** Status code of the app response to be generated */
+        mrcp_sig_status_code_e      status;
+        /** Number of in-progress sub requests */
+        apr_size_t                  subrequest_count;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** MRCP channel */
</span><span class="lines">@@ -86,10 +98,6 @@
</span><span class="cx">         apr_pool_t             *pool;
</span><span class="cx">         /** External object associated with channel */
</span><span class="cx">         void                   *obj;
</span><del>-        /** MRCP resource identifier */
-        mrcp_resource_id        resource_id;
-        /** MRCP resource name */
-        const apt_str_t        *resource_name;
</del><span class="cx">         /** MRCP resource */
</span><span class="cx">         mrcp_resource_t        *resource;
</span><span class="cx">         /** MRCP session entire channel belongs to */
</span><span class="lines">@@ -115,6 +123,10 @@
</span><span class="cx">         mpf_termination_t                *termination;
</span><span class="cx">         /** RTP termination descriptor */
</span><span class="cx">         mpf_rtp_termination_descriptor_t *descriptor;
</span><ins>+        /** Associated MRCP channel */
+        mrcp_channel_t                   *channel;
+        /** media descriptor id (index of media in session descriptor) */
+        apr_size_t                        id;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -149,7 +161,7 @@
</span><span class="cx"> /** Create channel */
</span><span class="cx"> mrcp_channel_t* mrcp_client_channel_create(
</span><span class="cx">                                         mrcp_session_t *session, 
</span><del>-                                        mrcp_resource_id resource_id, 
</del><ins>+                                        mrcp_resource_t *resource, 
</ins><span class="cx">                                         mpf_termination_t *termination, 
</span><span class="cx">                                         mpf_rtp_termination_descriptor_t *rtp_descriptor, 
</span><span class="cx">                                         void *obj);
</span><span class="lines">@@ -160,13 +172,11 @@
</span><span class="cx"> mrcp_app_message_t* mrcp_client_app_signaling_event_create(mrcp_sig_event_e event_id, apr_pool_t *pool);
</span><span class="cx"> /** Create control app_message_t */
</span><span class="cx"> mrcp_app_message_t* mrcp_client_app_control_message_create(apr_pool_t *pool);
</span><del>-/** Create response to app_message_t request */
-mrcp_app_message_t* mrcp_client_app_response_create(const mrcp_app_message_t *app_request, mrcp_sig_status_code_e status, apr_pool_t *pool);
</del><span class="cx"> 
</span><span class="cx"> /** Process application message */
</span><span class="cx"> apt_bool_t mrcp_client_app_message_process(mrcp_app_message_t *app_message);
</span><span class="cx"> /** Process MPF message */
</span><del>-apt_bool_t mrcp_client_mpf_message_process(mpf_message_t *mpf_message);
</del><ins>+apt_bool_t mrcp_client_mpf_message_process(mpf_message_container_t *mpf_message_container);
</ins><span class="cx"> 
</span><span class="cx"> /** Process session answer */
</span><span class="cx"> apt_bool_t mrcp_client_session_answer_process(mrcp_client_session_t *session, mrcp_session_descriptor_t *descriptor);
</span><span class="lines">@@ -187,6 +197,8 @@
</span><span class="cx"> apt_bool_t mrcp_client_on_channel_remove(mrcp_channel_t *channel, apt_bool_t status);
</span><span class="cx"> /** Process message receive event */
</span><span class="cx"> apt_bool_t mrcp_client_on_message_receive(mrcp_channel_t *channel, mrcp_message_t *message);
</span><ins>+/** Process disconnect event */
+apt_bool_t mrcp_client_on_disconnect(mrcp_channel_t *channel);
</ins><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpclientsrcmrcp_clientc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -17,12 +17,13 @@
</span><span class="cx"> #include &lt;apr_hash.h&gt;
</span><span class="cx"> #include &quot;mrcp_client.h&quot;
</span><span class="cx"> #include &quot;mrcp_resource_factory.h&quot;
</span><ins>+#include &quot;mrcp_resource.h&quot;
</ins><span class="cx"> #include &quot;mrcp_sig_agent.h&quot;
</span><span class="cx"> #include &quot;mrcp_client_session.h&quot;
</span><span class="cx"> #include &quot;mrcp_client_connection.h&quot;
</span><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mpf_engine.h&quot;
</span><del>-#include &quot;mpf_termination.h&quot;
</del><ins>+#include &quot;mpf_termination_factory.h&quot;
</ins><span class="cx"> #include &quot;mpf_codec_manager.h&quot;
</span><span class="cx"> #include &quot;apt_pool.h&quot;
</span><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="lines">@@ -112,6 +113,7 @@
</span><span class="cx">         CONNECTION_AGENT_TASK_MSG_MODIFY_CHANNEL,
</span><span class="cx">         CONNECTION_AGENT_TASK_MSG_REMOVE_CHANNEL,
</span><span class="cx">         CONNECTION_AGENT_TASK_MSG_RECEIVE_MESSAGE,
</span><ins>+        CONNECTION_AGENT_TASK_MSG_DISCONNECT
</ins><span class="cx"> } connection_agent_task_msg_type_e ;
</span><span class="cx"> 
</span><span class="cx"> typedef struct connection_agent_task_msg_data_t connection_agent_task_msg_data_t;
</span><span class="lines">@@ -126,12 +128,14 @@
</span><span class="cx"> static apt_bool_t mrcp_client_channel_modify_signal(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status);
</span><span class="cx"> static apt_bool_t mrcp_client_channel_remove_signal(mrcp_control_channel_t *channel, apt_bool_t status);
</span><span class="cx"> static apt_bool_t mrcp_client_message_signal(mrcp_control_channel_t *channel, mrcp_message_t *message);
</span><ins>+static apt_bool_t mrcp_client_disconnect_signal(mrcp_control_channel_t *channel);
</ins><span class="cx"> 
</span><span class="cx"> static const mrcp_connection_event_vtable_t connection_method_vtable = {
</span><span class="cx">         mrcp_client_channel_add_signal,
</span><span class="cx">         mrcp_client_channel_modify_signal,
</span><span class="cx">         mrcp_client_channel_remove_signal,
</span><del>-        mrcp_client_message_signal
</del><ins>+        mrcp_client_message_signal,
+        mrcp_client_disconnect_signal
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /* Task interface */
</span><span class="lines">@@ -497,6 +501,24 @@
</span><span class="cx">         return &amp;session-&gt;base;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Get memory pool the session object is created out of */
+MRCP_DECLARE(apr_pool_t*) mrcp_application_session_pool_get(mrcp_session_t *session)
+{
+        if(!session) {
+                return NULL;
+        }
+        return session-&gt;pool;
+}
+
+/** Get session identifier */
+MRCP_DECLARE(const apt_str_t*) mrcp_application_session_id_get(mrcp_session_t *session)
+{
+        if(!session) {
+                return NULL;
+        }
+        return &amp;session-&gt;id;
+}
+
</ins><span class="cx"> /** Get external object associated with the session */
</span><span class="cx"> MRCP_DECLARE(void*) mrcp_application_session_object_get(mrcp_session_t *session)
</span><span class="cx"> {
</span><span class="lines">@@ -507,6 +529,14 @@
</span><span class="cx">         return client_session-&gt;app_obj;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Set (associate) external object to the session */
+MRCP_DECLARE(void) mrcp_application_session_object_set(mrcp_session_t *session, void *obj)
+{
+        mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
+        if(client_session) {
+                client_session-&gt;app_obj = obj;
+        }
+}
</ins><span class="cx"> 
</span><span class="cx"> /** Send session update request */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_application_session_update(mrcp_session_t *session)
</span><span class="lines">@@ -546,14 +576,28 @@
</span><span class="cx">                                                                         mpf_rtp_termination_descriptor_t *rtp_descriptor, 
</span><span class="cx">                                                                         void *obj)
</span><span class="cx"> {
</span><ins>+        mrcp_resource_t *resource;
+        mrcp_profile_t *profile;
</ins><span class="cx">         mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
</span><span class="cx">         if(!client_session || !client_session-&gt;profile) {
</span><span class="cx">                 /* Invalid params */
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><ins>+        profile = client_session-&gt;profile;
+
+        if(!profile-&gt;resource_factory) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Channel: invalid profile&quot;);
+                return FALSE;
+        }
+        resource = mrcp_resource_get(profile-&gt;resource_factory,resource_id);
+        if(!resource) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Channel: no such resource&quot;);
+                return FALSE;
+        }
+
</ins><span class="cx">         if(termination) {
</span><span class="cx">                 /* Media engine and RTP factory must be specified in this case */
</span><del>-                if(!client_session-&gt;profile-&gt;media_engine || !client_session-&gt;profile-&gt;rtp_termination_factory) {
</del><ins>+                if(!profile-&gt;media_engine || !profile-&gt;rtp_termination_factory) {
</ins><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Channel: invalid profile&quot;);
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><span class="lines">@@ -565,7 +609,8 @@
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        return mrcp_client_channel_create(session,resource_id,termination,rtp_descriptor,obj);
</del><ins>+
+        return mrcp_client_channel_create(session,resource,termination,rtp_descriptor,obj);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Get external object associated with the channel */
</span><span class="lines">@@ -581,11 +626,40 @@
</span><span class="cx"> MRCP_DECLARE(mpf_rtp_termination_descriptor_t*) mrcp_application_rtp_descriptor_get(mrcp_channel_t *channel)
</span><span class="cx"> {
</span><span class="cx">         if(!channel || !channel-&gt;rtp_termination_slot) {
</span><del>-                return FALSE;
</del><ins>+                return NULL;
</ins><span class="cx">         }
</span><span class="cx">         return channel-&gt;rtp_termination_slot-&gt;descriptor;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Get codec descriptor of source stream */
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_source_descriptor_get(mrcp_channel_t *channel)
+{
+        mpf_audio_stream_t *audio_stream;
+        if(!channel || !channel-&gt;termination) {
+                return NULL;
+        }
+        audio_stream = mpf_termination_audio_stream_get(channel-&gt;termination);
+        if(!audio_stream) {
+                return NULL;
+        }
+        return audio_stream-&gt;rx_descriptor;
+}
+
+/** Get codec descriptor of sink stream */
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_sink_descriptor_get(mrcp_channel_t *channel)
+{
+        mpf_audio_stream_t *audio_stream;
+        if(!channel || !channel-&gt;termination) {
+                return NULL;
+        }
+        audio_stream = mpf_termination_audio_stream_get(channel-&gt;termination);
+        if(!audio_stream) {
+                return NULL;
+        }
+        return audio_stream-&gt;tx_descriptor;
+}
+
+
</ins><span class="cx"> /** Send channel add request */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_application_channel_add(mrcp_session_t *session, mrcp_channel_t *channel)
</span><span class="cx"> {
</span><span class="lines">@@ -619,18 +693,18 @@
</span><span class="cx">         mrcp_message_t *mrcp_message;
</span><span class="cx">         mrcp_profile_t *profile;
</span><span class="cx">         mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
</span><del>-        if(!client_session || !channel) {
</del><ins>+        if(!client_session || !channel || !channel-&gt;resource) {
</ins><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx">         profile = client_session-&gt;profile;
</span><span class="cx">         if(!profile || !profile-&gt;resource_factory) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><del>-        mrcp_message = mrcp_request_create(channel-&gt;resource_id,method_id,session-&gt;pool);
-        if(mrcp_message) {
-                mrcp_message-&gt;start_line.version = profile-&gt;signaling_agent-&gt;mrcp_version;
-                mrcp_message_resourcify_by_id(profile-&gt;resource_factory,mrcp_message);
-        }
</del><ins>+        mrcp_message = mrcp_request_create(
+                                                channel-&gt;resource,
+                                                profile-&gt;signaling_agent-&gt;mrcp_version,
+                                                method_id,
+                                                session-&gt;pool);
</ins><span class="cx">         return mrcp_message;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -643,6 +717,47 @@
</span><span class="cx">         return mrcp_app_control_task_msg_signal(session,channel,message);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** 
+ * Create audio termination
+ * @param session the session to create termination for
+ * @param stream_vtable the virtual table of audio stream
+ * @param capabilities the capabilities of the stream
+ * @param obj the external object
+ */
+MRCP_DECLARE(mpf_termination_t*) mrcp_application_audio_termination_create(
+                                                                                mrcp_session_t *session,
+                                                                                const mpf_audio_stream_vtable_t *stream_vtable,
+                                                                                mpf_stream_capabilities_t *capabilities,
+                                                                                void *obj)
+{
+        mpf_audio_stream_t *audio_stream;
+
+        if(!capabilities) {
+                return NULL;
+        }
+
+        if(mpf_codec_capabilities_validate(&amp;capabilities-&gt;codecs) == FALSE) {
+                return NULL;
+        }
+
+        /* create audio stream */
+        audio_stream = mpf_audio_stream_create(
+                        obj,                  /* object to associate */
+                        stream_vtable,        /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        session-&gt;pool);       /* memory pool to allocate memory from */
+        if(!audio_stream) {
+                return NULL;
+        }
+
+        /* create raw termination */
+        return mpf_raw_termination_create(
+                        NULL,                 /* no object to associate */
+                        audio_stream,         /* audio stream */
+                        NULL,                 /* no video stream */
+                        session-&gt;pool);       /* memory pool to allocate memory from */
+}
+
</ins><span class="cx"> /** Create source media termination */
</span><span class="cx"> MRCP_DECLARE(mpf_termination_t*) mrcp_application_source_termination_create(
</span><span class="cx">                                                                                 mrcp_session_t *session,
</span><span class="lines">@@ -650,19 +765,33 @@
</span><span class="cx">                                                                                 mpf_codec_descriptor_t *codec_descriptor,
</span><span class="cx">                                                                                 void *obj)
</span><span class="cx"> {
</span><ins>+        mpf_stream_capabilities_t *capabilities;
</ins><span class="cx">         mpf_audio_stream_t *audio_stream;
</span><ins>+
+        capabilities = mpf_source_stream_capabilities_create(session-&gt;pool);
+        if(codec_descriptor) {
+                mpf_codec_capabilities_add(
+                                                &amp;capabilities-&gt;codecs,
+                                                mpf_sample_rate_mask_get(codec_descriptor-&gt;sampling_rate),
+                                                codec_descriptor-&gt;name.buf);
+        }
+        else {
+                mpf_codec_default_capabilities_add(&amp;capabilities-&gt;codecs);
+        }
+
</ins><span class="cx">         /* create audio stream */
</span><span class="cx">         audio_stream = mpf_audio_stream_create(
</span><span class="cx">                         obj,                  /* object to associate */
</span><span class="cx">                         stream_vtable,        /* virtual methods table of audio stream */
</span><del>-                        STREAM_MODE_RECEIVE,  /* stream mode/direction */
</del><ins>+                        capabilities,         /* stream capabilities */
</ins><span class="cx">                         session-&gt;pool);       /* memory pool to allocate memory from */
</span><span class="cx"> 
</span><del>-        if(codec_descriptor) {
-                mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
-                audio_stream-&gt;rx_codec = mpf_codec_manager_codec_get(client_session-&gt;codec_manager,codec_descriptor,session-&gt;pool);
</del><ins>+        if(!audio_stream) {
+                return NULL;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        audio_stream-&gt;rx_descriptor = codec_descriptor;
+
</ins><span class="cx">         /* create raw termination */
</span><span class="cx">         return mpf_raw_termination_create(
</span><span class="cx">                         NULL,                 /* no object to associate */
</span><span class="lines">@@ -677,19 +806,32 @@
</span><span class="cx">                                                                                 mpf_codec_descriptor_t *codec_descriptor,
</span><span class="cx">                                                                                 void *obj)
</span><span class="cx"> {
</span><ins>+        mpf_stream_capabilities_t *capabilities;
</ins><span class="cx">         mpf_audio_stream_t *audio_stream;
</span><ins>+
+        capabilities = mpf_sink_stream_capabilities_create(session-&gt;pool);
+        if(codec_descriptor) {
+                mpf_codec_capabilities_add(
+                                                &amp;capabilities-&gt;codecs,
+                                                mpf_sample_rate_mask_get(codec_descriptor-&gt;sampling_rate),
+                                                codec_descriptor-&gt;name.buf);
+        }
+        else {
+                mpf_codec_default_capabilities_add(&amp;capabilities-&gt;codecs);
+        }
+
</ins><span class="cx">         /* create audio stream */
</span><span class="cx">         audio_stream = mpf_audio_stream_create(
</span><span class="cx">                         obj,                  /* object to associate */
</span><span class="cx">                         stream_vtable,        /* virtual methods table of audio stream */
</span><del>-                        STREAM_MODE_SEND,     /* stream mode/direction */
</del><ins>+                        capabilities,         /* stream capabilities */
</ins><span class="cx">                         session-&gt;pool);       /* memory pool to allocate memory from */
</span><del>-
-        if(codec_descriptor) {
-                mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
-                audio_stream-&gt;tx_codec = mpf_codec_manager_codec_get(client_session-&gt;codec_manager,codec_descriptor,session-&gt;pool);
</del><ins>+        if(!audio_stream) {
+                return NULL;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        audio_stream-&gt;tx_descriptor = codec_descriptor;
+
</ins><span class="cx">         /* create raw termination */
</span><span class="cx">         return mpf_raw_termination_create(
</span><span class="cx">                         NULL,                 /* no object to associate */
</span><span class="lines">@@ -793,6 +935,9 @@
</span><span class="cx">                                 case CONNECTION_AGENT_TASK_MSG_RECEIVE_MESSAGE:
</span><span class="cx">                                         mrcp_client_on_message_receive(data-&gt;channel,data-&gt;message);
</span><span class="cx">                                         break;
</span><ins>+                                case CONNECTION_AGENT_TASK_MSG_DISCONNECT:
+                                        mrcp_client_on_disconnect(data-&gt;channel);
+                                        break;
</ins><span class="cx">                                 default:
</span><span class="cx">                                         break;
</span><span class="cx">                         }
</span><span class="lines">@@ -800,9 +945,9 @@
</span><span class="cx">                 }
</span><span class="cx">                 case MRCP_CLIENT_MEDIA_TASK_MSG:
</span><span class="cx">                 {
</span><del>-                        mpf_message_t *mpf_message = (mpf_message_t*) msg-&gt;data;
-                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Receive Media Task Message [%d]&quot;, mpf_message-&gt;command_id);
-                        mrcp_client_mpf_message_process(mpf_message);
</del><ins>+                        mpf_message_container_t *container = (mpf_message_container_t*) msg-&gt;data;
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Receive Media Task Message&quot;);
+                        mrcp_client_mpf_message_process(container);
</ins><span class="cx">                         break;
</span><span class="cx">                 }
</span><span class="cx">                 case MRCP_CLIENT_APPLICATION_TASK_MSG:
</span><span class="lines">@@ -981,3 +1126,14 @@
</span><span class="cx">                                                                 mrcp_message,
</span><span class="cx">                                                                 TRUE);
</span><span class="cx"> }
</span><ins>+
+static apt_bool_t mrcp_client_disconnect_signal(mrcp_control_channel_t *channel)
+{
+        return mrcp_client_connection_task_msg_signal(
+                                                                CONNECTION_AGENT_TASK_MSG_DISCONNECT,
+                                                                channel-&gt;agent,
+                                                                channel,
+                                                                NULL,
+                                                                NULL,
+                                                                TRUE);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpclientsrcmrcp_client_sessionc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,18 +15,16 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_client_session.h&quot;
</span><ins>+#include &quot;mrcp_resource_factory.h&quot;
</ins><span class="cx"> #include &quot;mrcp_resource.h&quot;
</span><del>-#include &quot;mrcp_resource_factory.h&quot;
</del><span class="cx"> #include &quot;mrcp_sig_agent.h&quot;
</span><span class="cx"> #include &quot;mrcp_client_connection.h&quot;
</span><span class="cx"> #include &quot;mrcp_session.h&quot;
</span><span class="cx"> #include &quot;mrcp_session_descriptor.h&quot;
</span><span class="cx"> #include &quot;mrcp_control_descriptor.h&quot;
</span><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><del>-#include &quot;mpf_termination.h&quot;
</del><ins>+#include &quot;mpf_termination_factory.h&quot;
</ins><span class="cx"> #include &quot;mpf_stream.h&quot;
</span><del>-#include &quot;mpf_engine.h&quot;
-#include &quot;mpf_user.h&quot;
</del><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="cx"> #include &quot;apt_obj_list.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="lines">@@ -38,7 +36,7 @@
</span><span class="cx"> static apt_bool_t mrcp_client_session_offer_send(mrcp_client_session_t *session);
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mrcp_app_session_terminate_raise(mrcp_client_session_t *session, mrcp_sig_status_code_e status);
</span><del>-static apt_bool_t mrcp_app_sig_response_raise(mrcp_client_session_t *session, mrcp_sig_status_code_e status, apt_bool_t process_pending_requests);
</del><ins>+static apt_bool_t mrcp_app_sig_response_raise(mrcp_client_session_t *session, apt_bool_t process_pending_requests);
</ins><span class="cx"> static apt_bool_t mrcp_app_sig_event_raise(mrcp_client_session_t *session, mrcp_channel_t *channel);
</span><span class="cx"> static apt_bool_t mrcp_app_control_message_raise(mrcp_client_session_t *session, mrcp_channel_t *channel, mrcp_message_t *mrcp_message);
</span><span class="cx"> static apt_bool_t mrcp_app_request_dispatch(mrcp_client_session_t *session, const mrcp_app_message_t *app_message);
</span><span class="lines">@@ -49,13 +47,46 @@
</span><span class="cx"> 
</span><span class="cx"> static mrcp_channel_t* mrcp_client_channel_find_by_name(mrcp_client_session_t *session, const apt_str_t *resource_name);
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_client_mpf_request_send(
-                                                mpf_engine_t *engine, 
-                                                mpf_command_type_e command_id, 
-                                                mpf_context_t *context, 
-                                                mpf_termination_t *termination, 
-                                                void *descriptor);
</del><ins>+static APR_INLINE mrcp_version_e mrcp_session_version_get(mrcp_client_session_t *session)
+{
+        return session-&gt;base.signaling_agent-&gt;mrcp_version;
+}
</ins><span class="cx"> 
</span><ins>+static APR_INLINE void mrcp_client_session_state_set(mrcp_client_session_t *session, mrcp_client_session_state_e state)
+{
+        if(session-&gt;subrequest_count != 0) {
+                /* error case */
+                session-&gt;subrequest_count = 0;
+        }
+        session-&gt;state = state;
+}
+
+static APR_INLINE void mrcp_client_session_subrequest_add(mrcp_client_session_t *session)
+{
+        session-&gt;subrequest_count++;
+}
+
+static APR_INLINE apt_bool_t mrcp_client_session_subrequest_remove(mrcp_client_session_t *session)
+{
+        if(!session-&gt;subrequest_count) {
+                /* error case */
+                return FALSE;
+        }
+
+        session-&gt;subrequest_count--;
+        return (session-&gt;subrequest_count ? FALSE : TRUE);
+}
+
+static mrcp_app_message_t* mrcp_client_app_response_create(const mrcp_app_message_t *app_request, mrcp_sig_status_code_e status, apr_pool_t *pool)
+{
+        mrcp_app_message_t *app_response = apr_palloc(pool,sizeof(mrcp_app_message_t));
+        *app_response = *app_request;
+        app_response-&gt;sig_message.message_type = MRCP_SIG_MESSAGE_TYPE_RESPONSE;
+        app_response-&gt;sig_message.status = status;
+        return app_response;
+}
+
+
</ins><span class="cx"> mrcp_client_session_t* mrcp_client_session_create(mrcp_application_t *application, void *obj)
</span><span class="cx"> {
</span><span class="cx">         apr_pool_t *pool;
</span><span class="lines">@@ -73,37 +104,39 @@
</span><span class="cx">         session-&gt;answer = NULL;
</span><span class="cx">         session-&gt;active_request = NULL;
</span><span class="cx">         session-&gt;request_queue = apt_list_create(pool);
</span><del>-        session-&gt;offer_flag_count = 0;
-        session-&gt;answer_flag_count = 0;
-        session-&gt;terminate_flag_count = 0;
</del><ins>+        session-&gt;mpf_task_msg = NULL;
+        session-&gt;subrequest_count = 0;
+        session-&gt;state = SESSION_STATE_NONE;
+        session-&gt;status = MRCP_SIG_STATUS_CODE_SUCCESS;
</ins><span class="cx">         return session;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> mrcp_channel_t* mrcp_client_channel_create(
</span><del>-                                        mrcp_session_t *session, 
-                                        mrcp_resource_id resource_id, 
-                                        mpf_termination_t *termination, 
-                                        mpf_rtp_termination_descriptor_t *rtp_descriptor, 
</del><ins>+                                        mrcp_session_t *session,
+                                        mrcp_resource_t *resource,
+                                        mpf_termination_t *termination,
+                                        mpf_rtp_termination_descriptor_t *rtp_descriptor,
</ins><span class="cx">                                         void *obj)
</span><span class="cx"> {
</span><span class="cx">         mrcp_channel_t *channel = apr_palloc(session-&gt;pool,sizeof(mrcp_channel_t));
</span><span class="cx">         channel-&gt;pool = session-&gt;pool;
</span><span class="cx">         channel-&gt;obj = obj;
</span><span class="cx">         channel-&gt;session = session;
</span><del>-        channel-&gt;resource_id = resource_id;
-        channel-&gt;resource_name = NULL;
</del><span class="cx">         channel-&gt;control_channel = NULL;
</span><span class="cx">         channel-&gt;termination = termination;
</span><span class="cx">         channel-&gt;rtp_termination_slot = NULL;
</span><del>-        channel-&gt;resource = NULL;
</del><ins>+        channel-&gt;resource = resource;
</ins><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><span class="cx">         channel-&gt;waiting_for_termination = FALSE;
</span><span class="cx"> 
</span><span class="cx">         if(rtp_descriptor) {
</span><del>-                channel-&gt;rtp_termination_slot = apr_palloc(session-&gt;pool,sizeof(rtp_termination_slot_t));
-                channel-&gt;rtp_termination_slot-&gt;descriptor = rtp_descriptor;
-                channel-&gt;rtp_termination_slot-&gt;termination = NULL;
-                channel-&gt;rtp_termination_slot-&gt;waiting = FALSE;
</del><ins>+                rtp_termination_slot_t *termination_slot = apr_palloc(session-&gt;pool,sizeof(rtp_termination_slot_t));
+                termination_slot-&gt;descriptor = rtp_descriptor;
+                termination_slot-&gt;termination = NULL;
+                termination_slot-&gt;waiting = FALSE;
+                termination_slot-&gt;channel = channel;
+                termination_slot-&gt;id = 0;
+                channel-&gt;rtp_termination_slot = termination_slot;
</ins><span class="cx">         }
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create Channel &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(session));
</span><span class="cx">         return channel;
</span><span class="lines">@@ -111,15 +144,14 @@
</span><span class="cx"> 
</span><span class="cx"> apt_bool_t mrcp_client_session_answer_process(mrcp_client_session_t *session, mrcp_session_descriptor_t *descriptor)
</span><span class="cx"> {
</span><del>-        mrcp_sig_status_code_e status_code = MRCP_SIG_STATUS_CODE_SUCCESS;
</del><span class="cx">         if(!session-&gt;offer) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         if(!descriptor) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Receive Answer &quot;APT_PTRSID_FMT&quot; [null descriptor]&quot;,        MRCP_SESSION_PTRSID(&amp;session-&gt;base));
</span><del>-                status_code = MRCP_SIG_STATUS_CODE_FAILURE;
</del><ins>+                session-&gt;status = MRCP_SIG_STATUS_CODE_FAILURE;
</ins><span class="cx">                 /* raise app response */
</span><del>-                return mrcp_app_sig_response_raise(session,status_code,TRUE);
</del><ins>+                return mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Receive Answer &quot;APT_PTRSID_FMT&quot; [c:%d a:%d v:%d]&quot;,
</span><span class="lines">@@ -128,9 +160,20 @@
</span><span class="cx">                 descriptor-&gt;audio_media_arr-&gt;nelts,
</span><span class="cx">                 descriptor-&gt;video_media_arr-&gt;nelts);
</span><span class="cx"> 
</span><del>-        if(session-&gt;base.signaling_agent-&gt;mrcp_version == MRCP_VERSION_1) {
</del><ins>+        mrcp_client_session_state_set(session,SESSION_STATE_PROCESSING_ANSWER);
+        if(session-&gt;context) {
+                /* first, reset/destroy existing associations and topology */
+                if(mpf_engine_topology_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_RESET_ASSOCIATIONS,session-&gt;context,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE){
+                        mrcp_client_session_subrequest_add(session);
+                }
+        }
+
+        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
</ins><span class="cx">                 if(mrcp_client_resource_answer_process(session,descriptor) != TRUE) {
</span><del>-                        status_code = MRCP_SIG_STATUS_CODE_FAILURE;
</del><ins>+                        session-&gt;status = MRCP_SIG_STATUS_CODE_FAILURE;
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="lines">@@ -138,12 +181,24 @@
</span><span class="cx">                 mrcp_client_av_media_answer_process(session,descriptor);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if(session-&gt;context) {
+                /* apply topology based on assigned associations */
+                if(mpf_engine_topology_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_APPLY_TOPOLOGY,session-&gt;context,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
+                        mrcp_client_session_subrequest_add(session);
+                }
+
+                mpf_engine_message_send(session-&gt;profile-&gt;media_engine,&amp;session-&gt;mpf_task_msg);
+        }
+
</ins><span class="cx">         /* store received answer */
</span><span class="cx">         session-&gt;answer = descriptor;
</span><span class="cx"> 
</span><del>-        if(!session-&gt;answer_flag_count) {
</del><ins>+        if(!session-&gt;subrequest_count) {
</ins><span class="cx">                 /* raise app response */
</span><del>-                mrcp_app_sig_response_raise(session,status_code,TRUE);
</del><ins>+                mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -153,11 +208,7 @@
</span><span class="cx"> {
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Receive Terminate Response &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
</span><span class="cx"> 
</span><del>-        if(session-&gt;terminate_flag_count) {
-                session-&gt;terminate_flag_count--;
-        }
-
-        if(!session-&gt;terminate_flag_count) {
</del><ins>+        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
</ins><span class="cx">                 mrcp_app_session_terminate_raise(session,MRCP_SIG_STATUS_CODE_SUCCESS);
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -165,15 +216,33 @@
</span><span class="cx"> 
</span><span class="cx"> apt_bool_t mrcp_client_session_terminate_event_process(mrcp_client_session_t *session)
</span><span class="cx"> {
</span><ins>+        if(session-&gt;state == SESSION_STATE_TERMINATING) {
+                /* session termination request has been sent, still waiting for the response,
+                   all the events must be ignored at this stage */
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unexpected Event! &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                return FALSE;
+        }
+        
</ins><span class="cx">         if(session-&gt;active_request) {
</span><span class="cx">                 /* raise app response */
</span><del>-                mrcp_app_sig_response_raise(session,MRCP_SIG_STATUS_CODE_TERMINATE,FALSE);
</del><ins>+                session-&gt;status = MRCP_SIG_STATUS_CODE_TERMINATE;
+                mrcp_app_sig_response_raise(session,FALSE);
</ins><span class="cx"> 
</span><del>-                /* cancel remaing requests (if any) */
</del><ins>+                /* cancel remaing requests, but do process session termination request (if any) */
</ins><span class="cx">                 do {
</span><span class="cx">                         session-&gt;active_request = apt_list_pop_front(session-&gt;request_queue);
</span><span class="cx">                         if(session-&gt;active_request) {
</span><del>-                                mrcp_app_sig_response_raise(session,MRCP_SIG_STATUS_CODE_CANCEL,FALSE);
</del><ins>+                                const mrcp_app_message_t *app_message = session-&gt;active_request;
+                                if(app_message-&gt;message_type == MRCP_APP_MESSAGE_TYPE_SIGNALING &amp;&amp;
+                                        app_message-&gt;sig_message.command_id == MRCP_SIG_COMMAND_SESSION_TERMINATE) {
+                                        /* process session termination */
+                                        mrcp_app_request_dispatch(session,app_message);
+                                        break;
+                                }
+
+                                /* cancel pending request */
+                                session-&gt;status = MRCP_SIG_STATUS_CODE_CANCEL;
+                                mrcp_app_sig_response_raise(session,FALSE);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">                 while(session-&gt;active_request);
</span><span class="lines">@@ -203,27 +272,23 @@
</span><span class="cx"> 
</span><span class="cx">         if(!descriptor) {
</span><span class="cx">                 /* raise app response */
</span><del>-                return mrcp_app_sig_response_raise(session,MRCP_SIG_STATUS_CODE_FAILURE,TRUE);
</del><ins>+                session-&gt;status = MRCP_SIG_STATUS_CODE_FAILURE;
+                return mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(session-&gt;base.signaling_agent-&gt;mrcp_version == MRCP_VERSION_1) {
</del><ins>+        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
</ins><span class="cx">                 if(descriptor-&gt;resource_state == TRUE) {
</span><span class="cx">                         mrcp_control_descriptor_t *control_media;
</span><span class="cx">                         if(!session-&gt;answer) {
</span><span class="cx">                                 session-&gt;answer = descriptor;
</span><span class="cx">                         }
</span><del>-                        control_media = apr_palloc(session-&gt;base.pool,sizeof(mrcp_control_descriptor_t));
-                        mrcp_control_descriptor_init(control_media);
</del><ins>+                        control_media = mrcp_control_descriptor_create(session-&gt;base.pool);
</ins><span class="cx">                         control_media-&gt;id = mrcp_session_control_media_add(session-&gt;answer,control_media);
</span><span class="cx">                         control_media-&gt;resource_name = descriptor-&gt;resource_name;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(session-&gt;answer_flag_count) {
-                session-&gt;answer_flag_count--;
-        }
-
-        if(!session-&gt;answer_flag_count) {
</del><ins>+        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
</ins><span class="cx">                 mrcp_app_message_t *response;
</span><span class="cx">                 response = mrcp_client_app_response_create(session-&gt;active_request,MRCP_SIG_STATUS_CODE_SUCCESS,session-&gt;base.pool);
</span><span class="cx">                 response-&gt;descriptor = session-&gt;answer;
</span><span class="lines">@@ -247,12 +312,9 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><del>-        if(session-&gt;offer_flag_count) {
-                session-&gt;offer_flag_count--;
-                if(!session-&gt;offer_flag_count) {
-                        /* send offer to server */
-                        mrcp_client_session_offer_send(session);
-                }
</del><ins>+        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                /* send offer to server */
+                mrcp_client_session_offer_send(session);
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -265,15 +327,12 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><del>-        if(session-&gt;answer_flag_count) {
-                session-&gt;answer_flag_count--;
-                if(!session-&gt;answer_flag_count) {
-                        /* raise app response */
-                        mrcp_app_sig_response_raise(
-                                session,
-                                status == TRUE ? MRCP_SIG_STATUS_CODE_SUCCESS : MRCP_SIG_STATUS_CODE_FAILURE,
-                                TRUE);
</del><ins>+        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                /* raise app response */
+                if(status != TRUE) {
+                        session-&gt;status = MRCP_SIG_STATUS_CODE_FAILURE;
</ins><span class="cx">                 }
</span><ins>+                mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -286,13 +345,10 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><del>-        if(session-&gt;terminate_flag_count) {
-                session-&gt;terminate_flag_count--;
-                if(!session-&gt;terminate_flag_count) {
</del><ins>+        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
</ins><span class="cx">                         mrcp_app_session_terminate_raise(
</span><span class="cx">                                 session,
</span><span class="cx">                                 status == TRUE ? MRCP_SIG_STATUS_CODE_SUCCESS : MRCP_SIG_STATUS_CODE_FAILURE);
</span><del>-                }
</del><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -303,6 +359,12 @@
</span><span class="cx">         return mrcp_app_control_message_raise(session,channel,message);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+apt_bool_t mrcp_client_on_disconnect(mrcp_channel_t *channel)
+{
+        mrcp_client_session_t *session = (mrcp_client_session_t*)channel-&gt;session;
+        return mrcp_client_session_terminate_event_process(session);
+}
+
</ins><span class="cx"> mrcp_app_message_t* mrcp_client_app_signaling_request_create(mrcp_sig_command_e command_id, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mrcp_app_message_t *app_message = apr_palloc(pool,sizeof(mrcp_app_message_t));
</span><span class="lines">@@ -328,15 +390,6 @@
</span><span class="cx">         return app_message;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-mrcp_app_message_t* mrcp_client_app_response_create(const mrcp_app_message_t *app_request, mrcp_sig_status_code_e status, apr_pool_t *pool)
-{
-        mrcp_app_message_t *app_response = apr_palloc(pool,sizeof(mrcp_app_message_t));
-        *app_response = *app_request;
-        app_response-&gt;sig_message.message_type = MRCP_SIG_MESSAGE_TYPE_RESPONSE;
-        app_response-&gt;sig_message.status = status;
-        return app_response;
-}
-
</del><span class="cx"> apt_bool_t mrcp_client_app_message_process(mrcp_app_message_t *app_message)
</span><span class="cx"> {
</span><span class="cx">         mrcp_client_session_t *session = (mrcp_client_session_t*)app_message-&gt;session;
</span><span class="lines">@@ -376,7 +429,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 if(channel-&gt;control_channel) {
</span><span class="lines">@@ -387,10 +440,13 @@
</span><span class="cx"> 
</span><span class="cx">         mrcp_client_session_remove(session-&gt;application-&gt;client,session);
</span><span class="cx">         /* raise app response */
</span><del>-        return mrcp_app_sig_response_raise(session,status,FALSE);
</del><ins>+        if(status != MRCP_SIG_STATUS_CODE_SUCCESS) {
+                session-&gt;status = status;
+        }
+        return mrcp_app_sig_response_raise(session,FALSE);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_app_sig_response_raise(mrcp_client_session_t *session, mrcp_sig_status_code_e status, apt_bool_t process_pending_requests)
</del><ins>+static apt_bool_t mrcp_app_sig_response_raise(mrcp_client_session_t *session, apt_bool_t process_pending_requests)
</ins><span class="cx"> {
</span><span class="cx">         mrcp_app_message_t *response;
</span><span class="cx">         const mrcp_app_message_t *request = session-&gt;active_request;
</span><span class="lines">@@ -398,12 +454,12 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         session-&gt;active_request = NULL;
</span><del>-        response = mrcp_client_app_response_create(request,status,session-&gt;base.pool);
</del><ins>+        response = mrcp_client_app_response_create(request,session-&gt;status,session-&gt;base.pool);
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Raise App Response &quot;APT_PTRSID_FMT&quot; [%d] %s [%d]&quot;, 
</span><span class="cx">                 MRCP_SESSION_PTRSID(&amp;session-&gt;base),
</span><span class="cx">                 response-&gt;sig_message.command_id,
</span><del>-                status == MRCP_SIG_STATUS_CODE_SUCCESS ? &quot;SUCCESS&quot; : &quot;FAILURE&quot;,
-                status);
</del><ins>+                session-&gt;status == MRCP_SIG_STATUS_CODE_SUCCESS ? &quot;SUCCESS&quot; : &quot;FAILURE&quot;,
+                session-&gt;status);
</ins><span class="cx">         session-&gt;application-&gt;handler(response);
</span><span class="cx"> 
</span><span class="cx">         if(process_pending_requests) {
</span><span class="lines">@@ -468,8 +524,9 @@
</span><span class="cx"> static apt_bool_t mrcp_client_channel_find(mrcp_client_session_t *session, mrcp_channel_t *channel, int *index)
</span><span class="cx"> {
</span><span class="cx">         int i;
</span><ins>+        mrcp_channel_t *existing_channel;
</ins><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                mrcp_channel_t *existing_channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                existing_channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(existing_channel == channel) {
</span><span class="cx">                         if(index) {
</span><span class="cx">                                 *index = i;
</span><span class="lines">@@ -485,7 +542,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         rtp_termination_slot_t *slot;
</span><span class="cx">         for(i=0; i&lt;session-&gt;terminations-&gt;nelts; i++) {
</span><del>-                slot = &amp;((rtp_termination_slot_t*)session-&gt;terminations-&gt;elts)[i];
</del><ins>+                slot = &amp;APR_ARRAY_IDX(session-&gt;terminations,i,rtp_termination_slot_t);
</ins><span class="cx">                 if(slot &amp;&amp; slot-&gt;termination == termination) {
</span><span class="cx">                         return slot;
</span><span class="cx">                 }
</span><span class="lines">@@ -493,25 +550,12 @@
</span><span class="cx">         return NULL;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static int mrcp_client_audio_media_find_by_mid(const mrcp_session_descriptor_t *descriptor, apr_size_t mid)
-{
-        int i;
-        mpf_rtp_media_descriptor_t *media;
-        for(i=0; i&lt;descriptor-&gt;audio_media_arr-&gt;nelts; i++) {
-                media = ((mpf_rtp_media_descriptor_t**)descriptor-&gt;audio_media_arr-&gt;elts)[i];
-                if(media-&gt;mid == mid) {
-                        return i;
-                }
-        }
-        return -1;
-}
-
</del><span class="cx"> static mrcp_channel_t* mrcp_client_channel_termination_find(mrcp_client_session_t *session, mpf_termination_t *termination)
</span><span class="cx"> {
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 if(channel-&gt;termination == termination) {
</span><span class="lines">@@ -526,10 +570,10 @@
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
-                if(!channel) continue;
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
+                if(!channel || !channel-&gt;resource) continue;
</ins><span class="cx"> 
</span><del>-                if(apt_string_compare(channel-&gt;resource_name,resource_name) == TRUE) {
</del><ins>+                if(apt_string_compare(&amp;channel-&gt;resource-&gt;name,resource_name) == TRUE) {
</ins><span class="cx">                         return channel;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -548,9 +592,9 @@
</span><span class="cx"> 
</span><span class="cx">         message-&gt;channel_id.session_id = session-&gt;base.id;
</span><span class="cx">         message-&gt;start_line.request_id = ++session-&gt;base.last_request_id;
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Send MRCP Request &quot;APT_PTRSIDRES_FMT&quot; [%d]&quot;,
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Send MRCP Request &quot;APT_PTRSIDRES_FMT&quot; [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
</ins><span class="cx">                                         MRCP_SESSION_PTRSID(&amp;session-&gt;base),
</span><del>-                                        channel-&gt;resource_name-&gt;buf,
</del><ins>+                                        channel-&gt;resource-&gt;name.buf,
</ins><span class="cx">                                         message-&gt;start_line.request_id);
</span><span class="cx"> 
</span><span class="cx">         if(channel-&gt;control_channel) {
</span><span class="lines">@@ -571,48 +615,47 @@
</span><span class="cx">         if(!session-&gt;offer) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        if(!channel-&gt;resource_name) {
</del><ins>+        if(!channel-&gt;resource) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Modify Control Channel &quot;APT_PTRSIDRES_FMT&quot; [%d]&quot;,
</span><span class="cx">                                         MRCP_SESSION_PTRSID(&amp;session-&gt;base),
</span><del>-                                        channel-&gt;resource_name-&gt;buf,
</del><ins>+                                        channel-&gt;resource-&gt;name.buf,
</ins><span class="cx">                                         enable);
</span><span class="cx">         if(mrcp_client_channel_find(session,channel,&amp;index) == TRUE) {
</span><span class="cx">                 mrcp_control_descriptor_t *control_media = mrcp_session_control_media_get(session-&gt;offer,(apr_size_t)index);
</span><span class="cx">                 if(control_media) {
</span><del>-                        control_media-&gt;port = (enable == TRUE) ? 9 : 0;
-                        if(channel-&gt;termination &amp;&amp; channel-&gt;termination-&gt;audio_stream) {
-                                int i = mrcp_client_audio_media_find_by_mid(session-&gt;offer,control_media-&gt;cmid);
-                                if(i &gt;= 0) {
-                                        mpf_stream_mode_e mode = mpf_stream_mode_negotiate(channel-&gt;termination-&gt;audio_stream-&gt;mode);
-                                        mpf_rtp_media_descriptor_t *audio_media = mrcp_session_audio_media_get(session-&gt;offer,(apr_size_t)i);
-                                        if(audio_media) {
-                                                if(enable == TRUE) {
-                                                        audio_media-&gt;mode |= mode;
-                                                }
-                                                else {
-                                                        audio_media-&gt;mode &amp;= ~mode;
-                                                }
-                                                audio_media-&gt;base.state = (audio_media-&gt;mode != STREAM_MODE_NONE) ? MPF_MEDIA_ENABLED : MPF_MEDIA_DISABLED;
-                                        }
</del><ins>+                        control_media-&gt;port = (enable == TRUE) ? TCP_DISCARD_PORT : 0;
+                }
+                if(channel-&gt;termination &amp;&amp; channel-&gt;rtp_termination_slot) {
+                        mpf_audio_stream_t *audio_stream = mpf_termination_audio_stream_get(
+                                                                                                                channel-&gt;termination);
+                        mpf_rtp_media_descriptor_t *audio_media = mrcp_session_audio_media_get(
+                                                                                                                session-&gt;offer,
+                                                                                                                channel-&gt;rtp_termination_slot-&gt;id);
+                        if(audio_media &amp;&amp; audio_stream) {
+                                mpf_stream_direction_e direction = mpf_stream_reverse_direction_get(audio_stream-&gt;direction);
+                                if(enable == TRUE) {
+                                        audio_media-&gt;direction |= direction;
</ins><span class="cx">                                 }
</span><ins>+                                else {
+                                        audio_media-&gt;direction &amp;= ~direction;
+                                }
+                                audio_media-&gt;state = (audio_media-&gt;direction != STREAM_DIRECTION_NONE) ? MPF_MEDIA_ENABLED : MPF_MEDIA_DISABLED;
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        session-&gt;offer-&gt;resource_name = *channel-&gt;resource_name;
</del><ins>+        session-&gt;offer-&gt;resource_name = channel-&gt;resource-&gt;name;
</ins><span class="cx">         session-&gt;offer-&gt;resource_state = enable;
</span><span class="cx">         return mrcp_client_session_offer_send(session);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mrcp_client_channel_add(mrcp_client_session_t *session, mrcp_channel_t *channel)
</span><span class="cx"> {
</span><del>-        mrcp_channel_t **channel_slot;
-        mrcp_control_descriptor_t *control_media;
</del><span class="cx">         mpf_rtp_termination_descriptor_t *rtp_descriptor = NULL;
</span><del>-        rtp_termination_slot_t *termination_slot;
</del><ins>+        rtp_termination_slot_t *slot;
</ins><span class="cx">         apr_pool_t *pool = session-&gt;base.pool;
</span><span class="cx">         mrcp_profile_t *profile = session-&gt;profile;
</span><span class="cx">         if(mrcp_client_channel_find(session,channel,NULL) == TRUE) {
</span><span class="lines">@@ -622,93 +665,108 @@
</span><span class="cx"> 
</span><span class="cx">         if(!session-&gt;offer) {
</span><span class="cx">                 session-&gt;offer = mrcp_session_descriptor_create(pool);
</span><del>-                session-&gt;context = mpf_context_create(session,5,pool);
</del><span class="cx">         }
</span><del>-        if(!channel-&gt;resource) {
-                channel-&gt;resource = mrcp_resource_get(profile-&gt;resource_factory,channel-&gt;resource_id);
-                if(!channel-&gt;resource) {
-                        return FALSE;
-                }
-                channel-&gt;resource_name = mrcp_resource_name_get(profile-&gt;resource_factory,channel-&gt;resource_id);
-                if(!channel-&gt;resource_name) {
-                        return FALSE;
-                }
-        }
-        if(session-&gt;base.signaling_agent-&gt;mrcp_version == MRCP_VERSION_1) {
-                session-&gt;offer-&gt;resource_name = *channel-&gt;resource_name;
</del><ins>+        
+        mrcp_client_session_state_set(session,SESSION_STATE_GENERATING_OFFER);
+
+        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
+                session-&gt;offer-&gt;resource_name = channel-&gt;resource-&gt;name;
</ins><span class="cx">                 session-&gt;offer-&gt;resource_state = TRUE;
</span><span class="cx">         }
</span><span class="cx">         else {
</span><ins>+                mrcp_control_descriptor_t *control_media;
</ins><span class="cx">                 if(!channel-&gt;control_channel) {
</span><span class="cx">                         channel-&gt;control_channel = mrcp_client_control_channel_create(profile-&gt;connection_agent,channel,pool);
</span><span class="cx">                 }
</span><span class="cx">                 control_media = mrcp_control_offer_create(pool);
</span><span class="cx">                 control_media-&gt;id = mrcp_session_control_media_add(session-&gt;offer,control_media);
</span><del>-                control_media-&gt;cmid = session-&gt;offer-&gt;control_media_arr-&gt;nelts;
-                control_media-&gt;resource_name = *channel-&gt;resource_name;
</del><ins>+                mrcp_cmid_add(control_media-&gt;cmid_arr,session-&gt;offer-&gt;control_media_arr-&gt;nelts);
+                control_media-&gt;resource_name = channel-&gt;resource-&gt;name;
</ins><span class="cx">                 if(mrcp_client_control_channel_add(channel-&gt;control_channel,control_media) == TRUE) {
</span><span class="cx">                         channel-&gt;waiting_for_channel = TRUE;
</span><del>-                        session-&gt;offer_flag_count++;
</del><ins>+                        mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* add to channel array */
</del><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Add Control Channel &quot;APT_PTRSIDRES_FMT,
</span><span class="cx">                                         MRCP_SESSION_PTRSID(&amp;session-&gt;base),
</span><del>-                                        channel-&gt;resource_name-&gt;buf);
-        channel_slot = apr_array_push(session-&gt;channels);
-        *channel_slot = channel;
</del><ins>+                                        channel-&gt;resource-&gt;name.buf);
+        /* add control channel */
+        APR_ARRAY_PUSH(session-&gt;channels,mrcp_channel_t*) = channel;
</ins><span class="cx"> 
</span><ins>+        /* add rtp termination slot */
+        slot = apr_array_push(session-&gt;terminations);
+        slot-&gt;waiting = FALSE;
+        slot-&gt;termination = NULL;
+        slot-&gt;descriptor = NULL;
+        slot-&gt;channel = channel;
+        slot-&gt;id = 0;
+
</ins><span class="cx">         if(channel-&gt;termination) {
</span><del>-                if(mrcp_client_mpf_request_send(profile-&gt;media_engine,MPF_COMMAND_ADD,session-&gt;context,channel-&gt;termination,NULL) == TRUE) {
</del><ins>+                /* media termination mode */
+                mpf_termination_t *termination;
+                mpf_audio_stream_t *audio_stream;
+
+                if(!session-&gt;context) {
+                        /* create media context first */
+                        session-&gt;context = mpf_engine_context_create(profile-&gt;media_engine,session,5,pool);
+                }
+                if(mpf_engine_termination_message_add(
+                                profile-&gt;media_engine,
+                                MPF_ADD_TERMINATION,session-&gt;context,channel-&gt;termination,NULL,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
</ins><span class="cx">                         channel-&gt;waiting_for_termination = TRUE;
</span><del>-                        session-&gt;offer_flag_count++;
</del><ins>+                        mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        if(channel-&gt;rtp_termination_slot) {
-                rtp_descriptor = channel-&gt;rtp_termination_slot-&gt;descriptor;
-        }        
-        /* add to rtp termination array */
-        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add RTP Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-        termination_slot = apr_array_push(session-&gt;terminations);
-        termination_slot-&gt;waiting = FALSE;
-        termination_slot-&gt;termination = NULL;
-        termination_slot-&gt;descriptor = NULL;
-        if(rtp_descriptor) {
-                if(rtp_descriptor-&gt;audio.local) {
-                        session-&gt;offer-&gt;ip = rtp_descriptor-&gt;audio.local-&gt;base.ip;
-                        session-&gt;offer-&gt;ext_ip = rtp_descriptor-&gt;audio.local-&gt;base.ext_ip;
-                        rtp_descriptor-&gt;audio.local-&gt;base.id = mrcp_session_audio_media_add(session-&gt;offer,rtp_descriptor-&gt;audio.local);
-                        rtp_descriptor-&gt;audio.local-&gt;mid = session-&gt;offer-&gt;audio_media_arr-&gt;nelts;
-                }
-        }
-        else {
-                /* create rtp termination */
-                mpf_termination_t *termination = mpf_termination_create(profile-&gt;rtp_termination_factory,session,session-&gt;base.pool);
-                termination_slot-&gt;termination = termination;
-
</del><span class="cx">                 /* initialize rtp descriptor */
</span><span class="cx">                 rtp_descriptor = apr_palloc(pool,sizeof(mpf_rtp_termination_descriptor_t));
</span><span class="cx">                 mpf_rtp_termination_descriptor_init(rtp_descriptor);
</span><del>-                if(channel-&gt;termination &amp;&amp; channel-&gt;termination-&gt;audio_stream) {
</del><ins>+                audio_stream = mpf_termination_audio_stream_get(channel-&gt;termination);
+                if(audio_stream) {
</ins><span class="cx">                         mpf_rtp_media_descriptor_t *media;
</span><span class="cx">                         media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                         mpf_rtp_media_descriptor_init(media);
</span><del>-                        media-&gt;base.state = MPF_MEDIA_ENABLED;
-                        media-&gt;mode = mpf_stream_mode_negotiate(channel-&gt;termination-&gt;audio_stream-&gt;mode);
</del><ins>+                        media-&gt;state = MPF_MEDIA_ENABLED;
+                        media-&gt;direction = mpf_stream_reverse_direction_get(audio_stream-&gt;direction);
</ins><span class="cx">                         rtp_descriptor-&gt;audio.local = media;
</span><span class="cx">                 }
</span><ins>+
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add RTP Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                /* create rtp termination */
+                termination = mpf_termination_create(profile-&gt;rtp_termination_factory,session,pool);
+                slot-&gt;termination = termination;
+
</ins><span class="cx">                 /* send add termination request (add to media context) */
</span><del>-                if(mrcp_client_mpf_request_send(profile-&gt;media_engine,MPF_COMMAND_ADD,session-&gt;context,termination,rtp_descriptor) == TRUE) {
-                        termination_slot-&gt;waiting = TRUE;
-                        session-&gt;offer_flag_count++;
</del><ins>+                if(mpf_engine_termination_message_add(
+                                profile-&gt;media_engine,
+                                MPF_ADD_TERMINATION,session-&gt;context,termination,rtp_descriptor,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
+                        slot-&gt;waiting = TRUE;
+                        mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><ins>+                mpf_engine_message_send(profile-&gt;media_engine,&amp;session-&gt;mpf_task_msg);
</ins><span class="cx">         }
</span><del>-        termination_slot-&gt;descriptor = rtp_descriptor;
-        channel-&gt;rtp_termination_slot = termination_slot;
</del><ins>+        else {
+                /* bypass media mode */
+                if(channel-&gt;rtp_termination_slot) {
+                        rtp_descriptor = channel-&gt;rtp_termination_slot-&gt;descriptor;
+                        if(rtp_descriptor) {
+                                if(rtp_descriptor-&gt;audio.local) {
+                                        session-&gt;offer-&gt;ip = rtp_descriptor-&gt;audio.local-&gt;ip;
+                                        session-&gt;offer-&gt;ext_ip = rtp_descriptor-&gt;audio.local-&gt;ext_ip;
+                                        rtp_descriptor-&gt;audio.local-&gt;id = mrcp_session_audio_media_add(session-&gt;offer,rtp_descriptor-&gt;audio.local);
+                                        rtp_descriptor-&gt;audio.local-&gt;mid = session-&gt;offer-&gt;audio_media_arr-&gt;nelts;
+                                        slot-&gt;id = session-&gt;offer-&gt;audio_media_arr-&gt;nelts - 1;
+                                }
+                        }
+                }        
+        }
</ins><span class="cx"> 
</span><del>-        if(!session-&gt;offer_flag_count) {
</del><ins>+        slot-&gt;descriptor = rtp_descriptor;
+        channel-&gt;rtp_termination_slot = slot;
+
+        if(!session-&gt;subrequest_count) {
</ins><span class="cx">                 /* send offer to server */
</span><span class="cx">                 mrcp_client_session_offer_send(session);
</span><span class="cx">         }
</span><span class="lines">@@ -733,10 +791,21 @@
</span><span class="cx">         
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Terminate Session &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
</span><span class="cx">         profile = session-&gt;profile;
</span><ins>+
+        mrcp_client_session_state_set(session,SESSION_STATE_TERMINATING);
+        if(session-&gt;context) {
+                /* first destroy existing topology */
+                if(mpf_engine_topology_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_DESTROY_TOPOLOGY,session-&gt;context,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE){
+                        mrcp_client_session_subrequest_add(session);
+                }
+        }
</ins><span class="cx">         /* remove existing control channels */
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><span class="cx">                 /* get existing channel */
</span><del>-                channel = *((mrcp_channel_t**)session-&gt;channels-&gt;elts + i);
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 if(channel-&gt;control_channel) {
</span><span class="lines">@@ -744,37 +813,45 @@
</span><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Remove Control Channel &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
</span><span class="cx">                         if(mrcp_client_control_channel_remove(channel-&gt;control_channel) == TRUE) {
</span><span class="cx">                                 channel-&gt;waiting_for_channel = TRUE;
</span><del>-                                session-&gt;terminate_flag_count++;
</del><ins>+                                mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                if(channel-&gt;termination) {                
-                        /* send subtract termination request */
-                        if(channel-&gt;termination) {
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract Channel Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-                                if(mrcp_client_mpf_request_send(profile-&gt;media_engine,MPF_COMMAND_SUBTRACT,session-&gt;context,channel-&gt;termination,NULL) == TRUE) {
-                                        channel-&gt;waiting_for_termination = TRUE;
-                                        session-&gt;terminate_flag_count++;
-                                }
</del><ins>+                /* send subtract termination request */
+                if(channel-&gt;termination) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract Channel Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                        if(mpf_engine_termination_message_add(
+                                        profile-&gt;media_engine,
+                                        MPF_SUBTRACT_TERMINATION,session-&gt;context,channel-&gt;termination,NULL,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
+                                channel-&gt;waiting_for_termination = TRUE;
+                                mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* subtract existing terminations */
-        for(i=0; i&lt;session-&gt;terminations-&gt;nelts; i++) {
-                /* get existing termination */
-                slot = &amp;((rtp_termination_slot_t*)session-&gt;terminations-&gt;elts)[i];
-                if(!slot || !slot-&gt;termination) continue;
</del><ins>+        if(session-&gt;context) {
+                /* subtract existing terminations */
+                for(i=0; i&lt;session-&gt;terminations-&gt;nelts; i++) {
+                        /* get existing termination */
+                        slot = &amp;APR_ARRAY_IDX(session-&gt;terminations,i,rtp_termination_slot_t);
+                        if(!slot || !slot-&gt;termination) continue;
</ins><span class="cx"> 
</span><del>-                /* send subtract termination request */
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-                if(mrcp_client_mpf_request_send(profile-&gt;media_engine,MPF_COMMAND_SUBTRACT,session-&gt;context,slot-&gt;termination,NULL) == TRUE) {
-                        slot-&gt;waiting = TRUE;
-                        session-&gt;terminate_flag_count++;
</del><ins>+                        /* send subtract termination request */
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                        if(mpf_engine_termination_message_add(
+                                        profile-&gt;media_engine,
+                                        MPF_SUBTRACT_TERMINATION,session-&gt;context,slot-&gt;termination,NULL,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
+                                slot-&gt;waiting = TRUE;
+                                mrcp_client_session_subrequest_add(session);
+                        }
</ins><span class="cx">                 }
</span><ins>+
+                mpf_engine_message_send(profile-&gt;media_engine,&amp;session-&gt;mpf_task_msg);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        session-&gt;terminate_flag_count++;
</del><ins>+        mrcp_client_session_subrequest_add(session);
</ins><span class="cx">         mrcp_session_terminate_request(&amp;session-&gt;base);
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -785,34 +862,37 @@
</span><span class="cx">         
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Send Resource Discovery Request &quot;APT_PTR_FMT, MRCP_SESSION_PTR(&amp;session-&gt;base));
</span><span class="cx">         session-&gt;answer = NULL;
</span><del>-        if(session-&gt;base.signaling_agent-&gt;mrcp_version == MRCP_VERSION_1) {
-                const apt_str_t *resource_name;
</del><ins>+        mrcp_client_session_state_set(session,SESSION_STATE_DISCOVERING);
+
+        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
+                mrcp_resource_t *resource;
</ins><span class="cx">                 mrcp_resource_id i;
</span><span class="cx"> 
</span><span class="cx">                 for(i=0; i&lt;MRCP_RESOURCE_TYPE_COUNT; i++) {
</span><del>-                        resource_name = mrcp_resource_name_get(session-&gt;profile-&gt;resource_factory,i);
-                        if(!resource_name) continue;
</del><ins>+                        resource = mrcp_resource_get(session-&gt;profile-&gt;resource_factory,i);
+                        if(!resource) continue;
</ins><span class="cx">                 
</span><span class="cx">                         descriptor = mrcp_session_descriptor_create(session-&gt;base.pool);
</span><del>-                        apt_string_copy(&amp;descriptor-&gt;resource_name,resource_name,session-&gt;base.pool);
</del><ins>+                        apt_string_copy(&amp;descriptor-&gt;resource_name,&amp;resource-&gt;name,session-&gt;base.pool);
</ins><span class="cx">                         if(mrcp_session_discover_request(&amp;session-&gt;base,descriptor) == TRUE) {
</span><del>-                                session-&gt;answer_flag_count++;
</del><ins>+                                mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="cx">                 if(mrcp_session_discover_request(&amp;session-&gt;base,descriptor) == TRUE) {
</span><del>-                        session-&gt;answer_flag_count++;
</del><ins>+                        mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(session-&gt;answer_flag_count == 0) {
-                mrcp_app_sig_response_raise(session,MRCP_SIG_STATUS_CODE_FAILURE,TRUE);
</del><ins>+        if(session-&gt;subrequest_count == 0) {
+                session-&gt;status = MRCP_SIG_STATUS_CODE_FAILURE;
+                mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_client_on_termination_add(mrcp_client_session_t *session, mpf_message_t *mpf_message)
</del><ins>+static apt_bool_t mrcp_client_on_termination_add(mrcp_client_session_t *session, const mpf_message_t *mpf_message)
</ins><span class="cx"> {
</span><span class="cx">         rtp_termination_slot_t *termination_slot;
</span><span class="cx">         if(!session) {
</span><span class="lines">@@ -828,17 +908,15 @@
</span><span class="cx">                 termination_slot-&gt;waiting = FALSE;
</span><span class="cx">                 rtp_descriptor = mpf_message-&gt;descriptor;
</span><span class="cx">                 if(rtp_descriptor-&gt;audio.local) {
</span><del>-                        session-&gt;offer-&gt;ip = rtp_descriptor-&gt;audio.local-&gt;base.ip;
-                        session-&gt;offer-&gt;ext_ip = rtp_descriptor-&gt;audio.local-&gt;base.ext_ip;
-                        rtp_descriptor-&gt;audio.local-&gt;base.id = mrcp_session_audio_media_add(session-&gt;offer,rtp_descriptor-&gt;audio.local);
</del><ins>+                        session-&gt;offer-&gt;ip = rtp_descriptor-&gt;audio.local-&gt;ip;
+                        session-&gt;offer-&gt;ext_ip = rtp_descriptor-&gt;audio.local-&gt;ext_ip;
+                        rtp_descriptor-&gt;audio.local-&gt;id = mrcp_session_audio_media_add(session-&gt;offer,rtp_descriptor-&gt;audio.local);
</ins><span class="cx">                         rtp_descriptor-&gt;audio.local-&gt;mid = session-&gt;offer-&gt;audio_media_arr-&gt;nelts;
</span><ins>+                        termination_slot-&gt;id = session-&gt;offer-&gt;audio_media_arr-&gt;nelts - 1;
</ins><span class="cx">                 }
</span><del>-                if(session-&gt;offer_flag_count) {
-                        session-&gt;offer_flag_count--;
-                        if(!session-&gt;offer_flag_count) {
-                                /* send offer to server */
-                                mrcp_client_session_offer_send(session);
-                        }
</del><ins>+                if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                        /* send offer to server */
+                        mrcp_client_session_offer_send(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="lines">@@ -846,19 +924,16 @@
</span><span class="cx">                 mrcp_channel_t *channel = mrcp_client_channel_termination_find(session,mpf_message-&gt;termination);
</span><span class="cx">                 if(channel &amp;&amp; channel-&gt;waiting_for_termination == TRUE) {
</span><span class="cx">                         channel-&gt;waiting_for_termination = FALSE;
</span><del>-                        if(session-&gt;offer_flag_count) {
-                                session-&gt;offer_flag_count--;
-                                if(!session-&gt;offer_flag_count) {
-                                        /* send offer to server */
-                                        mrcp_client_session_offer_send(session);
-                                }
</del><ins>+                        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                                /* send offer to server */
+                                mrcp_client_session_offer_send(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_client_on_termination_modify(mrcp_client_session_t *session, mpf_message_t *mpf_message)
</del><ins>+static apt_bool_t mrcp_client_on_termination_modify(mrcp_client_session_t *session, const mpf_message_t *mpf_message)
</ins><span class="cx"> {
</span><span class="cx">         rtp_termination_slot_t *termination_slot;
</span><span class="cx">         if(!session) {
</span><span class="lines">@@ -873,25 +948,21 @@
</span><span class="cx">                 termination_slot-&gt;waiting = FALSE;
</span><span class="cx">                 termination_slot-&gt;descriptor = mpf_message-&gt;descriptor;;
</span><span class="cx"> 
</span><del>-                if(session-&gt;offer_flag_count) {
-                        session-&gt;offer_flag_count--;
-                        if(!session-&gt;offer_flag_count) {
</del><ins>+                if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                        if(session-&gt;state == SESSION_STATE_GENERATING_OFFER) {
</ins><span class="cx">                                 /* send offer to server */
</span><span class="cx">                                 mrcp_client_session_offer_send(session);
</span><span class="cx">                         }
</span><del>-                }
-                if(session-&gt;answer_flag_count) {
-                        session-&gt;answer_flag_count--;
-                        if(!session-&gt;answer_flag_count) {
</del><ins>+                        else if(session-&gt;state == SESSION_STATE_PROCESSING_ANSWER) {
</ins><span class="cx">                                 /* raise app response */
</span><del>-                                mrcp_app_sig_response_raise(session,MRCP_SIG_STATUS_CODE_SUCCESS,TRUE);
</del><ins>+                                mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_client_on_termination_subtract(mrcp_client_session_t *session, mpf_message_t *mpf_message)
</del><ins>+static apt_bool_t mrcp_client_on_termination_subtract(mrcp_client_session_t *session, const mpf_message_t *mpf_message)
</ins><span class="cx"> {
</span><span class="cx">         rtp_termination_slot_t *termination_slot;
</span><span class="cx">         if(!session) {
</span><span class="lines">@@ -904,11 +975,8 @@
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><span class="cx">                 termination_slot-&gt;waiting = FALSE;
</span><del>-                if(session-&gt;terminate_flag_count) {
-                        session-&gt;terminate_flag_count--;
-                        if(!session-&gt;terminate_flag_count) {
-                                mrcp_app_session_terminate_raise(session,MRCP_SIG_STATUS_CODE_SUCCESS);
-                        }
</del><ins>+                if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                        mrcp_app_session_terminate_raise(session,MRCP_SIG_STATUS_CODE_SUCCESS);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         else {
</span><span class="lines">@@ -916,48 +984,66 @@
</span><span class="cx">                 mrcp_channel_t *channel = mrcp_client_channel_termination_find(session,mpf_message-&gt;termination);
</span><span class="cx">                 if(channel &amp;&amp; channel-&gt;waiting_for_termination == TRUE) {
</span><span class="cx">                         channel-&gt;waiting_for_termination = FALSE;
</span><del>-                        if(session-&gt;terminate_flag_count) {
-                                session-&gt;terminate_flag_count--;
-                                if(!session-&gt;terminate_flag_count) {
-                                        /* raise app response */
-                                        mrcp_app_sig_response_raise(session,MRCP_SIG_STATUS_CODE_SUCCESS,TRUE);
-                                }
</del><ins>+                        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                                /* raise app response */
+                                mrcp_app_sig_response_raise(session,TRUE);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-apt_bool_t mrcp_client_mpf_message_process(mpf_message_t *mpf_message)
</del><ins>+apt_bool_t mrcp_client_mpf_message_process(mpf_message_container_t *mpf_message_container)
</ins><span class="cx"> {
</span><del>-        mrcp_client_session_t *session = NULL;
-        if(mpf_message-&gt;context) {
-                session = mpf_context_object_get(mpf_message-&gt;context);
-        }
-        if(!session) {
-                return FALSE;
-        }
-        if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_RESPONSE) {
-                switch(mpf_message-&gt;command_id) {
-                        case MPF_COMMAND_ADD:
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Add &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-                                mrcp_client_on_termination_add(session,mpf_message);
-                                break;
-                        case MPF_COMMAND_MODIFY:
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Modify &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-                                mrcp_client_on_termination_modify(session,mpf_message);
-                                break;
-                        case MPF_COMMAND_SUBTRACT:
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Subtract &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-                                mrcp_client_on_termination_subtract(session,mpf_message);
-                                break;
-                        default:
-                                break;
</del><ins>+        apr_size_t i;
+        mrcp_client_session_t *session;
+        const mpf_message_t *mpf_message;
+        for(i=0; i&lt;mpf_message_container-&gt;count; i++) {
+                mpf_message = &amp;mpf_message_container-&gt;messages[i];
+                if(mpf_message-&gt;context) {
+                        session = mpf_engine_context_object_get(mpf_message-&gt;context);
</ins><span class="cx">                 }
</span><ins>+                else {
+                        session = NULL;
+                }
+                if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_RESPONSE) {
+                        switch(mpf_message-&gt;command_id) {
+                                case MPF_ADD_TERMINATION:
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Add &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                                        mrcp_client_on_termination_add(session,mpf_message);
+                                        break;
+                                case MPF_MODIFY_TERMINATION:
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Modify &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                                        mrcp_client_on_termination_modify(session,mpf_message);
+                                        break;
+                                case MPF_SUBTRACT_TERMINATION:
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Subtract &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                                        mrcp_client_on_termination_subtract(session,mpf_message);
+                                        break;
+                                case MPF_ADD_ASSOCIATION:
+                                case MPF_REMOVE_ASSOCIATION:
+                                case MPF_RESET_ASSOCIATIONS:
+                                case MPF_APPLY_TOPOLOGY:
+                                case MPF_DESTROY_TOPOLOGY:
+                                        if(mrcp_client_session_subrequest_remove(session) == TRUE) {
+                                                if(session-&gt;state == SESSION_STATE_GENERATING_OFFER) {
+                                                        /* send offer to server */
+                                                        mrcp_client_session_offer_send(session);
+                                                }
+                                                else if(session-&gt;state == SESSION_STATE_PROCESSING_ANSWER) {
+                                                        /* raise app response */
+                                                        mrcp_app_sig_response_raise(session,TRUE);
+                                                }
+                                        }
+                                        break;
+                                default:
+                                        break;
+                        }
+                }
+                else if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_EVENT) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Event &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
+                }
</ins><span class="cx">         }
</span><del>-        else if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_EVENT) {
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Event &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
-        }
</del><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -998,7 +1084,7 @@
</span><span class="cx">         /* update existing control channels */
</span><span class="cx">         for(i=0; i&lt;count; i++) {
</span><span class="cx">                 /* get existing channel */
</span><del>-                channel = *((mrcp_channel_t**)session-&gt;channels-&gt;elts + i);
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 /* get control descriptor */
</span><span class="lines">@@ -1007,7 +1093,7 @@
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Modify Control Channel &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
</span><span class="cx">                 if(mrcp_client_control_channel_modify(channel-&gt;control_channel,control_descriptor) == TRUE) {
</span><span class="cx">                         channel-&gt;waiting_for_channel = TRUE;
</span><del>-                        session-&gt;answer_flag_count++;
</del><ins>+                        mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -1029,7 +1115,7 @@
</span><span class="cx">                 mpf_rtp_media_descriptor_t *remote_media;
</span><span class="cx">                 mpf_rtp_termination_descriptor_t *rtp_descriptor;
</span><span class="cx">                 /* get existing termination */
</span><del>-                slot = &amp;((rtp_termination_slot_t*)session-&gt;terminations-&gt;elts)[i];
</del><ins>+                slot = &amp;APR_ARRAY_IDX(session-&gt;terminations,i,rtp_termination_slot_t);
</ins><span class="cx">                 if(!slot) continue;
</span><span class="cx"> 
</span><span class="cx">                 remote_media = mrcp_session_audio_media_get(descriptor,i);
</span><span class="lines">@@ -1045,10 +1131,21 @@
</span><span class="cx"> 
</span><span class="cx">                         /* send modify termination request */
</span><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Modify Termination &quot;APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&amp;session-&gt;base));
</span><del>-                        if(mrcp_client_mpf_request_send(session-&gt;profile-&gt;media_engine,MPF_COMMAND_MODIFY,session-&gt;context,slot-&gt;termination,rtp_descriptor) == TRUE) {
</del><ins>+                        if(mpf_engine_termination_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_MODIFY_TERMINATION,session-&gt;context,slot-&gt;termination,rtp_descriptor,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
</ins><span class="cx">                                 slot-&gt;waiting = TRUE;
</span><del>-                                session-&gt;answer_flag_count++;
</del><ins>+                                mrcp_client_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><ins>+                        if(slot-&gt;channel &amp;&amp; slot-&gt;channel-&gt;termination) {
+                                if(mpf_engine_assoc_message_add(
+                                                session-&gt;profile-&gt;media_engine,
+                                                MPF_ADD_ASSOCIATION,session-&gt;context,slot-&gt;termination,slot-&gt;channel-&gt;termination,
+                                                &amp;session-&gt;mpf_task_msg) == TRUE) {
+                                        mrcp_client_session_subrequest_add(session);
+                                }
+                        }
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -1056,6 +1153,15 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mrcp_app_request_dispatch(mrcp_client_session_t *session, const mrcp_app_message_t *app_message)
</span><span class="cx"> {
</span><ins>+        if(session-&gt;state == SESSION_STATE_TERMINATING) {
+                /* no more requests are allowed, as session is being terminated!
+                   just return, it is horribly wrong and can crash anytime here */
+                apt_log(APT_LOG_MARK,APT_PRIO_ERROR,&quot;Inappropriate Application Request &quot;APT_PTRSID_FMT&quot; [%d]&quot;,
+                        MRCP_SESSION_PTRSID(&amp;session-&gt;base),
+                        app_message-&gt;sig_message.command_id);
+                return FALSE;
+        }
+        
</ins><span class="cx">         if(session-&gt;registered == FALSE) {
</span><span class="cx">                 session-&gt;base.signaling_agent = session-&gt;profile-&gt;signaling_agent;
</span><span class="cx">                 session-&gt;base.signaling_agent-&gt;create_client_session(&amp;session-&gt;base);
</span><span class="lines">@@ -1063,6 +1169,7 @@
</span><span class="cx">                 mrcp_client_session_add(session-&gt;application-&gt;client,session);
</span><span class="cx">                 session-&gt;registered = TRUE;
</span><span class="cx">         }
</span><ins>+        session-&gt;status = MRCP_SIG_STATUS_CODE_SUCCESS;
</ins><span class="cx">         switch(app_message-&gt;message_type) {
</span><span class="cx">                 case MRCP_APP_MESSAGE_TYPE_SIGNALING:
</span><span class="cx">                 {
</span><span class="lines">@@ -1192,29 +1299,3 @@
</span><span class="cx">         }
</span><span class="cx">         return status;
</span><span class="cx"> }
</span><del>-
-static apt_bool_t mrcp_client_mpf_request_send(
-                                                mpf_engine_t *engine, 
-                                                mpf_command_type_e command_id,
-                                                mpf_context_t *context, 
-                                                mpf_termination_t *termination, 
-                                                void *descriptor)
-{
-        apt_task_t *media_task;
-        apt_task_msg_t *msg;
-        mpf_message_t *mpf_message;
-        if(!engine) {
-                return FALSE;
-        }
-        media_task = mpf_task_get(engine);
-        msg = apt_task_msg_get(media_task);
-        msg-&gt;type = TASK_MSG_USER;
-        mpf_message = (mpf_message_t*) msg-&gt;data;
-
-        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-        mpf_message-&gt;command_id = command_id;
-        mpf_message-&gt;context = context;
-        mpf_message-&gt;termination = termination;
-        mpf_message-&gt;descriptor = descriptor;
-        return apt_task_msg_signal(media_task,msg);
-}
</del></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -11,7 +11,25 @@
</span><span class="cx"> 
</span><span class="cx"> noinst_LTLIBRARIES          = libmrcpengine.la
</span><span class="cx"> 
</span><del>-include_HEADERS             = include/mrcp_resource_plugin.h \
-                              include/mrcp_resource_engine.h
</del><ins>+include_HEADERS             = include/mrcp_engine_types.h \
+                              include/mrcp_engine_plugin.h \
+                              include/mrcp_engine_iface.h \
+                              include/mrcp_engine_impl.h \
+                              include/mrcp_synth_engine.h \
+                              include/mrcp_recog_engine.h \
+                              include/mrcp_recorder_engine.h \
+                              include/mrcp_resource_engine.h \
+                              include/mrcp_engine_factory.h \
+                              include/mrcp_engine_loader.h \
+                              include/mrcp_state_machine.h \
+                              include/mrcp_synth_state_machine.h \
+                              include/mrcp_recog_state_machine.h \
+                              include/mrcp_recorder_state_machine.h
</ins><span class="cx"> 
</span><del>-libmrcpengine_la_SOURCES    = src/mrcp_resource_engine.c
</del><ins>+libmrcpengine_la_SOURCES    = src/mrcp_engine_iface.c \
+                              src/mrcp_engine_impl.c \
+                              src/mrcp_engine_factory.c \
+                              src/mrcp_engine_loader.c \
+                              src/mrcp_synth_state_machine.c \
+                              src/mrcp_recog_state_machine.c \
+                              src/mrcp_recorder_state_machine.c
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_factoryh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,57 @@
</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 __MRCP_ENGINE_FACTORY_H__
+#define __MRCP_ENGINE_FACTORY_H__
+
+/**
+ * @file mrcp_engine_factory.h
+ * @brief Factory of MRCP Engines
+ */ 
+
+#include &quot;mrcp_engine_iface.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque engine factory declaration */
+typedef struct mrcp_engine_factory_t mrcp_engine_factory_t;
+
+/** Create engine factory */
+MRCP_DECLARE(mrcp_engine_factory_t*) mrcp_engine_factory_create(apr_pool_t *pool);
+
+/** Destroy registered engines and the factory */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_destroy(mrcp_engine_factory_t *factory);
+
+/** Open registered engines */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_open(mrcp_engine_factory_t *factory);
+
+/** Close registered engines */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_close(mrcp_engine_factory_t *factory);
+
+
+/** Register engine */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory_t *factory, mrcp_engine_t *engine, const char *name);
+
+/** Get engine by name */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(mrcp_engine_factory_t *factory, const char *name);
+
+/** Find engine by resource identifier */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(mrcp_engine_factory_t *factory, mrcp_resource_id resource_id);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_ENGINE_FACTORY_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_ifaceh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,93 @@
</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 __MRCP_ENGINE_IFACE_H__
+#define __MRCP_ENGINE_IFACE_H__
+
+/**
+ * @file mrcp_engine_iface.h
+ * @brief MRCP Engine User Interface (typically user is an MRCP server)
+ */ 
+
+#include &quot;mrcp_engine_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Destroy engine */
+static APR_INLINE apt_bool_t mrcp_engine_virtual_destroy(mrcp_engine_t *engine)
+{
+        return engine-&gt;method_vtable-&gt;destroy(engine);
+}
+
+/** Open engine */
+static APR_INLINE apt_bool_t mrcp_engine_virtual_open(mrcp_engine_t *engine)
+{
+        if(engine-&gt;is_open == FALSE) {
+                engine-&gt;is_open = engine-&gt;method_vtable-&gt;open(engine);
+                return engine-&gt;is_open;
+        }
+        return FALSE;
+}
+
+/** Close engine */
+static APR_INLINE apt_bool_t mrcp_engine_virtual_close(mrcp_engine_t *engine)
+{
+        if(engine-&gt;is_open == TRUE) {
+                engine-&gt;is_open = FALSE;
+                return engine-&gt;method_vtable-&gt;close(engine);
+        }
+        return FALSE;
+}
+
+/** Create engine channel */
+mrcp_engine_channel_t* mrcp_engine_channel_virtual_create(mrcp_engine_t *engine, mrcp_version_e mrcp_version, apr_pool_t *pool);
+
+/** Destroy engine channel */
+apt_bool_t mrcp_engine_channel_virtual_destroy(mrcp_engine_channel_t *channel);
+
+/** Open engine channel */
+static APR_INLINE apt_bool_t mrcp_engine_channel_virtual_open(mrcp_engine_channel_t *channel)
+{
+        if(channel-&gt;is_open == FALSE) {
+                channel-&gt;is_open = channel-&gt;method_vtable-&gt;open(channel);
+                return channel-&gt;is_open;
+        }
+        return FALSE;
+}
+
+/** Close engine channel */
+static APR_INLINE apt_bool_t mrcp_engine_channel_virtual_close(mrcp_engine_channel_t *channel)
+{
+        if(channel-&gt;is_open == TRUE) {
+                channel-&gt;is_open = FALSE;
+                return channel-&gt;method_vtable-&gt;close(channel);
+        }
+        return FALSE;
+}
+
+/** Process request */
+static APR_INLINE apt_bool_t mrcp_engine_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *message)
+{
+        return channel-&gt;method_vtable-&gt;process_request(channel,message);
+}
+
+/** Allocate engine config */
+mrcp_engine_config_t* mrcp_engine_config_alloc(apr_pool_t *pool);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_ENGINE_IFACE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_implh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,121 @@
</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 __MRCP_ENGINE_IMPL_H__
+#define __MRCP_ENGINE_IMPL_H__
+
+/**
+ * @file mrcp_engine_impl.h
+ * @brief MRCP Engine Realization Interface (typically should be implemented in plugins)
+ */ 
+
+#include &quot;mrcp_engine_types.h&quot;
+#include &quot;mpf_stream.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Create engine */
+mrcp_engine_t* mrcp_engine_create(
+                                        mrcp_resource_id resource_id,
+                                        void *obj, 
+                                        const mrcp_engine_method_vtable_t *vtable,
+                                        apr_pool_t *pool);
+
+
+/** Get engine config */
+const mrcp_engine_config_t* mrcp_engine_config_get(const mrcp_engine_t *engine);
+
+/** Get engine param by name */
+const char* mrcp_engine_param_get(const mrcp_engine_t *engine, const char *name);
+
+
+/** Create engine channel */
+mrcp_engine_channel_t* mrcp_engine_channel_create(
+                                        mrcp_engine_t *engine,
+                                        const mrcp_engine_channel_method_vtable_t *method_vtable,
+                                        void *method_obj,
+                                        mpf_termination_t *termination,
+                                        apr_pool_t *pool);
+
+/** Create audio termination */
+mpf_termination_t* mrcp_engine_audio_termination_create(
+                                                                void *obj,
+                                                                const mpf_audio_stream_vtable_t *stream_vtable,
+                                                                mpf_stream_capabilities_t *capabilities,
+                                                                apr_pool_t *pool);
+
+/** Create engine channel and source media termination 
+ * @deprecated @see mrcp_engine_channel_create() and mrcp_engine_audio_termination_create()
+ */
+mrcp_engine_channel_t* mrcp_engine_source_channel_create(
+                                                                mrcp_engine_t *engine,
+                                                                const mrcp_engine_channel_method_vtable_t *channel_vtable,
+                                                                const mpf_audio_stream_vtable_t *stream_vtable,
+                                                                void *method_obj,
+                                                                mpf_codec_descriptor_t *codec_descriptor,
+                                                                apr_pool_t *pool);
+
+/** Create engine channel and sink media termination 
+ * @deprecated @see mrcp_engine_channel_create() and mrcp_engine_audio_termination_create()
+ */
+mrcp_engine_channel_t* mrcp_engine_sink_channel_create(
+                                                                mrcp_engine_t *engine,
+                                                                const mrcp_engine_channel_method_vtable_t *channel_vtable,
+                                                                const mpf_audio_stream_vtable_t *stream_vtable,
+                                                                void *method_obj,
+                                                                mpf_codec_descriptor_t *codec_descriptor,
+                                                                apr_pool_t *pool);
+
+/** Send channel open response */
+static APR_INLINE apt_bool_t mrcp_engine_channel_open_respond(mrcp_engine_channel_t *channel, apt_bool_t status)
+{
+        return channel-&gt;event_vtable-&gt;on_open(channel,status);
+}
+
+/** Send channel close response */
+static APR_INLINE apt_bool_t mrcp_engine_channel_close_respond(mrcp_engine_channel_t *channel)
+{
+        return channel-&gt;event_vtable-&gt;on_close(channel);
+}
+
+/** Send response/event message */
+static APR_INLINE apt_bool_t mrcp_engine_channel_message_send(mrcp_engine_channel_t *channel, mrcp_message_t *message)
+{
+        return channel-&gt;event_vtable-&gt;on_message(channel,message);
+}
+
+/** Get channel identifier */
+static APR_INLINE const char* mrcp_engine_channel_id_get(mrcp_engine_channel_t *channel)
+{
+        return channel-&gt;id.buf;
+}
+
+/** Get MRCP version channel is created in the scope of */
+static APR_INLINE mrcp_version_e mrcp_engine_channel_version_get(mrcp_engine_channel_t *channel)
+{
+        return channel-&gt;mrcp_version;
+}
+
+/** Get codec descriptor of the audio source stream */
+const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(mrcp_engine_channel_t *channel);
+
+/** Get codec descriptor of the audio sink stream */
+const mpf_codec_descriptor_t* mrcp_engine_sink_stream_codec_get(mrcp_engine_channel_t *channel);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_ENGINE_IMPL_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_loaderh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,48 @@
</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 __MRCP_ENGINE_LOADER_H__
+#define __MRCP_ENGINE_LOADER_H__
+
+/**
+ * @file mrcp_engine_loader.h
+ * @brief Loader of plugins for MRCP engines
+ */ 
+
+#include &quot;mrcp_engine_iface.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque engine loader declaration */
+typedef struct mrcp_engine_loader_t mrcp_engine_loader_t;
+
+/** Create engine loader */
+MRCP_DECLARE(mrcp_engine_loader_t*) mrcp_engine_loader_create(apr_pool_t *pool);
+
+/** Destroy engine loader */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_loader_destroy(mrcp_engine_loader_t *loader);
+
+/** Unload loaded plugins */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_loader_plugins_unload(mrcp_engine_loader_t *loader);
+
+
+/** Load engine plugin */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(mrcp_engine_loader_t *loader, const char *path, const char *name);
+
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_ENGINE_LOADER_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_pluginh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,116 @@
</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 __MRCP_ENGINE_PLUGIN_H__
+#define __MRCP_ENGINE_PLUGIN_H__
+
+/**
+ * @file mrcp_engine_plugin.h
+ * @brief MRCP Engine Plugin
+ */ 
+
+#include &quot;apr_version.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;mrcp_engine_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Plugin export defines */
+#ifdef WIN32
+#define MRCP_PLUGIN_DECLARE(type) EXTERN_C __declspec(dllexport) type
+#else
+#define MRCP_PLUGIN_DECLARE(type) type
+#endif
+
+/** [REQUIRED] Symbol name of the main entry point in plugin DSO */
+#define MRCP_PLUGIN_ENGINE_SYM_NAME &quot;mrcp_plugin_create&quot;
+/** [REQUIRED] Symbol name of the vesrion number entry point in plugin DSO */
+#define MRCP_PLUGIN_VERSION_SYM_NAME &quot;mrcp_plugin_version&quot;
+/** [IMPLIED] Symbol name of the log accessor entry point in plugin DSO */
+#define MRCP_PLUGIN_LOGGER_SYM_NAME &quot;mrcp_plugin_logger_set&quot;
+
+/** Prototype of engine creator (entry point of plugin DSO) */
+typedef mrcp_engine_t* (*mrcp_plugin_creator_f)(apr_pool_t *pool);
+
+/** Prototype of log accessor (entry point of plugin DSO) */
+typedef apt_bool_t (*mrcp_plugin_log_accessor_f)(apt_logger_t *logger);
+
+/** Declare this macro in plugins to use log routine of the server */
+#define MRCP_PLUGIN_LOGGER_IMPLEMENT \
+        MRCP_PLUGIN_DECLARE(apt_bool_t) mrcp_plugin_logger_set(apt_logger_t *logger) \
+                { return apt_log_instance_set(logger); }
+
+/** Declare this macro in plugins to set plugin version */
+#define MRCP_PLUGIN_VERSION_DECLARE \
+        MRCP_PLUGIN_DECLARE(mrcp_plugin_version_t) mrcp_plugin_version =  \
+                {PLUGIN_MAJOR_VERSION, PLUGIN_MINOR_VERSION, PLUGIN_PATCH_VERSION};
+
+
+/** major version 
+ * Major API changes that could cause compatibility problems for older
+ * plugins such as structure size changes.  No binary compatibility is
+ * possible across a change in the major version.
+ */
+#define PLUGIN_MAJOR_VERSION   0
+
+/** minor version
+ * Minor API changes that do not cause binary compatibility problems.
+ * Reset to 0 when upgrading PLUGIN_MAJOR_VERSION
+ */
+#define PLUGIN_MINOR_VERSION   5
+
+/** patch level 
+ * The Patch Level never includes API changes, simply bug fixes.
+ * Reset to 0 when upgrading PLUGIN_MINOR_VERSION
+ */
+#define PLUGIN_PATCH_VERSION   0
+
+
+/**
+ * Check at compile time if the plugin version is at least a certain
+ * level.
+ */
+#define PLUGIN_VERSION_AT_LEAST(major,minor,patch)                    \
+(((major) &lt; PLUGIN_MAJOR_VERSION)                                     \
+ || ((major) == PLUGIN_MAJOR_VERSION &amp;&amp; (minor) &lt; PLUGIN_MINOR_VERSION) \
+ || ((major) == PLUGIN_MAJOR_VERSION &amp;&amp; (minor) == PLUGIN_MINOR_VERSION &amp;&amp; (patch) &lt;= PLUGIN_PATCH_VERSION))
+
+/** The formatted string of plugin's version */
+#define PLUGIN_VERSION_STRING \
+     APR_STRINGIFY(PLUGIN_MAJOR_VERSION) &quot;.&quot; \
+     APR_STRINGIFY(PLUGIN_MINOR_VERSION) &quot;.&quot; \
+     APR_STRINGIFY(PLUGIN_PATCH_VERSION)
+
+/** Plugin version */
+typedef apr_version_t mrcp_plugin_version_t;
+
+/** Get plugin version */
+static APR_INLINE void mrcp_plugin_version_get(mrcp_plugin_version_t *version)
+{
+        version-&gt;major = PLUGIN_MAJOR_VERSION;
+        version-&gt;minor = PLUGIN_MINOR_VERSION;
+        version-&gt;patch = PLUGIN_PATCH_VERSION;
+}
+
+/** Check plugin version */
+static APR_INLINE int mrcp_plugin_version_check(mrcp_plugin_version_t *version)
+{
+        return PLUGIN_VERSION_AT_LEAST(version-&gt;major,version-&gt;minor,version-&gt;patch);
+}
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_ENGINE_PLUGIN_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_engine_typesh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,141 @@
</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 __MRCP_ENGINE_TYPES_H__
+#define __MRCP_ENGINE_TYPES_H__
+
+/**
+ * @file mrcp_engine_types.h
+ * @brief MRCP Engine Types
+ */ 
+
+#include &lt;apr_tables.h&gt;
+#include &quot;mrcp_state_machine.h&quot;
+#include &quot;mpf_types.h&quot;
+#include &quot;apt_string.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** MRCP engine declaration */
+typedef struct mrcp_engine_t mrcp_engine_t;
+/** MRCP engine config declaration */
+typedef struct mrcp_engine_config_t mrcp_engine_config_t;
+/** MRCP engine vtable declaration */
+typedef struct mrcp_engine_method_vtable_t mrcp_engine_method_vtable_t;
+/** MRCP engine channel declaration */
+typedef struct mrcp_engine_channel_t mrcp_engine_channel_t;
+/** MRCP engine channel virtual method table declaration */
+typedef struct mrcp_engine_channel_method_vtable_t mrcp_engine_channel_method_vtable_t;
+/** MRCP engine channel virtual event table declaration */
+typedef struct mrcp_engine_channel_event_vtable_t mrcp_engine_channel_event_vtable_t;
+
+/** Table of channel virtual methods */
+struct mrcp_engine_channel_method_vtable_t {
+        /** Virtual destroy */
+        apt_bool_t (*destroy)(mrcp_engine_channel_t *channel);
+        /** Virtual open */
+        apt_bool_t (*open)(mrcp_engine_channel_t *channel);
+        /** Virtual close */
+        apt_bool_t (*close)(mrcp_engine_channel_t *channel);
+        /** Virtual process_request */
+        apt_bool_t (*process_request)(mrcp_engine_channel_t *channel, mrcp_message_t *request);
+};
+
+/** Table of channel virtual event handlers */
+struct mrcp_engine_channel_event_vtable_t {
+        /** Open event handler */
+        apt_bool_t (*on_open)(mrcp_engine_channel_t *channel, apt_bool_t status);
+        /** Close event handler */
+        apt_bool_t (*on_close)(mrcp_engine_channel_t *channel);
+        /** Message event handler */
+        apt_bool_t (*on_message)(mrcp_engine_channel_t *channel, mrcp_message_t *message);
+};
+
+/** MRCP engine channel declaration */
+struct mrcp_engine_channel_t {
+        /** Table of virtual methods */
+        const mrcp_engine_channel_method_vtable_t *method_vtable;
+        /** External object used with virtual methods */
+        void                                      *method_obj;
+        /** Table of virtual event handlers */
+        const mrcp_engine_channel_event_vtable_t  *event_vtable;
+        /** External object used with event handlers */
+        void                                      *event_obj;
+        /** Media termination */
+        mpf_termination_t                         *termination;
+        /** Back pointer to engine */
+        mrcp_engine_t                             *engine;
+        /** Unique identifier to be used in traces */
+        apt_str_t                                  id;
+        /** MRCP version */
+        mrcp_version_e                             mrcp_version;
+        /** Is channel successfully opened */
+        apt_bool_t                                is_open;
+        /** Pool to allocate memory from */
+        apr_pool_t                                *pool;
+};
+
+/** Table of MRCP engine virtual methods */
+struct mrcp_engine_method_vtable_t {
+        /** Virtual destroy */
+        apt_bool_t (*destroy)(mrcp_engine_t *engine);
+        /** Virtual open */
+        apt_bool_t (*open)(mrcp_engine_t *engine);
+        /** Virtual close */
+        apt_bool_t (*close)(mrcp_engine_t *engine);
+        /** Virtual channel create */
+        mrcp_engine_channel_t* (*create_channel)(mrcp_engine_t *engine, apr_pool_t *pool);
+};
+
+/** MRCP engine */
+struct mrcp_engine_t {
+        /** Resource identifier */
+        mrcp_resource_id                   resource_id;
+        /** External object associated with engine */
+        void                              *obj;
+        /** Table of virtual methods */
+        const mrcp_engine_method_vtable_t *method_vtable;
+        /** Codec manager */
+        const mpf_codec_manager_t         *codec_manager;
+        /** Dir layout structure */
+        const apt_dir_layout_t            *dir_layout;
+        /** Config of engine */
+        mrcp_engine_config_t              *config;
+        /** Number of simultaneous channels currently in use */
+        apr_size_t                         cur_channel_count;
+        /** Is engine successfully opened */
+        apt_bool_t                         is_open;
+        /** Pool to allocate memory from */
+        apr_pool_t                        *pool;
+
+
+        /** Create state machine */
+        mrcp_state_machine_t* (*create_state_machine)(void *obj, mrcp_version_e version, apr_pool_t *pool);
+};
+
+/** MRCP engine config */
+struct mrcp_engine_config_t {
+        /** Name of the engine */
+        const char  *name;
+        /** Max number of simultaneous channels */
+        apr_size_t   max_channel_count;
+        /** Table of name/value string params */
+        apr_table_t *params;
+};
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_ENGINE_TYPES_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recog_engineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,33 @@
</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 __MRCP_RECOG_ENGINE_H__
+#define __MRCP_RECOG_ENGINE_H__
+
+/**
+ * @file mrcp_recog_engine.h
+ * @brief Recognizer Engine Includes
+ */ 
+
+#include &quot;mrcp_engine_plugin.h&quot;
+#include &quot;mrcp_engine_impl.h&quot;
+
+#include &quot;mrcp_recog_resource.h&quot;
+#include &quot;mrcp_recog_header.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_message.h&quot;
+
+#endif /*__MRCP_RECOG_ENGINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recog_state_machineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,34 @@
</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 __MRCP_RECOG_STATE_MACHINE_H__
+#define __MRCP_RECOG_STATE_MACHINE_H__
+
+/**
+ * @file mrcp_recog_state_machine.h
+ * @brief MRCP Recognizer State Machine
+ */ 
+
+#include &quot;mrcp_state_machine.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Create MRCP recognizer state machine */
+mrcp_state_machine_t* mrcp_recog_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool);
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_RECOG_STATE_MACHINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recorder_engineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,33 @@
</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 __MRCP_RECORDER_ENGINE_H__
+#define __MRCP_RECORDER_ENGINE_H__
+
+/**
+ * @file mrcp_recorder_engine.h
+ * @brief Recorder Engine Includes
+ */ 
+
+#include &quot;mrcp_engine_plugin.h&quot;
+#include &quot;mrcp_engine_impl.h&quot;
+
+#include &quot;mrcp_recorder_resource.h&quot;
+#include &quot;mrcp_recorder_header.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_message.h&quot;
+
+#endif /*__MRCP_RECORDER_ENGINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_recorder_state_machineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,34 @@
</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 __MRCP_RECORDER_STATE_MACHINE_H__
+#define __MRCP_RECORDER_STATE_MACHINE_H__
+
+/**
+ * @file mrcp_recorder_state_machine.h
+ * @brief MRCP Recorder State Machine
+ */ 
+
+#include &quot;mrcp_state_machine.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Create MRCP recorder state machine */
+mrcp_state_machine_t* mrcp_recorder_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool);
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_RECORDER_STATE_MACHINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_resource_engineh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -19,197 +19,31 @@
</span><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * @file mrcp_resource_engine.h
</span><del>- * @brief MRCP Resource Engine Interface
</del><ins>+ * @brief Legacy MRCP Resource Engine
+ * @deprecated @see mrcp_engine_plugin.h and mrcp_engine_impl.h
</ins><span class="cx">  */ 
</span><span class="cx"> 
</span><del>-#include &quot;mrcp_types.h&quot;
-#include &quot;mpf_termination.h&quot;
-#include &quot;mpf_stream.h&quot;
-#include &quot;mrcp_resource_plugin.h&quot;
</del><ins>+#include &quot;mrcp_engine_plugin.h&quot;
+#include &quot;mrcp_engine_impl.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><del>-/** MRCP resource engine vtable declaration */
-typedef struct mrcp_engine_method_vtable_t mrcp_engine_method_vtable_t;
-/** MRCP engine channel declaration */
-typedef struct mrcp_engine_channel_t mrcp_engine_channel_t;
-/** MRCP engine channel virtual method table declaration */
-typedef struct mrcp_engine_channel_method_vtable_t mrcp_engine_channel_method_vtable_t;
-/** MRCP engine channel virtual event table declaration */
-typedef struct mrcp_engine_channel_event_vtable_t mrcp_engine_channel_event_vtable_t;
</del><ins>+/** Termorary define legacy mrcp_resource_engine_t as mrcp_engine_t */
+typedef mrcp_engine_t mrcp_resource_engine_t;
</ins><span class="cx"> 
</span><del>-/** Table of channel virtual methods */
-struct mrcp_engine_channel_method_vtable_t {
-        /** Virtual destroy */
-        apt_bool_t (*destroy)(mrcp_engine_channel_t *channel);
-        /** Virtual open */
-        apt_bool_t (*open)(mrcp_engine_channel_t *channel);
-        /** Virtual close */
-        apt_bool_t (*close)(mrcp_engine_channel_t *channel);
-        /** Virtual process_request */
-        apt_bool_t (*process_request)(mrcp_engine_channel_t *channel, mrcp_message_t *request);
-};
-
-/** Table of channel virtual event handlers */
-struct mrcp_engine_channel_event_vtable_t {
-        /** Open event handler */
-        apt_bool_t (*on_open)(mrcp_engine_channel_t *channel, apt_bool_t status);
-        /** Close event handler */
-        apt_bool_t (*on_close)(mrcp_engine_channel_t *channel);
-        /** Message event handler */
-        apt_bool_t (*on_message)(mrcp_engine_channel_t *channel, mrcp_message_t *message);
-};
-
-/** MRCP engine channel declaration */
-struct mrcp_engine_channel_t {
-        /** Table of virtual methods */
-        const mrcp_engine_channel_method_vtable_t *method_vtable;
-        /** External object used with virtual methods */
-        void                                      *method_obj;
-        /** Table of virtual event handlers */
-        const mrcp_engine_channel_event_vtable_t  *event_vtable;
-        /** External object used with event handlers */
-        void                                      *event_obj;
-        /** Media termination */
-        mpf_termination_t                         *termination;
-        /** Back pointer to resource engine */
-        mrcp_resource_engine_t                    *engine;
-        /** Unique identifier (useful for traces) */
-        apt_str_t                                  id;
-        /** Pool to allocate memory from */
-        apr_pool_t                                *pool;
-};
-
-/** Table of MRCP engine virtual methods */
-struct mrcp_engine_method_vtable_t {
-        /** Virtual destroy */
-        apt_bool_t (*destroy)(mrcp_resource_engine_t *engine);
-        /** Virtual open */
-        apt_bool_t (*open)(mrcp_resource_engine_t *engine);
-        /** Virtual close */
-        apt_bool_t (*close)(mrcp_resource_engine_t *engine);
-        /** Virtual channel create */
-        mrcp_engine_channel_t* (*create_channel)(mrcp_resource_engine_t *engine, apr_pool_t *pool);
-};
-
-/** MRCP resource engine */
-struct mrcp_resource_engine_t {
-        /** Plugin version */
-        mrcp_plugin_version_t              plugin_version;
-        /** Resource identifier */
-        mrcp_resource_id                   resource_id;
-        /** External object associated with engine */
-        void                              *obj;
-        /** Table of virtual methods */
-        const mrcp_engine_method_vtable_t *method_vtable;
-        /** Codec manager */
-        const mpf_codec_manager_t         *codec_manager;
-        /** Dir layout structure */
-        const apt_dir_layout_t            *dir_layout;
-        /** Pool to allocate memory from */
-        apr_pool_t                        *pool;
-};
-
-/** Create resource engine */
-mrcp_resource_engine_t* mrcp_resource_engine_create(
-                                                                mrcp_resource_id resource_id,
-                                                                void *obj, 
-                                                                const mrcp_engine_method_vtable_t *vtable,
-                                                                apr_pool_t *pool);
-
-/** Destroy resource engine */
-static APR_INLINE apt_bool_t mrcp_resource_engine_destroy(mrcp_resource_engine_t *engine)
</del><ins>+/** 
+ * Create resource engine
+ * @deprecated @see mrcp_engine_create
+ */
+static APR_INLINE mrcp_engine_t* mrcp_resource_engine_create(
+                                        mrcp_resource_id resource_id,
+                                        void *obj, 
+                                        const mrcp_engine_method_vtable_t *vtable,
+                                        apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        return engine-&gt;method_vtable-&gt;destroy(engine);
</del><ins>+        return mrcp_engine_create(resource_id,obj,vtable,pool);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Open resource engine */
-static APR_INLINE apt_bool_t mrcp_resource_engine_open(mrcp_resource_engine_t *engine)
-{
-        return engine-&gt;method_vtable-&gt;open(engine);
-}
-
-/** Close resource engine */
-static APR_INLINE apt_bool_t mrcp_resource_engine_close(mrcp_resource_engine_t *engine)
-{
-        return engine-&gt;method_vtable-&gt;close(engine);
-}
-
-/** Create engine channel */
-mrcp_engine_channel_t* mrcp_engine_channel_create(
-                                                                mrcp_resource_engine_t *engine,
-                                                                const mrcp_engine_channel_method_vtable_t *method_vtable,
-                                                                void *method_obj,
-                                                                mpf_termination_t *termination,
-                                                                apr_pool_t *pool);
-
-/** Create engine channel and source media termination */
-mrcp_engine_channel_t* mrcp_engine_source_channel_create(
-                                                                mrcp_resource_engine_t *engine,
-                                                                const mrcp_engine_channel_method_vtable_t *channel_vtable,
-                                                                const mpf_audio_stream_vtable_t *stream_vtable,
-                                                                void *method_obj,
-                                                                mpf_codec_descriptor_t *codec_descriptor,
-                                                                apr_pool_t *pool);
-
-/** Create engine channel and sink media termination */
-mrcp_engine_channel_t* mrcp_engine_sink_channel_create(
-                                                                mrcp_resource_engine_t *engine,
-                                                                const mrcp_engine_channel_method_vtable_t *channel_vtable,
-                                                                const mpf_audio_stream_vtable_t *stream_vtable,
-                                                                void *method_obj,
-                                                                mpf_codec_descriptor_t *codec_descriptor,
-                                                                apr_pool_t *pool);
-
-/** Destroy engine channel */
-static APR_INLINE apt_bool_t mrcp_engine_channel_destroy(mrcp_engine_channel_t *channel)
-{
-        return channel-&gt;method_vtable-&gt;destroy(channel);
-}
-
-/** Open engine channel */
-static APR_INLINE apt_bool_t mrcp_engine_channel_open(mrcp_engine_channel_t *channel)
-{
-        return channel-&gt;method_vtable-&gt;open(channel);
-}
-
-/** Close engine channel */
-static APR_INLINE apt_bool_t mrcp_engine_channel_close(mrcp_engine_channel_t *channel)
-{
-        return channel-&gt;method_vtable-&gt;close(channel);
-}
-
-/** Process request */
-static APR_INLINE apt_bool_t mrcp_engine_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *message)
-{
-        return channel-&gt;method_vtable-&gt;process_request(channel,message);
-}
-
-/** Send channel open response */
-static APR_INLINE apt_bool_t mrcp_engine_channel_open_respond(mrcp_engine_channel_t *channel, apt_bool_t status)
-{
-        return channel-&gt;event_vtable-&gt;on_open(channel,status);
-}
-
-/** Send channel close response */
-static APR_INLINE apt_bool_t mrcp_engine_channel_close_respond(mrcp_engine_channel_t *channel)
-{
-        return channel-&gt;event_vtable-&gt;on_close(channel);
-}
-
-/** Send response/event message */
-static APR_INLINE apt_bool_t mrcp_engine_channel_message_send(mrcp_engine_channel_t *channel, mrcp_message_t *message)
-{
-        return channel-&gt;event_vtable-&gt;on_message(channel,message);
-}
-
-/** Get codec of the audio source stream */
-mpf_codec_t* mrcp_engine_source_stream_codec_get(mrcp_engine_channel_t *channel);
-
-/** Get codec of the audio sink stream */
-mpf_codec_t* mrcp_engine_sink_stream_codec_get(mrcp_engine_channel_t *channel);
-
-
</del><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> #endif /*__MRCP_RESOURCE_ENGINE_H__*/
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_resource_pluginh"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_plugin.h</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_state_machineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,84 @@
</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 __MRCP_STATE_MACHINE_H__
+#define __MRCP_STATE_MACHINE_H__
+
+/**
+ * @file mrcp_state_machine.h
+ * @brief MRCP State Machine
+ */ 
+
+#include &quot;mrcp_types.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** MRCP state machine declaration */
+typedef struct mrcp_state_machine_t mrcp_state_machine_t;
+
+
+/** MRCP state machine */
+struct mrcp_state_machine_t {
+        /** External object associated with state machine */
+        void *obj;
+        /** State either active or deactivating */
+        apt_bool_t active;
+
+        /** Virtual update */
+        apt_bool_t (*update)(mrcp_state_machine_t *state_machine, mrcp_message_t *message);
+        /** Deactivate */
+        apt_bool_t (*deactivate)(mrcp_state_machine_t *state_machine);
+
+
+        /** Message dispatcher */
+        apt_bool_t (*on_dispatch)(mrcp_state_machine_t *state_machine, mrcp_message_t *message);
+        /** Deactivated */
+        apt_bool_t (*on_deactivate)(mrcp_state_machine_t *state_machine);
+};
+
+/** Initialize MRCP state machine */
+static APR_INLINE void mrcp_state_machine_init(mrcp_state_machine_t *state_machine, void *obj)
+{
+        state_machine-&gt;obj = obj;
+        state_machine-&gt;active = TRUE;
+        state_machine-&gt;on_dispatch = NULL;
+        state_machine-&gt;on_deactivate = NULL;
+        state_machine-&gt;update = NULL;
+        state_machine-&gt;deactivate = NULL;
+}
+
+/** Update MRCP state machine */
+static APR_INLINE apt_bool_t mrcp_state_machine_update(mrcp_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;update) {
+                return state_machine-&gt;update(state_machine,message);
+        }
+        return FALSE;
+}
+
+/** Deactivate MRCP state machine */
+static APR_INLINE apt_bool_t mrcp_state_machine_deactivate(mrcp_state_machine_t *state_machine)
+{
+        if(state_machine-&gt;deactivate) {
+                state_machine-&gt;active = FALSE;
+                return state_machine-&gt;deactivate(state_machine);
+        }
+        return FALSE;
+}
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_STATE_MACHINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_synth_engineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,33 @@
</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 __MRCP_SYNTH_ENGINE_H__
+#define __MRCP_SYNTH_ENGINE_H__
+
+/**
+ * @file mrcp_synth_engine.h
+ * @brief Synthesizer Engine Includes
+ */ 
+
+#include &quot;mrcp_engine_plugin.h&quot;
+#include &quot;mrcp_engine_impl.h&quot;
+
+#include &quot;mrcp_synth_resource.h&quot;
+#include &quot;mrcp_synth_header.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_message.h&quot;
+
+#endif /*__MRCP_SYNTH_ENGINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpengineincludemrcp_synth_state_machineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,34 @@
</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 __MRCP_SYNTH_STATE_MACHINE_H__
+#define __MRCP_SYNTH_STATE_MACHINE_H__
+
+/**
+ * @file mrcp_synth_state_machine.h
+ * @brief MRCP Synthesizer State Machine
+ */ 
+
+#include &quot;mrcp_state_machine.h&quot;
+
+APT_BEGIN_EXTERN_C
+
+/** Create MRCP synthesizer state machine */
+mrcp_state_machine_t* mrcp_synth_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool);
+
+APT_END_EXTERN_C
+
+#endif /*__MRCP_SYNTH_STATE_MACHINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginemrcpenginevcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -130,22 +130,94 @@
</span><span class="cx">                         UniqueIdentifier=&quot;{93995380-89BD-4b04-88EB-625FBE52EBFB}&quot;
</span><span class="cx">                         &gt;
</span><span class="cx">                         &lt;File
</span><ins>+                                RelativePath=&quot;.\include\mrcp_engine_factory.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_engine_iface.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_engine_impl.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_engine_loader.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_engine_plugin.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_engine_types.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_recog_engine.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_recog_state_machine.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_recorder_engine.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_recorder_state_machine.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
</ins><span class="cx">                                 RelativePath=&quot;.\include\mrcp_resource_engine.h&quot;
</span><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><span class="cx">                         &lt;File
</span><del>-                                RelativePath=&quot;.\include\mrcp_resource_plugin.h&quot;
</del><ins>+                                RelativePath=&quot;.\include\mrcp_state_machine.h&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><ins>+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_synth_engine.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\mrcp_synth_state_machine.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><del>-                                RelativePath=&quot;.\src\mrcp_resource_engine.c&quot;
</del><ins>+                                RelativePath=&quot;.\src\mrcp_engine_factory.c&quot;
</ins><span class="cx">                                 &gt;
</span><span class="cx">                         &lt;/File&gt;
</span><ins>+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_engine_iface.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_engine_impl.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_engine_loader.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_recog_state_machine.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_recorder_state_machine.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_synth_state_machine.c&quot;
+                                &gt;
+                        &lt;/File&gt;
</ins><span class="cx">                 &lt;/Filter&gt;
</span><span class="cx">         &lt;/Files&gt;
</span><span class="cx">         &lt;Globals&gt;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_factoryc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,147 @@
</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 &lt;apr_hash.h&gt;
+#include &quot;mrcp_engine_factory.h&quot;
+#include &quot;mrcp_synth_state_machine.h&quot;
+#include &quot;mrcp_recog_state_machine.h&quot;
+#include &quot;mrcp_recorder_state_machine.h&quot;
+#include &quot;apt_log.h&quot;
+
+/** Engine factory declaration */
+struct mrcp_engine_factory_t {
+        apr_hash_t *engines;
+        apr_pool_t *pool;
+};
+
+
+MRCP_DECLARE(mrcp_engine_factory_t*) mrcp_engine_factory_create(apr_pool_t *pool)
+{
+        mrcp_engine_factory_t *factory = apr_palloc(pool,sizeof(mrcp_engine_factory_t));
+        factory-&gt;pool = pool;
+        factory-&gt;engines = apr_hash_make(pool);
+        return factory;
+}
+
+/** Destroy registered engines and the factory */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_destroy(mrcp_engine_factory_t *factory)
+{
+        mrcp_engine_t *engine;
+        apr_hash_index_t *it;
+        void *val;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Destroy MRCP Engines&quot;);
+        it=apr_hash_first(factory-&gt;pool,factory-&gt;engines);
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                engine = val;
+                if(engine) {
+                        mrcp_engine_virtual_destroy(engine);
+                }
+        }
+        apr_hash_clear(factory-&gt;engines);
+        return TRUE;
+}
+
+/** Open registered engines */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_open(mrcp_engine_factory_t *factory)
+{
+        mrcp_engine_t *engine;
+        apr_hash_index_t *it;
+        void *val;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open MRCP Engines&quot;);
+        it = apr_hash_first(factory-&gt;pool,factory-&gt;engines);
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                engine = val;
+                if(engine) {
+                        mrcp_engine_virtual_open(engine);
+                }
+        }
+        return TRUE;
+}
+
+/** Close registered engines */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_close(mrcp_engine_factory_t *factory)
+{
+        mrcp_engine_t *engine;
+        apr_hash_index_t *it;
+        void *val;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close MRCP Engines&quot;);
+        it=apr_hash_first(factory-&gt;pool,factory-&gt;engines);
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                engine = val;
+                if(engine) {
+                        mrcp_engine_virtual_close(engine);
+                }
+        }
+        return TRUE;
+}
+
+/** Register new engine */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory_t *factory, mrcp_engine_t *engine, const char *name)
+{
+        if(!engine || !name) {
+                return FALSE;
+        }
+
+        switch(engine-&gt;resource_id) {
+                case MRCP_SYNTHESIZER_RESOURCE:
+                        engine-&gt;create_state_machine = mrcp_synth_state_machine_create;
+                        break;
+                case MRCP_RECOGNIZER_RESOURCE:
+                        engine-&gt;create_state_machine = mrcp_recog_state_machine_create;
+                        break;
+                case MRCP_RECORDER_RESOURCE:
+                        engine-&gt;create_state_machine = mrcp_recorder_state_machine_create;
+                        break;
+                default:
+                        break;
+        }
+
+        if(!engine-&gt;create_state_machine) {
+                return FALSE;
+        }
+
+        apr_hash_set(factory-&gt;engines,name,APR_HASH_KEY_STRING,engine);
+        return TRUE;
+}
+
+/** Get engine by name */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(mrcp_engine_factory_t *factory, const char *name)
+{
+        if(!name) {
+                return NULL;
+        }
+        return apr_hash_get(factory-&gt;engines,name,APR_HASH_KEY_STRING);
+}
+
+/** Find engine by resource identifier */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(mrcp_engine_factory_t *factory, mrcp_resource_id resource_id)
+{
+        mrcp_engine_t *engine;
+        void *val;
+        apr_hash_index_t *it = apr_hash_first(factory-&gt;pool,factory-&gt;engines);
+        /* walk through the engines */
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                engine = val;
+                if(engine &amp;&amp; engine-&gt;resource_id == resource_id) {
+                        return engine;
+                }
+        }
+        return NULL;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_ifacec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,55 @@
</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;mrcp_engine_iface.h&quot;
+
+/** Create engine channel */
+mrcp_engine_channel_t* mrcp_engine_channel_virtual_create(mrcp_engine_t *engine, mrcp_version_e mrcp_version, apr_pool_t *pool)
+{
+        mrcp_engine_channel_t *channel;
+        if(engine-&gt;is_open != TRUE) {
+                return NULL;
+        }
+        if(engine-&gt;config-&gt;max_channel_count &amp;&amp; engine-&gt;cur_channel_count &gt;= engine-&gt;config-&gt;max_channel_count) {
+                return NULL;
+        }
+        channel = engine-&gt;method_vtable-&gt;create_channel(engine,pool);
+        if(channel) {
+                channel-&gt;mrcp_version = mrcp_version;
+                engine-&gt;cur_channel_count++;
+        }
+        return channel;
+}
+
+/** Destroy engine channel */
+apt_bool_t mrcp_engine_channel_virtual_destroy(mrcp_engine_channel_t *channel)
+{
+        mrcp_engine_t *engine = channel-&gt;engine;
+        if(engine-&gt;cur_channel_count) {
+                engine-&gt;cur_channel_count--;
+        }
+        return channel-&gt;method_vtable-&gt;destroy(channel);
+}
+
+/** Allocate engine config */
+mrcp_engine_config_t* mrcp_engine_config_alloc(apr_pool_t *pool)
+{
+        mrcp_engine_config_t *config = apr_palloc(pool,sizeof(mrcp_engine_config_t));
+        config-&gt;name = NULL;
+        config-&gt;max_channel_count = 0;
+        config-&gt;params = NULL;
+        return config;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_implc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,241 @@
</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;mrcp_engine_impl.h&quot;
+#include &quot;mpf_termination_factory.h&quot;
+
+/** Create engine */
+mrcp_engine_t* mrcp_engine_create(
+                                        mrcp_resource_id resource_id,
+                                        void *obj, 
+                                        const mrcp_engine_method_vtable_t *vtable,
+                                        apr_pool_t *pool)
+{
+        mrcp_engine_t *engine = apr_palloc(pool,sizeof(mrcp_engine_t));
+        engine-&gt;resource_id = resource_id;
+        engine-&gt;obj = obj;
+        engine-&gt;method_vtable =vtable;
+        engine-&gt;config = NULL;
+        engine-&gt;codec_manager = NULL;
+        engine-&gt;dir_layout = NULL;
+        engine-&gt;cur_channel_count = 0;
+        engine-&gt;is_open = FALSE;
+        engine-&gt;pool = pool;
+        engine-&gt;create_state_machine = NULL;
+        return engine;
+}
+
+/** Get engine config */
+const mrcp_engine_config_t* mrcp_engine_config_get(const mrcp_engine_t *engine)
+{
+        return engine-&gt;config;
+}
+
+/** Get engine param by name */
+const char* mrcp_engine_param_get(const mrcp_engine_t *engine, const char *name)
+{
+        if(!engine-&gt;config || !engine-&gt;config-&gt;params) {
+                return NULL;
+        }
+        return apr_table_get(engine-&gt;config-&gt;params,name);
+}
+
+/** Create engine channel */
+mrcp_engine_channel_t* mrcp_engine_channel_create(
+                                                        mrcp_engine_t *engine, 
+                                                        const mrcp_engine_channel_method_vtable_t *method_vtable,
+                                                        void *method_obj,
+                                                        mpf_termination_t *termination,
+                                                        apr_pool_t *pool)
+{
+        mrcp_engine_channel_t *channel = apr_palloc(pool,sizeof(mrcp_engine_channel_t));
+        channel-&gt;method_vtable = method_vtable;
+        channel-&gt;method_obj = method_obj;
+        channel-&gt;event_vtable = NULL;
+        channel-&gt;event_obj = NULL;
+        channel-&gt;termination = termination;
+        channel-&gt;engine = engine;
+        channel-&gt;is_open = FALSE;
+        channel-&gt;pool = pool;
+        apt_string_reset(&amp;channel-&gt;id);
+        return channel;
+}
+
+/** Create audio termination */
+mpf_termination_t* mrcp_engine_audio_termination_create(
+                                                                void *obj,
+                                                                const mpf_audio_stream_vtable_t *stream_vtable,
+                                                                mpf_stream_capabilities_t *capabilities,
+                                                                apr_pool_t *pool)
+{
+        mpf_audio_stream_t *audio_stream;
+        if(!capabilities) {
+                return NULL;
+        }
+
+        if(mpf_codec_capabilities_validate(&amp;capabilities-&gt;codecs) == FALSE) {
+                return NULL;
+        }
+
+        /* create audio stream */
+        audio_stream = mpf_audio_stream_create(
+                        obj,                  /* object to associate */
+                        stream_vtable,        /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
+        if(!audio_stream) {
+                return NULL;
+        }
+
+        /* create media termination */
+        return mpf_raw_termination_create(
+                        NULL,                 /* no object to associate */
+                        audio_stream,         /* audio stream */
+                        NULL,                 /* no video stream */
+                        pool);                /* pool to allocate memory from */
+}
+
+
+/** Create engine channel and source media termination */
+mrcp_engine_channel_t* mrcp_engine_source_channel_create(
+                                                        mrcp_engine_t *engine,
+                                                        const mrcp_engine_channel_method_vtable_t *channel_vtable,
+                                                        const mpf_audio_stream_vtable_t *stream_vtable,
+                                                        void *method_obj,
+                                                        mpf_codec_descriptor_t *codec_descriptor,
+                                                        apr_pool_t *pool)
+{
+        mpf_stream_capabilities_t *capabilities;
+        mpf_audio_stream_t *audio_stream;
+        mpf_termination_t *termination;
+
+        capabilities = mpf_source_stream_capabilities_create(pool);
+        if(codec_descriptor) {
+                mpf_codec_capabilities_add(
+                                                &amp;capabilities-&gt;codecs,
+                                                mpf_sample_rate_mask_get(codec_descriptor-&gt;sampling_rate),
+                                                codec_descriptor-&gt;name.buf);
+        }
+        else {
+                mpf_codec_default_capabilities_add(&amp;capabilities-&gt;codecs);
+        }
+
+        /* create audio stream */
+        audio_stream = mpf_audio_stream_create(
+                        method_obj,           /* object to associate */
+                        stream_vtable,        /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
+        if(!audio_stream) {
+                return NULL;
+        }
+
+        audio_stream-&gt;rx_descriptor = codec_descriptor;
+        
+        /* create media termination */
+        termination = mpf_raw_termination_create(
+                        NULL,                 /* no object to associate */
+                        audio_stream,         /* audio stream */
+                        NULL,                 /* no video stream */
+                        pool);                /* pool to allocate memory from */
+
+        /* create engine channel base */
+        return mrcp_engine_channel_create(
+                        engine,          /* engine */
+                        channel_vtable,  /* virtual methods table of engine channel */
+                        method_obj,      /* object to associate */
+                        termination,     /* media termination, used to terminate audio stream */
+                        pool);           /* pool to allocate memory from */
+}
+
+/** Create engine channel and sink media termination */
+mrcp_engine_channel_t* mrcp_engine_sink_channel_create(
+                                                        mrcp_engine_t *engine,
+                                                        const mrcp_engine_channel_method_vtable_t *channel_vtable,
+                                                        const mpf_audio_stream_vtable_t *stream_vtable,
+                                                        void *method_obj,
+                                                        mpf_codec_descriptor_t *codec_descriptor,
+                                                        apr_pool_t *pool)
+{
+        mpf_stream_capabilities_t *capabilities;
+        mpf_audio_stream_t *audio_stream;
+        mpf_termination_t *termination;
+
+        capabilities = mpf_sink_stream_capabilities_create(pool);
+        if(codec_descriptor) {
+                mpf_codec_capabilities_add(
+                                                &amp;capabilities-&gt;codecs,
+                                                mpf_sample_rate_mask_get(codec_descriptor-&gt;sampling_rate),
+                                                codec_descriptor-&gt;name.buf);
+        }
+        else {
+                mpf_codec_default_capabilities_add(&amp;capabilities-&gt;codecs);
+        }
+
+        /* create audio stream */
+        audio_stream = mpf_audio_stream_create(
+                        method_obj,             /* object to associate */
+                        stream_vtable,          /* virtual methods table of audio stream */
+                        capabilities,           /* stream capabilities */
+                        pool);                  /* pool to allocate memory from */
+
+        if(!audio_stream) {
+                return NULL;
+        }
+
+        audio_stream-&gt;tx_descriptor = codec_descriptor;
+        
+        /* create media termination */
+        termination = mpf_raw_termination_create(
+                        NULL,            /* no object to associate */
+                        audio_stream,    /* audio stream */
+                        NULL,            /* no video stream */
+                        pool);           /* pool to allocate memory from */
+
+        /* create engine channel base */
+        return mrcp_engine_channel_create(
+                        engine,          /* engine */
+                        channel_vtable,  /* virtual methods table of engine channel */
+                        method_obj,      /* object to associate */
+                        termination,     /* media termination, used to terminate audio stream */
+                        pool);           /* pool to allocate memory from */
+}
+
+/** Get codec descriptor of the audio source stream */
+const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(mrcp_engine_channel_t *channel)
+{
+        if(channel &amp;&amp; channel-&gt;termination) {
+                mpf_audio_stream_t *audio_stream = mpf_termination_audio_stream_get(channel-&gt;termination);
+                if(audio_stream) {
+                        return audio_stream-&gt;rx_descriptor;
+                }
+        }
+        return NULL;
+}
+
+/** Get codec descriptor of the audio sink stream */
+const mpf_codec_descriptor_t* mrcp_engine_sink_stream_codec_get(mrcp_engine_channel_t *channel)
+{
+        if(channel &amp;&amp; channel-&gt;termination) {
+                mpf_audio_stream_t *audio_stream = mpf_termination_audio_stream_get(channel-&gt;termination);
+                if(audio_stream) {
+                        return audio_stream-&gt;tx_descriptor;
+                }
+        }
+        return NULL;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_engine_loaderc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,164 @@
</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 &lt;apr_dso.h&gt;
+#include &lt;apr_hash.h&gt;
+#include &quot;mrcp_engine_loader.h&quot;
+#include &quot;mrcp_engine_plugin.h&quot;
+#include &quot;apt_log.h&quot;
+
+/** Engine loader declaration */
+struct mrcp_engine_loader_t {
+        /** Table of plugins (apr_dso_handle_t*) */
+        apr_hash_t *plugins;
+        apr_pool_t *pool;
+};
+
+
+/** Create engine loader */
+MRCP_DECLARE(mrcp_engine_loader_t*) mrcp_engine_loader_create(apr_pool_t *pool)
+{
+        mrcp_engine_loader_t *loader = apr_palloc(pool,sizeof(mrcp_engine_loader_t));
+        loader-&gt;pool = pool;
+        loader-&gt;plugins = apr_hash_make(pool);
+        return loader;
+}
+
+/** Destroy engine loader */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_loader_destroy(mrcp_engine_loader_t *loader)
+{
+        return mrcp_engine_loader_plugins_unload(loader);
+}
+
+/** Unload loaded plugins */
+MRCP_DECLARE(apt_bool_t) mrcp_engine_loader_plugins_unload(mrcp_engine_loader_t *loader)
+{
+        apr_hash_index_t *it;
+        void *val;
+        apr_dso_handle_t *plugin;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unload Plugins&quot;);
+        it=apr_hash_first(loader-&gt;pool,loader-&gt;plugins);
+        for(; it; it = apr_hash_next(it)) {
+                apr_hash_this(it,NULL,NULL,&amp;val);
+                plugin = val;
+                if(plugin) {
+                        apr_dso_unload(plugin);
+                }
+        }
+        apr_hash_clear(loader-&gt;plugins);
+        return TRUE;
+}
+
+static apt_bool_t plugin_version_load(apr_dso_handle_t *plugin)
+{
+        apr_dso_handle_sym_t version_handle = NULL;
+        if(apr_dso_sym(&amp;version_handle,plugin,MRCP_PLUGIN_VERSION_SYM_NAME) != APR_SUCCESS) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Version Info Found: %s&quot;, MRCP_PLUGIN_VERSION_SYM_NAME);
+                return FALSE;
+        }
+        
+        if(version_handle) {
+                mrcp_plugin_version_t *version = (mrcp_plugin_version_t*)version_handle;
+                if(mrcp_plugin_version_check(version)) {
+                        return TRUE;
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Incompatible Plugin Version Found [%d.%d.%d] &lt; [&quot;PLUGIN_VERSION_STRING&quot;]&quot;,
+                                version-&gt;major,
+                                version-&gt;minor,
+                                version-&gt;patch);
+                }
+        }
+        return FALSE;
+}
+
+static mrcp_plugin_creator_f plugin_creator_load(apr_dso_handle_t *plugin)
+{
+        apr_dso_handle_sym_t func_handle = NULL;
+        mrcp_plugin_creator_f plugin_creator = NULL;
+        
+        if(apr_dso_sym(&amp;func_handle,plugin,MRCP_PLUGIN_ENGINE_SYM_NAME) == APR_SUCCESS) {
+                if(func_handle) {
+                        plugin_creator = (mrcp_plugin_creator_f)(intptr_t)func_handle;
+                }
+        }
+        else {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Load DSO Symbol: &quot;MRCP_PLUGIN_ENGINE_SYM_NAME);
+                return NULL;
+        }
+
+        return plugin_creator;
+}
+
+static apt_bool_t plugin_logger_load(apr_dso_handle_t *plugin)
+{
+        apr_dso_handle_sym_t func_handle = NULL;
+        if(apr_dso_sym(&amp;func_handle,plugin,MRCP_PLUGIN_LOGGER_SYM_NAME) != APR_SUCCESS) {
+                return FALSE;
+        }
+
+        if(func_handle) {
+                apt_logger_t *logger = apt_log_instance_get();
+                mrcp_plugin_log_accessor_f log_accessor;
+                log_accessor = (mrcp_plugin_log_accessor_f)(intptr_t)func_handle;
+                log_accessor(logger);
+        }
+        return TRUE;
+}
+
+
+/** Load engine plugin */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(mrcp_engine_loader_t *loader, const char *path, const char *name)
+{
+        apr_dso_handle_t *plugin = NULL;
+        mrcp_plugin_creator_f plugin_creator = NULL;
+        mrcp_engine_t *engine = NULL;
+        if(!path || !name) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Load Plugin: invalid params&quot;);
+                return NULL;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Load Plugin [%s] [%s]&quot;,path,name);
+        if(apr_dso_load(&amp;plugin,path,loader-&gt;pool) != APR_SUCCESS) {
+                char derr[512] = &quot;&quot;;
+                apr_dso_error(plugin,derr,sizeof(derr));
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Load DSO: %s&quot;, derr);
+                return NULL;
+        }
+
+        if(plugin_version_load(plugin) != TRUE) {
+                apr_dso_unload(plugin);
+                return NULL;
+        }
+
+        plugin_creator = plugin_creator_load(plugin);
+        if(!plugin_creator) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Entry Point Found for Plugin&quot;);
+                apr_dso_unload(plugin);
+                return NULL;
+        }
+
+        plugin_logger_load(plugin);
+
+        apr_hash_set(loader-&gt;plugins,name,APR_HASH_KEY_STRING,plugin);
+
+        engine = plugin_creator(loader-&gt;pool);
+        if(!engine) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create MRCP Engine&quot;);
+        }
+
+        return engine;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_recog_state_machinec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,531 @@
</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;apt_obj_list.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;mrcp_state_machine.h&quot;
+#include &quot;mrcp_recog_state_machine.h&quot;
+#include &quot;mrcp_recog_header.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_recog_resource.h&quot;
+#include &quot;mrcp_message.h&quot;
+
+/** MRCP recognizer states */
+typedef enum {
+        RECOGNIZER_STATE_IDLE,
+        RECOGNIZER_STATE_RECOGNIZING,
+        RECOGNIZER_STATE_RECOGNIZED,
+
+        RECOGNIZER_STATE_COUNT
+} mrcp_recog_state_e;
+
+static const char * state_names[RECOGNIZER_STATE_COUNT] = {
+        &quot;IDLE&quot;,
+        &quot;RECOGNIZING&quot;,
+        &quot;RECOGNIZED&quot;
+};
+
+typedef struct mrcp_recog_state_machine_t mrcp_recog_state_machine_t;
+struct mrcp_recog_state_machine_t {
+        /** state machine base */
+        mrcp_state_machine_t  base;
+        /** recognizer state */
+        mrcp_recog_state_e    state;
+        /** indicate whether active_request was processed from pending request queue */
+        apt_bool_t            is_pending;
+        /** request sent to recognition engine and waiting for the response to be received */
+        mrcp_message_t       *active_request;
+        /** in-progress recognize request */
+        mrcp_message_t       *recog;
+        /** queue of pending recognition requests */
+        apt_obj_list_t       *queue;
+        /** properties used in set/get params */
+        mrcp_message_header_t properties;
+};
+
+typedef apt_bool_t (*recog_method_f)(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message);
+
+static APR_INLINE apt_bool_t recog_request_dispatch(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        state_machine-&gt;active_request = message;
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE apt_bool_t recog_response_dispatch(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        state_machine-&gt;active_request = NULL;
+        if(state_machine-&gt;base.active == FALSE) {
+                /* this is the response to deactivation (STOP) request */
+                return state_machine-&gt;base.on_deactivate(&amp;state_machine-&gt;base);
+        }
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE apt_bool_t recog_event_dispatch(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;base.active == FALSE) {
+                /* do nothing, state machine has already been deactivated */
+                return FALSE;
+        }
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE void recog_state_change(mrcp_recog_state_machine_t *state_machine, mrcp_recog_state_e state)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;State Transition %s -&gt; %s&quot;,state_names[state_machine-&gt;state],state_names[state]);
+        state_machine-&gt;state = state;
+        if(state == RECOGNIZER_STATE_IDLE) {
+                state_machine-&gt;recog = NULL;
+        }
+}
+
+
+static apt_bool_t recog_request_set_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SET-PARAMS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        mrcp_message_header_set(&amp;state_machine-&gt;properties,&amp;message-&gt;header,message-&gt;pool);
+        return recog_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_response_set_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SET-PARAMS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_request_get_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-PARAMS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_response_get_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-PARAMS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        mrcp_message_header_set(&amp;message-&gt;header,&amp;state_machine-&gt;active_request-&gt;header,message-&gt;pool);
+        mrcp_message_header_get(&amp;message-&gt;header,&amp;state_machine-&gt;properties,message-&gt;pool);
+        return recog_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_request_define_grammar(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZING) {
+                mrcp_message_t *response_message = mrcp_response_create(message,message-&gt;pool);
+                response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+                return recog_response_dispatch(state_machine,response_message);
+        }
+        else if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZED) {
+                recog_state_change(state_machine,RECOGNIZER_STATE_IDLE);
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process DEFINE-GRAMMAR Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_response_define_grammar(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process DEFINE-GRAMMAR Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(mrcp_resource_header_property_check(message,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
+                mrcp_recog_header_t *recog_header = mrcp_resource_header_prepare(message);
+                recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS;
+                mrcp_resource_header_property_add(message,RECOGNIZER_HEADER_COMPLETION_CAUSE);
+        }
+        return recog_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_request_recognize(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_header_inherit(&amp;message-&gt;header,&amp;state_machine-&gt;properties,message-&gt;pool);
+        if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZING) {
+                mrcp_message_t *response;
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Queue Up RECOGNIZE Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                message-&gt;start_line.request_state = MRCP_REQUEST_STATE_PENDING;
+                apt_list_push_back(state_machine-&gt;queue,message,message-&gt;pool);
+                
+                response = mrcp_response_create(message,message-&gt;pool);
+                response-&gt;start_line.request_state = MRCP_REQUEST_STATE_PENDING;
+                return recog_response_dispatch(state_machine,response);
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RECOGNIZE Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_response_recognize(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RECOGNIZE Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(message-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
+                state_machine-&gt;recog = state_machine-&gt;active_request;
+                recog_state_change(state_machine,RECOGNIZER_STATE_RECOGNIZING);
+        }
+        if(state_machine-&gt;is_pending == TRUE) {
+                state_machine-&gt;is_pending = FALSE;
+                /* not to send the response for pending request */
+                return TRUE;
+        }
+        return recog_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_request_get_result(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZED) {
+                /* found recognized request */
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-RESULT Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return recog_request_dispatch(state_machine,message);
+        }
+
+        /* found no recognized request */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+        return recog_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t recog_response_get_result(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-RESULT Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_request_recognition_start_timers(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZING) {
+                /* found in-progress request */
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process START-INPUT-TIMERS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return recog_request_dispatch(state_machine,message);
+        }
+
+        /* found no in-progress request */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+        return recog_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t recog_response_recognition_start_timers(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process START-INPUT-TIMERS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_pending_requests_remove(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *request_message, mrcp_message_t *response_message)
+{
+        apt_list_elem_t *elem;
+        mrcp_message_t *pending_message;
+        mrcp_request_id_list_t *request_id_list = NULL;
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request_message);
+        mrcp_generic_header_t *response_generic_header = mrcp_generic_header_prepare(response_message);
+        if(generic_header &amp;&amp; mrcp_generic_header_property_check(request_message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) {
+                if(generic_header-&gt;active_request_id_list.ids &amp;&amp; generic_header-&gt;active_request_id_list.count) {
+                        /* selective STOP request */
+                        request_id_list = &amp;generic_header-&gt;active_request_id_list;
+                }
+        }
+
+        elem = apt_list_first_elem_get(state_machine-&gt;queue);
+        while(elem) {
+                pending_message = apt_list_elem_object_get(elem);
+                if(!request_id_list || active_request_id_list_find(generic_header,pending_message-&gt;start_line.request_id) == TRUE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove Pending RECOGNIZE Request [%d]&quot;,pending_message-&gt;start_line.request_id);
+                        elem = apt_list_elem_remove(state_machine-&gt;queue,elem);
+                        /* append active id list */
+                        active_request_id_list_append(response_generic_header,pending_message-&gt;start_line.request_id);
+                }
+                else {
+                        /* speak request remains in the queue, just proceed to the next one */
+                        elem = apt_list_next_elem_get(state_machine-&gt;queue,elem);
+                }
+        }
+        if(response_generic_header-&gt;active_request_id_list.count) {
+                mrcp_generic_header_property_add(response_message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        }
+        return TRUE;
+}
+
+static apt_bool_t recog_request_stop(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZING) {
+                mrcp_request_id_list_t *request_id_list = NULL;
+                mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
+                if(generic_header &amp;&amp; mrcp_generic_header_property_check(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) {
+                        if(generic_header-&gt;active_request_id_list.ids &amp;&amp; generic_header-&gt;active_request_id_list.count) {
+                                /* selective STOP request */
+                                request_id_list = &amp;generic_header-&gt;active_request_id_list;
+                        }
+                }
+
+                if(!request_id_list || active_request_id_list_find(generic_header,state_machine-&gt;recog-&gt;start_line.request_id) == TRUE) {
+                        /* found in-progress RECOGNIZE request, stop it */
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process STOP Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                                message-&gt;start_line.request_id);
+                        return recog_request_dispatch(state_machine,message);
+                }
+        }
+        else if(state_machine-&gt;state == RECOGNIZER_STATE_RECOGNIZED) {
+                recog_state_change(state_machine,RECOGNIZER_STATE_IDLE);
+        }
+
+        /* found no in-progress RECOGNIZE request, sending immediate response */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        recog_pending_requests_remove(state_machine,message,response_message);
+        return recog_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t recog_response_stop(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *pending_request;
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process STOP Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        /* append active id list */
+        active_request_id_list_append(generic_header,state_machine-&gt;recog-&gt;start_line.request_id);
+        mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        recog_pending_requests_remove(state_machine,state_machine-&gt;active_request,message);
+        recog_state_change(state_machine,RECOGNIZER_STATE_IDLE);
+        pending_request = apt_list_pop_front(state_machine-&gt;queue);
+        recog_response_dispatch(state_machine,message);
+
+        /* process pending RECOGNIZE requests / if any */
+        if(pending_request) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process Pending RECOGNIZE Request [%d]&quot;,pending_request-&gt;start_line.request_id);
+                state_machine-&gt;is_pending = TRUE;
+                recog_request_dispatch(state_machine,pending_request);
+        }
+        return TRUE;
+}
+
+static apt_bool_t recog_event_start_of_input(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(!state_machine-&gt;recog) {
+                /* unexpected event, no in-progress recognition request */
+                return FALSE;
+        }
+
+        if(state_machine-&gt;recog-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                /* unexpected event */
+                return FALSE;
+        }
+        
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process START-OF-INPUT Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        message-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        return recog_event_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_event_recognition_complete(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *pending_request;
+        if(!state_machine-&gt;recog) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unexpected RECOGNITION-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        if(state_machine-&gt;recog-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unexpected RECOGNITION-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        if(state_machine-&gt;active_request &amp;&amp; state_machine-&gt;active_request-&gt;start_line.method_id == RECOGNIZER_STOP) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Ignore RECOGNITION-COMPLETE Event [%d]: waiting for STOP response&quot;,message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RECOGNITION-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(mrcp_resource_header_property_check(message,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
+                mrcp_recog_header_t *recog_header = mrcp_resource_header_prepare(message);
+                recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS;
+                mrcp_resource_header_property_add(message,RECOGNIZER_HEADER_COMPLETION_CAUSE);
+        }
+        recog_state_change(state_machine,RECOGNIZER_STATE_RECOGNIZED);
+        recog_event_dispatch(state_machine,message);
+
+        /* process pending RECOGNIZE requests */
+        pending_request = apt_list_pop_front(state_machine-&gt;queue);
+        if(pending_request) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process Pending RECOGNIZE Request [%d]&quot;,pending_request-&gt;start_line.request_id);
+                state_machine-&gt;is_pending = TRUE;
+                recog_request_dispatch(state_machine,pending_request);
+        }
+        return TRUE;
+}
+
+static recog_method_f recog_request_method_array[RECOGNIZER_METHOD_COUNT] = {
+        recog_request_set_params,
+        recog_request_get_params,
+        recog_request_define_grammar,
+        recog_request_recognize,
+        recog_request_get_result,
+        recog_request_recognition_start_timers,
+        recog_request_stop
+};
+
+static recog_method_f recog_response_method_array[RECOGNIZER_METHOD_COUNT] = {
+        recog_response_set_params,
+        recog_response_get_params,
+        recog_response_define_grammar,
+        recog_response_recognize,
+        recog_response_get_result,
+        recog_response_recognition_start_timers,
+        recog_response_stop
+};
+
+static recog_method_f recog_event_method_array[RECOGNIZER_EVENT_COUNT] = {
+        recog_event_start_of_input,
+        recog_event_recognition_complete
+};
+
+/** Update state according to received incoming request from MRCP client */
+static apt_bool_t recog_request_state_update(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        recog_method_f method;
+        if(message-&gt;start_line.method_id &gt;= RECOGNIZER_METHOD_COUNT) {
+                return FALSE;
+        }
+        
+        method = recog_request_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return recog_request_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing response from recognition engine */
+static apt_bool_t recog_response_state_update(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        recog_method_f method;
+        if(!state_machine-&gt;active_request) {
+                /* unexpected response, no active request waiting for response */
+                return FALSE;
+        }
+        if(state_machine-&gt;active_request-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                /* unexpected response, request id doesn't match */
+                return FALSE;
+        }
+
+        if(message-&gt;start_line.method_id &gt;= RECOGNIZER_METHOD_COUNT) {
+                return FALSE;
+        }
+        
+        method = recog_response_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return recog_response_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing event from recognition engine */
+static apt_bool_t recog_event_state_update(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        recog_method_f method;
+        if(message-&gt;start_line.method_id &gt;= RECOGNIZER_EVENT_COUNT) {
+                return FALSE;
+        }
+        
+        method = recog_event_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return recog_event_dispatch(state_machine,message);
+}
+
+/** Update state according to request received from MRCP client or response/event received from recognition engine */
+static apt_bool_t recog_state_update(mrcp_state_machine_t *base, mrcp_message_t *message)
+{
+        mrcp_recog_state_machine_t *state_machine = (mrcp_recog_state_machine_t*)base;
+        apt_bool_t status = TRUE;
+        switch(message-&gt;start_line.message_type) {
+                case MRCP_MESSAGE_TYPE_REQUEST:
+                        status = recog_request_state_update(state_machine,message);
+                        break;
+                case MRCP_MESSAGE_TYPE_RESPONSE:
+                        status = recog_response_state_update(state_machine,message);
+                        break;
+                case MRCP_MESSAGE_TYPE_EVENT:
+                        status = recog_event_state_update(state_machine,message);
+                        break;
+                default:
+                        status = FALSE;
+                        break;
+        }
+        return status;
+}
+
+/** Deactivate state machine */
+static apt_bool_t recog_state_deactivate(mrcp_state_machine_t *base)
+{
+        mrcp_recog_state_machine_t *state_machine = (mrcp_recog_state_machine_t*)base;
+        mrcp_message_t *message;
+        mrcp_message_t *source;
+        if(state_machine-&gt;state != RECOGNIZER_STATE_RECOGNIZING) {
+                /* no in-progress RECOGNIZE request to deactivate */
+                return FALSE;
+        }
+        source = state_machine-&gt;recog;
+        if(!source) {
+                return FALSE;
+        }
+
+        /* create internal STOP request */
+        message = mrcp_request_create(
+                                                source-&gt;resource,
+                                                source-&gt;start_line.version,
+                                                RECOGNIZER_STOP,
+                                                source-&gt;pool);
+        message-&gt;channel_id = source-&gt;channel_id;
+        message-&gt;start_line.request_id = source-&gt;start_line.request_id + 1;
+        apt_string_set(&amp;message-&gt;start_line.method_name,&quot;DEACTIVATE&quot;); /* informative only */
+        message-&gt;header = source-&gt;header;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create and Process STOP Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recog_request_dispatch(state_machine,message);
+}
+
+/** Create MRCP recognizer state machine */
+mrcp_state_machine_t* mrcp_recog_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
+{
+        mrcp_message_header_t *properties;
+        mrcp_recog_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_recog_state_machine_t));
+        mrcp_state_machine_init(&amp;state_machine-&gt;base,obj);
+        state_machine-&gt;base.update = recog_state_update;
+        state_machine-&gt;base.deactivate = recog_state_deactivate;
+        state_machine-&gt;state = RECOGNIZER_STATE_IDLE;
+        state_machine-&gt;is_pending = FALSE;
+        state_machine-&gt;active_request = NULL;
+        state_machine-&gt;recog = NULL;
+        state_machine-&gt;queue = apt_list_create(pool);
+        properties = &amp;state_machine-&gt;properties;
+        mrcp_message_header_init(properties);
+        properties-&gt;generic_header_accessor.vtable = mrcp_generic_header_vtable_get(version);
+        properties-&gt;resource_header_accessor.vtable = mrcp_recog_header_vtable_get(version);
+        return &amp;state_machine-&gt;base;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_recorder_state_machinec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,392 @@
</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;apt_obj_list.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;mrcp_recorder_state_machine.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_recorder_header.h&quot;
+#include &quot;mrcp_recorder_resource.h&quot;
+#include &quot;mrcp_message.h&quot;
+
+/** MRCP recorder states */
+typedef enum {
+        RECORDER_STATE_IDLE,
+        RECORDER_STATE_RECORDING,
+
+        RECORDER_STATE_COUNT
+} mrcp_recorder_state_e;
+
+static const char * state_names[RECORDER_STATE_COUNT] = {
+        &quot;IDLE&quot;,
+        &quot;RECORDING&quot;,
+};
+
+typedef struct mrcp_recorder_state_machine_t mrcp_recorder_state_machine_t;
+
+struct mrcp_recorder_state_machine_t {
+        /** state machine base */
+        mrcp_state_machine_t  base;
+        /** recorder state */
+        mrcp_recorder_state_e state;
+        /** request sent to recorder engine and waiting for the response to be received */
+        mrcp_message_t       *active_request;
+        /** in-progress record request */
+        mrcp_message_t       *record;
+        /** properties used in set/get params */
+        mrcp_message_header_t properties;
+};
+
+typedef apt_bool_t (*recorder_method_f)(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message);
+
+static APR_INLINE apt_bool_t recorder_request_dispatch(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        state_machine-&gt;active_request = message;
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE apt_bool_t recorder_response_dispatch(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        state_machine-&gt;active_request = NULL;
+        if(state_machine-&gt;base.active == FALSE) {
+                /* this is the response to deactivation (STOP) request */
+                return state_machine-&gt;base.on_deactivate(&amp;state_machine-&gt;base);
+        }
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE apt_bool_t recorder_event_dispatch(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;base.active == FALSE) {
+                /* do nothing, state machine has already been deactivated */
+                return FALSE;
+        }
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE void recorder_state_change(mrcp_recorder_state_machine_t *state_machine, mrcp_recorder_state_e state)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;State Transition %s -&gt; %s&quot;,state_names[state_machine-&gt;state],state_names[state]);
+        state_machine-&gt;state = state;
+        if(state == RECORDER_STATE_IDLE) {
+                state_machine-&gt;record = NULL;
+        }
+}
+
+
+static apt_bool_t recorder_request_set_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SET-PARAMS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        mrcp_message_header_set(&amp;state_machine-&gt;properties,&amp;message-&gt;header,message-&gt;pool);
+        return recorder_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_response_set_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SET-PARAMS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recorder_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_request_get_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-PARAMS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recorder_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_response_get_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-PARAMS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        mrcp_message_header_set(&amp;message-&gt;header,&amp;state_machine-&gt;active_request-&gt;header,message-&gt;pool);
+        mrcp_message_header_get(&amp;message-&gt;header,&amp;state_machine-&gt;properties,message-&gt;pool);
+        return recorder_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_request_record(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_header_inherit(&amp;message-&gt;header,&amp;state_machine-&gt;properties,message-&gt;pool);
+        if(state_machine-&gt;state == RECORDER_STATE_RECORDING) {
+                mrcp_message_t *response;
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Reject RECORD Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                
+                /* there is in-progress request, reject this one */
+                response = mrcp_response_create(message,message-&gt;pool);
+                response-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+                return recorder_response_dispatch(state_machine,response);
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RECORD Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recorder_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_response_record(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RECORD Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(message-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
+                state_machine-&gt;record = state_machine-&gt;active_request;
+                recorder_state_change(state_machine,RECORDER_STATE_RECORDING);
+        }
+        return recorder_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_request_stop(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response;
+        if(state_machine-&gt;state == RECORDER_STATE_RECORDING) {
+                /* found in-progress RECORDER request, stop it */
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process STOP Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return recorder_request_dispatch(state_machine,message);
+        }
+
+        /* found no in-progress RECORDER request, sending immediate response */
+        response = mrcp_response_create(message,message-&gt;pool);
+        return recorder_response_dispatch(state_machine,response);
+}
+
+static apt_bool_t recorder_response_stop(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process STOP Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        /* append active id list */
+        active_request_id_list_append(generic_header,state_machine-&gt;record-&gt;start_line.request_id);
+        mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        recorder_state_change(state_machine,RECORDER_STATE_IDLE);
+        return recorder_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_request_start_timers(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response;
+        if(state_machine-&gt;state == RECORDER_STATE_RECORDING) {
+                /* found in-progress request */
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process START-INPUT-TIMERS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return recorder_request_dispatch(state_machine,message);
+        }
+
+        /* found no in-progress request */
+        response = mrcp_response_create(message,message-&gt;pool);
+        response-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+        return recorder_response_dispatch(state_machine,response);
+}
+
+static apt_bool_t recorder_response_start_timers(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process START-INPUT-TIMERS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recorder_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_event_start_of_input(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(!state_machine-&gt;record) {
+                /* unexpected event, no in-progress record request */
+                return FALSE;
+        }
+
+        if(state_machine-&gt;record-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                /* unexpected event */
+                return FALSE;
+        }
+        
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process START-OF-INPUT Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        message-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        return recorder_event_dispatch(state_machine,message);
+}
+
+static apt_bool_t recorder_event_record_complete(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(!state_machine-&gt;record) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unexpected RECORD-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        if(state_machine-&gt;record-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unexpected RECORD-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        if(state_machine-&gt;active_request &amp;&amp; state_machine-&gt;active_request-&gt;start_line.method_id == RECORDER_STOP) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Ignore RECORD-COMPLETE Event [%d]: waiting for STOP response&quot;,message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RECORD-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(mrcp_resource_header_property_check(message,RECORDER_HEADER_COMPLETION_CAUSE) != TRUE) {
+                mrcp_recorder_header_t *recorder_header = mrcp_resource_header_prepare(message);
+                recorder_header-&gt;completion_cause = RECORDER_COMPLETION_CAUSE_SUCCESS_SILENCE;
+                mrcp_resource_header_property_add(message,RECORDER_HEADER_COMPLETION_CAUSE);
+        }
+        recorder_state_change(state_machine,RECORDER_STATE_IDLE);
+        return recorder_event_dispatch(state_machine,message);
+}
+
+static recorder_method_f recorder_request_method_array[RECORDER_METHOD_COUNT] = {
+        recorder_request_set_params,
+        recorder_request_get_params,
+        recorder_request_record,
+        recorder_request_stop,
+        recorder_request_start_timers
+};
+
+static recorder_method_f recorder_response_method_array[RECORDER_METHOD_COUNT] = {
+        recorder_response_set_params,
+        recorder_response_get_params,
+        recorder_response_record,
+        recorder_response_stop,
+        recorder_response_start_timers
+};
+
+static recorder_method_f recorder_event_method_array[RECORDER_EVENT_COUNT] = {
+        recorder_event_start_of_input,
+        recorder_event_record_complete
+};
+
+/** Update state according to received incoming request from MRCP client */
+static apt_bool_t recorder_request_state_update(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        recorder_method_f method;
+        if(message-&gt;start_line.method_id &gt;= RECORDER_METHOD_COUNT) {
+                return FALSE;
+        }
+        
+        method = recorder_request_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return recorder_request_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing response from recorder engine */
+static apt_bool_t recorder_response_state_update(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        recorder_method_f method;
+        if(!state_machine-&gt;active_request) {
+                /* unexpected response, no active request waiting for response */
+                return FALSE;
+        }
+        if(state_machine-&gt;active_request-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                /* unexpected response, request id doesn't match */
+                return FALSE;
+        }
+
+        if(message-&gt;start_line.method_id &gt;= RECORDER_METHOD_COUNT) {
+                return FALSE;
+        }
+        
+        method = recorder_response_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return recorder_response_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing event from recorder engine */
+static apt_bool_t recorder_event_state_update(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        recorder_method_f method;
+        if(message-&gt;start_line.method_id &gt;= RECORDER_EVENT_COUNT) {
+                return FALSE;
+        }
+        
+        method = recorder_event_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return recorder_event_dispatch(state_machine,message);
+}
+
+/** Update state according to request received from MRCP client or response/event received from recorder engine */
+static apt_bool_t recorder_state_update(mrcp_state_machine_t *base, mrcp_message_t *message)
+{
+        mrcp_recorder_state_machine_t *state_machine = (mrcp_recorder_state_machine_t*)base;
+        apt_bool_t status = TRUE;
+        switch(message-&gt;start_line.message_type) {
+                case MRCP_MESSAGE_TYPE_REQUEST:
+                        status = recorder_request_state_update(state_machine,message);
+                        break;
+                case MRCP_MESSAGE_TYPE_RESPONSE:
+                        status = recorder_response_state_update(state_machine,message);
+                        break;
+                case MRCP_MESSAGE_TYPE_EVENT:
+                        status = recorder_event_state_update(state_machine,message);
+                        break;
+                default:
+                        status = FALSE;
+                        break;
+        }
+        return status;
+}
+
+/** Deactivate state machine */
+static apt_bool_t recorder_state_deactivate(mrcp_state_machine_t *base)
+{
+        mrcp_recorder_state_machine_t *state_machine = (mrcp_recorder_state_machine_t*)base;
+        mrcp_message_t *message;
+        mrcp_message_t *source;
+        if(state_machine-&gt;state != RECORDER_STATE_RECORDING) {
+                /* no in-progress RECORD request to deactivate */
+                return FALSE;
+        }
+        source = state_machine-&gt;record;
+        if(!source) {
+                return FALSE;
+        }
+
+        /* create internal STOP request */
+        message = mrcp_request_create(
+                                                source-&gt;resource,
+                                                source-&gt;start_line.version,
+                                                RECORDER_STOP,
+                                                source-&gt;pool);
+        message-&gt;channel_id = source-&gt;channel_id;
+        message-&gt;start_line.request_id = source-&gt;start_line.request_id + 1;
+        apt_string_set(&amp;message-&gt;start_line.method_name,&quot;DEACTIVATE&quot;); /* informative only */
+        message-&gt;header = source-&gt;header;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create and Process STOP Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return recorder_request_dispatch(state_machine,message);
+}
+
+/** Create MRCP recorder state machine */
+mrcp_state_machine_t* mrcp_recorder_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
+{
+        mrcp_message_header_t *properties;
+        mrcp_recorder_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_recorder_state_machine_t));
+        mrcp_state_machine_init(&amp;state_machine-&gt;base,obj);
+        state_machine-&gt;base.update = recorder_state_update;
+        state_machine-&gt;base.deactivate = recorder_state_deactivate;
+        state_machine-&gt;state = RECORDER_STATE_IDLE;
+        state_machine-&gt;active_request = NULL;
+        state_machine-&gt;record = NULL;
+        properties = &amp;state_machine-&gt;properties;
+        mrcp_message_header_init(properties);
+        properties-&gt;generic_header_accessor.vtable = mrcp_generic_header_vtable_get(version);
+        properties-&gt;resource_header_accessor.vtable = mrcp_recorder_header_vtable_get(version);
+        return &amp;state_machine-&gt;base;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_resource_enginec"></a>
<div class="delfile"><h4>Deleted: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_resource_engine.c</h4></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpenginesrcmrcp_synth_state_machinec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,620 @@
</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;apt_obj_list.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;mrcp_state_machine.h&quot;
+#include &quot;mrcp_synth_state_machine.h&quot;
+#include &quot;mrcp_synth_header.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_synth_resource.h&quot;
+#include &quot;mrcp_message.h&quot;
+
+/** MRCP synthesizer states */
+typedef enum {
+        SYNTHESIZER_STATE_IDLE,
+        SYNTHESIZER_STATE_SPEAKING,
+        SYNTHESIZER_STATE_PAUSED,
+
+        SYNTHESIZER_STATE_COUNT
+} mrcp_synth_state_e;
+
+static const char * state_names[SYNTHESIZER_STATE_COUNT] = {
+        &quot;IDLE&quot;,
+        &quot;SPEAKING&quot;,
+        &quot;PAUSED&quot;
+};
+
+typedef struct mrcp_synth_state_machine_t mrcp_synth_state_machine_t;
+struct mrcp_synth_state_machine_t {
+        /** state machine base */
+        mrcp_state_machine_t  base;
+        /** synthesizer state */
+        mrcp_synth_state_e    state;
+        /** indicate whether active_request was processed from pending request queue */
+        apt_bool_t            is_pending;
+        /** request sent to synthesizer engine and waiting for the response to be received */
+        mrcp_message_t       *active_request;
+        /** in-progress speak request */
+        mrcp_message_t       *speaker;
+        /** queue of pending speak requests */
+        apt_obj_list_t       *queue;
+        /** properties used in set/get params */
+        mrcp_message_header_t properties;
+};
+
+typedef apt_bool_t (*synth_method_f)(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message);
+
+static APR_INLINE apt_bool_t synth_request_dispatch(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        state_machine-&gt;active_request = message;
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE apt_bool_t synth_response_dispatch(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        state_machine-&gt;active_request = NULL;
+        if(state_machine-&gt;base.active == FALSE) {
+                /* this is the response to deactivation (STOP) request */
+                return state_machine-&gt;base.on_deactivate(&amp;state_machine-&gt;base);
+        }
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE apt_bool_t synth_event_dispatch(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;base.active == FALSE) {
+                /* do nothing, state machine has already been deactivated */
+                return FALSE;
+        }
+        return state_machine-&gt;base.on_dispatch(&amp;state_machine-&gt;base,message);
+}
+
+static APR_INLINE void synth_state_change(mrcp_synth_state_machine_t *state_machine, mrcp_synth_state_e state)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;State Transition %s -&gt; %s&quot;,state_names[state_machine-&gt;state],state_names[state]);
+        state_machine-&gt;state = state;
+        if(state == SYNTHESIZER_STATE_IDLE) {
+                state_machine-&gt;speaker = NULL;
+        }
+}
+
+
+static apt_bool_t synth_request_set_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SET-PARAMS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        mrcp_message_header_set(&amp;state_machine-&gt;properties,&amp;message-&gt;header,message-&gt;pool);
+        return synth_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_response_set_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SET-PARAMS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return synth_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_request_get_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-PARAMS Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return synth_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_response_get_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process GET-PARAMS Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        mrcp_message_header_set(&amp;message-&gt;header,&amp;state_machine-&gt;active_request-&gt;header,message-&gt;pool);
+        mrcp_message_header_get(&amp;message-&gt;header,&amp;state_machine-&gt;properties,message-&gt;pool);
+        return synth_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_request_speak(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_header_inherit(&amp;message-&gt;header,&amp;state_machine-&gt;properties,message-&gt;pool);
+        if(state_machine-&gt;speaker) {
+                mrcp_message_t *response;
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Queue Up SPEAK Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                message-&gt;start_line.request_state = MRCP_REQUEST_STATE_PENDING;
+                apt_list_push_back(state_machine-&gt;queue,message,message-&gt;pool);
+                
+                response = mrcp_response_create(message,message-&gt;pool);
+                response-&gt;start_line.request_state = MRCP_REQUEST_STATE_PENDING;
+                return synth_response_dispatch(state_machine,response);
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SPEAK Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return synth_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_response_speak(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SPEAK Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(message-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
+                state_machine-&gt;speaker = state_machine-&gt;active_request;
+                synth_state_change(state_machine,SYNTHESIZER_STATE_SPEAKING);
+        }
+        if(state_machine-&gt;is_pending == TRUE) {
+                mrcp_message_t *event_message = mrcp_event_create(
+                                                        state_machine-&gt;active_request,
+                                                        SYNTHESIZER_SPEECH_MARKER,
+                                                        state_machine-&gt;active_request-&gt;pool);
+                event_message-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+                state_machine-&gt;is_pending = FALSE;
+                /* not to send the response for pending request, instead send SPEECH-MARKER event */
+                return synth_event_dispatch(state_machine,event_message);
+        }
+        return synth_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_pending_requests_remove(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *request_message, mrcp_message_t *response_message)
+{
+        apt_list_elem_t *elem;
+        mrcp_message_t *pending_message;
+        mrcp_request_id_list_t *request_id_list = NULL;
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request_message);
+        mrcp_generic_header_t *response_generic_header = mrcp_generic_header_prepare(response_message);
+        if(generic_header &amp;&amp; mrcp_generic_header_property_check(request_message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) {
+                if(generic_header-&gt;active_request_id_list.ids &amp;&amp; generic_header-&gt;active_request_id_list.count) {
+                        /* selective STOP request */
+                        request_id_list = &amp;generic_header-&gt;active_request_id_list;
+                }
+        }
+
+        elem = apt_list_first_elem_get(state_machine-&gt;queue);
+        while(elem) {
+                pending_message = apt_list_elem_object_get(elem);
+                if(!request_id_list || active_request_id_list_find(generic_header,pending_message-&gt;start_line.request_id) == TRUE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove Pending SPEAK Request [%d]&quot;,pending_message-&gt;start_line.request_id);
+                        elem = apt_list_elem_remove(state_machine-&gt;queue,elem);
+                        /* append active id list */
+                        active_request_id_list_append(response_generic_header,pending_message-&gt;start_line.request_id);
+                }
+                else {
+                        /* speak request remains in the queue, just proceed to the next one */
+                        elem = apt_list_next_elem_get(state_machine-&gt;queue,elem);
+                }
+        }
+        if(response_generic_header-&gt;active_request_id_list.count) {
+                mrcp_generic_header_property_add(response_message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        }
+        return TRUE;
+}
+
+static apt_bool_t synth_request_stop(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;speaker) {
+                mrcp_request_id_list_t *request_id_list = NULL;
+                mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
+                if(generic_header &amp;&amp; mrcp_generic_header_property_check(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST) == TRUE) {
+                        if(generic_header-&gt;active_request_id_list.ids &amp;&amp; generic_header-&gt;active_request_id_list.count) {
+                                /* selective STOP request */
+                                request_id_list = &amp;generic_header-&gt;active_request_id_list;
+                        }
+                }
+
+                if(!request_id_list || active_request_id_list_find(generic_header,state_machine-&gt;speaker-&gt;start_line.request_id) == TRUE) {
+                        /* found in-progress SPEAK request, stop it */
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process STOP Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                                message-&gt;start_line.request_id);
+                        return synth_request_dispatch(state_machine,message);
+                }
+        }
+
+        /* found no in-progress SPEAK request, sending immediate response */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        synth_pending_requests_remove(state_machine,message,response_message);
+        return synth_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t synth_response_stop(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *pending_request;
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process STOP Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        /* append active id list */
+        active_request_id_list_append(generic_header,state_machine-&gt;speaker-&gt;start_line.request_id);
+        mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        synth_pending_requests_remove(state_machine,state_machine-&gt;active_request,message);
+        synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE);
+        pending_request = apt_list_pop_front(state_machine-&gt;queue);
+        synth_response_dispatch(state_machine,message);
+
+        /* process pending SPEAK requests / if any */
+        if(pending_request) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process Pending SPEAK Request [%d]&quot;,pending_request-&gt;start_line.request_id);
+                state_machine-&gt;is_pending = TRUE;
+                synth_request_dispatch(state_machine,pending_request);
+        }
+        return TRUE;
+}
+
+static apt_bool_t synth_request_pause(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;speaker) {
+                /* speaking or paused state */
+                if(state_machine-&gt;state == SYNTHESIZER_STATE_SPEAKING) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process PAUSE Request [%d]&quot;,state_machine-&gt;speaker-&gt;start_line.request_id);
+                        synth_request_dispatch(state_machine,message);
+                }
+                else {
+                        /* paused state */
+                        mrcp_message_t *response_message = mrcp_response_create(message,message-&gt;pool);
+                        synth_response_dispatch(state_machine,response_message);
+                }
+        }
+        else {
+                /* idle state */
+                mrcp_message_t *response_message = mrcp_response_create(message,message-&gt;pool);
+                response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+                synth_response_dispatch(state_machine,response_message);
+        }
+        return TRUE;
+}
+
+static apt_bool_t synth_response_pause(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process PAUSE Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(message-&gt;start_line.status_code == MRCP_STATUS_CODE_SUCCESS) {
+                mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+                /* append active id list */
+                active_request_id_list_append(generic_header,state_machine-&gt;speaker-&gt;start_line.request_id);
+                mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+                synth_state_change(state_machine,SYNTHESIZER_STATE_PAUSED);
+        }
+        synth_response_dispatch(state_machine,message);
+        return TRUE;
+}
+
+static apt_bool_t synth_request_resume(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(state_machine-&gt;speaker) {
+                /* speaking or paused state */
+                if(state_machine-&gt;state == SYNTHESIZER_STATE_PAUSED) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RESUME Request [%d]&quot;,state_machine-&gt;speaker-&gt;start_line.request_id);
+                        synth_request_dispatch(state_machine,message);
+                }
+                else {
+                        /* speaking state */
+                        mrcp_message_t *response_message = mrcp_response_create(message,message-&gt;pool);
+                        synth_response_dispatch(state_machine,response_message);
+                }
+        }
+        else {
+                /* idle state */
+                mrcp_message_t *response_message = mrcp_response_create(message,message-&gt;pool);
+                response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+                synth_response_dispatch(state_machine,response_message);
+        }
+        return TRUE;
+}
+
+static apt_bool_t synth_response_resume(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process RESUME Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(message-&gt;start_line.status_code == MRCP_STATUS_CODE_SUCCESS) {
+                mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+                /* append active id list */
+                active_request_id_list_append(generic_header,state_machine-&gt;speaker-&gt;start_line.request_id);
+                mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+                synth_state_change(state_machine,SYNTHESIZER_STATE_SPEAKING);
+        }
+        synth_response_dispatch(state_machine,message);
+        return TRUE;
+}
+
+static apt_bool_t synth_request_barge_in_occurred(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;speaker) {
+                apt_bool_t kill_on_barge_in = TRUE;
+                mrcp_synth_header_t *synth_header = mrcp_resource_header_get(message);
+                if(synth_header) {
+                        if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_KILL_ON_BARGE_IN) == TRUE) {
+                                kill_on_barge_in = synth_header-&gt;kill_on_barge_in;
+                        }
+                }
+        
+                if(kill_on_barge_in == TRUE) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process BARGE-IN Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                                message-&gt;start_line.request_id);
+                        return synth_request_dispatch(state_machine,message);
+                }
+        }
+
+        /* found no kill-on-bargein enabled in-progress SPEAK request, sending immediate response */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        return synth_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t synth_response_barge_in_occurred(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process BARGE-IN Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        /* append active id list */
+        active_request_id_list_append(generic_header,state_machine-&gt;speaker-&gt;start_line.request_id);
+        mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        synth_pending_requests_remove(state_machine,state_machine-&gt;active_request,message);
+        synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE);
+        return synth_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_request_control(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;state == SYNTHESIZER_STATE_SPEAKING) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process CONTROL Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return synth_request_dispatch(state_machine,message);
+        }
+
+        /* found no in-progress SPEAK request, sending immediate response */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        return synth_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t synth_response_control(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process CONTROL Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        /* append active id list */
+        active_request_id_list_append(generic_header,state_machine-&gt;speaker-&gt;start_line.request_id);
+        mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+        return synth_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_request_define_lexicon(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *response_message;
+        if(state_machine-&gt;state == SYNTHESIZER_STATE_IDLE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process DEFINE-LEXICON Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return synth_request_dispatch(state_machine,message);
+        }
+
+        /* sending failure response */
+        response_message = mrcp_response_create(message,message-&gt;pool);
+        response_message-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+        return synth_response_dispatch(state_machine,response_message);
+}
+
+static apt_bool_t synth_response_define_lexicon(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process DEFINE-LEXICON Response [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return synth_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_event_speech_marker(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        if(!state_machine-&gt;speaker) {
+                /* unexpected event, no in-progress speak request */
+                return FALSE;
+        }
+
+        if(state_machine-&gt;speaker-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                /* unexpected event */
+                return FALSE;
+        }
+        
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SPEECH-MARKER Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        message-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        return synth_event_dispatch(state_machine,message);
+}
+
+static apt_bool_t synth_event_speak_complete(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        mrcp_message_t *pending_request;
+        if(!state_machine-&gt;speaker) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unexpected SPEAK-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        if(state_machine-&gt;speaker-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unexpected SPEAK-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                        message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        if(state_machine-&gt;active_request &amp;&amp; state_machine-&gt;active_request-&gt;start_line.method_id == SYNTHESIZER_STOP) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Ignore SPEAK-COMPLETE Event [%d]: waiting for STOP response&quot;,message-&gt;start_line.request_id);
+                return FALSE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process SPEAK-COMPLETE Event [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
+                mrcp_synth_header_t *synth_header = mrcp_resource_header_prepare(message);
+                synth_header-&gt;completion_cause = SYNTHESIZER_COMPLETION_CAUSE_NORMAL;
+                mrcp_resource_header_property_add(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE);
+        }
+        synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE);
+        synth_event_dispatch(state_machine,message);
+
+        /* process pending SPEAK requests */
+        pending_request = apt_list_pop_front(state_machine-&gt;queue);
+        if(pending_request) {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Process Pending SPEAK Request [%d]&quot;,pending_request-&gt;start_line.request_id);
+                state_machine-&gt;is_pending = TRUE;
+                synth_request_dispatch(state_machine,pending_request);
+        }
+        return TRUE;
+}
+
+static synth_method_f synth_request_method_array[SYNTHESIZER_METHOD_COUNT] = {
+        synth_request_set_params,
+        synth_request_get_params,
+        synth_request_speak,
+        synth_request_stop,
+        synth_request_pause,
+        synth_request_resume,
+        synth_request_barge_in_occurred,
+        synth_request_control,
+        synth_request_define_lexicon
+};
+
+static synth_method_f synth_response_method_array[SYNTHESIZER_METHOD_COUNT] = {
+        synth_response_set_params,
+        synth_response_get_params,
+        synth_response_speak,
+        synth_response_stop,
+        synth_response_pause,
+        synth_response_resume,
+        synth_response_barge_in_occurred,
+        synth_response_control,
+        synth_response_define_lexicon,
+};
+
+static synth_method_f synth_event_method_array[SYNTHESIZER_EVENT_COUNT] = {
+        synth_event_speech_marker,
+        synth_event_speak_complete
+};
+
+/** Update state according to received incoming request from MRCP client */
+static apt_bool_t synth_request_state_update(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        synth_method_f method;
+        if(message-&gt;start_line.method_id &gt;= SYNTHESIZER_METHOD_COUNT) {
+                return FALSE;
+        }
+        
+        method = synth_request_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return synth_request_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing response from synthesizer engine */
+static apt_bool_t synth_response_state_update(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        synth_method_f method;
+        if(!state_machine-&gt;active_request) {
+                /* unexpected response, no active request waiting for response */
+                return FALSE;
+        }
+        if(state_machine-&gt;active_request-&gt;start_line.request_id != message-&gt;start_line.request_id) {
+                /* unexpected response, request id doesn't match */
+                return FALSE;
+        }
+
+        if(message-&gt;start_line.method_id &gt;= SYNTHESIZER_METHOD_COUNT) {
+                return FALSE;
+        }
+        
+        method = synth_response_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return synth_response_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing event from synthesizer engine */
+static apt_bool_t synth_event_state_update(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
+{
+        synth_method_f method;
+        if(message-&gt;start_line.method_id &gt;= SYNTHESIZER_EVENT_COUNT) {
+                return FALSE;
+        }
+        
+        method = synth_event_method_array[message-&gt;start_line.method_id];
+        if(method) {
+                return method(state_machine,message);
+        }
+        return synth_event_dispatch(state_machine,message);
+}
+
+/** Update state according to request received from MRCP client or response/event received from synthesizer engine */
+static apt_bool_t synth_state_update(mrcp_state_machine_t *base, mrcp_message_t *message)
+{
+        mrcp_synth_state_machine_t *synth_state_machine = (mrcp_synth_state_machine_t*)base;
+        apt_bool_t status = TRUE;
+        switch(message-&gt;start_line.message_type) {
+                case MRCP_MESSAGE_TYPE_REQUEST:
+                        status = synth_request_state_update(synth_state_machine,message);
+                        break;
+                case MRCP_MESSAGE_TYPE_RESPONSE:
+                        status = synth_response_state_update(synth_state_machine,message);
+                        break;
+                case MRCP_MESSAGE_TYPE_EVENT:
+                        status = synth_event_state_update(synth_state_machine,message);
+                        break;
+                default:
+                        status = FALSE;
+                        break;
+        }
+        return status;
+}
+
+/** Deactivate state machine */
+static apt_bool_t synth_state_deactivate(mrcp_state_machine_t *base)
+{
+        mrcp_synth_state_machine_t *state_machine = (mrcp_synth_state_machine_t*)base;
+        mrcp_message_t *message;
+        mrcp_message_t *source;
+        if(!state_machine-&gt;speaker) {
+                /* no in-progress SPEAK request to deactivate */
+                return FALSE;
+        }
+        source = state_machine-&gt;speaker;
+
+        /* create internal STOP request */
+        message = mrcp_request_create(
+                                                source-&gt;resource,
+                                                source-&gt;start_line.version,
+                                                SYNTHESIZER_STOP,
+                                                source-&gt;pool);
+        message-&gt;channel_id = source-&gt;channel_id;
+        message-&gt;start_line.request_id = source-&gt;start_line.request_id + 1;
+        apt_string_set(&amp;message-&gt;start_line.method_name,&quot;DEACTIVATE&quot;); /* informative only */
+        message-&gt;header = source-&gt;header;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create and Process STOP Request [%&quot;MRCP_REQUEST_ID_FMT&quot;]&quot;,
+                message-&gt;start_line.request_id);
+        return synth_request_dispatch(state_machine,message);
+}
+
+/** Create MRCP synthesizer state machine */
+mrcp_state_machine_t* mrcp_synth_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
+{
+        mrcp_message_header_t *properties;
+        mrcp_synth_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_synth_state_machine_t));
+        mrcp_state_machine_init(&amp;state_machine-&gt;base,obj);
+        state_machine-&gt;base.update = synth_state_update;
+        state_machine-&gt;base.deactivate = synth_state_deactivate;
+        state_machine-&gt;state = SYNTHESIZER_STATE_IDLE;
+        state_machine-&gt;is_pending = FALSE;
+        state_machine-&gt;active_request = NULL;
+        state_machine-&gt;speaker = NULL;
+        state_machine-&gt;queue = apt_list_create(pool);
+        properties = &amp;state_machine-&gt;properties;
+        mrcp_message_header_init(properties);
+        properties-&gt;generic_header_accessor.vtable = mrcp_generic_header_vtable_get(version);
+        properties-&gt;resource_header_accessor.vtable = mrcp_synth_header_vtable_get(version);
+        return &amp;state_machine-&gt;base;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpserverincludemrcp_serverh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><span class="cx"> #include &quot;mrcp_server_types.h&quot;
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
</del><ins>+#include &quot;mrcp_engine_iface.h&quot;
</ins><span class="cx"> #include &quot;apt_task.h&quot;
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="lines">@@ -62,12 +62,12 @@
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_server_resource_factory_register(mrcp_server_t *server, mrcp_resource_factory_t *resource_factory);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Register MRCP resource engine.
</del><ins>+ * Register MRCP engine.
</ins><span class="cx">  * @param server the MRCP server to set engine for
</span><del>- * @param engine the resource engine to set
- * @param name the name of the resource engine
</del><ins>+ * @param engine the engine to set
+ * @param config the config of the engine
</ins><span class="cx">  */
</span><del>-MRCP_DECLARE(apt_bool_t) mrcp_server_resource_engine_register(mrcp_server_t *server, mrcp_resource_engine_t *engine, const char *name);
</del><ins>+MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(mrcp_server_t *server, mrcp_engine_t *engine, mrcp_engine_config_t *config);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Register codec manager.
</span><span class="lines">@@ -127,7 +127,7 @@
</span><span class="cx">  * Register MRCP profile.
</span><span class="cx">  * @param server the MRCP server to set profile for
</span><span class="cx">  * @param profile the profile to set
</span><del>- * @param plugin_map the map of resource engines (plugins)
</del><ins>+ * @param plugin_map the map of engines (plugins)
</ins><span class="cx">  * @param name the name of the profile
</span><span class="cx">  */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_server_profile_register(
</span><span class="lines">@@ -137,12 +137,12 @@
</span><span class="cx">                                                                         const char *name);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Register resource engine plugin.
</del><ins>+ * Register MRCP engine plugin.
</ins><span class="cx">  * @param server the MRCP server to set engine for
</span><span class="cx">  * @param path the path to plugin
</span><del>- * @param name the name of the plugin
</del><ins>+ * @param config the config of the plugin
</ins><span class="cx">  */
</span><del>-MRCP_DECLARE(apt_bool_t) mrcp_server_plugin_register(mrcp_server_t *server, const char *path, const char *name);
</del><ins>+MRCP_DECLARE(apt_bool_t) mrcp_server_plugin_register(mrcp_server_t *server, const char *path, mrcp_engine_config_t *config);
</ins><span class="cx"> 
</span><span class="cx"> /**
</span><span class="cx">  * Get memory pool.
</span><span class="lines">@@ -151,13 +151,6 @@
</span><span class="cx"> MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(mrcp_server_t *server);
</span><span class="cx"> 
</span><span class="cx"> /**
</span><del>- * Get resource engine by name.
- * @param server the MRCP server to get resource engine from
- * @param name the name of the resource engine to lookup
- */
-MRCP_DECLARE(mrcp_resource_engine_t*) mrcp_server_resource_engine_get(mrcp_server_t *server, const char *name);
-
-/**
</del><span class="cx">  * Get media engine by name.
</span><span class="cx">  * @param server the MRCP server to get media engine from
</span><span class="cx">  * @param name the name of the media engine to lookup
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpserverincludemrcp_server_sessionh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -24,7 +24,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &lt;apr_hash.h&gt;
</span><span class="cx"> #include &quot;mrcp_session.h&quot;
</span><del>-#include &quot;mpf_message.h&quot;
</del><ins>+#include &quot;mpf_engine.h&quot;
</ins><span class="cx"> #include &quot;apt_task.h&quot;
</span><span class="cx"> #include &quot;apt_obj_list.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -61,45 +61,55 @@
</span><span class="cx">         mrcp_message_t               *message;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+/** Server session states */
+typedef enum {
+        SESSION_STATE_NONE,              /**&lt; initial state */
+        SESSION_STATE_GENERATING_ANSWER, /**&lt; received offer, generating answer now */
+        SESSION_STATE_INITIALIZING,      /**&lt; answer is ready, finally initializing channels now */
+        SESSION_STATE_DEACTIVATING,      /**&lt; received session termination request, deinitializing channels now */
+        SESSION_STATE_TERMINATING        /**&lt; finally terminating session */
+} mrcp_server_session_state_e;
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> /** MRCP server session */
</span><span class="cx"> struct mrcp_server_session_t {
</span><span class="cx">         /** Session base */
</span><del>-        mrcp_session_t             base;
</del><ins>+        mrcp_session_t              base;
</ins><span class="cx">         /** MRCP server */
</span><del>-        mrcp_server_t             *server;
</del><ins>+        mrcp_server_t              *server;
</ins><span class="cx">         /** MRCP profile */
</span><del>-        mrcp_profile_t            *profile;
</del><ins>+        mrcp_profile_t             *profile;
</ins><span class="cx"> 
</span><span class="cx">         /** Media context */
</span><del>-        mpf_context_t             *context;
</del><ins>+        mpf_context_t              *context;
</ins><span class="cx"> 
</span><span class="cx">         /** Media termination array */
</span><del>-        apr_array_header_t        *terminations;
</del><ins>+        apr_array_header_t         *terminations;
</ins><span class="cx">         /** MRCP control channel array */
</span><del>-        apr_array_header_t        *channels;
</del><ins>+        apr_array_header_t         *channels;
</ins><span class="cx"> 
</span><span class="cx">         /** In-progress signaling request */
</span><del>-        mrcp_signaling_message_t  *active_request;
</del><ins>+        mrcp_signaling_message_t   *active_request;
</ins><span class="cx">         /** Signaling request queue */
</span><del>-        apt_obj_list_t            *request_queue;
</del><ins>+        apt_obj_list_t             *request_queue;
</ins><span class="cx"> 
</span><span class="cx">         /** In-progress offer */
</span><del>-        mrcp_session_descriptor_t *offer;
</del><ins>+        mrcp_session_descriptor_t  *offer;
</ins><span class="cx">         /** In-progres answer */
</span><del>-        mrcp_session_descriptor_t *answer;
</del><ins>+        mrcp_session_descriptor_t  *answer;
</ins><span class="cx"> 
</span><del>-        /** Number of in-progress answer requests (flags) */
-        apr_size_t                 answer_flag_count;
-        /** Number of in-progress terminate requests (flags) */
-        apr_size_t                 terminate_flag_count;
-        /** Number of in-progress deactivare requests (flags) */
-        apr_size_t                 deactivate_flag_count;
</del><ins>+        /** MPF task message, which construction is in progress */
+        mpf_task_msg_t             *mpf_task_msg;
+
+        /** Session state */
+        mrcp_server_session_state_e state;
+        /** Number of in-progress sub requests */
+        apr_size_t                  subrequest_count;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** MRCP profile */
</span><span class="cx"> struct mrcp_profile_t {
</span><del>-        /** Table of resource engines (mrcp_resource_engine_t*) */
</del><ins>+        /** Table of engines (mrcp_engine_t*) */
</ins><span class="cx">         apr_hash_t                *engine_table;
</span><span class="cx">         /** MRCP resource factory */
</span><span class="cx">         mrcp_resource_factory_t   *resource_factory;
</span><span class="lines">@@ -114,12 +124,12 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Create server session */
</span><del>-mrcp_server_session_t* mrcp_server_session_create();
</del><ins>+mrcp_server_session_t* mrcp_server_session_create(void);
</ins><span class="cx"> 
</span><span class="cx"> /** Process signaling message */
</span><span class="cx"> apt_bool_t mrcp_server_signaling_message_process(mrcp_signaling_message_t *signaling_message);
</span><span class="cx"> /** Process MPF message */
</span><del>-apt_bool_t mrcp_server_mpf_message_process(mpf_message_t *mpf_message);
</del><ins>+apt_bool_t mrcp_server_mpf_message_process(mpf_message_container_t *mpf_message_container);
</ins><span class="cx"> 
</span><span class="cx"> /** Process channel modify event */
</span><span class="cx"> apt_bool_t mrcp_server_on_channel_modify(mrcp_channel_t *channel, mrcp_control_descriptor_t *answer, apt_bool_t status);
</span><span class="lines">@@ -127,6 +137,8 @@
</span><span class="cx"> apt_bool_t mrcp_server_on_channel_remove(mrcp_channel_t *channel, apt_bool_t status);
</span><span class="cx"> /** Process channel message receive */
</span><span class="cx"> apt_bool_t mrcp_server_on_channel_message(mrcp_channel_t *channel, mrcp_message_t *message);
</span><ins>+/** Process connection disconnect event */
+apt_bool_t mrcp_server_on_disconnect(mrcp_channel_t *channel);
</ins><span class="cx"> 
</span><span class="cx"> /** Process channel open event */
</span><span class="cx"> apt_bool_t mrcp_server_on_engine_channel_open(mrcp_channel_t *channel, apt_bool_t status);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpserversrcmrcp_serverc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -14,11 +14,13 @@
</span><span class="cx">  * limitations under the License.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#include &lt;apr_dso.h&gt;
</del><span class="cx"> #include &quot;mrcp_server.h&quot;
</span><span class="cx"> #include &quot;mrcp_server_session.h&quot;
</span><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_resource_factory.h&quot;
</span><ins>+#include &quot;mrcp_resource.h&quot;
+#include &quot;mrcp_engine_factory.h&quot;
+#include &quot;mrcp_engine_loader.h&quot;
</ins><span class="cx"> #include &quot;mrcp_sig_agent.h&quot;
</span><span class="cx"> #include &quot;mrcp_server_connection.h&quot;
</span><span class="cx"> #include &quot;mpf_engine.h&quot;
</span><span class="lines">@@ -36,10 +38,13 @@
</span><span class="cx"> 
</span><span class="cx">         /** MRCP resource factory */
</span><span class="cx">         mrcp_resource_factory_t *resource_factory;
</span><ins>+        /** MRCP engine factory */
+        mrcp_engine_factory_t   *engine_factory;
+        /** Loader of plugins for MRCP engines */
+        mrcp_engine_loader_t    *engine_loader;
+
</ins><span class="cx">         /** Codec manager */
</span><span class="cx">         mpf_codec_manager_t     *codec_manager;
</span><del>-        /** Table of resource engines (mrcp_resource_engine_t*) */
-        apr_hash_t              *resource_engine_table;
</del><span class="cx">         /** Table of media processing engines (mpf_engine_t*) */
</span><span class="cx">         apr_hash_t              *media_engine_table;
</span><span class="cx">         /** Table of RTP termination factories (mpf_termination_factory_t*) */
</span><span class="lines">@@ -50,16 +55,14 @@
</span><span class="cx">         apr_hash_t              *cnt_agent_table;
</span><span class="cx">         /** Table of profiles (mrcp_profile_t*) */
</span><span class="cx">         apr_hash_t              *profile_table;
</span><del>-        /** Table of plugins (apr_dso_handle_t*) */
-        apr_hash_t              *plugin_table;
</del><span class="cx"> 
</span><span class="cx">         /** Table of sessions */
</span><span class="cx">         apr_hash_t              *session_table;
</span><span class="cx"> 
</span><span class="cx">         /** Connection task message pool */
</span><span class="cx">         apt_task_msg_pool_t     *connection_msg_pool;
</span><del>-        /** Resource engine task message pool */
-        apt_task_msg_pool_t     *resource_engine_msg_pool;
</del><ins>+        /** Engine task message pool */
+        apt_task_msg_pool_t     *engine_msg_pool;
</ins><span class="cx"> 
</span><span class="cx">         /** Dir layout structure */
</span><span class="cx">         apt_dir_layout_t        *dir_layout;
</span><span class="lines">@@ -73,7 +76,7 @@
</span><span class="cx"> typedef enum {
</span><span class="cx">         MRCP_SERVER_SIGNALING_TASK_MSG = TASK_MSG_USER,
</span><span class="cx">         MRCP_SERVER_CONNECTION_TASK_MSG,
</span><del>-        MRCP_SERVER_RESOURCE_ENGINE_TASK_MSG,
</del><ins>+        MRCP_SERVER_ENGINE_TASK_MSG,
</ins><span class="cx">         MRCP_SERVER_MEDIA_TASK_MSG
</span><span class="cx"> } mrcp_server_task_msg_type_e;
</span><span class="cx"> 
</span><span class="lines">@@ -95,7 +98,7 @@
</span><span class="cx">         CONNECTION_AGENT_TASK_MSG_MODIFY_CHANNEL,
</span><span class="cx">         CONNECTION_AGENT_TASK_MSG_REMOVE_CHANNEL,
</span><span class="cx">         CONNECTION_AGENT_TASK_MSG_RECEIVE_MESSAGE,
</span><del>-        CONNECTION_AGENT_TASK_MSG_TERMINATE
</del><ins>+        CONNECTION_AGENT_TASK_MSG_DISCONNECT
</ins><span class="cx"> } connection_agent_task_msg_type_e;
</span><span class="cx"> 
</span><span class="cx"> typedef struct connection_agent_task_msg_data_t connection_agent_task_msg_data_t;
</span><span class="lines">@@ -110,24 +113,26 @@
</span><span class="cx"> static apt_bool_t mrcp_server_channel_modify_signal(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status);
</span><span class="cx"> static apt_bool_t mrcp_server_channel_remove_signal(mrcp_control_channel_t *channel, apt_bool_t status);
</span><span class="cx"> static apt_bool_t mrcp_server_message_signal(mrcp_control_channel_t *channel, mrcp_message_t *message);
</span><ins>+static apt_bool_t mrcp_server_disconnect_signal(mrcp_control_channel_t *channel);
</ins><span class="cx"> 
</span><span class="cx"> static const mrcp_connection_event_vtable_t connection_method_vtable = {
</span><span class="cx">         mrcp_server_channel_add_signal,
</span><span class="cx">         mrcp_server_channel_modify_signal,
</span><span class="cx">         mrcp_server_channel_remove_signal,
</span><del>-        mrcp_server_message_signal
</del><ins>+        mrcp_server_message_signal,
+        mrcp_server_disconnect_signal
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-/* Resource engine interface */
</del><ins>+/* MRCP engine interface */
</ins><span class="cx"> typedef enum {
</span><del>-        RESOURCE_ENGINE_TASK_MSG_OPEN_CHANNEL,
-        RESOURCE_ENGINE_TASK_MSG_CLOSE_CHANNEL,
-        RESOURCE_ENGINE_TASK_MSG_MESSAGE
-} resource_engine_task_msg_type_e;
</del><ins>+        ENGINE_TASK_MSG_OPEN_CHANNEL,
+        ENGINE_TASK_MSG_CLOSE_CHANNEL,
+        ENGINE_TASK_MSG_MESSAGE
+} engine_task_msg_type_e;
</ins><span class="cx"> 
</span><del>-typedef struct resource_engine_task_msg_data_t resource_engine_task_msg_data_t;
-struct resource_engine_task_msg_data_t {
</del><ins>+typedef struct engine_task_msg_data_t engine_task_msg_data_t;
+struct engine_task_msg_data_t {
</ins><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         apt_bool_t      status;
</span><span class="cx">         mrcp_message_t *mrcp_message;
</span><span class="lines">@@ -170,16 +175,16 @@
</span><span class="cx">         server-&gt;pool = pool;
</span><span class="cx">         server-&gt;dir_layout = dir_layout;
</span><span class="cx">         server-&gt;resource_factory = NULL;
</span><del>-        server-&gt;resource_engine_table = NULL;
</del><ins>+        server-&gt;engine_factory = NULL;
+        server-&gt;engine_loader = NULL;
</ins><span class="cx">         server-&gt;media_engine_table = NULL;
</span><span class="cx">         server-&gt;rtp_factory_table = NULL;
</span><span class="cx">         server-&gt;sig_agent_table = NULL;
</span><span class="cx">         server-&gt;cnt_agent_table = NULL;
</span><span class="cx">         server-&gt;profile_table = NULL;
</span><del>-        server-&gt;plugin_table = NULL;
</del><span class="cx">         server-&gt;session_table = NULL;
</span><span class="cx">         server-&gt;connection_msg_pool = NULL;
</span><del>-        server-&gt;resource_engine_msg_pool = NULL;
</del><ins>+        server-&gt;engine_msg_pool = NULL;
</ins><span class="cx"> 
</span><span class="cx">         msg_pool = apt_task_msg_pool_create_dynamic(0,pool);
</span><span class="cx"> 
</span><span class="lines">@@ -197,14 +202,15 @@
</span><span class="cx">                 vtable-&gt;on_terminate_complete = mrcp_server_on_terminate_complete;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        server-&gt;resource_engine_table = apr_hash_make(server-&gt;pool);
</del><ins>+        server-&gt;engine_factory = mrcp_engine_factory_create(server-&gt;pool);
+        server-&gt;engine_loader = mrcp_engine_loader_create(server-&gt;pool);
+
</ins><span class="cx">         server-&gt;media_engine_table = apr_hash_make(server-&gt;pool);
</span><span class="cx">         server-&gt;rtp_factory_table = apr_hash_make(server-&gt;pool);
</span><span class="cx">         server-&gt;sig_agent_table = apr_hash_make(server-&gt;pool);
</span><span class="cx">         server-&gt;cnt_agent_table = apr_hash_make(server-&gt;pool);
</span><span class="cx"> 
</span><span class="cx">         server-&gt;profile_table = apr_hash_make(server-&gt;pool);
</span><del>-        server-&gt;plugin_table = apr_hash_make(server-&gt;pool);
</del><span class="cx">         
</span><span class="cx">         server-&gt;session_table = apr_hash_make(server-&gt;pool);
</span><span class="cx">         return server;
</span><span class="lines">@@ -255,6 +261,10 @@
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Invalid Server&quot;);
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><ins>+
+        mrcp_engine_factory_destroy(server-&gt;engine_factory);
+        mrcp_engine_loader_destroy(server-&gt;engine_loader);
+
</ins><span class="cx">         task = apt_consumer_task_base_get(server-&gt;task);
</span><span class="cx">         apt_task_destroy(task);
</span><span class="cx"> 
</span><span class="lines">@@ -273,28 +283,22 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Register MRCP resource engine */
-MRCP_DECLARE(apt_bool_t) mrcp_server_resource_engine_register(mrcp_server_t *server, mrcp_resource_engine_t *engine, const char *name)
</del><ins>+/** Register MRCP engine */
+MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(mrcp_server_t *server, mrcp_engine_t *engine, mrcp_engine_config_t *config)
</ins><span class="cx"> {
</span><del>-        if(!engine || !name) {
</del><ins>+        if(!engine || !config || !config-&gt;name) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        if(!server-&gt;resource_engine_msg_pool) {
-                server-&gt;resource_engine_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(resource_engine_task_msg_data_t),server-&gt;pool);
</del><ins>+        if(!server-&gt;engine_msg_pool) {
+                server-&gt;engine_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(engine_task_msg_data_t),server-&gt;pool);
</ins><span class="cx">         }
</span><ins>+        engine-&gt;config = config;
</ins><span class="cx">         engine-&gt;codec_manager = server-&gt;codec_manager;
</span><span class="cx">         engine-&gt;dir_layout = server-&gt;dir_layout;
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Register Resource Engine [%s]&quot;,name);
-        apr_hash_set(server-&gt;resource_engine_table,name,APR_HASH_KEY_STRING,engine);
-        return TRUE;
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Register MRCP Engine [%s]&quot;,config-&gt;name);
+        return mrcp_engine_factory_engine_register(server-&gt;engine_factory,engine,config-&gt;name);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Get resource engine by name */
-MRCP_DECLARE(mrcp_resource_engine_t*) mrcp_server_resource_engine_get(mrcp_server_t *server, const char *name)
-{
-        return apr_hash_get(server-&gt;resource_engine_table,name,APR_HASH_KEY_STRING);
-}
-
</del><span class="cx"> /** Register codec manager */
</span><span class="cx"> MRCP_DECLARE(apt_bool_t) mrcp_server_codec_manager_register(mrcp_server_t *server, mpf_codec_manager_t *codec_manager)
</span><span class="cx"> {
</span><span class="lines">@@ -424,48 +428,37 @@
</span><span class="cx"> static apt_bool_t mrcp_server_engine_table_make(mrcp_server_t *server, mrcp_profile_t *profile, apr_table_t *plugin_map)
</span><span class="cx"> {
</span><span class="cx">         int i;
</span><del>-        const apt_str_t *resource_name;
</del><ins>+        mrcp_resource_t *resource;
</ins><span class="cx">         const char *plugin_name = NULL;
</span><del>-        mrcp_resource_engine_t *resource_engine;
</del><ins>+        mrcp_engine_t *engine;
</ins><span class="cx"> 
</span><span class="cx">         profile-&gt;engine_table = apr_hash_make(server-&gt;pool);
</span><span class="cx">         for(i=0; i&lt;MRCP_RESOURCE_TYPE_COUNT; i++) {
</span><del>-                resource_name = mrcp_resource_name_get(server-&gt;resource_factory,i);
-                if(!resource_name) continue;
</del><ins>+                resource = mrcp_resource_get(server-&gt;resource_factory,i);
+                if(!resource) continue;
</ins><span class="cx">                 
</span><del>-                resource_engine = NULL;
</del><ins>+                engine = NULL;
</ins><span class="cx">                 /* first, try to find engine by name specified in plugin map (if available) */
</span><span class="cx">                 if(plugin_map) {
</span><del>-                        plugin_name = apr_table_get(plugin_map,resource_name-&gt;buf);
</del><ins>+                        plugin_name = apr_table_get(plugin_map,resource-&gt;name.buf);
</ins><span class="cx">                         if(plugin_name) {
</span><del>-                                resource_engine = mrcp_server_resource_engine_get(server,plugin_name);
</del><ins>+                                engine = mrcp_engine_factory_engine_get(server-&gt;engine_factory,plugin_name);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><del>-                /* next, if no engine found, try to find the first available engine */
-                if(!resource_engine) {
-                        mrcp_resource_engine_t *cur_engine;
-                        void *val;
-                        apr_hash_index_t *it = apr_hash_first(server-&gt;pool,server-&gt;resource_engine_table);
-                        /* walk through the list of engines */
-                        for(; it; it = apr_hash_next(it)) {
-                                apr_hash_this(it,(void*)&amp;plugin_name,NULL,&amp;val);
-                                cur_engine = val;
-                                if(cur_engine &amp;&amp; cur_engine-&gt;resource_id == (mrcp_resource_id)i) {
-                                        resource_engine = cur_engine;
-                                        break;
-                                }
-                        }
</del><ins>+                /* next, if no engine found or specified, try to find the first available one */
+                if(!engine) {
+                        engine = mrcp_engine_factory_engine_find(server-&gt;engine_factory,i);
</ins><span class="cx">                 }
</span><span class="cx">                 
</span><del>-                if(resource_engine) {
-                        if(plugin_name) {
-                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Assign Resource Engine [%s] [%s]&quot;,resource_name-&gt;buf,plugin_name);
</del><ins>+                if(engine) {
+                        if(engine-&gt;config-&gt;name) {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Assign MRCP Engine [%s] [%s]&quot;,resource-&gt;name.buf,engine-&gt;config-&gt;name);
</ins><span class="cx">                         }
</span><del>-                        apr_hash_set(profile-&gt;engine_table,resource_name-&gt;buf,resource_name-&gt;length,resource_engine);
</del><ins>+                        apr_hash_set(profile-&gt;engine_table,resource-&gt;name.buf,resource-&gt;name.length,engine);
</ins><span class="cx">                 }
</span><span class="cx">                 else {
</span><del>-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Resource Engine Available [%s]&quot;,resource_name-&gt;buf);
</del><ins>+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No MRCP Engine Available [%s]&quot;,resource-&gt;name.buf);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -484,6 +477,10 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         if(!profile-&gt;resource_factory) {
</span><ins>+                if(!server-&gt;resource_factory) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Register Profile: no resources&quot;);
+                        return FALSE;
+                }
</ins><span class="cx">                 profile-&gt;resource_factory = server-&gt;resource_factory;
</span><span class="cx">         }
</span><span class="cx">         mrcp_server_engine_table_make(server,profile,plugin_map);
</span><span class="lines">@@ -517,74 +514,27 @@
</span><span class="cx">         return apr_hash_get(server-&gt;profile_table,name,APR_HASH_KEY_STRING);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Register resource engine plugin */
-MRCP_DECLARE(apt_bool_t) mrcp_server_plugin_register(mrcp_server_t *server, const char *path, const char *name)
</del><ins>+/** Register MRCP engine plugin */
+MRCP_DECLARE(apt_bool_t) mrcp_server_plugin_register(mrcp_server_t *server, const char *path, mrcp_engine_config_t *config)
</ins><span class="cx"> {
</span><del>-        apt_bool_t status = FALSE;
-        apr_dso_handle_t *plugin = NULL;
-        apr_dso_handle_sym_t func_handle = NULL;
-        mrcp_plugin_creator_f plugin_creator = NULL;
-        if(!path || !name) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Register Plugin: no name&quot;);
</del><ins>+        mrcp_engine_t *engine;
+        if(!config) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Register Plugin [%s] [%s]&quot;,path,name);
-        if(apr_dso_load(&amp;plugin,path,server-&gt;pool) == APR_SUCCESS) {
-                if(apr_dso_sym(&amp;func_handle,plugin,MRCP_PLUGIN_ENGINE_SYM_NAME) == APR_SUCCESS) {
-                        if(func_handle) {
-                                plugin_creator = (mrcp_plugin_creator_f)(intptr_t)func_handle;
-                        }
-                }
-                else {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Load DSO Symbol: &quot;MRCP_PLUGIN_ENGINE_SYM_NAME);
-                        apr_dso_unload(plugin);
-                        return FALSE;
-                }
-                
-                if(apr_dso_sym(&amp;func_handle,plugin,MRCP_PLUGIN_LOGGER_SYM_NAME) == APR_SUCCESS) {
-                        if(func_handle) {
-                                apt_logger_t *logger = apt_log_instance_get();
-                                mrcp_plugin_log_accessor_f log_accessor;
-                                log_accessor = (mrcp_plugin_log_accessor_f)(intptr_t)func_handle;
-                                log_accessor(logger);
-                        }
-                }
-        }
-        else {
-                char derr[512] = &quot;&quot;;
-                apr_dso_error(plugin,derr,sizeof(derr));
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Load DSO: %s&quot;, derr);
</del><ins>+        
+        engine = mrcp_engine_loader_plugin_load(server-&gt;engine_loader,path,config-&gt;name);
+        if(!engine) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(plugin_creator) {
-                mrcp_resource_engine_t *engine = plugin_creator(server-&gt;pool);
-                if(engine) {
-                        if(mrcp_plugin_version_check(&amp;engine-&gt;plugin_version)) {
-                                status = TRUE;
-                                mrcp_server_resource_engine_register(server,engine,name);
-                                apr_hash_set(server-&gt;plugin_table,name,APR_HASH_KEY_STRING,plugin);
-                        }
-                        else {
-                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Incompatible Plugin Version [%d.%d.%d] &lt; [&quot;PLUGIN_VERSION_STRING&quot;]&quot;,
-                                        engine-&gt;plugin_version.major,
-                                        engine-&gt;plugin_version.minor,
-                                        engine-&gt;plugin_version.patch);
-                        }
-                }
-                else {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Engine&quot;);
-                }
</del><ins>+        if(!server-&gt;engine_msg_pool) {
+                server-&gt;engine_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(engine_task_msg_data_t),server-&gt;pool);
</ins><span class="cx">         }
</span><del>-        else {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Entry Point Found for Plugin&quot;);
-        }
-
-        if(status == FALSE) {
-                apr_dso_unload(plugin);
-        }
-        return status;
</del><ins>+        engine-&gt;config = config;
+        engine-&gt;codec_manager = server-&gt;codec_manager;
+        engine-&gt;dir_layout = server-&gt;dir_layout;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Register MRCP Engine [%s]&quot;,config-&gt;name);
+        return mrcp_engine_factory_engine_register(server-&gt;engine_factory,engine,config-&gt;name);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(mrcp_server_t *server)
</span><span class="lines">@@ -613,22 +563,13 @@
</span><span class="cx">         return apr_hash_get(server-&gt;session_table,session_id-&gt;buf,session_id-&gt;length);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> static void mrcp_server_on_start_complete(apt_task_t *task)
</span><span class="cx"> {
</span><span class="cx">         apt_consumer_task_t *consumer_task = apt_task_object_get(task);
</span><span class="cx">         mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
</span><del>-        mrcp_resource_engine_t *resource_engine;
-        apr_hash_index_t *it;
-        void *val;
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open Resource Engines&quot;);
-        it = apr_hash_first(server-&gt;pool,server-&gt;resource_engine_table);
-        for(; it; it = apr_hash_next(it)) {
-                apr_hash_this(it,NULL,NULL,&amp;val);
-                resource_engine = val;
-                if(resource_engine) {
-                        mrcp_resource_engine_open(resource_engine);
-                }
-        }
</del><ins>+
+        mrcp_engine_factory_open(server-&gt;engine_factory);
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,SERVER_TASK_NAME&quot; Started&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -636,28 +577,8 @@
</span><span class="cx"> {
</span><span class="cx">         apt_consumer_task_t *consumer_task = apt_task_object_get(task);
</span><span class="cx">         mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
</span><del>-        mrcp_resource_engine_t *resource_engine;
-        apr_dso_handle_t *plugin;
-        apr_hash_index_t *it;
-        void *val;
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close Resource Engines&quot;);
-        it=apr_hash_first(server-&gt;pool,server-&gt;resource_engine_table);
-        for(; it; it = apr_hash_next(it)) {
-                apr_hash_this(it,NULL,NULL,&amp;val);
-                resource_engine = val;
-                if(resource_engine) {
-                        mrcp_resource_engine_close(resource_engine);
-                }
-        }
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Unload Plugins&quot;);
-        it=apr_hash_first(server-&gt;pool,server-&gt;plugin_table);
-        for(; it; it = apr_hash_next(it)) {
-                apr_hash_this(it,NULL,NULL,&amp;val);
-                plugin = val;
-                if(plugin) {
-                        apr_dso_unload(plugin);
-                }
-        }
</del><ins>+
+        mrcp_engine_factory_close(server-&gt;engine_factory);
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,SERVER_TASK_NAME&quot; Terminated&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -696,23 +617,28 @@
</span><span class="cx">                                         mrcp_server_on_channel_message(connection_message-&gt;channel, connection_message-&gt;message);
</span><span class="cx">                                         break;
</span><span class="cx">                                 }
</span><ins>+                                case CONNECTION_AGENT_TASK_MSG_DISCONNECT:
+                                {
+                                        mrcp_server_on_channel_message(connection_message-&gt;channel, connection_message-&gt;message);
+                                        break;
+                                }
</ins><span class="cx">                                 default:
</span><span class="cx">                                         break;
</span><span class="cx">                         }
</span><span class="cx">                         break;
</span><span class="cx">                 }
</span><del>-                case MRCP_SERVER_RESOURCE_ENGINE_TASK_MSG:
</del><ins>+                case MRCP_SERVER_ENGINE_TASK_MSG:
</ins><span class="cx">                 {
</span><del>-                        resource_engine_task_msg_data_t *data = (resource_engine_task_msg_data_t*)msg-&gt;data;
-                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Receive Resource Engine Task Message [%d]&quot;, msg-&gt;sub_type);
</del><ins>+                        engine_task_msg_data_t *data = (engine_task_msg_data_t*)msg-&gt;data;
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Receive Engine Task Message [%d]&quot;, msg-&gt;sub_type);
</ins><span class="cx">                         switch(msg-&gt;sub_type) {
</span><del>-                                case RESOURCE_ENGINE_TASK_MSG_OPEN_CHANNEL:
</del><ins>+                                case ENGINE_TASK_MSG_OPEN_CHANNEL:
</ins><span class="cx">                                         mrcp_server_on_engine_channel_open(data-&gt;channel,data-&gt;status);
</span><span class="cx">                                         break;
</span><del>-                                case RESOURCE_ENGINE_TASK_MSG_CLOSE_CHANNEL:
</del><ins>+                                case ENGINE_TASK_MSG_CLOSE_CHANNEL:
</ins><span class="cx">                                         mrcp_server_on_engine_channel_close(data-&gt;channel);
</span><span class="cx">                                         break;
</span><del>-                                case RESOURCE_ENGINE_TASK_MSG_MESSAGE:
</del><ins>+                                case ENGINE_TASK_MSG_MESSAGE:
</ins><span class="cx">                                         mrcp_server_on_engine_channel_message(data-&gt;channel,data-&gt;mrcp_message);
</span><span class="cx">                                         break;
</span><span class="cx">                                 default:
</span><span class="lines">@@ -722,9 +648,9 @@
</span><span class="cx">                 }
</span><span class="cx">                 case MRCP_SERVER_MEDIA_TASK_MSG:
</span><span class="cx">                 {
</span><del>-                        mpf_message_t *mpf_message = (mpf_message_t*) msg-&gt;data;
-                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Receive Media Task Message [%d]&quot;, mpf_message-&gt;command_id);
-                        mrcp_server_mpf_message_process(mpf_message);
</del><ins>+                        mpf_message_container_t *mpf_message_container = (mpf_message_container_t*) msg-&gt;data;
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Receive Media Task Message&quot;);
+                        mrcp_server_mpf_message_process(mpf_message_container);
</ins><span class="cx">                         break;
</span><span class="cx">                 }
</span><span class="cx">                 default:
</span><span class="lines">@@ -781,7 +707,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mrcp_server_engine_task_msg_signal(
</span><del>-                                                        resource_engine_task_msg_type_e  type,
</del><ins>+                                                        engine_task_msg_type_e  type,
</ins><span class="cx">                                                         mrcp_engine_channel_t           *engine_channel,
</span><span class="cx">                                                         apt_bool_t                       status,
</span><span class="cx">                                                         mrcp_message_t                  *message)
</span><span class="lines">@@ -790,16 +716,16 @@
</span><span class="cx">         mrcp_session_t *session = mrcp_server_channel_session_get(channel);
</span><span class="cx">         mrcp_server_t *server = session-&gt;signaling_agent-&gt;parent;
</span><span class="cx">         apt_task_t *task = apt_consumer_task_base_get(server-&gt;task);
</span><del>-        resource_engine_task_msg_data_t *data;
-        apt_task_msg_t *task_msg = apt_task_msg_acquire(server-&gt;resource_engine_msg_pool);
-        task_msg-&gt;type = MRCP_SERVER_RESOURCE_ENGINE_TASK_MSG;
</del><ins>+        engine_task_msg_data_t *data;
+        apt_task_msg_t *task_msg = apt_task_msg_acquire(server-&gt;engine_msg_pool);
+        task_msg-&gt;type = MRCP_SERVER_ENGINE_TASK_MSG;
</ins><span class="cx">         task_msg-&gt;sub_type = type;
</span><del>-        data = (resource_engine_task_msg_data_t*) task_msg-&gt;data;
</del><ins>+        data = (engine_task_msg_data_t*) task_msg-&gt;data;
</ins><span class="cx">         data-&gt;channel = channel;
</span><span class="cx">         data-&gt;status = status;
</span><span class="cx">         data-&gt;mrcp_message = message;
</span><span class="cx"> 
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Signal Resource Engine Task Message&quot;);
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Signal Engine Task Message&quot;);
</ins><span class="cx">         return apt_task_msg_signal(task,task_msg);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -902,10 +828,22 @@
</span><span class="cx">                                                                 TRUE);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static apt_bool_t mrcp_server_disconnect_signal(mrcp_control_channel_t *channel)
+{
+        mrcp_connection_agent_t *agent = channel-&gt;agent;
+        return mrcp_server_connection_task_msg_signal(
+                                                                CONNECTION_AGENT_TASK_MSG_DISCONNECT,
+                                                                agent,
+                                                                channel,
+                                                                NULL,
+                                                                NULL,
+                                                                TRUE);
+}
+
</ins><span class="cx"> static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel, apt_bool_t status)
</span><span class="cx"> {
</span><span class="cx">         return mrcp_server_engine_task_msg_signal(
</span><del>-                                                                RESOURCE_ENGINE_TASK_MSG_OPEN_CHANNEL,
</del><ins>+                                                                ENGINE_TASK_MSG_OPEN_CHANNEL,
</ins><span class="cx">                                                                 channel,
</span><span class="cx">                                                                 status,
</span><span class="cx">                                                                 NULL);
</span><span class="lines">@@ -914,7 +852,7 @@
</span><span class="cx"> static apt_bool_t mrcp_server_channel_close_signal(mrcp_engine_channel_t *channel)
</span><span class="cx"> {
</span><span class="cx">         return mrcp_server_engine_task_msg_signal(
</span><del>-                                                                RESOURCE_ENGINE_TASK_MSG_CLOSE_CHANNEL,
</del><ins>+                                                                ENGINE_TASK_MSG_CLOSE_CHANNEL,
</ins><span class="cx">                                                                 channel,
</span><span class="cx">                                                                 TRUE,
</span><span class="cx">                                                                 NULL);
</span><span class="lines">@@ -923,7 +861,7 @@
</span><span class="cx"> static apt_bool_t mrcp_server_channel_message_signal(mrcp_engine_channel_t *channel, mrcp_message_t *message)
</span><span class="cx"> {
</span><span class="cx">         return mrcp_server_engine_task_msg_signal(
</span><del>-                                                                RESOURCE_ENGINE_TASK_MSG_MESSAGE,
</del><ins>+                                                                ENGINE_TASK_MSG_MESSAGE,
</ins><span class="cx">                                                                 channel,
</span><span class="cx">                                                                 TRUE,
</span><span class="cx">                                                                 message);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpserversrcmrcp_server_sessionc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -18,16 +18,15 @@
</span><span class="cx"> #include &quot;mrcp_server_session.h&quot;
</span><span class="cx"> #include &quot;mrcp_resource.h&quot;
</span><span class="cx"> #include &quot;mrcp_resource_factory.h&quot;
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
</del><ins>+#include &quot;mrcp_engine_iface.h&quot;
</ins><span class="cx"> #include &quot;mrcp_sig_agent.h&quot;
</span><span class="cx"> #include &quot;mrcp_server_connection.h&quot;
</span><span class="cx"> #include &quot;mrcp_session_descriptor.h&quot;
</span><span class="cx"> #include &quot;mrcp_control_descriptor.h&quot;
</span><span class="cx"> #include &quot;mrcp_state_machine.h&quot;
</span><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><del>-#include &quot;mpf_user.h&quot;
-#include &quot;mpf_termination.h&quot;
-#include &quot;mpf_engine.h&quot;
</del><ins>+#include &quot;mpf_termination_factory.h&quot;
+#include &quot;mpf_stream.h&quot;
</ins><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -37,19 +36,19 @@
</span><span class="cx">         /** Memory pool */
</span><span class="cx">         apr_pool_t             *pool;
</span><span class="cx">         /** MRCP resource */
</span><del>-        apt_str_t               resource_name;
-        /** MRCP resource */
</del><span class="cx">         mrcp_resource_t        *resource;
</span><span class="cx">         /** MRCP session entire channel belongs to */
</span><span class="cx">         mrcp_session_t         *session;
</span><span class="cx">         /** MRCP control channel */
</span><span class="cx">         mrcp_control_channel_t *control_channel;
</span><del>-        /** MRCP resource engine channel */
</del><ins>+        /** MRCP engine channel */
</ins><span class="cx">         mrcp_engine_channel_t  *engine_channel;
</span><span class="cx">         /** MRCP resource state machine  */
</span><span class="cx">         mrcp_state_machine_t   *state_machine;
</span><del>-        /** media descriptor id */
</del><ins>+        /** media descriptor id (position in session descriptor) */
</ins><span class="cx">         apr_size_t              id;
</span><ins>+        /** array of cmid attributes (used for resource grouping) */
+        apr_array_header_t     *cmid_arr;
</ins><span class="cx">         /** waiting state of control media */
</span><span class="cx">         apt_bool_t              waiting_for_channel;
</span><span class="cx">         /** waiting state of media termination */
</span><span class="lines">@@ -60,11 +59,16 @@
</span><span class="cx"> 
</span><span class="cx"> struct mrcp_termination_slot_t {
</span><span class="cx">         /** RTP termination */
</span><del>-        mpf_termination_t *termination;
-        /** media descriptor id */
-        apr_size_t              id;
</del><ins>+        mpf_termination_t  *termination;
+        /** media descriptor id (position in SDP message) */
+        apr_size_t          id;
+        /** media id (used for resource grouping) */
+        apr_size_t          mid;
+        /** Array of associated MRCP channels (mrcp_channel_t*) */
+        apr_array_header_t *channels;
+
</ins><span class="cx">         /** waiting state */
</span><del>-        apt_bool_t         waiting;
</del><ins>+        apt_bool_t          waiting;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> extern const mrcp_engine_channel_event_vtable_t engine_channel_vtable;
</span><span class="lines">@@ -78,21 +82,13 @@
</span><span class="cx"> static apt_bool_t mrcp_server_control_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor);
</span><span class="cx"> static apt_bool_t mrcp_server_av_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor);
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_server_on_termination_modify(mrcp_server_session_t *session, const mpf_message_t *mpf_message);
-static apt_bool_t mrcp_server_on_termination_subtract(mrcp_server_session_t *session, const mpf_message_t *mpf_message);
-
</del><ins>+static apt_bool_t mrcp_server_engine_channels_update(mrcp_server_session_t *session);
</ins><span class="cx"> static apt_bool_t mrcp_server_session_answer_send(mrcp_server_session_t *session);
</span><ins>+static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *session);
</ins><span class="cx"> static apt_bool_t mrcp_server_session_terminate_send(mrcp_server_session_t *session);
</span><span class="cx"> 
</span><span class="cx"> static mrcp_channel_t* mrcp_server_channel_find(mrcp_server_session_t *session, const apt_str_t *resource_name);
</span><span class="cx"> 
</span><del>-static apt_bool_t mrcp_server_mpf_request_send(
-                                                mrcp_server_session_t *session, 
-                                                mpf_command_type_e command_id, 
-                                                mpf_context_t *context, 
-                                                mpf_termination_t *termination, 
-                                                void *descriptor);
-
</del><span class="cx"> static apt_bool_t state_machine_on_message_dispatch(mrcp_state_machine_t *state_machine, mrcp_message_t *message);
</span><span class="cx"> static apt_bool_t state_machine_on_deactivate(mrcp_state_machine_t *state_machine);
</span><span class="cx"> 
</span><span class="lines">@@ -107,27 +103,44 @@
</span><span class="cx">         session-&gt;request_queue = apt_list_create(session-&gt;base.pool);
</span><span class="cx">         session-&gt;offer = NULL;
</span><span class="cx">         session-&gt;answer = NULL;
</span><del>-        session-&gt;answer_flag_count = 0;
-        session-&gt;terminate_flag_count = 0;
-        session-&gt;deactivate_flag_count = 0;
</del><ins>+        session-&gt;mpf_task_msg = NULL;
+        session-&gt;subrequest_count = 0;
+        session-&gt;state = SESSION_STATE_NONE;
</ins><span class="cx">         return session;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static mrcp_engine_channel_t* mrcp_server_engine_channel_create(mrcp_server_session_t *session, const apt_str_t *resource_name)
</del><ins>+static APR_INLINE mrcp_version_e mrcp_session_version_get(mrcp_server_session_t *session)
</ins><span class="cx"> {
</span><del>-        mrcp_resource_engine_t *resource_engine = apr_hash_get(
-                                                                                                session-&gt;profile-&gt;engine_table,
-                                                                                                resource_name-&gt;buf,
-                                                                                                resource_name-&gt;length);
-        if(!resource_engine) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Find Resource Engine [%s]&quot;,resource_name-&gt;buf);
</del><ins>+        return session-&gt;base.signaling_agent-&gt;mrcp_version;
+}
+
+static mrcp_engine_channel_t* mrcp_server_engine_channel_create(
+                                                                mrcp_server_session_t *session,
+                                                                mrcp_channel_t *channel, 
+                                                                const apt_str_t *resource_name)
+{
+        mrcp_engine_t *engine = apr_hash_get(
+                                                                        session-&gt;profile-&gt;engine_table,
+                                                                        resource_name-&gt;buf,
+                                                                        resource_name-&gt;length);
+        if(!engine) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Find MRCP Engine [%s]&quot;,resource_name-&gt;buf);
</ins><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return resource_engine-&gt;method_vtable-&gt;create_channel(resource_engine,session-&gt;base.pool);
</del><ins>+        channel-&gt;state_machine = engine-&gt;create_state_machine(
+                                                channel,
+                                                mrcp_session_version_get(session),
+                                                channel-&gt;pool);
+        if(channel-&gt;state_machine) {
+                channel-&gt;state_machine-&gt;on_dispatch = state_machine_on_message_dispatch;
+                channel-&gt;state_machine-&gt;on_deactivate = state_machine_on_deactivate;
+        }
+
+        return mrcp_engine_channel_virtual_create(engine,mrcp_session_version_get(session),session-&gt;base.pool);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static mrcp_channel_t* mrcp_server_channel_create(mrcp_server_session_t *session, const apt_str_t *resource_name, apr_size_t id)
</del><ins>+static mrcp_channel_t* mrcp_server_channel_create(mrcp_server_session_t *session, const apt_str_t *resource_name, apr_size_t id, apr_array_header_t *cmid_arr)
</ins><span class="cx"> {
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         apr_pool_t *pool = session-&gt;base.pool;
</span><span class="lines">@@ -140,37 +153,23 @@
</span><span class="cx">         channel-&gt;state_machine = NULL;
</span><span class="cx">         channel-&gt;engine_channel = NULL;
</span><span class="cx">         channel-&gt;id = id;
</span><ins>+        channel-&gt;cmid_arr = cmid_arr;
</ins><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><span class="cx">         channel-&gt;waiting_for_termination = FALSE;
</span><del>-        apt_string_reset(&amp;channel-&gt;resource_name);
</del><span class="cx"> 
</span><span class="cx">         if(resource_name &amp;&amp; resource_name-&gt;buf) {
</span><del>-                mrcp_resource_id resource_id;
</del><span class="cx">                 mrcp_resource_t *resource;
</span><span class="cx">                 mrcp_engine_channel_t *engine_channel;
</span><del>-                channel-&gt;resource_name = *resource_name;
-                resource_id = mrcp_resource_id_find(
-                                                                session-&gt;profile-&gt;resource_factory,
-                                                                resource_name);
-                resource = mrcp_resource_get(session-&gt;profile-&gt;resource_factory,resource_id);
</del><ins>+                resource = mrcp_resource_find(session-&gt;profile-&gt;resource_factory,resource_name);
</ins><span class="cx">                 if(resource) {
</span><span class="cx">                         channel-&gt;resource = resource;
</span><del>-                        if(session-&gt;base.signaling_agent-&gt;mrcp_version == MRCP_VERSION_2) {
</del><ins>+                        if(mrcp_session_version_get(session) == MRCP_VERSION_2) {
</ins><span class="cx">                                 channel-&gt;control_channel = mrcp_server_control_channel_create(
</span><span class="cx">                                                                         session-&gt;profile-&gt;connection_agent,
</span><span class="cx">                                                                         channel,
</span><span class="cx">                                                                         pool);
</span><span class="cx">                         }
</span><del>-                        channel-&gt;state_machine = resource-&gt;create_server_state_machine(
-                                                                channel,
-                                                                session-&gt;base.signaling_agent-&gt;mrcp_version,
-                                                                pool);
-                        if(channel-&gt;state_machine) {
-                                channel-&gt;state_machine-&gt;on_dispatch = state_machine_on_message_dispatch;
-                                channel-&gt;state_machine-&gt;on_deactivate = state_machine_on_deactivate;
-                        }
-
-                        engine_channel = mrcp_server_engine_channel_create(session,resource_name);
</del><ins>+                        engine_channel = mrcp_server_engine_channel_create(session,channel,resource_name);
</ins><span class="cx">                         if(engine_channel) {
</span><span class="cx">                                 engine_channel-&gt;id = session-&gt;base.id;
</span><span class="cx">                                 engine_channel-&gt;event_obj = channel;
</span><span class="lines">@@ -178,7 +177,7 @@
</span><span class="cx">                                 channel-&gt;engine_channel = engine_channel;
</span><span class="cx">                         }
</span><span class="cx">                         else {
</span><del>-                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Engine Channel [%s]&quot;,resource_name-&gt;buf);
</del><ins>+                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Engine Channel [%s]&quot;,resource_name-&gt;buf);
</ins><span class="cx">                                 session-&gt;answer-&gt;status = MRCP_SESSION_STATUS_UNACCEPTABLE_RESOURCE;
</span><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="lines">@@ -195,6 +194,48 @@
</span><span class="cx">         return channel;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static APR_INLINE void mrcp_server_session_state_set(mrcp_server_session_t *session, mrcp_server_session_state_e state)
+{
+        if(session-&gt;subrequest_count != 0) {
+                /* error case */
+                session-&gt;subrequest_count = 0;
+        }
+        session-&gt;state = state;
+}
+
+static APR_INLINE void mrcp_server_session_subrequest_add(mrcp_server_session_t *session)
+{
+        session-&gt;subrequest_count++;
+}
+
+static void mrcp_server_session_subrequest_remove(mrcp_server_session_t *session)
+{
+        if(!session-&gt;subrequest_count) {
+                /* error case */
+                return;
+        }
+        session-&gt;subrequest_count--;
+        if(!session-&gt;subrequest_count) {
+                switch(session-&gt;state) {
+                        case SESSION_STATE_GENERATING_ANSWER:
+                                mrcp_server_engine_channels_update(session);
+                                break;
+                        case SESSION_STATE_INITIALIZING:
+                                /* send answer to client */
+                                mrcp_server_session_answer_send(session);
+                                break;
+                        case SESSION_STATE_DEACTIVATING:
+                                mrcp_server_session_terminate_process(session);
+                                break;
+                        case SESSION_STATE_TERMINATING:
+                                mrcp_server_session_terminate_send(session);
+                                break;
+                        default:
+                                break;
+                }
+        }
+}
+
</ins><span class="cx"> mrcp_session_t* mrcp_server_channel_session_get(mrcp_channel_t *channel)
</span><span class="cx"> {
</span><span class="cx">         return channel-&gt;session;
</span><span class="lines">@@ -227,13 +268,7 @@
</span><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><span class="cx">         answer-&gt;session_id = session-&gt;base.id;
</span><span class="cx">         mrcp_session_control_media_set(session-&gt;answer,channel-&gt;id,answer);
</span><del>-        if(session-&gt;answer_flag_count) {
-                session-&gt;answer_flag_count--;
-                if(!session-&gt;answer_flag_count) {
-                        /* send answer to client */
-                        mrcp_server_session_answer_send(session);
-                }
-        }
</del><ins>+        mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -245,12 +280,7 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         channel-&gt;waiting_for_channel = FALSE;
</span><del>-        if(session-&gt;terminate_flag_count) {
-                session-&gt;terminate_flag_count--;
-                if(!session-&gt;terminate_flag_count) {
-                        mrcp_server_session_terminate_send(session);
-                }
-        }
</del><ins>+        mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -267,6 +297,12 @@
</span><span class="cx">         return mrcp_server_signaling_message_process(signaling_message);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+apt_bool_t mrcp_server_on_disconnect(mrcp_channel_t *channel)
+{
+        /* to be processed */
+        return TRUE;
+}
+
</ins><span class="cx"> apt_bool_t mrcp_server_on_engine_channel_open(mrcp_channel_t *channel, apt_bool_t status)
</span><span class="cx"> {
</span><span class="cx">         mrcp_server_session_t *session = (mrcp_server_session_t*)channel-&gt;session;
</span><span class="lines">@@ -274,13 +310,7 @@
</span><span class="cx">         if(status == FALSE) {
</span><span class="cx">                 session-&gt;answer-&gt;status = MRCP_SESSION_STATUS_UNAVAILABLE_RESOURCE;
</span><span class="cx">         }
</span><del>-        if(session-&gt;answer_flag_count) {
-                session-&gt;answer_flag_count--;
-                if(!session-&gt;answer_flag_count) {
-                        /* send answer to client */
-                        mrcp_server_session_answer_send(session);
-                }
-        }
</del><ins>+        mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -288,12 +318,7 @@
</span><span class="cx"> {
</span><span class="cx">         mrcp_server_session_t *session = (mrcp_server_session_t*)channel-&gt;session;
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Engine Channel Close&quot;);
</span><del>-        if(session-&gt;terminate_flag_count) {
-                session-&gt;terminate_flag_count--;
-                if(!session-&gt;terminate_flag_count) {
-                        mrcp_server_session_terminate_send(session);
-                }
-        }
</del><ins>+        mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -307,41 +332,9 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-apt_bool_t mrcp_server_mpf_message_process(mpf_message_t *mpf_message)
-{
-        mrcp_server_session_t *session = NULL;
-        if(mpf_message-&gt;context) {
-                session = mpf_context_object_get(mpf_message-&gt;context);
-        }
-        if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_RESPONSE) {
-                switch(mpf_message-&gt;command_id) {
-                        case MPF_COMMAND_ADD:
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Add&quot;);
-                                mrcp_server_on_termination_modify(session,mpf_message);
-                                break;
-                        case MPF_COMMAND_MODIFY:
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Modify&quot;);
-                                mrcp_server_on_termination_modify(session,mpf_message);
-                                break;
-                        case MPF_COMMAND_SUBTRACT:
-                                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Subtract&quot;);
-                                mrcp_server_on_termination_subtract(session,mpf_message);
-                                break;
-                        default:
-                                break;
-                }
-        }
-        else if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_EVENT) {
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Event&quot;);
-        }
-        return TRUE;
-}
-
</del><span class="cx"> static mrcp_session_descriptor_t* mrcp_session_answer_create(mrcp_session_descriptor_t *offer, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         int i;
</span><del>-        void **control_slot;
-        mpf_rtp_media_descriptor_t **av_slot;
</del><span class="cx">         mrcp_session_descriptor_t *answer = apr_palloc(pool,sizeof(mrcp_session_descriptor_t));
</span><span class="cx">         apt_string_reset(&amp;answer-&gt;origin);
</span><span class="cx">         apt_string_reset(&amp;answer-&gt;ip);
</span><span class="lines">@@ -351,18 +344,15 @@
</span><span class="cx">         answer-&gt;status = offer-&gt;status;
</span><span class="cx">         answer-&gt;control_media_arr = apr_array_make(pool,offer-&gt;control_media_arr-&gt;nelts,sizeof(void*));
</span><span class="cx">         for(i=0; i&lt;offer-&gt;control_media_arr-&gt;nelts; i++) {
</span><del>-                control_slot = apr_array_push(answer-&gt;control_media_arr);
-                *control_slot = NULL;
</del><ins>+                APR_ARRAY_PUSH(answer-&gt;control_media_arr,void*) = NULL;
</ins><span class="cx">         }
</span><span class="cx">         answer-&gt;audio_media_arr = apr_array_make(pool,offer-&gt;audio_media_arr-&gt;nelts,sizeof(mpf_rtp_media_descriptor_t*));
</span><span class="cx">         for(i=0; i&lt;offer-&gt;audio_media_arr-&gt;nelts; i++) {
</span><del>-                av_slot = apr_array_push(answer-&gt;audio_media_arr);
-                *av_slot = NULL;
</del><ins>+                APR_ARRAY_PUSH(answer-&gt;audio_media_arr,mpf_rtp_media_descriptor_t*) = NULL;
</ins><span class="cx">         }
</span><span class="cx">         answer-&gt;video_media_arr = apr_array_make(pool,offer-&gt;video_media_arr-&gt;nelts,sizeof(mpf_rtp_media_descriptor_t*));
</span><span class="cx">         for(i=0; i&lt;offer-&gt;video_media_arr-&gt;nelts; i++) {
</span><del>-                av_slot = apr_array_push(answer-&gt;video_media_arr);
-                *av_slot = NULL;
</del><ins>+                APR_ARRAY_PUSH(answer-&gt;video_media_arr,mpf_rtp_media_descriptor_t*) = NULL;
</ins><span class="cx">         }
</span><span class="cx">         return answer;
</span><span class="cx"> }
</span><span class="lines">@@ -376,7 +366,7 @@
</span><span class="cx">                 }
</span><span class="cx">                 mrcp_server_session_add(session);
</span><span class="cx"> 
</span><del>-                session-&gt;context = mpf_context_create(session,5,session-&gt;base.pool);
</del><ins>+                session-&gt;context = mpf_engine_context_create(session-&gt;profile-&gt;media_engine,session,5,session-&gt;base.pool);
</ins><span class="cx">         }
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Receive Offer &quot;APT_SID_FMT&quot; [c:%d a:%d v:%d]&quot;,
</span><span class="cx">                 MRCP_SESSION_SID(&amp;session-&gt;base),
</span><span class="lines">@@ -388,7 +378,17 @@
</span><span class="cx">         session-&gt;offer = descriptor;
</span><span class="cx">         session-&gt;answer = mrcp_session_answer_create(descriptor,session-&gt;base.pool);
</span><span class="cx"> 
</span><del>-        if(session-&gt;base.signaling_agent-&gt;mrcp_version == MRCP_VERSION_1) {
</del><ins>+        mrcp_server_session_state_set(session,SESSION_STATE_GENERATING_ANSWER);
+
+        /* first, reset/destroy existing associations and topology */
+        if(mpf_engine_topology_message_add(
+                                session-&gt;profile-&gt;media_engine,
+                                MPF_RESET_ASSOCIATIONS,session-&gt;context,
+                                &amp;session-&gt;mpf_task_msg) == TRUE){
+                mrcp_server_session_subrequest_add(session);
+        }
+
+        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
</ins><span class="cx">                 if(mrcp_server_resource_offer_process(session,descriptor) == TRUE) {
</span><span class="cx">                         mrcp_server_av_media_offer_process(session,descriptor);
</span><span class="cx">                 }
</span><span class="lines">@@ -400,8 +400,17 @@
</span><span class="cx">                 mrcp_server_control_media_offer_process(session,descriptor);
</span><span class="cx">                 mrcp_server_av_media_offer_process(session,descriptor);
</span><span class="cx">         }
</span><del>-        
-        if(!session-&gt;answer_flag_count) {
</del><ins>+
+        /* apply topology based on assigned associations */
+        if(mpf_engine_topology_message_add(
+                                session-&gt;profile-&gt;media_engine,
+                                MPF_APPLY_TOPOLOGY,session-&gt;context,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
+                mrcp_server_session_subrequest_add(session);
+        }
+        mpf_engine_message_send(session-&gt;profile-&gt;media_engine,&amp;session-&gt;mpf_task_msg);
+
+        if(!session-&gt;subrequest_count) {
</ins><span class="cx">                 /* send answer to client */
</span><span class="cx">                 mrcp_server_session_answer_send(session);
</span><span class="cx">         }
</span><span class="lines">@@ -414,8 +423,21 @@
</span><span class="cx">         mrcp_termination_slot_t *slot;
</span><span class="cx">         int i;
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Receive Terminate Request &quot;APT_SID_FMT,MRCP_SESSION_SID(&amp;session-&gt;base));
</span><ins>+
+        mrcp_server_session_state_set(session,SESSION_STATE_TERMINATING);
+
+        if(session-&gt;context) {
+                /* first, destroy existing topology */
+                if(mpf_engine_topology_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_RESET_ASSOCIATIONS,session-&gt;context,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE){
+                        mrcp_server_session_subrequest_add(session);
+                }
+        }
+
</ins><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 /* send remove channel request */
</span><span class="lines">@@ -423,7 +445,7 @@
</span><span class="cx">                 if(channel-&gt;control_channel) {
</span><span class="cx">                         if(mrcp_server_control_channel_remove(channel-&gt;control_channel) == TRUE) {
</span><span class="cx">                                 channel-&gt;waiting_for_channel = TRUE;
</span><del>-                                session-&gt;terminate_flag_count++;
</del><ins>+                                mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -432,33 +454,44 @@
</span><span class="cx">                         /* send subtract termination request */
</span><span class="cx">                         if(termination) {
</span><span class="cx">                                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract Channel Termination&quot;);
</span><del>-                                if(mrcp_server_mpf_request_send(session,MPF_COMMAND_SUBTRACT,session-&gt;context,termination,NULL) == TRUE) {
</del><ins>+                                if(mpf_engine_termination_message_add(
+                                                        session-&gt;profile-&gt;media_engine,
+                                                        MPF_SUBTRACT_TERMINATION,session-&gt;context,termination,NULL,
+                                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
</ins><span class="cx">                                         channel-&gt;waiting_for_termination = TRUE;
</span><del>-                                        session-&gt;terminate_flag_count++;
</del><ins>+                                        mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="cx"> 
</span><del>-                        /* close resource engine channel */
-                        if(mrcp_engine_channel_close(channel-&gt;engine_channel) == TRUE) {
-                                session-&gt;terminate_flag_count++;
</del><ins>+                        /* close engine channel */
+                        if(mrcp_engine_channel_virtual_close(channel-&gt;engine_channel) == TRUE) {
+                                mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         for(i=0; i&lt;session-&gt;terminations-&gt;nelts; i++) {
</span><span class="cx">                 /* get existing termination */
</span><del>-                slot = &amp;((mrcp_termination_slot_t*)session-&gt;terminations-&gt;elts)[i];
</del><ins>+                slot = &amp;APR_ARRAY_IDX(session-&gt;terminations,i,mrcp_termination_slot_t);
</ins><span class="cx">                 if(!slot || !slot-&gt;termination) continue;
</span><span class="cx"> 
</span><span class="cx">                 /* send subtract termination request */
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Subtract RTP Termination [%d]&quot;,i);
</span><del>-                if(mrcp_server_mpf_request_send(session,MPF_COMMAND_SUBTRACT,session-&gt;context,slot-&gt;termination,NULL) == TRUE) {
</del><ins>+                if(mpf_engine_termination_message_add(
+                                session-&gt;profile-&gt;media_engine,
+                                MPF_SUBTRACT_TERMINATION,session-&gt;context,slot-&gt;termination,NULL,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
</ins><span class="cx">                         slot-&gt;waiting = TRUE;
</span><del>-                        session-&gt;terminate_flag_count++;
</del><ins>+                        mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+
+        if(session-&gt;context) {
+                mpf_engine_message_send(session-&gt;profile-&gt;media_engine,&amp;session-&gt;mpf_task_msg);
+        }
+
</ins><span class="cx">         mrcp_server_session_remove(session);
</span><span class="cx"> 
</span><del>-        if(!session-&gt;terminate_flag_count) {
</del><ins>+        if(!session-&gt;subrequest_count) {
</ins><span class="cx">                 mrcp_server_session_terminate_send(session);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -470,16 +503,17 @@
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         int i;
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Deactivate Session &quot;APT_SID_FMT,MRCP_SESSION_SID(&amp;session-&gt;base));
</span><ins>+        mrcp_server_session_state_set(session,SESSION_STATE_DEACTIVATING);
</ins><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel || !channel-&gt;state_machine) continue;
</span><span class="cx"> 
</span><span class="cx">                 if(mrcp_state_machine_deactivate(channel-&gt;state_machine) == TRUE) {
</span><del>-                        session-&gt;deactivate_flag_count++;
</del><ins>+                        mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        if(!session-&gt;deactivate_flag_count) {
</del><ins>+        if(!session-&gt;subrequest_count) {
</ins><span class="cx">                 mrcp_server_session_terminate_process(session);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -523,12 +557,63 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static apt_bool_t mrcp_server_engine_channels_update(mrcp_server_session_t *session)
+{
+        mrcp_channel_t *channel;
+        mrcp_session_descriptor_t *descriptor = session-&gt;offer;
+        if(!descriptor) {
+                return FALSE;
+        }
+        
+        mrcp_server_session_state_set(session,SESSION_STATE_INITIALIZING);
+
+        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
+                if(session-&gt;offer) {
+                        channel = mrcp_server_channel_find(session,&amp;descriptor-&gt;resource_name);
+                        if(channel &amp;&amp; channel-&gt;engine_channel) {
+                                /* open engine channel */
+                                if(mrcp_engine_channel_virtual_open(channel-&gt;engine_channel) == TRUE) {
+                                        mrcp_server_session_subrequest_add(session);
+                                }
+                        }
+                }
+        }
+        else {
+                int i;
+                mrcp_control_descriptor_t *control_descriptor;
+                for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
+                        channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
+                        if(!channel || !channel-&gt;engine_channel) continue;
+
+                        control_descriptor = mrcp_session_control_media_get(descriptor,i);
+                        if(!control_descriptor) continue;
+
+                        if(control_descriptor-&gt;port) {
+                                /* open engine channel */
+                                if(mrcp_engine_channel_virtual_open(channel-&gt;engine_channel) == TRUE) {
+                                        mrcp_server_session_subrequest_add(session);
+                                }
+                        }
+                        else {
+                                /* close engine channel */
+                                if(mrcp_engine_channel_virtual_close(channel-&gt;engine_channel) == TRUE) {
+                                        mrcp_server_session_subrequest_add(session);
+                                }
+                        }
+                }
+        }
+
+        if(!session-&gt;subrequest_count) {
+                mrcp_server_session_answer_send(session);
+        }
+        return TRUE;
+}
+
</ins><span class="cx"> static apt_bool_t mrcp_server_resource_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor)
</span><span class="cx"> {
</span><span class="cx">         if(descriptor-&gt;resource_state == TRUE) {
</span><span class="cx">                 /* setup */
</span><span class="cx">                 mrcp_channel_t *channel;
</span><del>-                mrcp_channel_t **slot;
</del><span class="cx">                 int count = session-&gt;channels-&gt;nelts;
</span><span class="cx">                 channel = mrcp_server_channel_find(session,&amp;descriptor-&gt;resource_name);
</span><span class="cx">                 if(channel) {
</span><span class="lines">@@ -536,36 +621,22 @@
</span><span class="cx">                         return TRUE;
</span><span class="cx">                 }
</span><span class="cx">                 /* create new MRCP channel instance */
</span><del>-                channel = mrcp_server_channel_create(session,&amp;descriptor-&gt;resource_name,count);
</del><ins>+                channel = mrcp_server_channel_create(session,&amp;descriptor-&gt;resource_name,count,NULL);
</ins><span class="cx">                 if(!channel || !channel-&gt;resource) {
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><span class="cx">                 /* add to channel array */
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add Control Channel [%d]&quot;,count);
</span><del>-                slot = apr_array_push(session-&gt;channels);
-                *slot = channel;
-
-                if(channel-&gt;engine_channel) {
-                        /* open resource engine channel */
-                        if(mrcp_engine_channel_open(channel-&gt;engine_channel) == TRUE) {
-                                mpf_termination_t *termination = channel-&gt;engine_channel-&gt;termination;
-                                session-&gt;answer_flag_count++;
-
-                                if(termination) {
-                                        /* send add termination request (add to media context) */
-                                        if(mrcp_server_mpf_request_send(session,MPF_COMMAND_ADD,session-&gt;context,termination,NULL) == TRUE) {
-                                                channel-&gt;waiting_for_termination = TRUE;
-                                                session-&gt;answer_flag_count++;
-                                        }
-
-                                        if(termination-&gt;audio_stream) {
-                                                mpf_rtp_media_descriptor_t *rtp_media_descriptor = mrcp_session_audio_media_get(descriptor,0);
-                                                if(rtp_media_descriptor) {
-                                                        mpf_stream_mode_e mode = termination-&gt;audio_stream-&gt;mode;
-                                                        rtp_media_descriptor-&gt;mode |= mode;
-                                                }
-                                        }
-                                }
</del><ins>+                APR_ARRAY_PUSH(session-&gt;channels,mrcp_channel_t*) = channel;
+                if(channel-&gt;engine_channel &amp;&amp; channel-&gt;engine_channel-&gt;termination) {
+                        mpf_termination_t *termination = channel-&gt;engine_channel-&gt;termination;
+                        /* send add termination request (add to media context) */
+                        if(mpf_engine_termination_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_ADD_TERMINATION,session-&gt;context,termination,NULL,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
+                                channel-&gt;waiting_for_termination = TRUE;
+                                mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -589,8 +660,7 @@
</span><span class="cx">         
</span><span class="cx">         /* update existing control channels */
</span><span class="cx">         for(i=0; i&lt;count; i++) {
</span><del>-                /* get existing termination */
-                channel = *((mrcp_channel_t**)session-&gt;channels-&gt;elts + i);
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 channel-&gt;waiting_for_channel = FALSE;
</span><span class="lines">@@ -603,7 +673,7 @@
</span><span class="cx">                         /* send offer */
</span><span class="cx">                         if(mrcp_server_control_channel_modify(channel-&gt;control_channel,control_descriptor) == TRUE) {
</span><span class="cx">                                 channel-&gt;waiting_for_channel = TRUE;
</span><del>-                                session-&gt;answer_flag_count++;
</del><ins>+                                mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -617,26 +687,23 @@
</span><span class="cx">         
</span><span class="cx">         /* add new control channels */
</span><span class="cx">         for(; i&lt;descriptor-&gt;control_media_arr-&gt;nelts; i++) {
</span><del>-                mrcp_channel_t **slot;
</del><span class="cx">                 /* get control descriptor */
</span><span class="cx">                 control_descriptor = mrcp_session_control_media_get(descriptor,i);
</span><span class="cx">                 if(!control_descriptor) continue;
</span><span class="cx"> 
</span><span class="cx">                 /* create new MRCP channel instance */
</span><del>-                channel = mrcp_server_channel_create(session,&amp;control_descriptor-&gt;resource_name,i);
</del><ins>+                channel = mrcp_server_channel_create(session,&amp;control_descriptor-&gt;resource_name,i,control_descriptor-&gt;cmid_arr);
</ins><span class="cx">                 if(!channel) continue;
</span><del>-                /* add to channel array */
</del><span class="cx"> 
</span><span class="cx">                 control_descriptor-&gt;session_id = session-&gt;base.id;
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add Control Channel [%d]&quot;,i);
</span><del>-                slot = apr_array_push(session-&gt;channels);
-                *slot = channel;
</del><ins>+                APR_ARRAY_PUSH(session-&gt;channels,mrcp_channel_t*) = channel;
</ins><span class="cx"> 
</span><span class="cx">                 if(channel-&gt;control_channel) {
</span><span class="cx">                         /* send modify connection request */
</span><span class="cx">                         if(mrcp_server_control_channel_add(channel-&gt;control_channel,control_descriptor) == TRUE) {
</span><span class="cx">                                 channel-&gt;waiting_for_channel = TRUE;
</span><del>-                                session-&gt;answer_flag_count++;
</del><ins>+                                mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -647,28 +714,108 @@
</span><span class="cx">                         mrcp_session_control_media_set(session-&gt;answer,channel-&gt;id,answer);
</span><span class="cx">                 }
</span><span class="cx">                 
</span><del>-                if(channel-&gt;engine_channel) {
-                        /* open resource engine channel */
-                        if(mrcp_engine_channel_open(channel-&gt;engine_channel) == TRUE) {
-                                mpf_termination_t *termination = channel-&gt;engine_channel-&gt;termination;
-                                session-&gt;answer_flag_count++;
</del><ins>+                if(channel-&gt;engine_channel &amp;&amp; channel-&gt;engine_channel-&gt;termination) {
+                        mpf_termination_t *termination = channel-&gt;engine_channel-&gt;termination;
+                        /* send add termination request (add to media context) */
+                        if(mpf_engine_termination_message_add(
+                                        session-&gt;profile-&gt;media_engine,
+                                        MPF_ADD_TERMINATION,session-&gt;context,termination,NULL,
+                                        &amp;session-&gt;mpf_task_msg) == TRUE) {
+                                channel-&gt;waiting_for_termination = TRUE;
+                                mrcp_server_session_subrequest_add(session);
+                        }
+                }
+        }
</ins><span class="cx"> 
</span><del>-                                if(termination) {
-                                        /* send add termination request (add to media context) */
-                                        if(mrcp_server_mpf_request_send(session,MPF_COMMAND_ADD,session-&gt;context,termination,NULL) == TRUE) {
-                                                channel-&gt;waiting_for_termination = TRUE;
-                                                session-&gt;answer_flag_count++;
</del><ins>+        return TRUE;
+}
+
+static mpf_rtp_termination_descriptor_t* mrcp_server_associations_build(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_termination_slot_t *slot)
+{
+        int i;
+        mrcp_channel_t *channel;
+        mpf_audio_stream_t *audio_stream;
+        mpf_stream_capabilities_t *capabilities = NULL;
+        mpf_rtp_termination_descriptor_t *rtp_descriptor;
+        mpf_rtp_media_descriptor_t *media_descriptor = mrcp_session_audio_media_get(descriptor,slot-&gt;id);
+        if(!media_descriptor) {
+                return NULL;
+        }
+        /* construct termination descriptor */
+        rtp_descriptor = apr_palloc(session-&gt;base.pool,sizeof(mpf_rtp_termination_descriptor_t));
+        mpf_rtp_termination_descriptor_init(rtp_descriptor);
+        rtp_descriptor-&gt;audio.local = NULL;
+        rtp_descriptor-&gt;audio.remote = media_descriptor;
+
+        slot-&gt;mid = media_descriptor-&gt;mid;
+        slot-&gt;channels = apr_array_make(session-&gt;base.pool,1,sizeof(mrcp_channel_t*));
+        for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
+                if(!channel) continue;
+
+                if(!channel-&gt;cmid_arr || mrcp_cmid_find(channel-&gt;cmid_arr,slot-&gt;mid) == TRUE) {
+                        APR_ARRAY_PUSH(slot-&gt;channels, mrcp_channel_t*) = channel;
+
+                        audio_stream = NULL;
+                        if(channel-&gt;engine_channel &amp;&amp; channel-&gt;engine_channel-&gt;termination) {
+                                audio_stream = mpf_termination_audio_stream_get(channel-&gt;engine_channel-&gt;termination);
+                        }
+                        if(!audio_stream) continue;
+
+                        if(audio_stream-&gt;capabilities) {
+                                /* set descriptor according to media termination(s) 
+                                of associated control channel(s) */
+                                if(capabilities) {
+                                        mpf_stream_capabilities_merge(
+                                                capabilities,
+                                                audio_stream-&gt;capabilities,
+                                                session-&gt;base.pool);
</ins><span class="cx">                                         }
</span><ins>+                                else {
+                                        capabilities = mpf_stream_capabilities_clone(
+                                                audio_stream-&gt;capabilities,
+                                                session-&gt;base.pool);
</ins><span class="cx">                                 }
</span><span class="cx">                         }
</span><ins>+
+                        if(mrcp_session_version_get(session) == MRCP_VERSION_1) {
+                                /* implicitly modify the descriptor, if needed */
+                                mpf_stream_direction_e direction = audio_stream-&gt;direction;
+                                media_descriptor-&gt;direction |= direction;
+                                if(media_descriptor-&gt;state == MPF_MEDIA_DISABLED) {
+                                        media_descriptor-&gt;state = MPF_MEDIA_ENABLED;
+                                }
+                        }
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+        if(capabilities) {
+                capabilities-&gt;direction = mpf_stream_reverse_direction_get(capabilities-&gt;direction);
+                rtp_descriptor-&gt;audio.capabilities = capabilities;
+        }
+        return rtp_descriptor;
+}
</ins><span class="cx"> 
</span><ins>+static apt_bool_t mrcp_server_associations_set(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_termination_slot_t *slot)
+{
+        int i;
+        mrcp_channel_t *channel;
+        for(i=0; i&lt;slot-&gt;channels-&gt;nelts; i++) {
+                channel = ((mrcp_channel_t**)slot-&gt;channels-&gt;elts)[i];
+                if(!channel || !channel-&gt;engine_channel) continue;
+
+                if(mpf_engine_assoc_message_add(
+                                session-&gt;profile-&gt;media_engine,
+                                MPF_ADD_ASSOCIATION,session-&gt;context,slot-&gt;termination,channel-&gt;engine_channel-&gt;termination,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
+                        mrcp_server_session_subrequest_add(session);
+                }
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t mrcp_server_av_media_offer_process(mrcp_server_session_t *session, mrcp_session_descriptor_t *descriptor)
</span><span class="cx"> {
</span><ins>+        mpf_rtp_termination_descriptor_t *rtp_descriptor;
</ins><span class="cx">         mrcp_termination_slot_t *slot;
</span><span class="cx">         int i;
</span><span class="cx">         int count = session-&gt;terminations-&gt;nelts;
</span><span class="lines">@@ -684,28 +831,30 @@
</span><span class="cx">         
</span><span class="cx">         /* update existing terminations */
</span><span class="cx">         for(i=0; i&lt;count; i++) {
</span><del>-                mpf_rtp_termination_descriptor_t *rtp_descriptor;
</del><span class="cx">                 /* get existing termination */
</span><del>-                slot = &amp;((mrcp_termination_slot_t*)session-&gt;terminations-&gt;elts)[i];
</del><ins>+                slot = &amp;APR_ARRAY_IDX(session-&gt;terminations,i,mrcp_termination_slot_t);
</ins><span class="cx">                 if(!slot || !slot-&gt;termination) continue;
</span><span class="cx"> 
</span><del>-                /* construct termination descriptor */
-                rtp_descriptor = apr_palloc(session-&gt;base.pool,sizeof(mpf_rtp_termination_descriptor_t));
-                mpf_rtp_termination_descriptor_init(rtp_descriptor);
-                rtp_descriptor-&gt;audio.local = NULL;
-                rtp_descriptor-&gt;audio.remote = mrcp_session_audio_media_get(descriptor,i);
</del><ins>+                /* build associations between specified RTP termination and control channels */
+                rtp_descriptor = mrcp_server_associations_build(session,descriptor,slot);
+                if(!rtp_descriptor) continue;
</ins><span class="cx"> 
</span><span class="cx">                 /* send modify termination request */
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Modify RTP Termination [%d]&quot;,i);
</span><del>-                if(mrcp_server_mpf_request_send(session,MPF_COMMAND_MODIFY,session-&gt;context,slot-&gt;termination,rtp_descriptor) == TRUE) {
</del><ins>+                if(mpf_engine_termination_message_add(
+                                session-&gt;profile-&gt;media_engine,
+                                MPF_MODIFY_TERMINATION,session-&gt;context,slot-&gt;termination,rtp_descriptor,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
</ins><span class="cx">                         slot-&gt;waiting = TRUE;
</span><del>-                        session-&gt;answer_flag_count++;
</del><ins>+                        mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><ins>+
+                /* set built associations */
+                mrcp_server_associations_set(session,descriptor,slot);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         /* add new terminations */
</span><span class="cx">         for(; i&lt;descriptor-&gt;audio_media_arr-&gt;nelts; i++) {
</span><del>-                mpf_rtp_termination_descriptor_t *rtp_descriptor;
</del><span class="cx">                 mpf_termination_t *termination;
</span><span class="cx">                 /* create new RTP termination instance */
</span><span class="cx">                 termination = mpf_termination_create(session-&gt;profile-&gt;rtp_termination_factory,session,session-&gt;base.pool);
</span><span class="lines">@@ -713,20 +862,26 @@
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Add RTP Termination [%d]&quot;,i);
</span><span class="cx">                 slot = apr_array_push(session-&gt;terminations);
</span><span class="cx">                 slot-&gt;id = i;
</span><ins>+                slot-&gt;mid = 0;
</ins><span class="cx">                 slot-&gt;waiting = FALSE;
</span><span class="cx">                 slot-&gt;termination = termination;
</span><ins>+                slot-&gt;channels = NULL;
</ins><span class="cx"> 
</span><del>-                /* construct termination descriptor */
-                rtp_descriptor = apr_palloc(session-&gt;base.pool,sizeof(mpf_rtp_termination_descriptor_t));
-                mpf_rtp_termination_descriptor_init(rtp_descriptor);
-                rtp_descriptor-&gt;audio.local = NULL;
-                rtp_descriptor-&gt;audio.remote = mrcp_session_audio_media_get(descriptor,i);
</del><ins>+                /* build associations between specified RTP termination and control channels */
+                rtp_descriptor = mrcp_server_associations_build(session,descriptor,slot);
+                if(!rtp_descriptor) continue;
</ins><span class="cx"> 
</span><span class="cx">                 /* send add termination request (add to media context) */
</span><del>-                if(mrcp_server_mpf_request_send(session,MPF_COMMAND_ADD,session-&gt;context,termination,rtp_descriptor) == TRUE) {
</del><ins>+                if(mpf_engine_termination_message_add(
+                                session-&gt;profile-&gt;media_engine,
+                                MPF_ADD_TERMINATION,session-&gt;context,termination,rtp_descriptor,
+                                &amp;session-&gt;mpf_task_msg) == TRUE) {
</ins><span class="cx">                         slot-&gt;waiting = TRUE;
</span><del>-                        session-&gt;answer_flag_count++;
</del><ins>+                        mrcp_server_session_subrequest_add(session);
</ins><span class="cx">                 }
</span><ins>+
+                /* set built associations */
+                mrcp_server_associations_set(session,descriptor,slot);
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -757,7 +912,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 if(channel-&gt;control_channel) {
</span><span class="lines">@@ -765,7 +920,7 @@
</span><span class="cx">                         channel-&gt;control_channel = NULL;
</span><span class="cx">                 }
</span><span class="cx">                 if(channel-&gt;engine_channel) {
</span><del>-                        mrcp_engine_channel_destroy(channel-&gt;engine_channel);
</del><ins>+                        mrcp_engine_channel_virtual_destroy(channel-&gt;engine_channel);
</ins><span class="cx">                         channel-&gt;engine_channel = NULL;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -780,7 +935,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_termination_slot_t *slot;
</span><span class="cx">         for(i=0; i&lt;session-&gt;terminations-&gt;nelts; i++) {
</span><del>-                slot = &amp;((mrcp_termination_slot_t*)session-&gt;terminations-&gt;elts)[i];
</del><ins>+                slot = &amp;APR_ARRAY_IDX(session-&gt;terminations,i,mrcp_termination_slot_t);
</ins><span class="cx">                 if(slot &amp;&amp; slot-&gt;termination == termination) {
</span><span class="cx">                         return slot;
</span><span class="cx">                 }
</span><span class="lines">@@ -793,7 +948,7 @@
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><span class="cx">                 if(channel-&gt;engine_channel &amp;&amp; channel-&gt;engine_channel-&gt;termination == termination) {
</span><span class="lines">@@ -808,10 +963,10 @@
</span><span class="cx">         int i;
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         for(i=0; i&lt;session-&gt;channels-&gt;nelts; i++) {
</span><del>-                channel = ((mrcp_channel_t**)session-&gt;channels-&gt;elts)[i];
</del><ins>+                channel = APR_ARRAY_IDX(session-&gt;channels,i,mrcp_channel_t*);
</ins><span class="cx">                 if(!channel) continue;
</span><span class="cx"> 
</span><del>-                if(apt_string_compare(&amp;channel-&gt;resource_name,resource_name) == TRUE) {
</del><ins>+                if(apt_string_compare(&amp;channel-&gt;resource-&gt;name,resource_name) == TRUE) {
</ins><span class="cx">                         return channel;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="lines">@@ -834,30 +989,18 @@
</span><span class="cx">                 termination_slot-&gt;waiting = FALSE;
</span><span class="cx">                 rtp_descriptor = mpf_message-&gt;descriptor;
</span><span class="cx">                 if(rtp_descriptor-&gt;audio.local) {
</span><del>-                        session-&gt;answer-&gt;ip = rtp_descriptor-&gt;audio.local-&gt;base.ip;
-                        session-&gt;answer-&gt;ext_ip = rtp_descriptor-&gt;audio.local-&gt;base.ext_ip;
</del><ins>+                        session-&gt;answer-&gt;ip = rtp_descriptor-&gt;audio.local-&gt;ip;
+                        session-&gt;answer-&gt;ext_ip = rtp_descriptor-&gt;audio.local-&gt;ext_ip;
</ins><span class="cx">                         mrcp_session_audio_media_set(session-&gt;answer,termination_slot-&gt;id,rtp_descriptor-&gt;audio.local);
</span><span class="cx">                 }
</span><del>-                if(session-&gt;answer_flag_count) {
-                        session-&gt;answer_flag_count--;
-                        if(!session-&gt;answer_flag_count) {
-                                /* send answer to client */
-                                mrcp_server_session_answer_send(session);
-                        }
-                }
</del><ins>+                mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><span class="cx">                 /* engine channel termination */
</span><span class="cx">                 mrcp_channel_t *channel = mrcp_server_channel_termination_find(session,mpf_message-&gt;termination);
</span><span class="cx">                 if(channel &amp;&amp; channel-&gt;waiting_for_termination == TRUE) {
</span><span class="cx">                         channel-&gt;waiting_for_termination = FALSE;
</span><del>-                        if(session-&gt;answer_flag_count) {
-                                session-&gt;answer_flag_count--;
-                                if(!session-&gt;answer_flag_count) {
-                                        /* send answer to client */
-                                        mrcp_server_session_answer_send(session);
-                                }
-                        }
</del><ins>+                        mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -876,25 +1019,61 @@
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><span class="cx">                 termination_slot-&gt;waiting = FALSE;
</span><del>-                if(session-&gt;terminate_flag_count) {
-                        session-&gt;terminate_flag_count--;
-                        if(!session-&gt;terminate_flag_count) {
-                                mrcp_server_session_terminate_send(session);
-                        }
-                }
</del><ins>+                mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><span class="cx">                 /* engine channel termination */
</span><span class="cx">                 mrcp_channel_t *channel = mrcp_server_channel_termination_find(session,mpf_message-&gt;termination);
</span><span class="cx">                 if(channel &amp;&amp; channel-&gt;waiting_for_termination == TRUE) {
</span><span class="cx">                         channel-&gt;waiting_for_termination = FALSE;
</span><del>-                        if(session-&gt;terminate_flag_count) {
-                                session-&gt;terminate_flag_count--;
-                                if(!session-&gt;terminate_flag_count) {
-                                        mrcp_server_session_terminate_send(session);
-                                }
</del><ins>+                        mrcp_server_session_subrequest_remove(session);
+                }
+        }
+        return TRUE;
+}
+
+apt_bool_t mrcp_server_mpf_message_process(mpf_message_container_t *mpf_message_container)
+{
+        apr_size_t i;
+        mrcp_server_session_t *session;
+        const mpf_message_t *mpf_message;
+        for(i=0; i&lt;mpf_message_container-&gt;count; i++) {
+                mpf_message = &amp;mpf_message_container-&gt;messages[i];
+                if(mpf_message-&gt;context) {
+                        session = mpf_engine_context_object_get(mpf_message-&gt;context);
+                }
+                else {
+                        session = NULL;
+                }
+                
+                if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_RESPONSE) {
+                        switch(mpf_message-&gt;command_id) {
+                                case MPF_ADD_TERMINATION:
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Add&quot;);
+                                        mrcp_server_on_termination_modify(session,mpf_message);
+                                        break;
+                                case MPF_MODIFY_TERMINATION:
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Modify&quot;);
+                                        mrcp_server_on_termination_modify(session,mpf_message);
+                                        break;
+                                case MPF_SUBTRACT_TERMINATION:
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Termination Subtract&quot;);
+                                        mrcp_server_on_termination_subtract(session,mpf_message);
+                                        break;
+                                case MPF_ADD_ASSOCIATION:
+                                case MPF_REMOVE_ASSOCIATION:
+                                case MPF_RESET_ASSOCIATIONS:
+                                case MPF_APPLY_TOPOLOGY:
+                                case MPF_DESTROY_TOPOLOGY:
+                                        mrcp_server_session_subrequest_remove(session);
+                                        break;
+                                default:
+                                        break;
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><ins>+                else if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_EVENT) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Event&quot;);
+                }
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -904,7 +1083,7 @@
</span><span class="cx">         mrcp_channel_t *channel = state_machine-&gt;obj;
</span><span class="cx"> 
</span><span class="cx">         if(message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
</span><del>-                /* send request message to resource engine for actual processing */
</del><ins>+                /* send request message to engine for actual processing */
</ins><span class="cx">                 if(channel-&gt;engine_channel) {
</span><span class="cx">                         mrcp_engine_channel_request_process(channel-&gt;engine_channel,message);
</span><span class="cx">                 }
</span><span class="lines">@@ -944,33 +1123,6 @@
</span><span class="cx"> {
</span><span class="cx">         mrcp_channel_t *channel = state_machine-&gt;obj;
</span><span class="cx">         mrcp_server_session_t *session = (mrcp_server_session_t*)channel-&gt;session;
</span><del>-        if(session-&gt;deactivate_flag_count) {
-                session-&gt;deactivate_flag_count --;
-                if(!session-&gt;deactivate_flag_count) {
-                        mrcp_server_session_terminate_process(session);
-                }
-        }
</del><ins>+        mrcp_server_session_subrequest_remove(session);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><del>-
-static apt_bool_t mrcp_server_mpf_request_send(
-                                                mrcp_server_session_t *session, 
-                                                mpf_command_type_e command_id, 
-                                                mpf_context_t *context, 
-                                                mpf_termination_t *termination, 
-                                                void *descriptor)
-{
-        apt_task_t *media_task = mpf_task_get(session-&gt;profile-&gt;media_engine);
-        apt_task_msg_t *msg;
-        mpf_message_t *mpf_message;
-        msg = apt_task_msg_get(media_task);
-        msg-&gt;type = TASK_MSG_USER;
-        mpf_message = (mpf_message_t*) msg-&gt;data;
-
-        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-        mpf_message-&gt;command_id = command_id;
-        mpf_message-&gt;context = context;
-        mpf_message-&gt;termination = termination;
-        mpf_message-&gt;descriptor = descriptor;
-        return apt_task_msg_signal(media_task,msg);
-}
</del></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpsignalingincludemrcp_sessionh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -27,10 +27,13 @@
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><ins>+/** Macro to log session pointers */
</ins><span class="cx"> #define MRCP_SESSION_PTR(session) (session)
</span><ins>+/** Macro to log session string identifiers */
</ins><span class="cx"> #define MRCP_SESSION_SID(session) \
</span><span class="cx">         (session)-&gt;id.buf ? (session)-&gt;id.buf : &quot;new&quot;
</span><span class="cx"> 
</span><ins>+/** Macro to log session pointers and string identifiers */
</ins><span class="cx"> #define MRCP_SESSION_PTRSID(session) \
</span><span class="cx">         MRCP_SESSION_PTR(session), MRCP_SESSION_SID(session)
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpsignalingincludemrcp_session_descriptorh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -69,8 +69,7 @@
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE apr_size_t mrcp_session_control_media_add(mrcp_session_descriptor_t *descriptor, void *media)
</span><span class="cx"> {
</span><del>-        void **slot = apr_array_push(descriptor-&gt;control_media_arr);
-        *slot = media;
</del><ins>+        APR_ARRAY_PUSH(descriptor-&gt;control_media_arr,void*) = media;
</ins><span class="cx">         return mrcp_session_media_count_get(descriptor) - 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -79,7 +78,7 @@
</span><span class="cx">         if((int)id &gt;= descriptor-&gt;control_media_arr-&gt;nelts) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><del>-        return ((void**)descriptor-&gt;control_media_arr-&gt;elts)[id];
</del><ins>+        return APR_ARRAY_IDX(descriptor-&gt;control_media_arr,id,void*);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE apt_bool_t mrcp_session_control_media_set(mrcp_session_descriptor_t *descriptor, apr_size_t id, void *media)
</span><span class="lines">@@ -87,15 +86,14 @@
</span><span class="cx">         if((int)id &gt;= descriptor-&gt;control_media_arr-&gt;nelts) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        ((void**)descriptor-&gt;control_media_arr-&gt;elts)[id] = media;
</del><ins>+        APR_ARRAY_IDX(descriptor-&gt;control_media_arr,id,void*) = media;
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE apr_size_t mrcp_session_audio_media_add(mrcp_session_descriptor_t *descriptor, mpf_rtp_media_descriptor_t *media)
</span><span class="cx"> {
</span><del>-        mpf_rtp_media_descriptor_t **slot = apr_array_push(descriptor-&gt;audio_media_arr);
-        *slot = media;
</del><ins>+        APR_ARRAY_PUSH(descriptor-&gt;audio_media_arr,mpf_rtp_media_descriptor_t*) = media;
</ins><span class="cx">         return mrcp_session_media_count_get(descriptor) - 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -104,7 +102,7 @@
</span><span class="cx">         if((int)id &gt;= descriptor-&gt;audio_media_arr-&gt;nelts) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><del>-        return ((mpf_rtp_media_descriptor_t**)descriptor-&gt;audio_media_arr-&gt;elts)[id];
</del><ins>+        return APR_ARRAY_IDX(descriptor-&gt;audio_media_arr,id,mpf_rtp_media_descriptor_t*);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE apt_bool_t mrcp_session_audio_media_set(const mrcp_session_descriptor_t *descriptor, apr_size_t id, mpf_rtp_media_descriptor_t* media)
</span><span class="lines">@@ -112,15 +110,14 @@
</span><span class="cx">         if((int)id &gt;= descriptor-&gt;audio_media_arr-&gt;nelts) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        ((mpf_rtp_media_descriptor_t**)descriptor-&gt;audio_media_arr-&gt;elts)[id] = media;
</del><ins>+        APR_ARRAY_IDX(descriptor-&gt;audio_media_arr,id,mpf_rtp_media_descriptor_t*) = media;
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE apr_size_t mrcp_session_video_media_add(mrcp_session_descriptor_t *descriptor, mpf_rtp_media_descriptor_t *media)
</span><span class="cx"> {
</span><del>-        mpf_rtp_media_descriptor_t **slot = apr_array_push(descriptor-&gt;video_media_arr);
-        *slot = media;
</del><ins>+        APR_ARRAY_PUSH(descriptor-&gt;video_media_arr,mpf_rtp_media_descriptor_t*) = media;
</ins><span class="cx">         return mrcp_session_media_count_get(descriptor) - 1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -129,7 +126,7 @@
</span><span class="cx">         if((int)id &gt;= descriptor-&gt;video_media_arr-&gt;nelts) {
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><del>-        return ((mpf_rtp_media_descriptor_t**)descriptor-&gt;video_media_arr-&gt;elts)[id];
</del><ins>+        return APR_ARRAY_IDX(descriptor-&gt;video_media_arr,id,mpf_rtp_media_descriptor_t*);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static APR_INLINE apt_bool_t mrcp_session_video_media_set(mrcp_session_descriptor_t *descriptor, apr_size_t id, mpf_rtp_media_descriptor_t* media)
</span><span class="lines">@@ -137,7 +134,7 @@
</span><span class="cx">         if((int)id &gt;= descriptor-&gt;video_media_arr-&gt;nelts) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        ((mpf_rtp_media_descriptor_t**)descriptor-&gt;video_media_arr-&gt;elts)[id] = media;
</del><ins>+        APR_ARRAY_IDX(descriptor-&gt;video_media_arr,id,mpf_rtp_media_descriptor_t*) = media;
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportincludemrcp_connectionh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -77,7 +77,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Create MRCP connection. */
</span><del>-mrcp_connection_t* mrcp_connection_create();
</del><ins>+mrcp_connection_t* mrcp_connection_create(void);
</ins><span class="cx"> 
</span><span class="cx"> /** Destroy MRCP connection. */
</span><span class="cx"> void mrcp_connection_destroy(mrcp_connection_t *connection);
</span><span class="lines">@@ -91,6 +91,8 @@
</span><span class="cx"> /** Remove Control Channel from MRCP connection. */
</span><span class="cx"> apt_bool_t mrcp_connection_channel_remove(mrcp_connection_t *connection, mrcp_control_channel_t *channel);
</span><span class="cx"> 
</span><ins>+/** Raise disconnect event for each channel from the specified connection. */
+apt_bool_t mrcp_connection_disconnect_raise(mrcp_connection_t *connection, const mrcp_connection_event_vtable_t *vtable);
</ins><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportincludemrcp_connection_typesh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -53,6 +53,8 @@
</span><span class="cx">         apt_bool_t (*on_remove)(mrcp_control_channel_t *channel, apt_bool_t status);
</span><span class="cx">         /** Message receive event handler */
</span><span class="cx">         apt_bool_t (*on_receive)(mrcp_control_channel_t *channel, mrcp_message_t *message);
</span><ins>+        /** Disconnect event handler */
+        apt_bool_t (*on_disconnect)(mrcp_control_channel_t *channel);
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** MRCPv2 control channel */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportincludemrcp_control_descriptorh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -22,11 +22,16 @@
</span><span class="cx">  * @brief MRCPv2 Control Descriptor
</span><span class="cx">  */ 
</span><span class="cx"> 
</span><ins>+#include &lt;apr_tables.h&gt;
</ins><span class="cx"> #include &quot;apt_string.h&quot;
</span><span class="cx"> #include &quot;mrcp_connection_types.h&quot;
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><ins>+/** TCP discard port used in offer/answer */
+#define TCP_DISCARD_PORT 9
+
+
</ins><span class="cx"> /** MRCPv2 proto transport */
</span><span class="cx"> typedef enum {
</span><span class="cx">         MRCP_PROTO_TCP,
</span><span class="lines">@@ -85,32 +90,28 @@
</span><span class="cx">         apt_str_t              resource_name;
</span><span class="cx">         /** Session identifier */
</span><span class="cx">         apt_str_t              session_id;
</span><del>-        /** Control media identifier */
-        apr_size_t             cmid;
</del><ins>+        /** Array of cmid attributes */
+        apr_array_header_t    *cmid_arr;
</ins><span class="cx">         /** Base identifier */
</span><span class="cx">         apr_size_t             id;
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-/** Initialize MRCP control descriptor */
-static APR_INLINE void mrcp_control_descriptor_init(mrcp_control_descriptor_t *descriptor)
-{
-        apt_string_reset(&amp;descriptor-&gt;ip);
-        descriptor-&gt;port = 0;
-        descriptor-&gt;proto = MRCP_PROTO_UNKNOWN;
-        descriptor-&gt;setup_type = MRCP_SETUP_TYPE_UNKNOWN;
-        descriptor-&gt;connection_type = MRCP_CONNECTION_TYPE_UNKNOWN;
-        apt_string_reset(&amp;descriptor-&gt;resource_name);
-        apt_string_reset(&amp;descriptor-&gt;session_id);
-        descriptor-&gt;cmid = 0;
-        descriptor-&gt;id = 0;
-}
</del><span class="cx"> 
</span><ins>+/** Create MRCP control descriptor */
+MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_descriptor_create(apr_pool_t *pool);
+
</ins><span class="cx"> /** Create MRCP control offer */
</span><span class="cx"> MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_offer_create(apr_pool_t *pool);
</span><span class="cx"> 
</span><span class="cx"> /** Create MRCP control answer */
</span><span class="cx"> MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_answer_create(mrcp_control_descriptor_t *offer, apr_pool_t *pool);
</span><span class="cx"> 
</span><ins>+/** Add cmid to cmid_arr */
+MRCP_DECLARE(void) mrcp_cmid_add(apr_array_header_t *cmid_arr, apr_size_t cmid);
+
+/** Find cmid in cmid_arr */
+MRCP_DECLARE(apt_bool_t) mrcp_cmid_find(apr_array_header_t *cmid_arr, apr_size_t cmid);
+
</ins><span class="cx"> /** Get MRCP protocol transport name by identifier */
</span><span class="cx"> MRCP_DECLARE(const apt_str_t*) mrcp_proto_get(mrcp_proto_type_e proto);
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_client_connectionc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -96,6 +96,7 @@
</span><span class="cx">                 vtable-&gt;terminate = mrcp_client_agent_task_terminate;
</span><span class="cx">                 vtable-&gt;destroy = mrcp_client_agent_task_on_destroy;
</span><span class="cx">         }
</span><ins>+        apt_task_auto_ready_set(agent-&gt;task,FALSE);
</ins><span class="cx"> 
</span><span class="cx">         agent-&gt;connection_list = apt_list_create(pool);
</span><span class="cx"> 
</span><span class="lines">@@ -310,7 +311,8 @@
</span><span class="cx">                 connection = apt_list_elem_object_get(elem);
</span><span class="cx">                 if(connection) {
</span><span class="cx">                         if(apr_sockaddr_info_get(&amp;sockaddr,descriptor-&gt;ip.buf,APR_INET,descriptor-&gt;port,0,connection-&gt;pool) == APR_SUCCESS) {
</span><del>-                                if(apr_sockaddr_equal(sockaddr,connection-&gt;r_sockaddr) != 0) {
</del><ins>+                                if(apr_sockaddr_equal(sockaddr,connection-&gt;r_sockaddr) != 0 &amp;&amp; 
+                                        descriptor-&gt;port == connection-&gt;r_sockaddr-&gt;port) {
</ins><span class="cx">                                         return connection;
</span><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="lines">@@ -514,7 +516,7 @@
</span><span class="cx">                 apr_socket_close(connection-&gt;sock);
</span><span class="cx">                 connection-&gt;sock = NULL;
</span><span class="cx"> 
</span><del>-//                agent-&gt;vtable-&gt;on_disconnect(agent,connection);
</del><ins>+                mrcp_connection_disconnect_raise(connection,agent-&gt;vtable);
</ins><span class="cx">                 return TRUE;
</span><span class="cx">         }
</span><span class="cx">         /* calculate actual length of the stream */
</span><span class="lines">@@ -588,6 +590,9 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* explicitly indicate task is ready to process messages */
+        apt_task_ready(agent-&gt;task);
+
</ins><span class="cx">         while(running) {
</span><span class="cx">                 status = apt_pollset_poll(agent-&gt;pollset, -1, &amp;num, &amp;ret_pfd);
</span><span class="cx">                 if(status != APR_SUCCESS) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_connectionc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -78,3 +78,21 @@
</span><span class="cx">         connection-&gt;access_count--;
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><ins>+
+apt_bool_t mrcp_connection_disconnect_raise(mrcp_connection_t *connection, const mrcp_connection_event_vtable_t *vtable)
+{
+        if(vtable &amp;&amp; vtable-&gt;on_disconnect) {
+                mrcp_control_channel_t *channel;
+                void *val;
+                apr_hash_index_t *it = apr_hash_first(connection-&gt;pool,connection-&gt;channel_table);
+                /* walk through the list of channels and raise disconnect event for them */
+                for(; it; it = apr_hash_next(it)) {
+                        apr_hash_this(it,NULL,NULL,&amp;val);
+                        channel = val;
+                        if(channel) {
+                                vtable-&gt;on_disconnect(channel);
+                        }
+                }
+        }
+        return TRUE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_control_descriptorc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -85,14 +85,30 @@
</span><span class="cx">         return apt_string_table_id_find(mrcp_connection_value_table,MRCP_CONNECTION_TYPE_COUNT,attrib);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Create MRCP control descriptor */
+MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_descriptor_create(apr_pool_t *pool)
+{
+        mrcp_control_descriptor_t *descriptor;
+        descriptor = apr_palloc(pool,sizeof(mrcp_control_descriptor_t));
+
+        apt_string_reset(&amp;descriptor-&gt;ip);
+        descriptor-&gt;port = 0;
+        descriptor-&gt;proto = MRCP_PROTO_UNKNOWN;
+        descriptor-&gt;setup_type = MRCP_SETUP_TYPE_UNKNOWN;
+        descriptor-&gt;connection_type = MRCP_CONNECTION_TYPE_UNKNOWN;
+        apt_string_reset(&amp;descriptor-&gt;resource_name);
+        apt_string_reset(&amp;descriptor-&gt;session_id);
+        descriptor-&gt;cmid_arr = apr_array_make(pool,1,sizeof(apr_size_t));
+        descriptor-&gt;id = 0;
+        return descriptor;
+}
+
</ins><span class="cx"> /** Create MRCP control offer */
</span><span class="cx"> MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_offer_create(apr_pool_t *pool)
</span><span class="cx"> {
</span><del>-        mrcp_control_descriptor_t *offer;
-        offer = apr_palloc(pool,sizeof(mrcp_control_descriptor_t));
-        mrcp_control_descriptor_init(offer);
</del><ins>+        mrcp_control_descriptor_t *offer = mrcp_control_descriptor_create(pool);
</ins><span class="cx">         offer-&gt;proto = MRCP_PROTO_TCP;
</span><del>-        offer-&gt;port = 9;
</del><ins>+        offer-&gt;port = TCP_DISCARD_PORT;
</ins><span class="cx">         offer-&gt;setup_type = MRCP_SETUP_TYPE_ACTIVE;
</span><span class="cx">         offer-&gt;connection_type = MRCP_CONNECTION_TYPE_EXISTING;
</span><span class="cx">         return offer;
</span><span class="lines">@@ -101,12 +117,29 @@
</span><span class="cx"> /** Create MRCP control answer */
</span><span class="cx"> MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_answer_create(mrcp_control_descriptor_t *offer, apr_pool_t *pool)
</span><span class="cx"> {
</span><del>-        mrcp_control_descriptor_t *answer;
-        answer = apr_palloc(pool,sizeof(mrcp_control_descriptor_t));
-        mrcp_control_descriptor_init(answer);
</del><ins>+        mrcp_control_descriptor_t *answer = mrcp_control_descriptor_create(pool);
</ins><span class="cx">         if(offer) {
</span><span class="cx">                 *answer = *offer;
</span><ins>+                answer-&gt;cmid_arr = apr_array_copy(pool,offer-&gt;cmid_arr);
</ins><span class="cx">         }
</span><span class="cx">         answer-&gt;setup_type = MRCP_SETUP_TYPE_PASSIVE;
</span><span class="cx">         return answer;
</span><span class="cx"> }
</span><ins>+
+/** Add cmid to cmid_arr */
+MRCP_DECLARE(void) mrcp_cmid_add(apr_array_header_t *cmid_arr, apr_size_t cmid)
+{
+        APR_ARRAY_PUSH(cmid_arr, apr_size_t) = cmid;
+}
+
+/** Find cmid in cmid_arr */
+MRCP_DECLARE(apt_bool_t) mrcp_cmid_find(apr_array_header_t *cmid_arr, apr_size_t cmid)
+{
+        int i;
+        for(i=0; i&lt;cmid_arr-&gt;nelts; i++) {
+                if(APR_ARRAY_IDX(cmid_arr,i,apr_size_t) == cmid) {
+                        return TRUE;
+                }
+        }
+        return FALSE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsmrcpv2transportsrcmrcp_server_connectionc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -114,6 +114,7 @@
</span><span class="cx">                 vtable-&gt;terminate = mrcp_server_agent_task_terminate;
</span><span class="cx">                 vtable-&gt;destroy = mrcp_server_agent_task_on_destroy;
</span><span class="cx">         }
</span><ins>+        apt_task_auto_ready_set(agent-&gt;task,FALSE);
</ins><span class="cx"> 
</span><span class="cx">         agent-&gt;msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
</span><span class="cx">         apr_thread_mutex_create(&amp;agent-&gt;guard,APR_THREAD_MUTEX_UNNESTED,pool);
</span><span class="lines">@@ -610,12 +611,14 @@
</span><span class="cx">         }
</span><span class="cx">         else if(result == MRCP_STREAM_MESSAGE_INVALID) {
</span><span class="cx">                 /* error case */
</span><del>-                mrcp_message_t *response;
</del><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Parse MRCPv2 Stream&quot;);
</span><del>-                response = mrcp_response_create(message,message-&gt;pool);
-                response-&gt;start_line.status_code = MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE;
-                if(mrcp_server_agent_messsage_send(agent,connection,response) == FALSE) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Send MRCPv2 Response&quot;);
</del><ins>+                if(message-&gt;resource) {
+                        mrcp_message_t *response;
+                        response = mrcp_response_create(message,message-&gt;pool);
+                        response-&gt;start_line.status_code = MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE;
+                        if(mrcp_server_agent_messsage_send(agent,connection,response) == FALSE) {
+                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Send MRCPv2 Response&quot;);
+                        }
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -713,6 +716,9 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* explicitly indicate task is ready to process messages */
+        apt_task_ready(agent-&gt;task);
+
</ins><span class="cx">         while(running) {
</span><span class="cx">                 status = apt_pollset_poll(agent-&gt;pollset, -1, &amp;num, &amp;ret_pfd);
</span><span class="cx">                 if(status != APR_SUCCESS) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsunirtspincludertsp_headerh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx">         RTSP_TRANSPORT_ATTRIB_DESTINATION,
</span><span class="cx">         RTSP_TRANSPORT_ATTRIB_UNICAST,
</span><span class="cx">         RTSP_TRANSPORT_ATTRIB_MULTICAST,
</span><ins>+        RTSP_TRANSPORT_ATTRIB_MODE,
</ins><span class="cx"> 
</span><span class="cx">         RTSP_TRANSPORT_ATTRIB_COUNT,
</span><span class="cx">         RTSP_TRANSPORT_ATTRIB_NONE = RTSP_TRANSPORT_ATTRIB_COUNT
</span><span class="lines">@@ -135,6 +136,8 @@
</span><span class="cx">         apt_str_t                source;
</span><span class="cx">         /** Destination IP address */
</span><span class="cx">         apt_str_t                destination;
</span><ins>+        /** Mode indicates the method to support (either PLAY or RECORD) */
+        apt_str_t                mode;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** RTSP header */
</span><span class="lines">@@ -181,6 +184,7 @@
</span><span class="cx">         rtsp_port_range_init(&amp;transport-&gt;server_port_range);
</span><span class="cx">         apt_string_reset(&amp;transport-&gt;source);
</span><span class="cx">         apt_string_reset(&amp;transport-&gt;destination);
</span><ins>+        apt_string_reset(&amp;transport-&gt;mode);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Initialize header */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_clientc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -582,10 +582,12 @@
</span><span class="cx">                 apr_hash_set(session-&gt;resource_table,resource_name,APR_HASH_KEY_STRING,NULL);
</span><span class="cx"> 
</span><span class="cx">                 if(apr_hash_count(session-&gt;resource_table) == 0) {
</span><del>-                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove RTSP Session &quot;APT_PTRSID_FMT,
-                                session,
-                                session-&gt;id.buf);
-                        apr_hash_set(session-&gt;connection-&gt;session_table,session-&gt;id.buf,session-&gt;id.length,NULL);
</del><ins>+                        if(session-&gt;connection) {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove RTSP Session &quot;APT_PTRSID_FMT,
+                                        session,
+                                        session-&gt;id.buf);
+                                apr_hash_set(session-&gt;connection-&gt;session_table,session-&gt;id.buf,session-&gt;id.length,NULL);
+                        }
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_headerc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -53,11 +53,12 @@
</span><span class="cx"> /** String table of RTSP transport attributes (rtsp_transport_attrib_e) */
</span><span class="cx"> static const apt_str_table_item_t rtsp_transport_attrib_string_table[] = {
</span><span class="cx">         {{&quot;client_port&quot;, 11},0},
</span><del>-        {{&quot;server_port&quot;, 11},1},
-        {{&quot;source&quot;,      6}, 1},
</del><ins>+        {{&quot;server_port&quot;, 11},2},
+        {{&quot;source&quot;,       6},2},
</ins><span class="cx">         {{&quot;destination&quot;, 11},0},
</span><del>-        {{&quot;unicast&quot;,     7}, 0},
-        {{&quot;multicast&quot;,   9}, 0}
</del><ins>+        {{&quot;unicast&quot;,      7},0},
+        {{&quot;multicast&quot;,    9},1},
+        {{&quot;mode&quot;,         4},2}
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> /** Parse RTSP transport port range */
</span><span class="lines">@@ -96,15 +97,15 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Parse RTSP source/destination address */
-static apt_bool_t rtsp_address_parse(apt_str_t *address, apt_text_stream_t *stream, apr_pool_t *pool)
</del><ins>+/** Parse text value of RTSP transport attrib (source/destination, e.t.c) */
+static apt_bool_t rtsp_transport_attrib_value_parse(apt_str_t *value, apt_text_stream_t *stream, apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        apt_str_t value;
-        /* read min value */
-        if(apt_text_field_read(stream,';',TRUE,&amp;value) == FALSE) {
</del><ins>+        apt_str_t field;
+        /* read value */
+        if(apt_text_field_read(stream,';',TRUE,&amp;field) == FALSE) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-        apt_string_copy(address,&amp;value,pool);
</del><ins>+        apt_string_copy(value,&amp;field,pool);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -132,10 +133,10 @@
</span><span class="cx">                         rtsp_port_range_parse(&amp;transport-&gt;client_port_range,&amp;stream);
</span><span class="cx">                         break;
</span><span class="cx">                 case RTSP_TRANSPORT_ATTRIB_SOURCE:
</span><del>-                        rtsp_address_parse(&amp;transport-&gt;source,&amp;stream,pool);
</del><ins>+                        rtsp_transport_attrib_value_parse(&amp;transport-&gt;source,&amp;stream,pool);
</ins><span class="cx">                         break;
</span><span class="cx">                 case RTSP_TRANSPORT_ATTRIB_DESTINATION:
</span><del>-                        rtsp_address_parse(&amp;transport-&gt;destination,&amp;stream,pool);
</del><ins>+                        rtsp_transport_attrib_value_parse(&amp;transport-&gt;destination,&amp;stream,pool);
</ins><span class="cx">                         break;
</span><span class="cx">                 case RTSP_TRANSPORT_ATTRIB_UNICAST:
</span><span class="cx">                         transport-&gt;delivery = RTSP_DELIVERY_UNICAST;
</span><span class="lines">@@ -143,6 +144,9 @@
</span><span class="cx">                 case RTSP_TRANSPORT_ATTRIB_MULTICAST:
</span><span class="cx">                         transport-&gt;delivery = RTSP_DELIVERY_MULTICAST;
</span><span class="cx">                         break;
</span><ins>+                case RTSP_TRANSPORT_ATTRIB_MODE:
+                        rtsp_transport_attrib_value_parse(&amp;transport-&gt;mode,&amp;stream,pool);
+                        break;
</ins><span class="cx">                 default:
</span><span class="cx">                         break;
</span><span class="cx">         }
</span><span class="lines">@@ -180,7 +184,7 @@
</span><span class="cx">         if(transport-&gt;profile &gt;= RTSP_PROFILE_COUNT) {
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><del>-                
</del><ins>+
</ins><span class="cx">         /* read optional lower transport protocol (UDP) */
</span><span class="cx">         if(apt_text_field_read(&amp;stream,'/',TRUE,&amp;field) == TRUE) {
</span><span class="cx">                 transport-&gt;lower_protocol = apt_string_table_id_find(rtsp_lower_transport_string_table,RTSP_LOWER_TRANSPORT_COUNT,&amp;field);
</span><span class="lines">@@ -256,6 +260,17 @@
</span><span class="cx">                 apt_text_char_insert(text_stream,';');
</span><span class="cx">                 rtsp_port_range_generate(RTSP_TRANSPORT_ATTRIB_SERVER_PORT,&amp;transport-&gt;server_port_range,text_stream);
</span><span class="cx">         }
</span><ins>+
+        if(transport-&gt;mode.length) {
+                const apt_str_t *str;
+                str = apt_string_table_str_get(rtsp_transport_attrib_string_table,RTSP_TRANSPORT_ATTRIB_COUNT,RTSP_TRANSPORT_ATTRIB_MODE);
+                if(str) {
+                        apt_text_char_insert(text_stream,';');
+                        apt_string_value_generate(str,text_stream);
+                        apt_text_char_insert(text_stream,'=');
+                        apt_string_value_generate(&amp;transport-&gt;mode,text_stream);
+                }
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_messagec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -46,13 +46,13 @@
</span><span class="cx"> {
</span><span class="cx">         const apt_str_t *reason_str;
</span><span class="cx">         rtsp_status_line_t *status_line;
</span><del>-        rtsp_message_t *response = rtsp_message_create(RTSP_MESSAGE_TYPE_RESPONSE,request-&gt;pool);
</del><ins>+        rtsp_message_t *response = rtsp_message_create(RTSP_MESSAGE_TYPE_RESPONSE,pool);
</ins><span class="cx">         status_line = &amp;response-&gt;start_line.common.status_line;
</span><span class="cx">         status_line-&gt;version = request-&gt;start_line.common.request_line.version;
</span><span class="cx">         status_line-&gt;status_code = status_code;
</span><span class="cx">         reason_str = rtsp_reason_phrase_get(reason);
</span><span class="cx">         if(reason_str) {
</span><del>-                apt_string_copy(&amp;status_line-&gt;reason,reason_str,request-&gt;pool);
</del><ins>+                apt_string_copy(&amp;status_line-&gt;reason,reason_str,pool);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(rtsp_header_property_check(&amp;request-&gt;header.property_set,RTSP_HEADER_FIELD_CSEQ) == TRUE) {
</span><span class="lines">@@ -60,6 +60,15 @@
</span><span class="cx">                 rtsp_header_property_add(&amp;response-&gt;header.property_set,RTSP_HEADER_FIELD_CSEQ);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if(rtsp_header_property_check(&amp;request-&gt;header.property_set,RTSP_HEADER_FIELD_TRANSPORT) == TRUE) {
+                const rtsp_transport_t *req_transport = &amp;request-&gt;header.transport;
+                rtsp_transport_t *res_transport = &amp;response-&gt;header.transport;
+                if(req_transport-&gt;mode.length) {
+                        apt_string_copy(&amp;res_transport-&gt;mode,&amp;req_transport-&gt;mode,pool);
+                        rtsp_header_property_add(&amp;response-&gt;header.property_set,RTSP_HEADER_FIELD_TRANSPORT);
+                }
+        }
+
</ins><span class="cx">         return response;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcplibsunirtspsrcrtsp_serverc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -70,7 +70,6 @@
</span><span class="cx"> 
</span><span class="cx">         /** Session identifier */
</span><span class="cx">         apt_str_t                 id;
</span><del>-        apt_str_t                 url;
</del><span class="cx"> 
</span><span class="cx">         /** Last cseq sent */
</span><span class="cx">         apr_size_t                last_cseq;
</span><span class="lines">@@ -80,6 +79,9 @@
</span><span class="cx">         /** request queue */
</span><span class="cx">         apt_obj_list_t           *request_queue;
</span><span class="cx"> 
</span><ins>+        /** Resource table */
+        apr_hash_t               *resource_table;
+
</ins><span class="cx">         /** In-progress termination request */
</span><span class="cx">         apt_bool_t                terminating;
</span><span class="cx"> };
</span><span class="lines">@@ -261,9 +263,9 @@
</span><span class="cx">         session-&gt;last_cseq = 0;
</span><span class="cx">         session-&gt;active_request = NULL;
</span><span class="cx">         session-&gt;request_queue = apt_list_create(pool);
</span><ins>+        session-&gt;resource_table = apr_hash_make(pool);
</ins><span class="cx">         session-&gt;terminating = FALSE;
</span><span class="cx"> 
</span><del>-        apt_string_reset(&amp;session-&gt;url);
</del><span class="cx">         apt_unique_id_generate(&amp;session-&gt;id,RTSP_SESSION_ID_HEX_STRING_LENGTH,pool);
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Create RTSP Session &quot;APT_SID_FMT,session-&gt;id.buf);
</span><span class="cx">         if(server-&gt;vtable-&gt;create_session(server,session) != TRUE) {
</span><span class="lines">@@ -335,8 +337,14 @@
</span><span class="cx"> static apt_bool_t rtsp_server_session_message_handle(rtsp_server_t *server, rtsp_server_session_t *session, rtsp_message_t *message)
</span><span class="cx"> {
</span><span class="cx">         if(message-&gt;start_line.common.request_line.method_id == RTSP_METHOD_TEARDOWN) {
</span><del>-                rtsp_server_session_terminate_request(server,session);
-                return TRUE;
</del><ins>+                /* remove resource */
+                const char *resource_name = message-&gt;start_line.common.request_line.resource_name;
+                apr_hash_set(session-&gt;resource_table,resource_name,APR_HASH_KEY_STRING,NULL);
+
+                if(apr_hash_count(session-&gt;resource_table) == 0) {
+                        rtsp_server_session_terminate_request(server,session);
+                        return TRUE;
+                }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(server-&gt;vtable-&gt;handle_message(server,session,message) != TRUE) {
</span><span class="lines">@@ -349,7 +357,7 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/* Process incoming SETUP request */
</del><ins>+/* Process incoming SETUP/DESCRIBE request */
</ins><span class="cx"> static rtsp_server_session_t* rtsp_server_session_setup_process(rtsp_server_t *server, rtsp_server_connection_t *rtsp_connection, rtsp_message_t *message)
</span><span class="cx"> {
</span><span class="cx">         rtsp_server_session_t *session = NULL;
</span><span class="lines">@@ -357,7 +365,6 @@
</span><span class="cx">                 /* create new session */
</span><span class="cx">                 session = rtsp_server_session_create(server);
</span><span class="cx">                 session-&gt;connection = rtsp_connection;
</span><del>-                session-&gt;url = message-&gt;start_line.common.request_line.url;
</del><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Add RTSP Session &quot;APT_SID_FMT,session-&gt;id.buf);
</span><span class="cx">                 apr_hash_set(rtsp_connection-&gt;session_table,session-&gt;id.buf,session-&gt;id.length,session);
</span><span class="cx">         }
</span><span class="lines">@@ -405,13 +412,21 @@
</span><span class="cx">                                 message-&gt;header.session_id.buf,
</span><span class="cx">                                 message-&gt;header.session_id.length);
</span><span class="cx">         if(!session) {
</span><del>-                /* error case */
</del><ins>+                /* error case, no such session */
</ins><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Such RTSP Session &quot;APT_SID_FMT,message-&gt;header.session_id.buf);
</span><span class="cx">                 return rtsp_server_error_respond(server,rtsp_connection,message,
</span><span class="cx">                                                                 RTSP_STATUS_CODE_NOT_FOUND,
</span><span class="cx">                                                                 RTSP_REASON_PHRASE_NOT_FOUND);
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        if(session-&gt;terminating == TRUE) {
+                /* error case, session is being terminated */
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Not Acceptable Request &quot;APT_SID_FMT,message-&gt;header.session_id.buf);
+                return rtsp_server_error_respond(server,rtsp_connection,message,
+                                                                RTSP_STATUS_CODE_NOT_ACCEPTABLE,
+                                                                RTSP_REASON_PHRASE_NOT_ACCEPTABLE);
+        }
+        
</ins><span class="cx">         if(session-&gt;active_request) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Push RTSP Request to Queue &quot;APT_SID_FMT,session-&gt;id.buf);
</span><span class="cx">                 apt_list_push_back(session-&gt;request_queue,message,message-&gt;pool);
</span><span class="lines">@@ -427,36 +442,64 @@
</span><span class="cx"> /* Process outgoing RTSP response */
</span><span class="cx"> static apt_bool_t rtsp_server_session_response_process(rtsp_server_t *server, rtsp_server_session_t *session, rtsp_message_t *message)
</span><span class="cx"> {
</span><del>-        if(session-&gt;id.buf) {
-                message-&gt;header.session_id = session-&gt;id;
-                rtsp_header_property_add(&amp;message-&gt;header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
-        }
-
</del><ins>+        apt_bool_t terminate = FALSE;
+        rtsp_message_t *request = NULL;
</ins><span class="cx">         if(message-&gt;start_line.message_type == RTSP_MESSAGE_TYPE_REQUEST) {
</span><span class="cx">                 /* RTSP ANNOUNCE request (asynch event) */
</span><del>-                message-&gt;start_line.common.request_line.url = session-&gt;url;
</del><ins>+                const char *resource_name = message-&gt;start_line.common.request_line.resource_name;
+                if(resource_name) {
+                        request = apr_hash_get(session-&gt;resource_table,resource_name,APR_HASH_KEY_STRING);
+                }
+                if(!request) {
+                        return FALSE;
+                }
+                message-&gt;start_line.common.request_line.url = request-&gt;start_line.common.request_line.url;
</ins><span class="cx">                 message-&gt;header.cseq = session-&gt;last_cseq;
</span><span class="cx">                 rtsp_header_property_add(&amp;message-&gt;header.property_set,RTSP_HEADER_FIELD_CSEQ);
</span><span class="cx">                 
</span><ins>+                if(session-&gt;id.buf) {
+                        message-&gt;header.session_id = session-&gt;id;
+                        rtsp_header_property_add(&amp;message-&gt;header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+                }
</ins><span class="cx">                 rtsp_server_message_send(server,session-&gt;connection-&gt;base,message);
</span><span class="cx">                 return TRUE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        session-&gt;last_cseq = message-&gt;header.cseq;
-        rtsp_server_message_send(server,session-&gt;connection-&gt;base,message);
</del><ins>+        if(!session-&gt;active_request) {
+                /* unexpected response */
+                return FALSE;
+        }
</ins><span class="cx"> 
</span><del>-        if(session-&gt;active_request) {
-                rtsp_message_t *request = session-&gt;active_request;
</del><ins>+        request = session-&gt;active_request;
+        if(request-&gt;start_line.common.request_line.method_id == RTSP_METHOD_DESCRIBE) {
+                terminate = TRUE;
+        }
+        else {
+                if(session-&gt;id.buf) {
+                        message-&gt;header.session_id = session-&gt;id;
+                        rtsp_header_property_add(&amp;message-&gt;header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+                }
</ins><span class="cx">                 if(request-&gt;start_line.common.request_line.method_id == RTSP_METHOD_SETUP) {
</span><del>-                        if(message-&gt;start_line.common.status_line.status_code != RTSP_STATUS_CODE_OK) {
-                                rtsp_server_session_terminate_request(server,session);
</del><ins>+                        if(message-&gt;start_line.common.status_line.status_code == RTSP_STATUS_CODE_OK) {
+                                /* add resource */
+                                const char *resource_name = request-&gt;start_line.common.request_line.resource_name;
+                                apr_hash_set(session-&gt;resource_table,resource_name,APR_HASH_KEY_STRING,request);
</ins><span class="cx">                         }
</span><ins>+                        else if(apr_hash_count(session-&gt;resource_table) == 0) {
+                                terminate = TRUE;
+                        }
</ins><span class="cx">                 }
</span><del>-                else if(request-&gt;start_line.common.request_line.method_id == RTSP_METHOD_DESCRIBE) {
-                        rtsp_server_session_terminate_request(server,session);
-                }
</del><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        session-&gt;last_cseq = message-&gt;header.cseq;
+        rtsp_server_message_send(server,session-&gt;connection-&gt;base,message);
+
+        if(terminate == TRUE) {
+                session-&gt;active_request = NULL;
+                rtsp_server_session_terminate_request(server,session);
+                return TRUE;
+        }
+
</ins><span class="cx">         session-&gt;active_request = apt_list_pop_front(session-&gt;request_queue);
</span><span class="cx">         if(session-&gt;active_request) {
</span><span class="cx">                 rtsp_server_session_message_handle(server,session,session-&gt;active_request);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpmodulesmrcpsofiasipsrcmrcp_sdpc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -56,14 +56,14 @@
</span><span class="cx">         count = mrcp_session_media_count_get(descriptor);
</span><span class="cx">         for(i=0; i&lt;count; i++) {
</span><span class="cx">                 audio_media = mrcp_session_audio_media_get(descriptor,audio_index);
</span><del>-                if(audio_media &amp;&amp; audio_media-&gt;base.id == i) {
</del><ins>+                if(audio_media &amp;&amp; audio_media-&gt;id == i) {
</ins><span class="cx">                         /* generate audio media */
</span><span class="cx">                         audio_index++;
</span><span class="cx">                         offset += sdp_rtp_media_generate(buffer+offset,size-offset,descriptor,audio_media);
</span><span class="cx">                         continue;
</span><span class="cx">                 }
</span><span class="cx">                 video_media = mrcp_session_video_media_get(descriptor,video_index);
</span><del>-                if(video_media &amp;&amp; video_media-&gt;base.id == i) {
</del><ins>+                if(video_media &amp;&amp; video_media-&gt;id == i) {
</ins><span class="cx">                         /* generate video media */
</span><span class="cx">                         video_index++;
</span><span class="cx">                         offset += sdp_rtp_media_generate(buffer+offset,size-offset,descriptor,video_media);
</span><span class="lines">@@ -106,7 +106,7 @@
</span><span class="cx">                         {
</span><span class="cx">                                 mpf_rtp_media_descriptor_t *media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                                 mpf_rtp_media_descriptor_init(media);
</span><del>-                                media-&gt;base.id = mrcp_session_audio_media_add(descriptor,media);
</del><ins>+                                media-&gt;id = mrcp_session_audio_media_add(descriptor,media);
</ins><span class="cx">                                 mpf_rtp_media_generate(media,sdp_media,&amp;descriptor-&gt;ip,pool);
</span><span class="cx">                                 break;
</span><span class="cx">                         }
</span><span class="lines">@@ -114,14 +114,13 @@
</span><span class="cx">                         {
</span><span class="cx">                                 mpf_rtp_media_descriptor_t *media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                                 mpf_rtp_media_descriptor_init(media);
</span><del>-                                media-&gt;base.id = mrcp_session_video_media_add(descriptor,media);
</del><ins>+                                media-&gt;id = mrcp_session_video_media_add(descriptor,media);
</ins><span class="cx">                                 mpf_rtp_media_generate(media,sdp_media,&amp;descriptor-&gt;ip,pool);
</span><span class="cx">                                 break;
</span><span class="cx">                         }
</span><span class="cx">                         case sdp_media_application:
</span><span class="cx">                         {
</span><del>-                                mrcp_control_descriptor_t *control_media = apr_palloc(pool,sizeof(mrcp_control_descriptor_t));
-                                mrcp_control_descriptor_init(control_media);
</del><ins>+                                mrcp_control_descriptor_t *control_media = mrcp_control_descriptor_create(pool);
</ins><span class="cx">                                 control_media-&gt;id = mrcp_session_control_media_add(descriptor,control_media);
</span><span class="cx">                                 mrcp_control_media_generate(control_media,sdp_media,&amp;descriptor-&gt;ip,pool);
</span><span class="cx">                                 break;
</span><span class="lines">@@ -147,31 +146,38 @@
</span><span class="cx">         }
</span><span class="cx">         offset += snprintf(buffer+offset,size-offset,
</span><span class="cx">                 &quot;m=audio %d RTP/AVP&quot;, 
</span><del>-                audio_media-&gt;base.state == MPF_MEDIA_ENABLED ? audio_media-&gt;base.port : 0);
</del><ins>+                audio_media-&gt;state == MPF_MEDIA_ENABLED ? audio_media-&gt;port : 0);
</ins><span class="cx">         for(i=0; i&lt;descriptor_arr-&gt;nelts; i++) {
</span><del>-                codec_descriptor = (mpf_codec_descriptor_t*)descriptor_arr-&gt;elts + i;
</del><ins>+                codec_descriptor = &amp;APR_ARRAY_IDX(descriptor_arr,i,mpf_codec_descriptor_t);
</ins><span class="cx">                 if(codec_descriptor-&gt;enabled == TRUE) {
</span><span class="cx">                         offset += snprintf(buffer+offset,size-offset,&quot; %d&quot;, codec_descriptor-&gt;payload_type);
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         offset += snprintf(buffer+offset,size-offset,&quot;\r\n&quot;);
</span><del>-        if(descriptor-&gt;ip.length &amp;&amp; audio_media-&gt;base.ip.length &amp;&amp; 
-                apt_string_compare(&amp;descriptor-&gt;ip,&amp;audio_media-&gt;base.ip) != TRUE) {
-                const char *media_ip = audio_media-&gt;base.ext_ip.buf ? audio_media-&gt;base.ext_ip.buf : audio_media-&gt;base.ip.buf;
</del><ins>+        if(descriptor-&gt;ip.length &amp;&amp; audio_media-&gt;ip.length &amp;&amp; 
+                apt_string_compare(&amp;descriptor-&gt;ip,&amp;audio_media-&gt;ip) != TRUE) {
+                const char *media_ip = audio_media-&gt;ext_ip.buf ? audio_media-&gt;ext_ip.buf : audio_media-&gt;ip.buf;
</ins><span class="cx">                 offset += sprintf(buffer+offset,&quot;c=IN IP4 %s\r\n&quot;,media_ip);
</span><span class="cx">         }
</span><del>-        if(audio_media-&gt;base.state == MPF_MEDIA_ENABLED) {
-                const apt_str_t *mode_str = mpf_stream_mode_str_get(audio_media-&gt;mode);
</del><ins>+        if(audio_media-&gt;state == MPF_MEDIA_ENABLED) {
+                const apt_str_t *direction_str = mpf_rtp_direction_str_get(audio_media-&gt;direction);
</ins><span class="cx">                 for(i=0; i&lt;descriptor_arr-&gt;nelts; i++) {
</span><del>-                        codec_descriptor = (mpf_codec_descriptor_t*)descriptor_arr-&gt;elts + i;
</del><ins>+                        codec_descriptor = &amp;APR_ARRAY_IDX(descriptor_arr,i,mpf_codec_descriptor_t);
</ins><span class="cx">                         if(codec_descriptor-&gt;enabled == TRUE &amp;&amp; codec_descriptor-&gt;name.buf) {
</span><span class="cx">                                 offset += snprintf(buffer+offset,size-offset,&quot;a=rtpmap:%d %s/%d\r\n&quot;,
</span><span class="cx">                                         codec_descriptor-&gt;payload_type,
</span><span class="cx">                                         codec_descriptor-&gt;name.buf,
</span><span class="cx">                                         codec_descriptor-&gt;sampling_rate);
</span><ins>+                                if(codec_descriptor-&gt;format.buf) {
+                                        offset += snprintf(buffer+offset,size-offset,&quot;a=fmtp:%d %s\r\n&quot;,
+                                                codec_descriptor-&gt;payload_type,
+                                                codec_descriptor-&gt;format.buf);
+                                }
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><del>-                offset += snprintf(buffer+offset,size-offset,&quot;a=%s\r\n&quot;,mode_str ? mode_str-&gt;buf : &quot;&quot;);
</del><ins>+                if(direction_str) {
+                        offset += snprintf(buffer+offset,size-offset,&quot;a=%s\r\n&quot;,direction_str-&gt;buf);
+                }
</ins><span class="cx">                 
</span><span class="cx">                 if(audio_media-&gt;ptime) {
</span><span class="cx">                         offset += snprintf(buffer+offset,size-offset,&quot;a=ptime:%hu\r\n&quot;,audio_media-&gt;ptime);
</span><span class="lines">@@ -184,6 +190,7 @@
</span><span class="cx"> /** Generate SDP media by MRCP control media descriptor */
</span><span class="cx"> static apr_size_t sdp_control_media_generate(char *buffer, apr_size_t size, const mrcp_session_descriptor_t *descriptor, const mrcp_control_descriptor_t *control_media, apt_bool_t offer)
</span><span class="cx"> {
</span><ins>+        int i;
</ins><span class="cx">         apr_size_t offset = 0;
</span><span class="cx">         const apt_str_t *proto;
</span><span class="cx">         const apt_str_t *setup_type;
</span><span class="lines">@@ -197,24 +204,21 @@
</span><span class="cx">                                 &quot;m=application %d %s 1\r\n&quot;
</span><span class="cx">                                 &quot;a=setup:%s\r\n&quot;
</span><span class="cx">                                 &quot;a=connection:%s\r\n&quot;
</span><del>-                                &quot;a=resource:%s\r\n&quot;
-                                &quot;a=cmid:%d\r\n&quot;,
</del><ins>+                                &quot;a=resource:%s\r\n&quot;,
</ins><span class="cx">                                 control_media-&gt;port,
</span><span class="cx">                                 proto ? proto-&gt;buf : &quot;&quot;,
</span><span class="cx">                                 setup_type ? setup_type-&gt;buf : &quot;&quot;,
</span><span class="cx">                                 connection_type ? connection_type-&gt;buf : &quot;&quot;,
</span><del>-                                control_media-&gt;resource_name.buf,
-                                control_media-&gt;cmid);
</del><ins>+                                control_media-&gt;resource_name.buf);
+
</ins><span class="cx">                 }
</span><span class="cx">                 else {
</span><span class="cx">                         offset += snprintf(buffer+offset,size-offset,
</span><span class="cx">                                 &quot;m=application %d %s 1\r\n&quot;
</span><del>-                                &quot;a=resource:%s\r\n&quot;
-                                &quot;a=cmid:%d\r\n&quot;,
</del><ins>+                                &quot;a=resource:%s\r\n&quot;,
</ins><span class="cx">                                 control_media-&gt;port,
</span><span class="cx">                                 proto ? proto-&gt;buf : &quot;&quot;,
</span><del>-                                control_media-&gt;resource_name.buf,
-                                control_media-&gt;cmid);
</del><ins>+                                control_media-&gt;resource_name.buf);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         else { /* answer */
</span><span class="lines">@@ -223,29 +227,32 @@
</span><span class="cx">                                 &quot;m=application %d %s 1\r\n&quot;
</span><span class="cx">                                 &quot;a=setup:%s\r\n&quot;
</span><span class="cx">                                 &quot;a=connection:%s\r\n&quot;
</span><del>-                                &quot;a=channel:%s@%s\r\n&quot;
-                                &quot;a=cmid:%d\r\n&quot;,
</del><ins>+                                &quot;a=channel:%s@%s\r\n&quot;,
</ins><span class="cx">                                 control_media-&gt;port,
</span><span class="cx">                                 proto ? proto-&gt;buf : &quot;&quot;,
</span><span class="cx">                                 setup_type ? setup_type-&gt;buf : &quot;&quot;,
</span><span class="cx">                                 connection_type ? connection_type-&gt;buf : &quot;&quot;,
</span><span class="cx">                                 control_media-&gt;session_id.buf,
</span><del>-                                control_media-&gt;resource_name.buf,
-                                control_media-&gt;cmid);
</del><ins>+                                control_media-&gt;resource_name.buf);
</ins><span class="cx">                 }
</span><span class="cx">                 else {
</span><span class="cx">                         offset += sprintf(buffer+offset,
</span><span class="cx">                                 &quot;m=application %d %s 1\r\n&quot;
</span><del>-                                &quot;a=channel:%s@%s\r\n&quot;
-                                &quot;a=cmid:%d\r\n&quot;,
</del><ins>+                                &quot;a=channel:%s@%s\r\n&quot;,
</ins><span class="cx">                                 control_media-&gt;port,
</span><span class="cx">                                 proto ? proto-&gt;buf : &quot;&quot;,
</span><span class="cx">                                 control_media-&gt;session_id.buf,
</span><del>-                                control_media-&gt;resource_name.buf,
-                                control_media-&gt;cmid);
</del><ins>+                                control_media-&gt;resource_name.buf);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        for(i=0; i&lt;control_media-&gt;cmid_arr-&gt;nelts; i++) {
+                offset += snprintf(buffer+offset,size-offset,
+                        &quot;a=cmid:%d\r\n&quot;,
+                        APR_ARRAY_IDX(control_media-&gt;cmid_arr,i,apr_size_t));
+
+        }
+
</ins><span class="cx">         return offset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -285,31 +292,31 @@
</span><span class="cx"> 
</span><span class="cx">         switch(sdp_media-&gt;m_mode) {
</span><span class="cx">                 case sdp_inactive:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_NONE;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_NONE;
</ins><span class="cx">                         break;
</span><span class="cx">                 case sdp_sendonly:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_SEND;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_SEND;
</ins><span class="cx">                         break;
</span><span class="cx">                 case sdp_recvonly:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_RECEIVE;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_RECEIVE;
</ins><span class="cx">                         break;
</span><span class="cx">                 case sdp_sendrecv:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_SEND_RECEIVE;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_DUPLEX;
</ins><span class="cx">                         break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(sdp_media-&gt;m_connections) {
</span><del>-                apt_string_assign(&amp;rtp_media-&gt;base.ip,sdp_media-&gt;m_connections-&gt;c_address,pool);
</del><ins>+                apt_string_assign(&amp;rtp_media-&gt;ip,sdp_media-&gt;m_connections-&gt;c_address,pool);
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><del>-                rtp_media-&gt;base.ip = *ip;
</del><ins>+                rtp_media-&gt;ip = *ip;
</ins><span class="cx">         }
</span><span class="cx">         if(sdp_media-&gt;m_port) {
</span><del>-                rtp_media-&gt;base.port = (apr_port_t)sdp_media-&gt;m_port;
-                rtp_media-&gt;base.state = MPF_MEDIA_ENABLED;
</del><ins>+                rtp_media-&gt;port = (apr_port_t)sdp_media-&gt;m_port;
+                rtp_media-&gt;state = MPF_MEDIA_ENABLED;
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><del>-                rtp_media-&gt;base.state = MPF_MEDIA_DISABLED;
</del><ins>+                rtp_media-&gt;state = MPF_MEDIA_DISABLED;
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -348,7 +355,7 @@
</span><span class="cx">                                 apt_id_resource_parse(&amp;value,'@',&amp;control_media-&gt;session_id,&amp;control_media-&gt;resource_name,pool);
</span><span class="cx">                                 break;
</span><span class="cx">                         case MRCP_ATTRIB_CMID:
</span><del>-                                control_media-&gt;cmid = atoi(attrib-&gt;a_value);
</del><ins>+                                mrcp_cmid_add(control_media-&gt;cmid_arr,atoi(attrib-&gt;a_value));
</ins><span class="cx">                                 break;
</span><span class="cx">                         default:
</span><span class="cx">                                 break;
</span><span class="lines">@@ -385,9 +392,11 @@
</span><span class="cx">                         &quot;m=application 0 TCP/MRCPv2 1\r\n&quot;
</span><span class="cx">                         &quot;a=resource:speechsynth\r\n&quot;
</span><span class="cx">                         &quot;a=resource:speechrecog\r\n&quot;
</span><del>-                        &quot;m=audio 0 RTP/AVP 0 8\r\n&quot;
</del><ins>+                        &quot;m=audio 0 RTP/AVP 0 8 96 101\r\n&quot;
</ins><span class="cx">                         &quot;a=rtpmap:0 PCMU/8000\r\n&quot;
</span><del>-                        &quot;a=rtpmap:8 PCMA/8000\r\n&quot;,
</del><ins>+                        &quot;a=rtpmap:8 PCMA/8000\r\n&quot;
+                        &quot;a=rtpmap:96 L16/8000\r\n&quot;
+                        &quot;a=rtpmap:101 telephone-event/8000\r\n&quot;,
</ins><span class="cx">                         origin,
</span><span class="cx">                         ip,
</span><span class="cx">                         ip);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpmodulesmrcpsofiasipsrcmrcp_sofiasip_client_agentc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -521,8 +521,11 @@
</span><span class="cx">                         mrcp_sofia_on_resource_discover(status,sofia_agent,nh,sofia_session,sip,tags);
</span><span class="cx">                         break;
</span><span class="cx">                 case nua_r_shutdown:
</span><del>-                        /* break main loop of sofia thread */
-                        su_root_break(sofia_agent-&gt;root);
</del><ins>+                        /* if status &lt; 200, shutdown still in progress */
+                        if(status &gt;= 200) {
+                                /* break main loop of sofia thread */
+                                su_root_break(sofia_agent-&gt;root);
+                        }
</ins><span class="cx">                         break;
</span><span class="cx">                 default: 
</span><span class="cx">                         break;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpmodulesmrcpsofiasipsrcmrcp_sofiasip_server_agentc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -276,7 +276,8 @@
</span><span class="cx">         nua_respond(sofia_session-&gt;nh, SIP_200_OK, 
</span><span class="cx">                                 SIPTAG_CONTACT_STR(sofia_agent-&gt;sip_contact_str),
</span><span class="cx">                                 TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
</span><del>-                            NUTAG_AUTOANSWER(0),
</del><ins>+                                SOATAG_AUDIO_AUX(&quot;telephone-event&quot;),
+                                NUTAG_AUTOANSWER(0),
</ins><span class="cx">                                 TAG_END());
</span><span class="cx">         
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -403,6 +404,7 @@
</span><span class="cx">                                 NUTAG_WITH_CURRENT(sofia_agent-&gt;nua),
</span><span class="cx">                                 SIPTAG_CONTACT_STR(sofia_agent-&gt;sip_contact_str),
</span><span class="cx">                                 TAG_IF(local_sdp_str,SOATAG_USER_SDP_STR(local_sdp_str)),
</span><ins>+                                SOATAG_AUDIO_AUX(&quot;telephone-event&quot;),
</ins><span class="cx">                                 TAG_END());
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -427,10 +429,13 @@
</span><span class="cx">                         mrcp_sofia_on_resource_discover(sofia_agent,nh,sofia_session,sip,tags);
</span><span class="cx">                         break;
</span><span class="cx">                 case nua_r_shutdown:
</span><del>-                        /* break main loop of sofia thread */
-                        su_root_break(sofia_agent-&gt;root);
</del><ins>+                        /* if status &lt; 200, shutdown still in progress */
+                        if(status &gt;= 200) {
+                                /* break main loop of sofia thread */
+                                su_root_break(sofia_agent-&gt;root);
+                        }
</ins><span class="cx">                         break;
</span><del>-                default: 
</del><ins>+                default:
</ins><span class="cx">                         break;
</span><span class="cx">         }
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpmodulesmrcpunirtspincludemrcp_unirtsp_sdph"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -61,7 +61,7 @@
</span><span class="cx">                                                                                         const apr_table_t *resource_map,
</span><span class="cx">                                                                                         apr_pool_t *pool);
</span><span class="cx"> 
</span><del>-/** Generate resource descovery descriptor by RTSP response */
</del><ins>+/** Generate resource discovery descriptor by RTSP response */
</ins><span class="cx"> MRCP_DECLARE(mrcp_session_descriptor_t*) mrcp_resource_discovery_response_generate(
</span><span class="cx">                                                                                         const rtsp_message_t *request, 
</span><span class="cx">                                                                                         const rtsp_message_t *response,
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpmodulesmrcpunirtspsrcmrcp_unirtsp_sdpc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -36,26 +36,33 @@
</span><span class="cx">         }
</span><span class="cx">         offset += snprintf(buffer+offset,size-offset,
</span><span class="cx">                 &quot;m=audio %d RTP/AVP&quot;, 
</span><del>-                audio_media-&gt;base.state == MPF_MEDIA_ENABLED ? audio_media-&gt;base.port : 0);
</del><ins>+                audio_media-&gt;state == MPF_MEDIA_ENABLED ? audio_media-&gt;port : 0);
</ins><span class="cx">         for(i=0; i&lt;descriptor_arr-&gt;nelts; i++) {
</span><del>-                codec_descriptor = (mpf_codec_descriptor_t*)descriptor_arr-&gt;elts + i;
</del><ins>+                codec_descriptor = &amp;APR_ARRAY_IDX(descriptor_arr,i,mpf_codec_descriptor_t);
</ins><span class="cx">                 if(codec_descriptor-&gt;enabled == TRUE) {
</span><span class="cx">                         offset += snprintf(buffer+offset,size-offset,&quot; %d&quot;, codec_descriptor-&gt;payload_type);
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx">         offset += snprintf(buffer+offset,size-offset,&quot;\r\n&quot;);
</span><del>-        if(audio_media-&gt;base.state == MPF_MEDIA_ENABLED) {
-                const apt_str_t *mode_str = mpf_stream_mode_str_get(audio_media-&gt;mode);
</del><ins>+        if(audio_media-&gt;state == MPF_MEDIA_ENABLED) {
+                const apt_str_t *direction_str = mpf_rtp_direction_str_get(audio_media-&gt;direction);
</ins><span class="cx">                 for(i=0; i&lt;descriptor_arr-&gt;nelts; i++) {
</span><del>-                        codec_descriptor = (mpf_codec_descriptor_t*)descriptor_arr-&gt;elts + i;
</del><ins>+                        codec_descriptor = &amp;APR_ARRAY_IDX(descriptor_arr,i,mpf_codec_descriptor_t);
</ins><span class="cx">                         if(codec_descriptor-&gt;enabled == TRUE &amp;&amp; codec_descriptor-&gt;name.buf) {
</span><span class="cx">                                 offset += snprintf(buffer+offset,size-offset,&quot;a=rtpmap:%d %s/%d\r\n&quot;,
</span><span class="cx">                                         codec_descriptor-&gt;payload_type,
</span><span class="cx">                                         codec_descriptor-&gt;name.buf,
</span><span class="cx">                                         codec_descriptor-&gt;sampling_rate);
</span><ins>+                                if(codec_descriptor-&gt;format.buf) {
+                                        offset += snprintf(buffer+offset,size-offset,&quot;a=fmtp:%d %s\r\n&quot;,
+                                                codec_descriptor-&gt;payload_type,
+                                                codec_descriptor-&gt;format.buf);
+                                }
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><del>-                offset += snprintf(buffer+offset,size-offset,&quot;a=%s\r\n&quot;,mode_str ? mode_str-&gt;buf : &quot;&quot;);
</del><ins>+                if(direction_str) {
+                        offset += snprintf(buffer+offset,size-offset,&quot;a=%s\r\n&quot;,direction_str-&gt;buf);
+                }
</ins><span class="cx">                 
</span><span class="cx">                 if(audio_media-&gt;ptime) {
</span><span class="cx">                         offset += snprintf(buffer+offset,size-offset,&quot;a=ptime:%hu\r\n&quot;,
</span><span class="lines">@@ -98,31 +105,31 @@
</span><span class="cx"> 
</span><span class="cx">         switch(sdp_media-&gt;m_mode) {
</span><span class="cx">                 case sdp_inactive:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_NONE;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_NONE;
</ins><span class="cx">                         break;
</span><span class="cx">                 case sdp_sendonly:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_SEND;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_SEND;
</ins><span class="cx">                         break;
</span><span class="cx">                 case sdp_recvonly:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_RECEIVE;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_RECEIVE;
</ins><span class="cx">                         break;
</span><span class="cx">                 case sdp_sendrecv:
</span><del>-                        rtp_media-&gt;mode = STREAM_MODE_SEND_RECEIVE;
</del><ins>+                        rtp_media-&gt;direction = STREAM_DIRECTION_DUPLEX;
</ins><span class="cx">                         break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(sdp_media-&gt;m_connections) {
</span><del>-                apt_string_assign(&amp;rtp_media-&gt;base.ip,sdp_media-&gt;m_connections-&gt;c_address,pool);
</del><ins>+                apt_string_assign(&amp;rtp_media-&gt;ip,sdp_media-&gt;m_connections-&gt;c_address,pool);
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><del>-                rtp_media-&gt;base.ip = *ip;
</del><ins>+                rtp_media-&gt;ip = *ip;
</ins><span class="cx">         }
</span><span class="cx">         if(sdp_media-&gt;m_port) {
</span><del>-                rtp_media-&gt;base.port = (apr_port_t)sdp_media-&gt;m_port;
-                rtp_media-&gt;base.state = MPF_MEDIA_ENABLED;
</del><ins>+                rtp_media-&gt;port = (apr_port_t)sdp_media-&gt;m_port;
+                rtp_media-&gt;state = MPF_MEDIA_ENABLED;
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><del>-                rtp_media-&gt;base.state = MPF_MEDIA_DISABLED;
</del><ins>+                rtp_media-&gt;state = MPF_MEDIA_DISABLED;
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -145,7 +152,7 @@
</span><span class="cx">                         {
</span><span class="cx">                                 mpf_rtp_media_descriptor_t *media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                                 mpf_rtp_media_descriptor_init(media);
</span><del>-                                media-&gt;base.id = mrcp_session_audio_media_add(descriptor,media);
</del><ins>+                                media-&gt;id = mrcp_session_audio_media_add(descriptor,media);
</ins><span class="cx">                                 mpf_rtp_media_generate(media,sdp_media,&amp;descriptor-&gt;ip,pool);
</span><span class="cx">                                 break;
</span><span class="cx">                         }
</span><span class="lines">@@ -153,7 +160,7 @@
</span><span class="cx">                         {
</span><span class="cx">                                 mpf_rtp_media_descriptor_t *media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                                 mpf_rtp_media_descriptor_init(media);
</span><del>-                                media-&gt;base.id = mrcp_session_video_media_add(descriptor,media);
</del><ins>+                                media-&gt;id = mrcp_session_video_media_add(descriptor,media);
</ins><span class="cx">                                 mpf_rtp_media_generate(media,sdp_media,&amp;descriptor-&gt;ip,pool);
</span><span class="cx">                                 break;
</span><span class="cx">                         }
</span><span class="lines">@@ -207,11 +214,11 @@
</span><span class="cx">                         descriptor = mrcp_session_descriptor_create(pool);
</span><span class="cx">                         media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">                         mpf_rtp_media_descriptor_init(media);
</span><del>-                        media-&gt;base.state = MPF_MEDIA_ENABLED;
-                        media-&gt;base.id = mrcp_session_audio_media_add(descriptor,media);
</del><ins>+                        media-&gt;state = MPF_MEDIA_ENABLED;
+                        media-&gt;id = mrcp_session_audio_media_add(descriptor,media);
</ins><span class="cx">                         if(rtsp_header_property_check(&amp;request-&gt;header.property_set,RTSP_HEADER_FIELD_TRANSPORT) == TRUE) {
</span><del>-                                media-&gt;base.port = request-&gt;header.transport.client_port_range.min;
-                                media-&gt;base.ip = request-&gt;header.transport.destination;
</del><ins>+                                media-&gt;port = request-&gt;header.transport.client_port_range.min;
+                                media-&gt;ip = request-&gt;header.transport.destination;
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="lines">@@ -321,16 +328,16 @@
</span><span class="cx">         count = mrcp_session_media_count_get(descriptor);
</span><span class="cx">         for(i=0; i&lt;count; i++) {
</span><span class="cx">                 audio_media = mrcp_session_audio_media_get(descriptor,audio_index);
</span><del>-                if(audio_media &amp;&amp; audio_media-&gt;base.id == i) {
</del><ins>+                if(audio_media &amp;&amp; audio_media-&gt;id == i) {
</ins><span class="cx">                         /* generate audio media */
</span><span class="cx">                         audio_index++;
</span><span class="cx">                         offset += sdp_rtp_media_generate(buffer+offset,size-offset,descriptor,audio_media);
</span><del>-                        request-&gt;header.transport.client_port_range.min = audio_media-&gt;base.port;
-                        request-&gt;header.transport.client_port_range.max = audio_media-&gt;base.port+1;
</del><ins>+                        request-&gt;header.transport.client_port_range.min = audio_media-&gt;port;
+                        request-&gt;header.transport.client_port_range.max = audio_media-&gt;port+1;
</ins><span class="cx">                         continue;
</span><span class="cx">                 }
</span><span class="cx">                 video_media = mrcp_session_video_media_get(descriptor,video_index);
</span><del>-                if(video_media &amp;&amp; video_media-&gt;base.id == i) {
</del><ins>+                if(video_media &amp;&amp; video_media-&gt;id == i) {
</ins><span class="cx">                         /* generate video media */
</span><span class="cx">                         video_index++;
</span><span class="cx">                         offset += sdp_rtp_media_generate(buffer+offset,size-offset,descriptor,video_media);
</span><span class="lines">@@ -403,17 +410,19 @@
</span><span class="cx">                 count = mrcp_session_media_count_get(descriptor);
</span><span class="cx">                 for(i=0; i&lt;count; i++) {
</span><span class="cx">                         audio_media = mrcp_session_audio_media_get(descriptor,audio_index);
</span><del>-                        if(audio_media &amp;&amp; audio_media-&gt;base.id == i) {
</del><ins>+                        if(audio_media &amp;&amp; audio_media-&gt;id == i) {
</ins><span class="cx">                                 /* generate audio media */
</span><ins>+                                rtsp_transport_t *transport;
</ins><span class="cx">                                 audio_index++;
</span><span class="cx">                                 offset += sdp_rtp_media_generate(buffer+offset,size-offset,descriptor,audio_media);
</span><del>-                                response-&gt;header.transport.server_port_range.min = audio_media-&gt;base.port;
-                                response-&gt;header.transport.server_port_range.max = audio_media-&gt;base.port+1;
-                                response-&gt;header.transport.client_port_range = request-&gt;header.transport.client_port_range;
</del><ins>+                                transport = &amp;response-&gt;header.transport;
+                                transport-&gt;server_port_range.min = audio_media-&gt;port;
+                                transport-&gt;server_port_range.max = audio_media-&gt;port+1;
+                                transport-&gt;client_port_range = request-&gt;header.transport.client_port_range;
</ins><span class="cx">                                 continue;
</span><span class="cx">                         }
</span><span class="cx">                         video_media = mrcp_session_video_media_get(descriptor,video_index);
</span><del>-                        if(video_media &amp;&amp; video_media-&gt;base.id == i) {
</del><ins>+                        if(video_media &amp;&amp; video_media-&gt;id == i) {
</ins><span class="cx">                                 /* generate video media */
</span><span class="cx">                                 video_index++;
</span><span class="cx">                                 offset += sdp_rtp_media_generate(buffer+offset,size-offset,descriptor,video_media);
</span><span class="lines">@@ -453,7 +462,7 @@
</span><span class="cx">         return request;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Generate resource descovery descriptor by RTSP response */
</del><ins>+/** Generate resource discovery descriptor by RTSP response */
</ins><span class="cx"> MRCP_DECLARE(mrcp_session_descriptor_t*) mrcp_resource_discovery_response_generate(
</span><span class="cx">                                                                                         const rtsp_message_t *request, 
</span><span class="cx">                                                                                         const rtsp_message_t *response,
</span><span class="lines">@@ -525,18 +534,15 @@
</span><span class="cx">                         &quot;s=-\r\n&quot;
</span><span class="cx">                         &quot;c=IN IP4 %s\r\n&quot;
</span><span class="cx">                         &quot;t=0 0\r\n&quot;
</span><del>-                        &quot;m=audio 0 RTP/AVP 0 8\r\n&quot;
</del><ins>+                        &quot;m=audio 0 RTP/AVP 0 8 96 101\r\n&quot;
</ins><span class="cx">                         &quot;a=rtpmap:0 PCMU/8000\r\n&quot;
</span><del>-                        &quot;a=rtpmap:8 PCMA/8000\r\n&quot;,
</del><ins>+                        &quot;a=rtpmap:8 PCMA/8000\r\n&quot;
+                        &quot;a=rtpmap:96 L16/8000\r\n&quot;
+                        &quot;a=rtpmap:101 telephone-event/8000\r\n&quot;,
</ins><span class="cx">                         origin,
</span><span class="cx">                         ip,
</span><span class="cx">                         ip);
</span><span class="cx">                 
</span><del>-                response-&gt;header.transport.protocol = RTSP_TRANSPORT_RTP;
-                response-&gt;header.transport.profile = RTSP_PROFILE_AVP;
-                response-&gt;header.transport.delivery = RTSP_DELIVERY_UNICAST;
-                rtsp_header_property_add(&amp;response-&gt;header.property_set,RTSP_HEADER_FIELD_TRANSPORT);
-
</del><span class="cx">                 if(offset) {
</span><span class="cx">                         apt_string_assign_n(&amp;response-&gt;body,buffer,offset,pool);
</span><span class="cx">                         response-&gt;header.content_type = RTSP_CONTENT_TYPE_SDP;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpmodulesmrcpunirtspsrcmrcp_unirtsp_server_agentc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -355,6 +355,9 @@
</span><span class="cx">         else if(mrcp_message-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
</span><span class="cx">                 /* send RTSP announce */
</span><span class="cx">                 rtsp_message = rtsp_request_create(mrcp_session-&gt;pool);
</span><ins>+                rtsp_message-&gt;start_line.common.request_line.resource_name = rtsp_name_get_by_mrcp_name(
+                                                                        agent-&gt;config-&gt;resource_map,
+                                                                        mrcp_message-&gt;channel_id.resource_name.buf);
</ins><span class="cx">                 rtsp_message-&gt;start_line.common.request_line.method_id = RTSP_METHOD_ANNOUNCE;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppackagesinnosetupsetupiss"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/packages/inno-setup/setup.iss (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/packages/inno-setup/setup.iss        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/packages/inno-setup/setup.iss        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-#define uni_version &quot;0.6.0&quot;
</del><ins>+#define uni_version &quot;0.8.0&quot;
</ins><span class="cx"> 
</span><span class="cx"> AppName=UniMRCP
</span><span class="cx"> AppVerName=UniMRCP-{#= uni_version}
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -1,4 +1,6 @@
</span><span class="cx"> MAINTAINERCLEANFILES   = Makefile.in
</span><span class="cx"> 
</span><span class="cx"> SUBDIRS                = libunimrcp-server unimrcp-server \
</span><del>-                         libunimrcp-client unimrcp-client
</del><ins>+                         libunimrcp-client unimrcp-client \
+                         libasr-client asr-client \
+                         umc
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsasrclientMakefileam"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/asr-client/Makefile.am (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/asr-client/Makefile.am                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/asr-client/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+MAINTAINERCLEANFILES   = Makefile.in
+
+INCLUDES               = -Iinclude \
+                         -I$(top_srcdir)/platforms/libasr-client/include \
+                         -I$(top_srcdir)/platforms/libunimrcp-client/include \
+                         -I$(top_srcdir)/libs/mrcp-client/include \
+                         -I$(top_srcdir)/libs/mrcp-signaling/include \
+                         -I$(top_srcdir)/libs/mrcpv2-transport/include \
+                         -I$(top_srcdir)/libs/mrcp/include \
+                         -I$(top_srcdir)/libs/mrcp/message/include \
+                         -I$(top_srcdir)/libs/mrcp/control/include \
+                         -I$(top_srcdir)/libs/mrcp/resources/include \
+                         -I$(top_srcdir)/libs/mpf/include \
+                         -I$(top_srcdir)/libs/apr-toolkit/include \
+                         $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
+
+bin_PROGRAMS           = asrclient
+asrclient_SOURCES      = src/main.c 
+                         
+asrclient_LDADD        = $(top_builddir)/platforms/libasr-client/libasrclient.la
+
+if ISMAC
+asrclient_LDFLAGS      = -framework CoreFoundation -framework SystemConfiguration
+endif
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsasrclientasrclientvcproj"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/asr-client/asrclient.vcproj (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/asr-client/asrclient.vcproj                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/asr-client/asrclient.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,166 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;windows-1251&quot;?&gt;
+&lt;VisualStudioProject
+        ProjectType=&quot;Visual C++&quot;
+        Version=&quot;8.00&quot;
+        Name=&quot;asrclient&quot;
+        ProjectGUID=&quot;{6B83AC6D-01CE-4E1C-81CE-02AD8116C684}&quot;
+        RootNamespace=&quot;asrclient&quot;
+        &gt;
+        &lt;Platforms&gt;
+                &lt;Platform
+                        Name=&quot;Win32&quot;
+                /&gt;
+        &lt;/Platforms&gt;
+        &lt;ToolFiles&gt;
+        &lt;/ToolFiles&gt;
+        &lt;Configurations&gt;
+                &lt;Configuration
+                        Name=&quot;Debug|Win32&quot;
+                        ConfigurationType=&quot;1&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unidebug.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpclient.vsprops&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include;&amp;quot;..\libasr-client\include&amp;quot;&quot;
+                                RuntimeLibrary=&quot;3&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalDependencies=&quot;libasrclient.lib libapr-1.lib&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+                &lt;Configuration
+                        Name=&quot;Release|Win32&quot;
+                        ConfigurationType=&quot;1&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unirelease.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpclient.vsprops&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include;&amp;quot;..\libasr-client\include&amp;quot;&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalDependencies=&quot;libasrclient.lib libapr-1.lib&quot;
+                                LinkTimeCodeGeneration=&quot;1&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+        &lt;/Configurations&gt;
+        &lt;References&gt;
+        &lt;/References&gt;
+        &lt;Files&gt;
+                &lt;Filter
+                        Name=&quot;src&quot;
+                        Filter=&quot;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx&quot;
+                        UniqueIdentifier=&quot;{4FC737F1-C7A5-4376-A066-2A32D752A2FF}&quot;
+                        &gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\main.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                &lt;/Filter&gt;
+                &lt;Filter
+                        Name=&quot;include&quot;
+                        Filter=&quot;h;hpp;hxx;hm;inl;inc;xsd&quot;
+                        UniqueIdentifier=&quot;{93995380-89BD-4b04-88EB-625FBE52EBFB}&quot;
+                        &gt;
+                &lt;/Filter&gt;
+        &lt;/Files&gt;
+        &lt;Globals&gt;
+        &lt;/Globals&gt;
+&lt;/VisualStudioProject&gt;
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsasrclientsrcmainc"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/asr-client/src/main.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/asr-client/src/main.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/asr-client/src/main.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,298 @@
</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 &lt;stdio.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;apr_getopt.h&gt;
+#include &lt;apr_file_info.h&gt;
+#include &lt;apr_thread_proc.h&gt;
+#include &quot;asr_engine.h&quot;
+
+typedef struct {
+        const char        *root_dir_path;
+        apt_log_priority_e log_priority;
+        apt_log_output_e   log_output;
+        apr_pool_t        *pool;
+} client_options_t;
+
+typedef struct {
+        asr_engine_t      *engine;
+        const char        *grammar_file;
+        const char        *input_file;
+        const char        *profile;
+        
+        apr_thread_t      *thread;
+        apr_pool_t        *pool;
+} asr_params_t;
+
+/** Thread function to run ASR scenario in */
+static void* APR_THREAD_FUNC asr_session_run(apr_thread_t *thread, void *data)
+{
+        asr_params_t *params = data;
+        asr_session_t *session = asr_session_create(params-&gt;engine,params-&gt;profile);
+        if(session) {
+                const char *result = asr_session_recognize(session,params-&gt;grammar_file,params-&gt;input_file);
+                if(result) {
+                        printf(&quot;Recog Result [%s]&quot;,result);
+                }
+
+                asr_session_destroy(session);
+        }
+
+        /* destroy pool params allocated from */
+        apr_pool_destroy(params-&gt;pool);
+        return NULL;
+}
+
+/** Launch demo ASR session */
+static apt_bool_t asr_session_launch(asr_engine_t *engine, const char *grammar_file, const char *input_file, const char *profile)
+{
+        apr_pool_t *pool;
+        asr_params_t *params;
+        
+        /* create pool to allocate params from */
+        apr_pool_create(&amp;pool,NULL);
+        params = apr_palloc(pool,sizeof(asr_params_t));
+        params-&gt;pool = pool;
+        params-&gt;engine = engine;
+
+        if(grammar_file) {
+                params-&gt;grammar_file = apr_pstrdup(pool,grammar_file);
+        }
+        else {
+                params-&gt;grammar_file = &quot;grammar.xml&quot;;
+        }
+
+        if(input_file) {
+                params-&gt;input_file = apr_pstrdup(pool,input_file);
+        }
+        else {
+                params-&gt;input_file = &quot;one-8kHz.pcm&quot;;
+        }
+        
+        if(profile) {
+                params-&gt;profile = apr_pstrdup(pool,profile);
+        }
+        else {
+                params-&gt;profile = &quot;MRCPv2-Default&quot;;
+        }
+
+        /* Launch a thread to run demo ASR session in */
+        if(apr_thread_create(&amp;params-&gt;thread,NULL,asr_session_run,params,pool) != APR_SUCCESS) {
+                apr_pool_destroy(pool);
+                return FALSE;
+        }
+        
+        return TRUE;
+}
+
+static apt_bool_t cmdline_process(asr_engine_t *engine, char *cmdline)
+{
+        apt_bool_t running = TRUE;
+        char *name;
+        char *last;
+        name = apr_strtok(cmdline, &quot; &quot;, &amp;last);
+
+        if(strcasecmp(name,&quot;run&quot;) == 0) {
+                char *grammar = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                char *input = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                char *profile = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                asr_session_launch(engine,grammar,input,profile);
+        }
+        else if(strcasecmp(name,&quot;loglevel&quot;) == 0) {
+                char *priority = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                if(priority) {
+                        asr_engine_log_priority_set(atol(priority));
+                }
+        }
+        else if(strcasecmp(name,&quot;exit&quot;) == 0 || strcmp(name,&quot;quit&quot;) == 0) {
+                running = FALSE;
+        }
+        else if(strcasecmp(name,&quot;help&quot;) == 0) {
+                printf(&quot;usage:\n&quot;
+                        &quot;\n- run [grammar_file] [audio_input_file] [profile_name] (run demo asr client)\n&quot;
+                        &quot;       grammar_file is the name of grammar file, (path is relative to data dir)\n&quot;
+                        &quot;       audio_input_file is the name of audio file, (path is relative to data dir)\n&quot;
+                        &quot;       profile_name is one of 'MRCPv2-Default', 'MRCPv1-Default', ...\n&quot;
+                        &quot;\n       examples: \n&quot;
+                        &quot;           run\n&quot;
+                        &quot;           run grammar.xml one.pcm\n&quot;
+                        &quot;           run grammar.xml one.pcm MRCPv1-Default\n&quot;
+                    &quot;\n- loglevel [level] (set loglevel, one of 0,1...7)\n&quot;
+                    &quot;\n- quit, exit\n&quot;);
+        }
+        else {
+                printf(&quot;unknown command: %s (input help for usage)\n&quot;,name);
+        }
+        return running;
+}
+
+static apt_bool_t cmdline_run(asr_engine_t *engine)
+{
+        apt_bool_t running = TRUE;
+        char cmdline[1024];
+        int i;
+        do {
+                printf(&quot;&gt;&quot;);
+                memset(&amp;cmdline, 0, sizeof(cmdline));
+                for(i = 0; i &lt; sizeof(cmdline); i++) {
+                        cmdline[i] = (char) getchar();
+                        if(cmdline[i] == '\n') {
+                                cmdline[i] = '\0';
+                                break;
+                        }
+                }
+                if(*cmdline) {
+                        running = cmdline_process(engine,cmdline);
+                }
+        }
+        while(running != 0);
+        return TRUE;
+}
+
+static void usage()
+{
+        printf(
+                &quot;\n&quot;
+                &quot;Usage:\n&quot;
+                &quot;\n&quot;
+                &quot;  asrclient [options]\n&quot;
+                &quot;\n&quot;
+                &quot;  Available options:\n&quot;
+                &quot;\n&quot;
+                &quot;   -r [--root-dir] path     : Set the project root directory path.\n&quot;
+                &quot;\n&quot;
+                &quot;   -l [--log-prio] priority : Set the log priority.\n&quot;
+                &quot;                              (0-emergency, ..., 7-debug)\n&quot;
+                &quot;\n&quot;
+                &quot;   -o [--log-output] mode   : Set the log output mode.\n&quot;
+                &quot;                              (0-none, 1-console only, 2-file only, 3-both)\n&quot;
+                &quot;\n&quot;
+                &quot;   -h [--help]              : Show the help.\n&quot;
+                &quot;\n&quot;);
+}
+
+static void options_destroy(client_options_t *options)
+{
+        if(options-&gt;pool) {
+                apr_pool_destroy(options-&gt;pool);
+        }
+}
+
+static client_options_t* options_load(int argc, const char * const *argv)
+{
+        apr_status_t rv;
+        apr_getopt_t *opt = NULL;
+        int optch;
+        const char *optarg;
+        apr_pool_t *pool;
+        client_options_t *options;
+
+        const apr_getopt_option_t opt_option[] = {
+                /* long-option, short-option, has-arg flag, description */
+                { &quot;root-dir&quot;,    'r', TRUE,  &quot;path to root dir&quot; },  /* -r arg or --root-dir arg */
+                { &quot;log-prio&quot;,    'l', TRUE,  &quot;log priority&quot; },      /* -l arg or --log-prio arg */
+                { &quot;log-output&quot;,  'o', TRUE,  &quot;log output mode&quot; },   /* -o arg or --log-output arg */
+                { &quot;help&quot;,        'h', FALSE, &quot;show help&quot; },         /* -h or --help */
+                { NULL, 0, 0, NULL },                               /* end */
+        };
+
+        /* create APR pool to allocate options from */
+        apr_pool_create(&amp;pool,NULL);
+        if(!pool) {
+                return NULL;
+        }
+        options = apr_palloc(pool,sizeof(client_options_t));
+        options-&gt;pool = pool;
+        /* set the default options */
+        options-&gt;root_dir_path = &quot;../&quot;;
+        options-&gt;log_priority = APT_PRIO_INFO;
+        options-&gt;log_output = APT_LOG_OUTPUT_CONSOLE;
+
+
+        rv = apr_getopt_init(&amp;opt, pool , argc, argv);
+        if(rv != APR_SUCCESS) {
+                options_destroy(options);
+                return NULL;
+        }
+
+        while((rv = apr_getopt_long(opt, opt_option, &amp;optch, &amp;optarg)) == APR_SUCCESS) {
+                switch(optch) {
+                        case 'r':
+                                options-&gt;root_dir_path = optarg;
+                                break;
+                        case 'l':
+                                if(optarg) {
+                                        options-&gt;log_priority = atoi(optarg);
+                                }
+                                break;
+                        case 'o':
+                                if(optarg) {
+                                        options-&gt;log_output = atoi(optarg);
+                                }
+                                break;
+                        case 'h':
+                                usage();
+                                return FALSE;
+                }
+        }
+
+        if(rv != APR_EOF) {
+                usage();
+                options_destroy(options);
+                return NULL;
+        }
+
+        return options;
+}
+
+int main(int argc, const char * const *argv)
+{
+        client_options_t *options;
+        asr_engine_t *engine;
+
+        /* APR global initialization */
+        if(apr_initialize() != APR_SUCCESS) {
+                apr_terminate();
+                return 0;
+        }
+
+        /* load options */
+        options = options_load(argc,argv);
+        if(!options) {
+                apr_terminate();
+                return 0;
+        }
+
+        /* create asr engine */
+        engine = asr_engine_create(
+                                options-&gt;root_dir_path,
+                                options-&gt;log_priority,
+                                options-&gt;log_output);
+        if(engine) {
+                /* run command line  */
+                cmdline_run(engine);
+                /* destroy demo framework */
+                asr_engine_destroy(engine);
+        }
+
+        /* destroy options */
+        options_destroy(options);
+
+        /* APR global termination */
+        apr_terminate();
+        return 0;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibasrclientMakefileam"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/libasr-client/Makefile.am (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libasr-client/Makefile.am                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/libasr-client/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+MAINTAINERCLEANFILES             = Makefile.in
+
+INCLUDES                    = -Iinclude \
+                              -I$(top_srcdir)/platforms/libunimrcp-client/include \
+                              -I$(top_srcdir)/libs/mrcp-client/include \
+                              -I$(top_srcdir)/libs/mrcp-signaling/include \
+                              -I$(top_srcdir)/libs/mrcpv2-transport/include \
+                              -I$(top_srcdir)/libs/mrcp/include \
+                              -I$(top_srcdir)/libs/mrcp/message/include \
+                              -I$(top_srcdir)/libs/mrcp/control/include \
+                              -I$(top_srcdir)/libs/mrcp/resources/include \
+                              -I$(top_srcdir)/libs/mpf/include \
+                              -I$(top_srcdir)/libs/apr-toolkit/include \
+                              $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
+
+lib_LTLIBRARIES             = libasrclient.la
+
+include_HEADERS             = include/asr_engine.h
+
+libasrclient_la_SOURCES     = src/asr_engine.c
+
+libasrclient_la_LIBADD      = $(top_builddir)/platforms/libunimrcp-client/libunimrcpclient.la
+                              
+libasrclient_la_LDFLAGS     = $(UNI_LT_VERSION)
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibasrclientincludeasr_engineh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/libasr-client/include/asr_engine.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libasr-client/include/asr_engine.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/libasr-client/include/asr_engine.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,102 @@
</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.
+ */
+
+#ifndef __ASR_ENGINE_H__
+#define __ASR_ENGINE_H__
+
+/**
+ * @file asr_engine.h
+ * @brief Basic ASR engine on top of UniMRCP client library
+ */ 
+
+#include &quot;apt_log.h&quot;
+
+/** Lib export/import defines (win32) */
+#ifdef WIN32
+#ifdef ASR_CLIENT_STATIC_LIB
+#define ASR_CLIENT_DECLARE(type)   type __stdcall
+#else
+#ifdef ASR_CLIENT_LIB_EXPORT
+#define ASR_CLIENT_DECLARE(type)   __declspec(dllexport) type __stdcall
+#else
+#define ASR_CLIENT_DECLARE(type)   __declspec(dllimport) type __stdcall
+#endif
+#endif
+#else
+#define ASR_CLIENT_DECLARE(type) type
+#endif
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque ASR engine */
+typedef struct asr_engine_t asr_engine_t;
+
+/** Opaque ASR session */
+typedef struct asr_session_t asr_session_t;
+
+
+/**
+ * Create ASR engine.
+ * @param root_dir_path the path to root directory
+ * @param log_priority the log priority level
+ * @param log_output the log output mode
+ */
+ASR_CLIENT_DECLARE(asr_engine_t*) asr_engine_create(
+                                                                        const char *root_dir_path,
+                                                                        apt_log_priority_e log_priority,
+                                                                        apt_log_output_e log_output);
+
+/**
+ * Destroy ASR engine.
+ * @param engine the engine to destroy
+ */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_engine_destroy(asr_engine_t *engine);
+
+
+
+/**
+ * Create ASR session.
+ * @param engine the engine session belongs to
+ * @param profile the name of UniMRCP profile to use
+ */
+ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, const char *profile);
+
+/**
+ * Initiate recognition.
+ * @param session the session to run recognition in the scope of
+ * @param grammar_file the name of the grammar file to use (path is relative to data dir)
+ * @param input_file the name of the audio input file to use (path is relative to data dir)
+ * @return the recognition result (input element of NLSML content)
+ */
+ASR_CLIENT_DECLARE(const char*) asr_session_recognize(asr_session_t *session, const char *grammar_file, const char *input_file);
+
+/**
+ * Destroy ASR session.
+ * @param session the session to destroy
+ */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_session_destroy(asr_session_t *session);
+
+
+/**
+ * Set log priority.
+ * @param priority the priority to set
+ */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_engine_log_priority_set(apt_log_priority_e log_priority);
+
+
+APT_END_EXTERN_C
+
+#endif /*__ASR_ENGINE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibasrclientlibasrclientvcproj"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/libasr-client/libasrclient.vcproj (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libasr-client/libasrclient.vcproj                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/libasr-client/libasrclient.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,173 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;?&gt;
+&lt;VisualStudioProject
+        ProjectType=&quot;Visual C++&quot;
+        Version=&quot;8.00&quot;
+        Name=&quot;libasrclient&quot;
+        ProjectGUID=&quot;{272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}&quot;
+        RootNamespace=&quot;libasrclient&quot;
+        Keyword=&quot;Win32Proj&quot;
+        &gt;
+        &lt;Platforms&gt;
+                &lt;Platform
+                        Name=&quot;Win32&quot;
+                /&gt;
+        &lt;/Platforms&gt;
+        &lt;ToolFiles&gt;
+        &lt;/ToolFiles&gt;
+        &lt;Configurations&gt;
+                &lt;Configuration
+                        Name=&quot;Debug|Win32&quot;
+                        ConfigurationType=&quot;2&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unidebug.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpclient.vsprops&quot;
+                        CharacterSet=&quot;1&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include&quot;
+                                PreprocessorDefinitions=&quot;ASR_CLIENT_LIB_EXPORT&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalDependencies=&quot;$(UniMRCPClientLibs)&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+                &lt;Configuration
+                        Name=&quot;Release|Win32&quot;
+                        ConfigurationType=&quot;2&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unirelease.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpclient.vsprops&quot;
+                        CharacterSet=&quot;1&quot;
+                        WholeProgramOptimization=&quot;1&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include&quot;
+                                PreprocessorDefinitions=&quot;ASR_CLIENT_LIB_EXPORT&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalDependencies=&quot;$(UniMRCPClientLibs)&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+        &lt;/Configurations&gt;
+        &lt;References&gt;
+        &lt;/References&gt;
+        &lt;Files&gt;
+                &lt;Filter
+                        Name=&quot;include&quot;
+                        Filter=&quot;h;hpp;hxx;hm;inl;inc;xsd&quot;
+                        UniqueIdentifier=&quot;{93995380-89BD-4b04-88EB-625FBE52EBFB}&quot;
+                        &gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\asr_engine.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                &lt;/Filter&gt;
+                &lt;Filter
+                        Name=&quot;src&quot;
+                        Filter=&quot;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx&quot;
+                        &gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\asr_engine.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                &lt;/Filter&gt;
+        &lt;/Files&gt;
+        &lt;Globals&gt;
+        &lt;/Globals&gt;
+&lt;/VisualStudioProject&gt;
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibasrclientsrcasr_enginec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/libasr-client/src/asr_engine.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libasr-client/src/asr_engine.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/libasr-client/src/asr_engine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,586 @@
</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 &lt;stdlib.h&gt;
+
+/* APR includes */
+#include &lt;apr_thread_cond.h&gt;
+#include &lt;apr_thread_proc.h&gt;
+
+/* common includes */
+#include &quot;unimrcp_client.h&quot;
+#include &quot;mrcp_application.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+/* recognizer includes */
+#include &quot;mrcp_recog_header.h&quot;
+#include &quot;mrcp_recog_resource.h&quot;
+/* APT includes */
+#include &quot;apt_nlsml_doc.h&quot;
+#include &quot;apt_log.h&quot;
+#include &quot;apt_pool.h&quot;
+
+#include &quot;asr_engine.h&quot;
+
+
+/** ASR engine on top of UniMRCP client stack */
+struct asr_engine_t {
+        /** MRCP client stack */
+        mrcp_client_t      *mrcp_client;
+        /** MRCP client stack */
+        mrcp_application_t *mrcp_app;
+        /** Memory pool */
+        apr_pool_t         *pool;
+};
+
+
+/** ASR session on top of UniMRCP session/channel */
+struct asr_session_t {
+        /** Back pointer to engine */
+        asr_engine_t       *engine;
+        /** MRCP session */
+        mrcp_session_t     *mrcp_session;
+        /** MRCP channel */
+        mrcp_channel_t     *mrcp_channel;
+        /** RECOGNITION-COMPLETE message  */
+        mrcp_message_t     *recog_complete;
+
+        /** File to read audio stream from */
+        FILE               *audio_in;
+        /** Streaming is in-progress */
+        apt_bool_t          streaming;
+
+        /** Conditional wait object */
+        apr_thread_cond_t  *wait_object;
+        /** Mutex of the wait object */
+        apr_thread_mutex_t *mutex;
+
+        /** Message sent from client stack */
+        const mrcp_app_message_t *app_message;
+};
+
+
+/** Declaration of recognizer audio stream methods */
+static apt_bool_t asr_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
+
+static const mpf_audio_stream_vtable_t audio_stream_vtable = {
+        NULL,
+        NULL,
+        NULL,
+        asr_stream_read,
+        NULL,
+        NULL,
+        NULL
+};
+
+static apt_bool_t app_message_handler(const mrcp_app_message_t *app_message);
+
+
+/** Create ASR engine */
+ASR_CLIENT_DECLARE(asr_engine_t*) asr_engine_create(
+                                                                        const char *root_dir_path,
+                                                                        apt_log_priority_e log_priority,
+                                                                        apt_log_output_e log_output)
+{
+        apr_pool_t *pool = NULL;
+        apt_dir_layout_t *dir_layout;
+        asr_engine_t *engine;
+        mrcp_client_t *mrcp_client;
+        mrcp_application_t *mrcp_app;
+
+        /* create APR pool */
+        pool = apt_pool_create();
+        if(!pool) {
+                return NULL;
+        }
+
+        /* create the structure of default directories layout */
+        dir_layout = apt_default_dir_layout_create(root_dir_path,pool);
+        /* create singleton logger */
+        apt_log_instance_create(log_output,log_priority,pool);
+
+        if((log_output &amp; APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) {
+                /* open the log file */
+                apt_log_file_open(dir_layout-&gt;log_dir_path,&quot;unimrcpclient&quot;,MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
+        }
+
+        engine = apr_palloc(pool,sizeof(asr_engine_t));
+        engine-&gt;pool = pool;
+        engine-&gt;mrcp_client = NULL;
+        engine-&gt;mrcp_app = NULL;
+
+        /* create UniMRCP client stack */
+        mrcp_client = unimrcp_client_create(dir_layout);
+        if(!mrcp_client) {
+                apt_log_instance_destroy();
+                apr_pool_destroy(pool);
+                return NULL;
+        }
+        
+        /* create an application */
+        mrcp_app = mrcp_application_create(
+                                                                app_message_handler,
+                                                                engine,
+                                                                pool);
+        if(!mrcp_app) {
+                mrcp_client_destroy(mrcp_client);
+                apt_log_instance_destroy();
+                apr_pool_destroy(pool);
+                return NULL;
+        }
+
+        /* register application in client stack */
+        mrcp_client_application_register(mrcp_client,mrcp_app,&quot;ASRAPP&quot;);
+
+        /* start client stack */
+        if(mrcp_client_start(mrcp_client) != TRUE) {
+                mrcp_client_destroy(mrcp_client);
+                apt_log_instance_destroy();
+                apr_pool_destroy(pool);
+                return NULL;
+        }
+
+        engine-&gt;mrcp_client = mrcp_client;
+        engine-&gt;mrcp_app = mrcp_app;
+        return engine;
+}
+
+/** Destroy ASR engine */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_engine_destroy(asr_engine_t *engine)
+{
+        if(engine-&gt;mrcp_client) {
+                /* shutdown client stack */
+                mrcp_client_shutdown(engine-&gt;mrcp_client);
+                /* destroy client stack */
+                mrcp_client_destroy(engine-&gt;mrcp_client);
+                engine-&gt;mrcp_client = NULL;
+                engine-&gt;mrcp_app = NULL;
+        }
+
+        /* destroy singleton logger */
+        apt_log_instance_destroy();
+        /* destroy APR pool */
+        apr_pool_destroy(engine-&gt;pool);
+        return TRUE;
+}
+
+
+
+/** Destroy ASR session */
+static apt_bool_t asr_session_destroy_ex(asr_session_t *asr_session, apt_bool_t terminate)
+{
+        if(terminate == TRUE) {
+                apr_thread_mutex_lock(asr_session-&gt;mutex);
+                if(mrcp_application_session_terminate(asr_session-&gt;mrcp_session) == TRUE) {
+                        apr_thread_cond_wait(asr_session-&gt;wait_object,asr_session-&gt;mutex);
+                        /* the response must be checked to be the valid one */
+                }
+                apr_thread_mutex_unlock(asr_session-&gt;mutex);
+        }
+
+        if(asr_session-&gt;audio_in) {
+                fclose(asr_session-&gt;audio_in);
+                asr_session-&gt;audio_in = NULL;
+        }
+
+        if(asr_session-&gt;mutex) {
+                apr_thread_mutex_destroy(asr_session-&gt;mutex);
+                asr_session-&gt;mutex = NULL;
+        }
+        if(asr_session-&gt;wait_object) {
+                apr_thread_cond_destroy(asr_session-&gt;wait_object);
+                asr_session-&gt;wait_object = NULL;
+        }
+        if(asr_session-&gt;mrcp_session) {
+                mrcp_application_session_destroy(asr_session-&gt;mrcp_session);
+                asr_session-&gt;mrcp_session = NULL;
+        }
+        free(asr_session);
+        return TRUE;
+}
+
+/** Open audio input file */
+static apt_bool_t asr_input_file_open(asr_session_t *asr_session, const char *input_file)
+{
+        const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(asr_session-&gt;engine-&gt;mrcp_app);
+        apr_pool_t *pool = mrcp_application_session_pool_get(asr_session-&gt;mrcp_session);
+        char *input_file_path = apt_datadir_filepath_get(dir_layout,input_file,pool);
+        if(!input_file_path) {
+                return FALSE;
+        }
+        
+        if(asr_session-&gt;audio_in) {
+                fclose(asr_session-&gt;audio_in);
+                asr_session-&gt;audio_in = NULL;
+        }
+
+        asr_session-&gt;audio_in = fopen(input_file_path,&quot;rb&quot;);
+        if(!asr_session-&gt;audio_in) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot Open [%s]&quot;,input_file_path);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+/** MPF callback to read audio frame */
+static apt_bool_t asr_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
+{
+        asr_session_t *asr_session = stream-&gt;obj;
+        if(asr_session &amp;&amp; asr_session-&gt;streaming == TRUE) {
+                if(asr_session-&gt;audio_in) {
+                        if(fread(frame-&gt;codec_frame.buffer,1,frame-&gt;codec_frame.size,asr_session-&gt;audio_in) == frame-&gt;codec_frame.size) {
+                                /* normal read */
+                                frame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+                        }
+                        else {
+                                /* file is over */
+                                asr_session-&gt;streaming = FALSE;
+                        }
+                }
+        }
+        return TRUE;
+}
+
+/** Create DEFINE-GRAMMAR request */
+static mrcp_message_t* define_grammar_message_create(asr_session_t *asr_session, const char *grammar_file)
+{
+        /* create MRCP message */
+        mrcp_message_t *mrcp_message = mrcp_application_message_create(
+                                                asr_session-&gt;mrcp_session,
+                                                asr_session-&gt;mrcp_channel,
+                                                RECOGNIZER_DEFINE_GRAMMAR);
+        if(mrcp_message) {
+                mrcp_generic_header_t *generic_header;
+
+                /* set message body */
+                const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(asr_session-&gt;engine-&gt;mrcp_app);
+                apr_pool_t *pool = mrcp_application_session_pool_get(asr_session-&gt;mrcp_session);
+                char *grammar_file_path = apt_datadir_filepath_get(dir_layout,grammar_file,pool);
+                if(grammar_file_path) {
+                        char text[1024];
+                        apr_size_t size;
+                        FILE *grammar = fopen(grammar_file_path,&quot;r&quot;);
+                        if(!grammar) {
+                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot Open [%s]&quot;,grammar_file_path);
+                                return NULL;
+                        }
+
+                        size = fread(text,1,sizeof(text),grammar);
+                        apt_string_assign_n(&amp;mrcp_message-&gt;body,text,size,mrcp_message-&gt;pool);
+                        fclose(grammar);
+                }
+
+                /* get/allocate generic header */
+                generic_header = mrcp_generic_header_prepare(mrcp_message);
+                if(generic_header) {
+                        /* set generic header fields */
+                        if(mrcp_message-&gt;start_line.version == MRCP_VERSION_2) {
+                                apt_string_assign(&amp;generic_header-&gt;content_type,&quot;application/srgs+xml&quot;,mrcp_message-&gt;pool);
+                        }
+                        else {
+                                apt_string_assign(&amp;generic_header-&gt;content_type,&quot;application/grammar+xml&quot;,mrcp_message-&gt;pool);
+                        }
+                        mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE);
+                        apt_string_assign(&amp;generic_header-&gt;content_id,&quot;demo-grammar&quot;,mrcp_message-&gt;pool);
+                        mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_ID);
+                }
+        }
+        return mrcp_message;
+}
+
+/** Create RECOGNIZE request */
+static mrcp_message_t* recognize_message_create(asr_session_t *asr_session)
+{
+        /* create MRCP message */
+        mrcp_message_t *mrcp_message = mrcp_application_message_create(
+                                                                                asr_session-&gt;mrcp_session,
+                                                                                asr_session-&gt;mrcp_channel,
+                                                                                RECOGNIZER_RECOGNIZE);
+        if(mrcp_message) {
+                mrcp_recog_header_t *recog_header;
+                mrcp_generic_header_t *generic_header;
+                /* get/allocate generic header */
+                generic_header = mrcp_generic_header_prepare(mrcp_message);
+                if(generic_header) {
+                        /* set generic header fields */
+                        apt_string_assign(&amp;generic_header-&gt;content_type,&quot;text/uri-list&quot;,mrcp_message-&gt;pool);
+                        mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE);
+                        /* set message body */
+                        apt_string_assign(&amp;mrcp_message-&gt;body,&quot;session:demo-grammar&quot;,mrcp_message-&gt;pool);
+                }
+                /* get/allocate recognizer header */
+                recog_header = mrcp_resource_header_prepare(mrcp_message);
+                if(recog_header) {
+                        if(mrcp_message-&gt;start_line.version == MRCP_VERSION_2) {
+                                /* set recognizer header fields */
+                                recog_header-&gt;cancel_if_queue = FALSE;
+                                mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CANCEL_IF_QUEUE);
+                        }
+                        recog_header-&gt;no_input_timeout = 5000;
+                        mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_NO_INPUT_TIMEOUT);
+                        recog_header-&gt;recognition_timeout = 10000;
+                        mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_RECOGNITION_TIMEOUT);
+                        recog_header-&gt;start_input_timers = TRUE;
+                        mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_START_INPUT_TIMERS);
+                        recog_header-&gt;confidence_threshold = 0.87f;
+                        mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD);
+                }
+        }
+        return mrcp_message;
+}
+
+/** Get NLSML input result */
+static const char* nlsml_input_get(mrcp_message_t *message)
+{
+        apr_xml_elem *interpret;
+        apr_xml_elem *instance;
+        apr_xml_elem *input;
+        apr_xml_doc *doc = nlsml_doc_load(&amp;message-&gt;body,message-&gt;pool);
+        if(!doc) {
+                return NULL;
+        }
+        
+        /* get interpreted result */
+        interpret = nlsml_first_interpret_get(doc);
+        if(!interpret) {
+                return NULL;
+        }
+        /* get instance and input */
+        nlsml_interpret_results_get(interpret,&amp;instance,&amp;input);
+        if(!input || !input-&gt;first_cdata.first) {
+                return NULL;
+        }
+        
+        /* return input */
+        return input-&gt;first_cdata.first-&gt;text;
+}
+
+
+/** Application message handler */
+static apt_bool_t app_message_handler(const mrcp_app_message_t *app_message)
+{
+        if((app_message-&gt;message_type == MRCP_APP_MESSAGE_TYPE_SIGNALING &amp;&amp; 
+                app_message-&gt;sig_message.message_type == MRCP_SIG_MESSAGE_TYPE_RESPONSE) ||
+                app_message-&gt;message_type == MRCP_APP_MESSAGE_TYPE_CONTROL) {
+
+                asr_session_t *asr_session = mrcp_application_session_object_get(app_message-&gt;session);
+                if(asr_session) {
+                        apr_thread_mutex_lock(asr_session-&gt;mutex);
+                        asr_session-&gt;app_message = app_message;
+                        apr_thread_cond_signal(asr_session-&gt;wait_object);
+                        apr_thread_mutex_unlock(asr_session-&gt;mutex);
+                }
+        }
+        return TRUE;
+}
+
+/** Check signaling response */
+static apt_bool_t sig_response_check(const mrcp_app_message_t *app_message)
+{
+        if(!app_message || app_message-&gt;message_type != MRCP_APP_MESSAGE_TYPE_SIGNALING) {
+                return FALSE;
+        }
+
+        return (app_message-&gt;sig_message.status == MRCP_SIG_STATUS_CODE_SUCCESS) ? TRUE : FALSE;
+}
+
+/** Check MRCP response */
+static apt_bool_t mrcp_response_check(const mrcp_app_message_t *app_message, mrcp_request_state_e state)
+{
+        mrcp_message_t *mrcp_message = NULL;
+        if(app_message &amp;&amp; app_message-&gt;message_type == MRCP_APP_MESSAGE_TYPE_CONTROL) {
+                mrcp_message = app_message-&gt;control_message;
+        }
+
+        if(!mrcp_message || mrcp_message-&gt;start_line.message_type != MRCP_MESSAGE_TYPE_RESPONSE ) {
+                return FALSE;
+        }
+        return (mrcp_message-&gt;start_line.request_state == state) ? TRUE : FALSE;
+}
+
+/** Get MRCP event */
+static mrcp_message_t* mrcp_event_get(const mrcp_app_message_t *app_message)
+{
+        mrcp_message_t *mrcp_message = NULL;
+        if(app_message &amp;&amp; app_message-&gt;message_type == MRCP_APP_MESSAGE_TYPE_CONTROL) {
+                mrcp_message = app_message-&gt;control_message;
+        }
+
+        if(!mrcp_message || mrcp_message-&gt;start_line.message_type != MRCP_MESSAGE_TYPE_EVENT) {
+                return NULL;
+        }
+        return mrcp_message;
+}
+
+/** Create ASR session */
+ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, const char *profile)
+{
+        mpf_termination_t *termination;
+        mrcp_channel_t *channel;
+        mrcp_session_t *session;
+        const mrcp_app_message_t *app_message;
+        apr_pool_t *pool;
+
+        asr_session_t *asr_session = malloc(sizeof(asr_session_t));
+
+        /* create session */
+        session = mrcp_application_session_create(engine-&gt;mrcp_app,profile,asr_session);
+        if(!session) {
+                free(asr_session);
+                return NULL;
+        }
+        pool = mrcp_application_session_pool_get(session);
+        
+        termination = mrcp_application_source_termination_create(
+                        session,                   /* session, termination belongs to */
+                        &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
+                        NULL,                      /* codec descriptor of audio stream (NULL by default) */
+                        asr_session);              /* object to associate */
+        
+        channel = mrcp_application_channel_create(
+                        session,                   /* session, channel belongs to */
+                        MRCP_RECOGNIZER_RESOURCE,  /* MRCP resource identifier */
+                        termination,               /* media termination, used to terminate audio stream */
+                        NULL,                      /* RTP descriptor, used to create RTP termination (NULL by default) */
+                        asr_session);              /* object to associate */
+
+        if(!channel) {
+                mrcp_application_session_destroy(session);
+                free(asr_session);
+                return NULL;
+        }
+        
+        asr_session-&gt;engine = engine;
+        asr_session-&gt;mrcp_session = session;
+        asr_session-&gt;mrcp_channel = channel;
+        asr_session-&gt;recog_complete = NULL;
+        asr_session-&gt;streaming = FALSE;
+        asr_session-&gt;audio_in = NULL;
+        asr_session-&gt;mutex = NULL;
+        asr_session-&gt;wait_object = NULL;
+        asr_session-&gt;app_message = NULL;
+
+        /* Create cond wait object and mutex */
+        apr_thread_mutex_create(&amp;asr_session-&gt;mutex,APR_THREAD_MUTEX_DEFAULT,pool);
+        apr_thread_cond_create(&amp;asr_session-&gt;wait_object,pool);
+
+        /* Send add channel request and wait for the response */
+        apr_thread_mutex_lock(asr_session-&gt;mutex);
+        app_message = NULL;
+        if(mrcp_application_channel_add(asr_session-&gt;mrcp_session,asr_session-&gt;mrcp_channel) == TRUE) {
+                apr_thread_cond_wait(asr_session-&gt;wait_object,asr_session-&gt;mutex);
+                app_message = asr_session-&gt;app_message;
+                asr_session-&gt;app_message = NULL;
+        }
+        apr_thread_mutex_unlock(asr_session-&gt;mutex);
+
+        if(sig_response_check(app_message) == FALSE) {
+                asr_session_destroy_ex(asr_session,TRUE);
+                return NULL;
+        }
+        return asr_session;
+}
+
+/** Initiate recognition */
+ASR_CLIENT_DECLARE(const char*) asr_session_recognize(asr_session_t *asr_session, const char *grammar_file, const char *input_file)
+{
+        const mrcp_app_message_t *app_message;
+        mrcp_message_t *mrcp_message;
+
+        app_message = NULL;
+        mrcp_message = define_grammar_message_create(asr_session,grammar_file);
+        if(!mrcp_message) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create DEFINE-GRAMMAR Request&quot;);
+                return NULL;
+        }
+
+        /* Send DEFINE-GRAMMAR request and wait for the response */
+        apr_thread_mutex_lock(asr_session-&gt;mutex);
+        if(mrcp_application_message_send(asr_session-&gt;mrcp_session,asr_session-&gt;mrcp_channel,mrcp_message) == TRUE) {
+                apr_thread_cond_wait(asr_session-&gt;wait_object,asr_session-&gt;mutex);
+                app_message = asr_session-&gt;app_message;
+                asr_session-&gt;app_message = NULL;
+        }
+        apr_thread_mutex_unlock(asr_session-&gt;mutex);
+
+        if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_COMPLETE) == FALSE) {
+                return NULL;
+        }
+
+        /* Reset prev recog result (if any) */
+        asr_session-&gt;recog_complete = NULL;
+
+        app_message = NULL;
+        mrcp_message = recognize_message_create(asr_session);
+        if(!mrcp_message) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create RECOGNIZE Request&quot;);
+                return NULL;
+        }
+
+        /* Send RECOGNIZE request and wait for the response */
+        apr_thread_mutex_lock(asr_session-&gt;mutex);
+        if(mrcp_application_message_send(asr_session-&gt;mrcp_session,asr_session-&gt;mrcp_channel,mrcp_message) == TRUE) {
+                apr_thread_cond_wait(asr_session-&gt;wait_object,asr_session-&gt;mutex);
+                app_message = asr_session-&gt;app_message;
+                asr_session-&gt;app_message = NULL;
+        }
+        apr_thread_mutex_unlock(asr_session-&gt;mutex);
+
+        if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_INPROGRESS) == FALSE) {
+                return NULL;
+        }
+        
+        /* Open input file and start streaming */
+        if(asr_input_file_open(asr_session,input_file) == FALSE) {
+                return NULL;
+        }
+        asr_session-&gt;streaming = TRUE;
+
+        /* Wait for events either START-OF-INPUT or RECOGNITION-COMPLETE */
+        do {
+                apr_thread_mutex_lock(asr_session-&gt;mutex);
+                app_message = NULL;
+                if(apr_thread_cond_timedwait(asr_session-&gt;wait_object,asr_session-&gt;mutex, 60 * 1000000) != APR_SUCCESS) {
+                        apr_thread_mutex_unlock(asr_session-&gt;mutex);
+                        return NULL;
+                }
+                app_message = asr_session-&gt;app_message;
+                asr_session-&gt;app_message = NULL;
+                apr_thread_mutex_unlock(asr_session-&gt;mutex);
+
+                mrcp_message = mrcp_event_get(app_message);
+                if(mrcp_message &amp;&amp; mrcp_message-&gt;start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
+                        asr_session-&gt;recog_complete = mrcp_message;
+                }
+        }
+        while(!asr_session-&gt;recog_complete);
+
+        /* Get results */
+        return nlsml_input_get(asr_session-&gt;recog_complete);
+}
+
+/** Destroy ASR session */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_session_destroy(asr_session_t *asr_session)
+{
+        return asr_session_destroy_ex(asr_session,TRUE);
+}
+
+/** Set log priority */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_engine_log_priority_set(apt_log_priority_e log_priority)
+{
+        return apt_log_priority_set(log_priority);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibunimrcpclientMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -29,6 +29,6 @@
</span><span class="cx">                               $(top_builddir)/libs/mrcp/libmrcp.la \
</span><span class="cx">                               $(top_builddir)/libs/mpf/libmpf.la \
</span><span class="cx">                               $(top_builddir)/libs/apr-toolkit/libaprtoolkit.la \
</span><del>-                              $(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS) $(UNIMRCP_SOFIA_LIBS)
</del><ins>+                              $(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS) $(UNIMRCP_SOFIA_LIBS) -lm
</ins><span class="cx">                               
</span><span class="cx"> libunimrcpclient_la_LDFLAGS = $(UNI_LT_VERSION)
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibunimrcpclientsrcunimrcp_clientc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> #include &lt;apr_xml.h&gt;
</span><span class="cx"> #include &quot;unimrcp_client.h&quot;
</span><span class="cx"> #include &quot;uni_version.h&quot;
</span><del>-#include &quot;mrcp_default_factory.h&quot;
</del><ins>+#include &quot;mrcp_resource_loader.h&quot;
</ins><span class="cx"> #include &quot;mpf_engine.h&quot;
</span><span class="cx"> #include &quot;mpf_codec_manager.h&quot;
</span><span class="cx"> #include &quot;mpf_rtp_termination_factory.h&quot;
</span><span class="lines">@@ -52,8 +52,6 @@
</span><span class="cx"> {
</span><span class="cx">         apr_pool_t *pool;
</span><span class="cx">         apr_xml_doc *doc;
</span><del>-        mrcp_resource_factory_t *resource_factory;
-        mpf_codec_manager_t *codec_manager;
</del><span class="cx">         mrcp_client_t *client;
</span><span class="cx"> 
</span><span class="cx">         if(!dir_layout) {
</span><span class="lines">@@ -71,16 +69,6 @@
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        resource_factory = mrcp_default_factory_create(pool);
-        if(resource_factory) {
-                mrcp_client_resource_factory_register(client,resource_factory);
-        }
-
-        codec_manager = mpf_engine_codec_manager_create(pool);
-        if(codec_manager) {
-                mrcp_client_codec_manager_register(client,codec_manager);
-        }
-
</del><span class="cx">         doc = unimrcp_client_config_parse(dir_layout-&gt;conf_dir_path,pool);
</span><span class="cx">         if(doc) {
</span><span class="cx">                 unimrcp_client_config_load(client,doc,pool);
</span><span class="lines">@@ -118,7 +106,7 @@
</span><span class="cx">         rv = apr_xml_parse_file(pool,&amp;parser,&amp;doc,fd,XML_FILE_BUFFER_LENGTH);
</span><span class="cx">         if(rv != APR_SUCCESS) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Parse Config File [%s]&quot;,file_path);
</span><del>-                return NULL;
</del><ins>+                doc = NULL;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apr_file_close(fd);
</span><span class="lines">@@ -419,6 +407,18 @@
</span><span class="cx">                                 else if(strcasecmp(attr_name-&gt;value,&quot;ptime&quot;) == 0) {
</span><span class="cx">                                         rtp_config-&gt;ptime = (apr_uint16_t)atol(attr_value-&gt;value);
</span><span class="cx">                                 }
</span><ins>+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp&quot;) == 0) {
+                                        rtp_config-&gt;rtcp = atoi(attr_value-&gt;value);
+                                }
+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp-bye&quot;) == 0) {
+                                        rtp_config-&gt;rtcp_bye_policy = atoi(attr_value-&gt;value);
+                                }
+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp-tx-interval&quot;) == 0) {
+                                        rtp_config-&gt;rtcp_tx_interval = (apr_uint16_t)atoi(attr_value-&gt;value);
+                                }
+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp-rx-resolution&quot;) == 0) {
+                                        rtp_config-&gt;rtcp_rx_resolution = (apr_uint16_t)atol(attr_value-&gt;value);
+                                }
</ins><span class="cx">                                 else {
</span><span class="cx">                                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr_name-&gt;value);
</span><span class="cx">                                 }
</span><span class="lines">@@ -436,22 +436,33 @@
</span><span class="cx"> static apt_bool_t unimrcp_client_media_engines_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         const apr_xml_elem *elem;
</span><ins>+
+        /* create codec manager first */
+        mpf_codec_manager_t *codec_manager = mpf_engine_codec_manager_create(pool);
+        if(codec_manager) {
+                mrcp_client_codec_manager_register(client,codec_manager);
+        }
+
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Media Engines&quot;);
</span><span class="cx">         for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
</span><span class="cx">                 if(strcasecmp(elem-&gt;name,&quot;engine&quot;) == 0) {
</span><span class="cx">                         mpf_engine_t *media_engine;
</span><ins>+                        unsigned long rate = 1;
</ins><span class="cx">                         const char *name = NULL;
</span><span class="cx">                         const apr_xml_attr *attr;
</span><span class="cx">                         for(attr = elem-&gt;attr; attr; attr = attr-&gt;next) {
</span><span class="cx">                                 if(strcasecmp(attr-&gt;name,&quot;name&quot;) == 0) {
</span><span class="cx">                                         name = apr_pstrdup(pool,attr-&gt;value);
</span><span class="cx">                                 }
</span><ins>+                                else if(strcasecmp(attr-&gt;name,&quot;rate&quot;) == 0) {
+                                        rate = atol(attr-&gt;value);
+                                }
</ins><span class="cx">                                 else {
</span><span class="cx">                                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr-&gt;name);
</span><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Media Engine&quot;);
</span><del>-                        media_engine = mpf_engine_create(pool);
</del><ins>+                        media_engine = mpf_engine_create(rate,pool);
</ins><span class="cx">                         if(media_engine) {
</span><span class="cx">                                 mrcp_client_media_engine_register(client,media_engine,name);
</span><span class="cx">                         }
</span><span class="lines">@@ -480,6 +491,57 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Load resource */
+static apt_bool_t unimrcp_client_resource_load(mrcp_client_t *client, mrcp_resource_loader_t *resource_loader, const apr_xml_elem *root, apr_pool_t *pool)
+{
+        apt_str_t resource_class;
+        apt_bool_t resource_enabled = TRUE;
+        const apr_xml_attr *attr;
+        apt_string_reset(&amp;resource_class);
+        for(attr = root-&gt;attr; attr; attr = attr-&gt;next) {
+                if(strcasecmp(attr-&gt;name,&quot;class&quot;) == 0) {
+                        apt_string_set(&amp;resource_class,attr-&gt;value);
+                }
+                else if(strcasecmp(attr-&gt;name,&quot;enable&quot;) == 0) {
+                        resource_enabled = atoi(attr-&gt;value);
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr-&gt;name);
+                }
+        }
+
+        if(!resource_class.buf || !resource_enabled) {
+                return FALSE;
+        }
+
+        return mrcp_resource_load(resource_loader,&amp;resource_class);
+}
+
+/** Load resources */
+static apt_bool_t unimrcp_client_resources_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
+{
+        const apr_xml_elem *elem;
+        mrcp_resource_factory_t *resource_factory;
+        mrcp_resource_loader_t *resource_loader = mrcp_resource_loader_create(FALSE,pool);
+        if(!resource_loader) {
+                return FALSE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Resources&quot;);
+        for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
+                if(strcasecmp(elem-&gt;name,&quot;resource&quot;) == 0) {
+                        unimrcp_client_resource_load(client,resource_loader,elem,pool);
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Element &lt;%s&gt;&quot;,elem-&gt;name);
+                }
+        }    
+        
+        resource_factory = mrcp_resource_factory_get(resource_loader);
+        mrcp_client_resource_factory_register(client,resource_factory);
+        return TRUE;
+}
+
</ins><span class="cx"> /** Load settings */
</span><span class="cx"> static apt_bool_t unimrcp_client_settings_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="lines">@@ -582,7 +644,10 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
</span><del>-                if(strcasecmp(elem-&gt;name,&quot;settings&quot;) == 0) {
</del><ins>+                if(strcasecmp(elem-&gt;name,&quot;resources&quot;) == 0) {
+                        unimrcp_client_resources_load(client,elem,pool);
+                }
+                else if(strcasecmp(elem-&gt;name,&quot;settings&quot;) == 0) {
</ins><span class="cx">                         unimrcp_client_settings_load(client,elem,pool);
</span><span class="cx">                 }
</span><span class="cx">                 else if(strcasecmp(elem-&gt;name,&quot;profiles&quot;) == 0) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibunimrcpserverMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -31,6 +31,6 @@
</span><span class="cx">                               $(top_builddir)/libs/mrcp/libmrcp.la \
</span><span class="cx">                               $(top_builddir)/libs/mpf/libmpf.la \
</span><span class="cx">                               $(top_builddir)/libs/apr-toolkit/libaprtoolkit.la \
</span><del>-                              $(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS) $(UNIMRCP_SOFIA_LIBS)
</del><ins>+                              $(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS) $(UNIMRCP_SOFIA_LIBS) -lm
</ins><span class="cx"> 
</span><span class="cx"> libunimrcpserver_la_LDFLAGS = $(UNI_LT_VERSION)
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformslibunimrcpserversrcunimrcp_serverc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx"> #include &lt;apr_xml.h&gt;
</span><span class="cx"> #include &quot;unimrcp_server.h&quot;
</span><span class="cx"> #include &quot;uni_version.h&quot;
</span><del>-#include &quot;mrcp_default_factory.h&quot;
</del><ins>+#include &quot;mrcp_resource_loader.h&quot;
</ins><span class="cx"> #include &quot;mpf_engine.h&quot;
</span><span class="cx"> #include &quot;mpf_codec_manager.h&quot;
</span><span class="cx"> #include &quot;mpf_rtp_termination_factory.h&quot;
</span><span class="lines">@@ -57,8 +57,6 @@
</span><span class="cx"> {
</span><span class="cx">         apr_pool_t *pool;
</span><span class="cx">         apr_xml_doc *doc;
</span><del>-        mrcp_resource_factory_t *resource_factory;
-        mpf_codec_manager_t *codec_manager;
</del><span class="cx">         mrcp_server_t *server;
</span><span class="cx"> 
</span><span class="cx">         if(!dir_layout) {
</span><span class="lines">@@ -76,16 +74,6 @@
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        resource_factory = mrcp_default_factory_create(pool);
-        if(resource_factory) {
-                mrcp_server_resource_factory_register(server,resource_factory);
-        }
-
-        codec_manager = mpf_engine_codec_manager_create(pool);
-        if(codec_manager) {
-                mrcp_server_codec_manager_register(server,codec_manager);
-        }
-
</del><span class="cx">         doc = unimrcp_server_config_parse(dir_layout-&gt;conf_dir_path,pool);
</span><span class="cx">         if(doc) {
</span><span class="cx">                 unimrcp_server_config_load(server,dir_layout-&gt;plugin_dir_path,doc,pool);
</span><span class="lines">@@ -134,7 +122,7 @@
</span><span class="cx">         rv = apr_xml_parse_file(pool,&amp;parser,&amp;doc,fd,XML_FILE_BUFFER_LENGTH);
</span><span class="cx">         if(rv != APR_SUCCESS) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Parse Config File [%s]&quot;,file_path);
</span><del>-                return NULL;
</del><ins>+                doc = NULL;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apr_file_close(fd);
</span><span class="lines">@@ -452,6 +440,18 @@
</span><span class="cx">                                 else if(strcasecmp(attr_name-&gt;value,&quot;own-preference&quot;) == 0) {
</span><span class="cx">                                         rtp_config-&gt;own_preferrence = atoi(attr_value-&gt;value);
</span><span class="cx">                                 }
</span><ins>+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp&quot;) == 0) {
+                                        rtp_config-&gt;rtcp = atoi(attr_value-&gt;value);
+                                }
+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp-bye&quot;) == 0) {
+                                        rtp_config-&gt;rtcp_bye_policy = atoi(attr_value-&gt;value);
+                                }
+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp-tx-interval&quot;) == 0) {
+                                        rtp_config-&gt;rtcp_tx_interval = (apr_uint16_t)atoi(attr_value-&gt;value);
+                                }
+                                else if(strcasecmp(attr_name-&gt;value,&quot;rtcp-rx-resolution&quot;) == 0) {
+                                        rtp_config-&gt;rtcp_rx_resolution = (apr_uint16_t)atol(attr_value-&gt;value);
+                                }
</ins><span class="cx">                                 else {
</span><span class="cx">                                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr_name-&gt;value);
</span><span class="cx">                                 }
</span><span class="lines">@@ -469,22 +469,33 @@
</span><span class="cx"> static apt_bool_t unimrcp_server_media_engines_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         const apr_xml_elem *elem;
</span><ins>+
+        /* create codec manager first */
+        mpf_codec_manager_t *codec_manager = mpf_engine_codec_manager_create(pool);
+        if(codec_manager) {
+                mrcp_server_codec_manager_register(server,codec_manager);
+        }
+
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Media Engines&quot;);
</span><span class="cx">         for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
</span><span class="cx">                 if(strcasecmp(elem-&gt;name,&quot;engine&quot;) == 0) {
</span><span class="cx">                         mpf_engine_t *media_engine;
</span><ins>+                        unsigned long rate = 1;
</ins><span class="cx">                         const char *name = NULL;
</span><span class="cx">                         const apr_xml_attr *attr;
</span><span class="cx">                         for(attr = elem-&gt;attr; attr; attr = attr-&gt;next) {
</span><span class="cx">                                 if(strcasecmp(attr-&gt;name,&quot;name&quot;) == 0) {
</span><span class="cx">                                         name = apr_pstrdup(pool,attr-&gt;value);
</span><span class="cx">                                 }
</span><ins>+                                else if(strcasecmp(attr-&gt;name,&quot;rate&quot;) == 0) {
+                                        rate = atol(attr-&gt;value);
+                                }
</ins><span class="cx">                                 else {
</span><span class="cx">                                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr-&gt;name);
</span><span class="cx">                                 }
</span><span class="cx">                         }
</span><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Media Engine&quot;);
</span><del>-                        media_engine = mpf_engine_create(pool);
</del><ins>+                        media_engine = mpf_engine_create(rate,pool);
</ins><span class="cx">                         if(media_engine) {
</span><span class="cx">                                 mrcp_server_media_engine_register(server,media_engine,name);
</span><span class="cx">                         }
</span><span class="lines">@@ -513,18 +524,70 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Load resource */
+static apt_bool_t unimrcp_server_resource_load(mrcp_server_t *server, mrcp_resource_loader_t *resource_loader, const apr_xml_elem *root, apr_pool_t *pool)
+{
+        apt_str_t resource_class;
+        apt_bool_t resource_enabled = TRUE;
+        const apr_xml_attr *attr;
+        apt_string_reset(&amp;resource_class);
+        for(attr = root-&gt;attr; attr; attr = attr-&gt;next) {
+                if(strcasecmp(attr-&gt;name,&quot;class&quot;) == 0) {
+                        apt_string_set(&amp;resource_class,attr-&gt;value);
+                }
+                else if(strcasecmp(attr-&gt;name,&quot;enable&quot;) == 0) {
+                        resource_enabled = atoi(attr-&gt;value);
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr-&gt;name);
+                }
+        }
+
+        if(!resource_class.buf || !resource_enabled) {
+                return FALSE;
+        }
+
+        return mrcp_resource_load(resource_loader,&amp;resource_class);
+}
+
+/** Load resources */
+static apt_bool_t unimrcp_server_resources_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
+{
+        const apr_xml_elem *elem;
+        mrcp_resource_factory_t *resource_factory;
+        mrcp_resource_loader_t *resource_loader = mrcp_resource_loader_create(FALSE,pool);
+        if(!resource_loader) {
+                return FALSE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Resources&quot;);
+        for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
+                if(strcasecmp(elem-&gt;name,&quot;resource&quot;) == 0) {
+                        unimrcp_server_resource_load(server,resource_loader,elem,pool);
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Element &lt;%s&gt;&quot;,elem-&gt;name);
+                }
+        }    
+        
+        resource_factory = mrcp_resource_factory_get(resource_loader);
+        mrcp_server_resource_factory_register(server,resource_factory);
+        return TRUE;
+}
+
</ins><span class="cx"> /** Load plugin */
</span><span class="cx"> static apt_bool_t unimrcp_server_plugin_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_elem *root, apr_pool_t *pool)
</span><span class="cx"> {
</span><del>-        const char *plugin_name = NULL;
</del><ins>+        mrcp_engine_config_t *config;
</ins><span class="cx">         const char *plugin_class = NULL;
</span><span class="cx">         const char *plugin_ext = NULL;
</span><span class="cx">         const char *plugin_path = NULL;
</span><span class="cx">         apt_bool_t plugin_enabled = TRUE;
</span><span class="cx">         const apr_xml_attr *attr;
</span><ins>+        config = mrcp_engine_config_alloc(pool);
</ins><span class="cx">         for(attr = root-&gt;attr; attr; attr = attr-&gt;next) {
</span><span class="cx">                 if(strcasecmp(attr-&gt;name,&quot;name&quot;) == 0) {
</span><del>-                        plugin_name = apr_pstrdup(pool,attr-&gt;value);
</del><ins>+                        config-&gt;name = apr_pstrdup(pool,attr-&gt;value);
</ins><span class="cx">                 }
</span><span class="cx">                 else if(strcasecmp(attr-&gt;name,&quot;class&quot;) == 0) {
</span><span class="cx">                         plugin_class = attr-&gt;value;
</span><span class="lines">@@ -535,6 +598,9 @@
</span><span class="cx">                 else if(strcasecmp(attr-&gt;name,&quot;enable&quot;) == 0) {
</span><span class="cx">                         plugin_enabled = atoi(attr-&gt;value);
</span><span class="cx">                 }
</span><ins>+                else if(strcasecmp(attr-&gt;name,&quot;max-channel-count&quot;) == 0) {
+                        config-&gt;max_channel_count = atol(attr-&gt;value);
+                }
</ins><span class="cx">                 else {
</span><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Attribute &lt;%s&gt;&quot;,attr-&gt;name);
</span><span class="cx">                 }
</span><span class="lines">@@ -557,14 +623,31 @@
</span><span class="cx">                 plugin_path = apr_psprintf(pool,&quot;%s/%s.%s&quot;,plugin_dir_path,plugin_class,plugin_ext);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return mrcp_server_plugin_register(server,plugin_path,plugin_name);
</del><ins>+        /* load optional name/value params */
+        if(root-&gt;first_child){
+                const apr_xml_attr *attr_name;
+                const apr_xml_attr *attr_value;
+                const apr_xml_elem *elem;
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Engine Params&quot;);
+                config-&gt;params = apr_table_make(pool,1);
+                for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
+                        if(strcasecmp(elem-&gt;name,&quot;param&quot;) == 0) {
+                                if(param_name_value_get(elem,&amp;attr_name,&amp;attr_value) == TRUE) {
+                                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Param %s:%s&quot;,attr_name-&gt;value,attr_value-&gt;value);
+                                        apr_table_set(config-&gt;params,attr_name-&gt;value,attr_value-&gt;value);
+                                }
+                        }
+                }
+        }
+
+        return mrcp_server_plugin_register(server,plugin_path,config);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Load plugins */
</span><span class="cx"> static apt_bool_t unimrcp_server_plugins_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_elem *root, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         const apr_xml_elem *elem;
</span><del>-        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Plugins (Resource Engines)&quot;);
</del><ins>+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Loading Engine Plugins&quot;);
</ins><span class="cx">         for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
</span><span class="cx">                 if(strcasecmp(elem-&gt;name,&quot;engine&quot;) == 0) {
</span><span class="cx">                         unimrcp_server_plugin_load(server,plugin_dir_path,elem,pool);
</span><span class="lines">@@ -687,7 +770,10 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx">         for(elem = root-&gt;first_child; elem; elem = elem-&gt;next) {
</span><del>-                if(strcasecmp(elem-&gt;name,&quot;settings&quot;) == 0) {
</del><ins>+                if(strcasecmp(elem-&gt;name,&quot;resources&quot;) == 0) {
+                        unimrcp_server_resources_load(server,elem,pool);
+                }
+                else if(strcasecmp(elem-&gt;name,&quot;settings&quot;) == 0) {
</ins><span class="cx">                         unimrcp_server_settings_load(server,plugin_dir_path,elem,pool);
</span><span class="cx">                 }
</span><span class="cx">                 else if(strcasecmp(elem-&gt;name,&quot;profiles&quot;) == 0) {
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcMakefileam"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/Makefile.am (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/Makefile.am                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+MAINTAINERCLEANFILES   = Makefile.in
+
+INCLUDES               = -Iinclude \
+                         -I$(top_srcdir)/platforms/libunimrcp-client/include \
+                         -I$(top_srcdir)/libs/mrcp-client/include \
+                         -I$(top_srcdir)/libs/mrcp-signaling/include \
+                         -I$(top_srcdir)/libs/mrcpv2-transport/include \
+                         -I$(top_srcdir)/libs/mrcp/include \
+                         -I$(top_srcdir)/libs/mrcp/message/include \
+                         -I$(top_srcdir)/libs/mrcp/control/include \
+                         -I$(top_srcdir)/libs/mrcp/resources/include \
+                         -I$(top_srcdir)/libs/mpf/include \
+                         -I$(top_srcdir)/libs/apr-toolkit/include \
+                         $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
+
+bin_PROGRAMS           = umc
+umc_SOURCES            = src/main.cpp \
+                         src/umcconsole.cpp \
+                         src/umcframework.cpp \
+                         src/umcscenario.cpp \
+                         src/umcsession.cpp \
+                         src/synthscenario.cpp \
+                         src/synthsession.cpp \
+                         src/recogscenario.cpp \
+                         src/recogsession.cpp \
+                         src/recorderscenario.cpp \
+                         src/recordersession.cpp \
+                         src/dtmfscenario.cpp \
+                         src/dtmfsession.cpp
+umc_LDADD              = $(top_builddir)/platforms/libunimrcp-client/libunimrcpclient.la
+
+if ISMAC
+umc_LDFLAGS            = -framework CoreFoundation -framework SystemConfiguration
+endif
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludedtmfscenarioh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfscenario.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfscenario.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfscenario.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,75 @@
</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 __DTMF_SCENARIO_H__
+#define __DTMF_SCENARIO_H__
+
+/**
+ * @file dtmfscenario.h
+ * @brief DTMF Recognition Scenario
+ */ 
+
+#include &quot;umcscenario.h&quot;
+
+class DtmfScenario : public UmcScenario
+{
+public:
+/* ============================ CREATORS =================================== */
+        DtmfScenario();
+        virtual ~DtmfScenario();
+
+/* ============================ MANIPULATORS =============================== */
+        virtual void Destroy();
+
+        virtual UmcSession* CreateSession();
+
+/* ============================ ACCESSORS ================================== */
+        const char* GetContentType() const;
+        const char* GetGrammar() const;
+        const char* GetDigits() const;
+
+/* ============================ INQUIRIES ================================== */
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+        bool LoadRecognize(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+/* ============================ DATA ======================================= */
+        const char* m_ContentType;
+        const char* m_Grammar;
+        const char* m_Digits;
+};
+
+/* ============================ INLINE METHODS ============================= */
+inline const char* DtmfScenario::GetContentType() const
+{
+        return m_ContentType;
+}
+
+inline const char* DtmfScenario::GetGrammar() const
+{
+        return m_Grammar;
+}
+
+inline const char* DtmfScenario::GetDigits() const
+{
+        return m_Digits;
+}
+
+
+#endif /*__DTMF_SCENARIO_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludedtmfsessionh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfsession.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfsession.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/dtmfsession.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,69 @@
</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 __DTMF_SESSION_H__
+#define __DTMF_SESSION_H__
+
+/**
+ * @file dtmfsession.h
+ * @brief DTMF Recognition Session
+ */ 
+
+#include &quot;umcsession.h&quot;
+
+class DtmfScenario;
+struct RecogChannel;
+
+class DtmfSession : public UmcSession
+{
+public:
+/* ============================ CREATORS =================================== */
+        DtmfSession(const DtmfScenario* pScenario);
+        virtual ~DtmfSession();
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Start();
+
+        RecogChannel* CreateRecogChannel();
+        bool StartRecognition(mrcp_channel_t* pMrcpChannel);
+
+        mrcp_message_t* CreateRecognizeRequest(mrcp_channel_t* pMrcpChannel);
+
+        bool ParseNLSMLResult(mrcp_message_t* pMrcpMessage) const;
+
+/* ============================ HANDLERS =================================== */
+        virtual bool OnSessionTerminate(mrcp_sig_status_code_e status);
+        virtual bool OnChannelAdd(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnChannelRemove(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnMessageReceive(mrcp_channel_t* channel, mrcp_message_t* message);
+
+/* ============================ ACCESSORS ================================== */
+        const DtmfScenario* GetScenario() const;
+
+private:
+/* ============================ DATA ======================================= */
+        RecogChannel*         m_pRecogChannel;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline const DtmfScenario* DtmfSession::GetScenario() const
+{
+        return (DtmfScenario*)m_pScenario;
+}
+
+#endif /*__DTMF_SESSION_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincluderecogscenarioh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogscenario.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogscenario.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogscenario.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,88 @@
</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 __RECOG_SCENARIO_H__
+#define __RECOG_SCENARIO_H__
+
+/**
+ * @file recogscenario.h
+ * @brief Recognizer Scenario
+ */ 
+
+#include &quot;umcscenario.h&quot;
+
+class RecogScenario : public UmcScenario
+{
+public:
+/* ============================ CREATORS =================================== */
+        RecogScenario();
+        virtual ~RecogScenario();
+
+/* ============================ MANIPULATORS =============================== */
+        virtual void Destroy();
+
+        virtual UmcSession* CreateSession();
+
+/* ============================ ACCESSORS ================================== */
+        const char* GetContentType() const;
+        const char* GetContent() const;
+        const char* GetAudioSource() const;
+
+/* ============================ INQUIRIES ================================== */
+        bool IsDefineGrammarEnabled() const;
+        bool IsRecognizeEnabled() const;
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+        bool LoadRecognize(const apr_xml_elem* pElem, apr_pool_t* pool);
+        bool LoadDefineGrammar(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+/* ============================ DATA ======================================= */
+        bool        m_DefineGrammar;
+        bool        m_Recognize;
+        const char* m_ContentType;
+        const char* m_Content;
+        const char* m_AudioSource;
+};
+
+/* ============================ INLINE METHODS ============================= */
+inline const char* RecogScenario::GetContentType() const
+{
+        return m_ContentType;
+}
+
+inline const char* RecogScenario::GetContent() const
+{
+        return m_Content;
+}
+
+inline const char* RecogScenario::GetAudioSource() const
+{
+        return m_AudioSource;
+}
+
+inline bool RecogScenario::IsDefineGrammarEnabled() const
+{
+        return m_DefineGrammar;
+}
+
+inline bool RecogScenario::IsRecognizeEnabled() const
+{
+        return m_Recognize;
+}
+
+#endif /*__RECOG_SCENARIO_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincluderecogsessionh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogsession.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogsession.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/recogsession.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,73 @@
</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 __RECOG_SESSION_H__
+#define __RECOG_SESSION_H__
+
+/**
+ * @file recogsession.h
+ * @brief Recognizer Session
+ */ 
+
+#include &quot;umcsession.h&quot;
+
+class RecogScenario;
+struct RecogChannel;
+
+class RecogSession : public UmcSession
+{
+public:
+/* ============================ CREATORS =================================== */
+        RecogSession(const RecogScenario* pScenario);
+        virtual ~RecogSession();
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Start();
+
+        RecogChannel* CreateRecogChannel();
+        bool StartRecognition(mrcp_channel_t* pMrcpChannel);
+        bool OnDefineGrammar(mrcp_channel_t* pMrcpChannel);
+
+        mrcp_message_t* CreateDefineGrammarRequest(mrcp_channel_t* pMrcpChannel);
+        mrcp_message_t* CreateRecognizeRequest(mrcp_channel_t* pMrcpChannel);
+
+        bool ParseNLSMLResult(mrcp_message_t* pMrcpMessage) const;
+        FILE* GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const;
+
+/* ============================ HANDLERS =================================== */
+        virtual bool OnSessionTerminate(mrcp_sig_status_code_e status);
+        virtual bool OnChannelAdd(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnChannelRemove(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnMessageReceive(mrcp_channel_t* channel, mrcp_message_t* message);
+
+/* ============================ ACCESSORS ================================== */
+        const RecogScenario* GetScenario() const;
+
+private:
+/* ============================ DATA ======================================= */
+        RecogChannel* m_pRecogChannel;
+        const char*   m_ContentId;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline const RecogScenario* RecogSession::GetScenario() const
+{
+        return (RecogScenario*)m_pScenario;
+}
+
+#endif /*__RECOG_SESSION_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincluderecorderscenarioh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/recorderscenario.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/recorderscenario.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/recorderscenario.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,66 @@
</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 __RECORDER_SCENARIO_H__
+#define __RECORDER_SCENARIO_H__
+
+/**
+ * @file recorderscenario.h
+ * @brief Recorder Scenario
+ */ 
+
+#include &quot;umcscenario.h&quot;
+
+class RecorderScenario : public UmcScenario
+{
+public:
+/* ============================ CREATORS =================================== */
+        RecorderScenario();
+        virtual ~RecorderScenario();
+
+/* ============================ MANIPULATORS =============================== */
+        virtual void Destroy();
+
+        virtual UmcSession* CreateSession();
+
+/* ============================ ACCESSORS ================================== */
+        const char* GetAudioSource() const;
+
+/* ============================ INQUIRIES ================================== */
+        bool IsRecordEnabled() const;
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+        bool LoadRecord(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+/* ============================ DATA ======================================= */
+        bool        m_Record;
+        const char* m_AudioSource;
+};
+
+/* ============================ INLINE METHODS ============================= */
+inline const char* RecorderScenario::GetAudioSource() const
+{
+        return m_AudioSource;
+}
+
+inline bool RecorderScenario::IsRecordEnabled() const
+{
+        return m_Record;
+}
+
+#endif /*__RECORDER_SCENARIO_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincluderecordersessionh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/recordersession.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/recordersession.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/recordersession.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,69 @@
</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 __RECORDER_SESSION_H__
+#define __RECORDER_SESSION_H__
+
+/**
+ * @file recordersession.h
+ * @brief Recorder Session
+ */ 
+
+#include &quot;umcsession.h&quot;
+
+class RecorderScenario;
+struct RecorderChannel;
+
+class RecorderSession : public UmcSession
+{
+public:
+/* ============================ CREATORS =================================== */
+        RecorderSession(const RecorderScenario* pScenario);
+        virtual ~RecorderSession();
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Start();
+
+        RecorderChannel* CreateRecorderChannel();
+        bool StartRecorder(mrcp_channel_t* pMrcpChannel);
+
+        mrcp_message_t* CreateRecordRequest(mrcp_channel_t* pMrcpChannel);
+
+        FILE* GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const;
+
+/* ============================ HANDLERS =================================== */
+        virtual bool OnSessionTerminate(mrcp_sig_status_code_e status);
+        virtual bool OnChannelAdd(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnChannelRemove(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnMessageReceive(mrcp_channel_t* channel, mrcp_message_t* message);
+
+/* ============================ ACCESSORS ================================== */
+        const RecorderScenario* GetScenario() const;
+
+private:
+/* ============================ DATA ======================================= */
+        RecorderChannel* m_pRecorderChannel;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline const RecorderScenario* RecorderSession::GetScenario() const
+{
+        return (RecorderScenario*)m_pScenario;
+}
+
+#endif /*__RECORDER_SESSION_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludesynthscenarioh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthscenario.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthscenario.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthscenario.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,74 @@
</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 __SYNTH_SCENARIO_H__
+#define __SYNTH_SCENARIO_H__
+
+/**
+ * @file synthscenario.h
+ * @brief Synthesizer Scenario
+ */ 
+
+#include &quot;umcscenario.h&quot;
+
+class SynthScenario : public UmcScenario
+{
+public:
+/* ============================ CREATORS =================================== */
+        SynthScenario();
+        virtual ~SynthScenario();
+
+/* ============================ MANIPULATORS =============================== */
+        virtual void Destroy();
+
+        virtual UmcSession* CreateSession();
+
+/* ============================ ACCESSORS ================================== */
+        const char* GetContentType() const;
+        const char* GetContent() const;
+
+/* ============================ INQUIRIES ================================== */
+        bool IsSpeakEnabled() const;
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+        bool LoadSpeak(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+/* ============================ DATA ======================================= */
+        bool        m_Speak;
+        const char* m_ContentType;
+        const char* m_Content;
+};
+
+/* ============================ INLINE METHODS ============================= */
+inline const char* SynthScenario::GetContentType() const
+{
+        return m_ContentType;
+}
+
+inline const char* SynthScenario::GetContent() const
+{
+        return m_Content;
+}
+
+inline bool SynthScenario::IsSpeakEnabled() const
+{
+        return m_Speak;
+}
+
+#endif /*__SYNTH_SCENARIO_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludesynthsessionh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthsession.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthsession.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/synthsession.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,67 @@
</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 __SYNTH_SESSION_H__
+#define __SYNTH_SESSION_H__
+
+/**
+ * @file synthsession.h
+ * @brief Synthesizer Session
+ */ 
+
+#include &quot;umcsession.h&quot;
+
+class SynthScenario;
+struct SynthChannel;
+
+class SynthSession : public UmcSession
+{
+public:
+/* ============================ CREATORS =================================== */
+        SynthSession(const SynthScenario* pScenario);
+        virtual ~SynthSession();
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Start();
+
+        SynthChannel* CreateSynthChannel();
+
+        mrcp_message_t* CreateSpeakRequest(mrcp_channel_t* pMrcpChannel);
+        FILE* GetAudioOut(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const;
+
+/* ============================ HANDLERS =================================== */
+        virtual bool OnSessionTerminate(mrcp_sig_status_code_e status);
+        virtual bool OnChannelAdd(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnChannelRemove(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+        virtual bool OnMessageReceive(mrcp_channel_t* channel, mrcp_message_t* message);
+
+/* ============================ ACCESSORS ================================== */
+        const SynthScenario* GetScenario() const;
+        
+private:
+/* ============================ DATA ======================================= */
+        SynthChannel* m_pSynthChannel;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline const SynthScenario* SynthSession::GetScenario() const
+{
+        return (SynthScenario*)m_pScenario;
+}
+
+#endif /*__SYNTH_SESSION_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludeumcconsoleh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcconsole.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcconsole.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcconsole.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,58 @@
</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 __UMC_CONSOLE_H__
+#define __UMC_CONSOLE_H__
+
+/**
+ * @file umcconsole.h
+ * @brief UMC Application Console
+ */ 
+
+#include &quot;apt_log.h&quot;
+
+class UmcFramework;
+
+class UmcConsole
+{
+public:
+/* ============================ CREATORS =================================== */
+        UmcConsole();
+        ~UmcConsole();
+
+/* ============================ MANIPULATORS =============================== */
+        bool Run(int argc, const char * const *argv);
+
+protected:
+        bool LoadOptions(int argc, const char * const *argv, apr_pool_t *pool);
+        bool RunCmdLine();
+        bool ProcessCmdLine(char* pCmdLine);
+        void Usage() const;
+
+private:
+/* ============================ DATA ======================================= */
+        struct UmcOptions
+        {
+                const char*        m_RootDirPath;
+                apt_log_priority_e m_LogPriority;
+                apt_log_output_e   m_LogOutput;
+        };
+
+        UmcOptions    m_Options;
+        UmcFramework* m_pFramework;
+};
+
+#endif /*__UMC_CONSOLE_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludeumcframeworkh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcframework.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcframework.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcframework.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,95 @@
</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 __UMC_FRAMEWORK_H__
+#define __UMC_FRAMEWORK_H__
+
+/**
+ * @file umcframework.h
+ * @brief UMC Application Framework
+ */ 
+
+#include &lt;apr_xml.h&gt;
+#include &lt;apr_hash.h&gt;
+#include &quot;mrcp_application.h&quot;
+#include &quot;apt_consumer_task.h&quot;
+
+class UmcSession;
+class UmcScenario;
+
+class UmcFramework
+{
+public:
+/* ============================ CREATORS =================================== */
+        UmcFramework();
+        ~UmcFramework();
+
+/* ============================ MANIPULATORS =============================== */
+        bool Create(apt_dir_layout_t* pDirLayout, apr_pool_t* pool);
+        void Destroy();
+
+        void RunSession(const char* pScenarioName, const char* pProfileName);
+        void KillSession(const char* id);
+
+        void ShowScenarios();
+        void ShowSessions();
+
+protected:
+        bool CreateMrcpClient();
+        void DestroyMrcpClient();
+
+        bool CreateTask();
+        void DestroyTask();
+
+        UmcScenario* CreateScenario(const char* pType);
+        apr_xml_doc* LoadDocument();
+
+        bool LoadScenarios();
+        void DestroyScenarios();
+
+        bool ProcessRunRequest(const char* pScenarioName, const char* pProfileName);
+        void ProcessKillRequest(const char* id);
+        void ProcessShowScenarios();
+        void ProcessShowSessions();
+
+        bool AddSession(UmcSession* pSession);
+        bool RemoveSession(UmcSession* pSession);
+
+/* ============================ HANDLERS =================================== */
+        friend apt_bool_t UmcProcessMsg(apt_task_t* pTask, apt_task_msg_t* pMsg);
+        friend void UmcOnStartComplete(apt_task_t* pTask);
+        friend void UmcOnTerminateComplete(apt_task_t* pTask);
+
+        friend apt_bool_t AppMessageHandler(const mrcp_app_message_t* pAppMessage);
+        friend apt_bool_t AppOnReady(mrcp_application_t* pMrcpApplication, mrcp_sig_status_code_e status);
+        friend apt_bool_t AppOnSessionTerminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
+
+private:
+/* ============================ DATA ======================================= */
+        apr_pool_t*          m_pPool;
+        apt_dir_layout_t*    m_pDirLayout;
+        apt_consumer_task_t* m_pTask;
+
+        mrcp_client_t*       m_pMrcpClient;
+        mrcp_application_t*  m_pMrcpApplication;
+
+        bool                 m_Ready;
+
+        apr_hash_t*          m_pScenarioTable;
+        apr_hash_t*          m_pSessionTable;
+};
+
+#endif /*__UMC_FRAMEWORK_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludeumcscenarioh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcscenario.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcscenario.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcscenario.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,120 @@
</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 __UMC_SCENARIO_H__
+#define __UMC_SCENARIO_H__
+
+/**
+ * @file umcscenario.h
+ * @brief UMC Scenario
+ */ 
+
+#include &lt;apr_xml.h&gt;
+#include &quot;mrcp_application.h&quot;
+
+class UmcSession;
+
+class UmcScenario
+{
+public:
+/* ============================ CREATORS =================================== */
+        UmcScenario();
+        virtual ~UmcScenario();
+
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Load(const apr_xml_elem* pElem, apr_pool_t* pool);
+        virtual void Destroy();
+
+        virtual UmcSession* CreateSession() = 0;
+
+        void SetDirLayout(apt_dir_layout_t* pDirLayout);
+        void SetName(const char* pName);
+        void SetMrcpProfile(const char* pMrcpProfile);
+
+        bool InitCapabilities(mpf_stream_capabilities_t* pCapabilities) const;
+
+/* ============================ ACCESSORS ================================== */
+        apt_dir_layout_t* GetDirLayout() const;
+        const char* GetName() const;
+        const char* GetMrcpProfile() const;
+
+/* ============================ INQUIRIES ================================== */
+        bool IsDiscoveryEnabled() const;
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool);
+        
+        bool LoadDiscovery(const apr_xml_elem* pElem, apr_pool_t* pool);
+        bool LoadTermination(const apr_xml_elem* pElem, apr_pool_t* pool);
+        bool LoadCapabilities(const apr_xml_elem* pElem, apr_pool_t* pool);
+        bool LoadRtpTermination(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+        const char* LoadFileContent(const char* pFileName, apr_pool_t* pool) const;
+        int ParseRates(const char* pStr, apr_pool_t* pool) const;
+
+/* ============================ INQUIRIES ================================== */
+        bool IsElementEnabled(const apr_xml_elem* pElem) const;
+
+/* ============================ DATA ======================================= */
+        const char*                       m_pName;
+        const char*                       m_pMrcpProfile;
+        apt_dir_layout_t*                 m_pDirLayout;
+
+        bool                              m_ResourceDiscovery;
+        mpf_codec_capabilities_t*         m_pCapabilities;
+        mpf_rtp_termination_descriptor_t* m_pRtpDescriptor;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline void UmcScenario::SetDirLayout(apt_dir_layout_t* pDirLayout)
+{
+        m_pDirLayout = pDirLayout;
+}
+
+inline apt_dir_layout_t* UmcScenario::GetDirLayout() const
+{
+        return m_pDirLayout;
+}
+
+inline void UmcScenario::SetName(const char* pName)
+{
+        m_pName = pName;
+}
+
+inline const char* UmcScenario::GetName() const
+{
+        return m_pName;
+}
+
+inline void UmcScenario::SetMrcpProfile(const char* pMrcpProfile)
+{
+        m_pMrcpProfile = pMrcpProfile;
+}
+
+inline const char* UmcScenario::GetMrcpProfile() const
+{
+        return m_pMrcpProfile;
+}
+
+inline bool UmcScenario::IsDiscoveryEnabled() const
+{
+        return m_ResourceDiscovery;
+}
+
+
+#endif /*__UMC_SCENARIO_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcincludeumcsessionh"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcsession.h (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcsession.h                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/include/umcsession.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,121 @@
</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 __UMC_SESSION_H__
+#define __UMC_SESSION_H__
+
+/**
+ * @file umcsession.h
+ * @brief UMC Session
+ */ 
+
+#include &quot;mrcp_application.h&quot;
+
+class UmcScenario;
+
+class UmcSession
+{
+public:
+/* ============================ CREATORS =================================== */
+        UmcSession(const UmcScenario* pScenario);
+        virtual ~UmcSession();
+
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Run();
+        virtual bool Terminate();
+
+        void SetMrcpProfile(const char* pMrcpProfile);
+        void SetMrcpApplication(mrcp_application_t* pMrcpApplication);
+
+/* ============================ HANDLERS =================================== */
+        virtual bool OnSessionTerminate(mrcp_sig_status_code_e status);
+        virtual bool OnSessionUpdate(mrcp_sig_status_code_e status);
+        virtual bool OnChannelAdd(mrcp_channel_t *channel, mrcp_sig_status_code_e status);
+        virtual bool OnChannelRemove(mrcp_channel_t *channel, mrcp_sig_status_code_e status);
+        virtual bool OnMessageReceive(mrcp_channel_t *channel, mrcp_message_t *message);
+        virtual bool OnTerminateEvent(mrcp_channel_t *channel);
+        virtual bool OnResourceDiscover(mrcp_session_descriptor_t* descriptor, mrcp_sig_status_code_e status);
+
+/* ============================ ACCESSORS ================================== */
+        const UmcScenario* GetScenario() const;
+
+        const char* GetId() const;
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+        virtual bool Start() = 0;
+
+        bool CreateMrcpSession(const char* pProfileName);
+        bool DestroyMrcpSession();
+
+        bool AddMrcpChannel(mrcp_channel_t* pMrcpChannel);
+        bool RemoveMrcpChannel(mrcp_channel_t* pMrcpChannel);
+        bool SendMrcpRequest(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage);
+        bool ResourceDiscover();
+
+        mrcp_channel_t* CreateMrcpChannel(
+                        mrcp_resource_id resource_id, 
+                        mpf_termination_t* pTermination, 
+                        mpf_rtp_termination_descriptor_t* pRtpDescriptor, 
+                        void* pObj);
+        mpf_termination_t* CreateAudioTermination(
+                        const mpf_audio_stream_vtable_t* pStreamVtable,
+                        mpf_stream_capabilities_t* pCapabilities,
+                        void* pObj);
+        mrcp_message_t* CreateMrcpMessage(
+                        mrcp_channel_t* pMrcpChannel, 
+                        mrcp_method_id method_id);
+
+/* ============================ ACCESSORS ================================== */
+        apr_pool_t* GetSessionPool() const;
+        const char* GetMrcpSessionId() const;
+
+/* ============================ DATA ======================================= */
+        const UmcScenario*  m_pScenario;
+        const char*         m_pMrcpProfile;
+        char                m_Id[10];
+
+private:
+/* ============================ DATA ======================================= */
+        mrcp_application_t* m_pMrcpApplication;
+        mrcp_session_t*     m_pMrcpSession;
+        bool                m_Running;
+        bool                m_Terminating;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline const UmcScenario* UmcSession::GetScenario() const
+{
+        return m_pScenario;
+}
+
+inline const char* UmcSession::GetId() const
+{
+        return m_Id;
+}
+
+inline void UmcSession::SetMrcpApplication(mrcp_application_t* pMrcpApplication)
+{
+        m_pMrcpApplication = pMrcpApplication;
+}
+
+inline void UmcSession::SetMrcpProfile(const char* pMrcpProfile)
+{
+        m_pMrcpProfile = pMrcpProfile;
+}
+
+#endif /*__UMC_SESSION_H__*/
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcdtmfscenariocpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,77 @@
</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 &lt;stdlib.h&gt;
+#include &quot;dtmfscenario.h&quot;
+#include &quot;dtmfsession.h&quot;
+#include &quot;apt_log.h&quot;
+
+DtmfScenario::DtmfScenario() :
+        m_ContentType(NULL),
+        m_Grammar(NULL),
+        m_Digits(NULL)
+{
+}
+
+DtmfScenario::~DtmfScenario()
+{
+}
+
+void DtmfScenario::Destroy()
+{
+}
+
+bool DtmfScenario::LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        if(UmcScenario::LoadElement(pElem,pool))
+                return true;
+        
+        if(strcasecmp(pElem-&gt;name,&quot;recognize&quot;) == 0)
+        {
+                LoadRecognize(pElem,pool);
+                return true;
+        }
+                
+        return false;
+}
+
+bool DtmfScenario::LoadRecognize(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_attr* pAttr;
+        for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+        {
+                if(strcasecmp(pAttr-&gt;name,&quot;content-type&quot;) == 0)
+                {
+                        m_ContentType = pAttr-&gt;value;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;grammar&quot;) == 0)
+                {
+                        m_Grammar = pAttr-&gt;value;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;digits&quot;) == 0)
+                {
+                        m_Digits = pAttr-&gt;value;
+                }
+        }
+
+        return true;
+}
+
+
+UmcSession* DtmfScenario::CreateSession()
+{
+        return new DtmfSession(this);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcdtmfsessioncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfsession.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfsession.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/dtmfsession.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,326 @@
</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;dtmfsession.h&quot;
+#include &quot;dtmfscenario.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_recog_header.h&quot;
+#include &quot;mrcp_recog_resource.h&quot;
+#include &quot;mpf_dtmf_generator.h&quot;
+#include &quot;apt_nlsml_doc.h&quot;
+#include &quot;apt_log.h&quot;
+
+struct RecogChannel
+{
+        /** MRCP control channel */
+        mrcp_channel_t*       m_pMrcpChannel;
+        /** DTMF generator */
+        mpf_dtmf_generator_t* m_pDtmfGenerator;
+        /** Audio stream */
+        mpf_audio_stream_t*   m_pStream;
+        /** Streaming is in-progress */
+        bool                  m_Streaming;
+};
+
+DtmfSession::DtmfSession(const DtmfScenario* pScenario) :
+        UmcSession(pScenario),
+        m_pRecogChannel(NULL)
+{
+}
+
+DtmfSession::~DtmfSession()
+{
+}
+
+bool DtmfSession::Start()
+{
+        /* create channel and associate all the required data */
+        m_pRecogChannel = CreateRecogChannel();
+        if(!m_pRecogChannel) 
+                return false;
+
+        /* add channel to session (send asynchronous request) */
+        if(!AddMrcpChannel(m_pRecogChannel-&gt;m_pMrcpChannel))
+        {
+                delete m_pRecogChannel;
+                m_pRecogChannel = NULL;
+                return false;
+        }
+        return true;
+}
+
+bool DtmfSession::OnSessionTerminate(mrcp_sig_status_code_e status)
+{
+        if(m_pRecogChannel)
+        {
+                if(m_pRecogChannel-&gt;m_pDtmfGenerator)
+                {
+                        mpf_dtmf_generator_destroy(m_pRecogChannel-&gt;m_pDtmfGenerator);
+                        m_pRecogChannel-&gt;m_pDtmfGenerator = NULL;
+                }
+                
+                delete m_pRecogChannel;
+                m_pRecogChannel = NULL;
+        }
+        return UmcSession::OnSessionTerminate(status);
+}
+
+static apt_bool_t OpenStream(mpf_audio_stream_t* pStream, mpf_codec_t *codec)
+{
+        RecogChannel* pRecogChannel = (RecogChannel*) pStream-&gt;obj;
+        pRecogChannel-&gt;m_pStream = pStream;
+        return TRUE;
+}
+
+static apt_bool_t ReadStream(mpf_audio_stream_t* pStream, mpf_frame_t* pFrame)
+{
+        RecogChannel* pRecogChannel = (RecogChannel*) pStream-&gt;obj;
+        if(pRecogChannel &amp;&amp; pRecogChannel-&gt;m_Streaming) 
+        {
+                if(pRecogChannel-&gt;m_pDtmfGenerator) 
+                {
+                        mpf_dtmf_generator_put_frame(pRecogChannel-&gt;m_pDtmfGenerator,pFrame);
+                }
+        }
+        return TRUE;
+}
+
+RecogChannel* DtmfSession::CreateRecogChannel()
+{
+        mrcp_channel_t* pChannel;
+        mpf_termination_t* pTermination;
+        mpf_stream_capabilities_t* pCapabilities;
+        apr_pool_t* pool = GetSessionPool();
+
+        /* create channel */
+        RecogChannel *pRecogChannel = new RecogChannel;
+        pRecogChannel-&gt;m_pMrcpChannel = NULL;
+        pRecogChannel-&gt;m_pDtmfGenerator = NULL;
+        pRecogChannel-&gt;m_pStream = NULL;
+        pRecogChannel-&gt;m_Streaming = false;
+
+        /* create source stream capabilities */
+        pCapabilities = mpf_source_stream_capabilities_create(pool);
+        GetScenario()-&gt;InitCapabilities(pCapabilities);
+
+        static const mpf_audio_stream_vtable_t audio_stream_vtable = 
+        {
+                NULL,
+                OpenStream,
+                NULL,
+                ReadStream,
+                NULL,
+                NULL,
+                NULL
+        };
+
+        pTermination = CreateAudioTermination(
+                        &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
+                        pCapabilities,             /* capabilities of audio stream */
+                        pRecogChannel);            /* object to associate */
+
+        pChannel = CreateMrcpChannel(
+                        MRCP_RECOGNIZER_RESOURCE,  /* MRCP resource identifier */
+                        pTermination,              /* media termination, used to terminate audio stream */
+                        NULL,                      /* RTP descriptor, used to create RTP termination (NULL by default) */
+                        pRecogChannel);            /* object to associate */
+        if(!pChannel)
+        {
+                delete pRecogChannel;
+                return NULL;
+        }
+        
+        pRecogChannel-&gt;m_pMrcpChannel = pChannel;
+        return pRecogChannel;
+}
+
+bool DtmfSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelAdd(pMrcpChannel,status))
+                return false;
+
+        if(status != MRCP_SIG_STATUS_CODE_SUCCESS)
+        {
+                /* error case, just terminate the demo */
+                return Terminate();
+        }
+
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pRecogChannel)
+        {
+                pRecogChannel-&gt;m_pDtmfGenerator = mpf_dtmf_generator_create(pRecogChannel-&gt;m_pStream,GetSessionPool());
+        }
+
+        return StartRecognition(pMrcpChannel);
+}
+
+bool DtmfSession::OnChannelRemove(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelRemove(pMrcpChannel,status))
+                return false;
+
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pRecogChannel)
+        {
+                if(pRecogChannel-&gt;m_pDtmfGenerator)
+                {
+                        mpf_dtmf_generator_destroy(pRecogChannel-&gt;m_pDtmfGenerator);
+                        pRecogChannel-&gt;m_pDtmfGenerator = NULL;
+                }
+        }
+        
+        /* terminate the demo */
+        return Terminate();
+}
+
+bool DtmfSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
+{
+        if(!UmcSession::OnMessageReceive(pMrcpChannel,pMrcpMessage))
+                return false;
+
+        const DtmfScenario* pScenario = GetScenario();
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) 
+        {
+                if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_RECOGNIZE)
+                {
+                        /* received the response to RECOGNIZE request */
+                        if(pMrcpMessage-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
+                        {
+                                /* start to stream the DTMFs to recognize */
+                                if(pRecogChannel &amp;&amp; pRecogChannel-&gt;m_pDtmfGenerator)
+                                {
+                                        const char* digits = pScenario-&gt;GetDigits();
+                                        if(digits)
+                                        {
+                                                mpf_dtmf_generator_enqueue(pRecogChannel-&gt;m_pDtmfGenerator,digits);
+                                                pRecogChannel-&gt;m_Streaming = true;
+                                        }
+                                }
+                        }
+                        else 
+                        {
+                                /* received unexpected response, remove channel */
+                                RemoveMrcpChannel(pMrcpChannel);
+                        }
+                }
+                else 
+                {
+                        /* received unexpected response */
+                }
+        }
+        else if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) 
+        {
+                if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) 
+                {
+                        ParseNLSMLResult(pMrcpMessage);
+                        if(pRecogChannel) 
+                        {
+                                pRecogChannel-&gt;m_Streaming = false;
+                        }
+                        RemoveMrcpChannel(pMrcpChannel);
+                }
+                else if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_START_OF_INPUT) 
+                {
+                        /* received start-of-input, do whatever you need here */
+                }
+        }
+        return true;
+}
+
+bool DtmfSession::StartRecognition(mrcp_channel_t* pMrcpChannel)
+{
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        /* create and send RECOGNIZE request */
+        mrcp_message_t* pMrcpMessage = CreateRecognizeRequest(pMrcpChannel);
+        if(pMrcpMessage)
+        {
+                SendMrcpRequest(pRecogChannel-&gt;m_pMrcpChannel,pMrcpMessage);
+        }
+
+        return true;
+}
+
+mrcp_message_t* DtmfSession::CreateRecognizeRequest(mrcp_channel_t* pMrcpChannel)
+{
+        mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,RECOGNIZER_RECOGNIZE);
+        if(!pMrcpMessage)
+                return NULL;
+
+        const DtmfScenario* pScenario = GetScenario();
+
+        mrcp_generic_header_t* pGenericHeader;
+        mrcp_recog_header_t* pRecogHeader;
+
+        /* get/allocate generic header */
+        pGenericHeader = (mrcp_generic_header_t*) mrcp_generic_header_prepare(pMrcpMessage);
+        if(pGenericHeader)
+        {
+                apt_string_assign(&amp;pGenericHeader-&gt;content_type,pScenario-&gt;GetContentType(),pMrcpMessage-&gt;pool);
+                mrcp_generic_header_property_add(pMrcpMessage,GENERIC_HEADER_CONTENT_TYPE);
+                /* set message body */
+                if(pScenario-&gt;GetGrammar())
+                        apt_string_assign(&amp;pMrcpMessage-&gt;body,pScenario-&gt;GetGrammar(),pMrcpMessage-&gt;pool);
+        }
+        /* get/allocate recognizer header */
+        pRecogHeader = (mrcp_recog_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
+        if(pRecogHeader)
+        {
+                /* set recognizer header fields */
+                if(pMrcpMessage-&gt;start_line.version == MRCP_VERSION_2)
+                {
+                        pRecogHeader-&gt;cancel_if_queue = FALSE;
+                        mrcp_resource_header_property_add(pMrcpMessage,RECOGNIZER_HEADER_CANCEL_IF_QUEUE);
+                }
+        }
+        return pMrcpMessage;
+}
+
+bool DtmfSession::ParseNLSMLResult(mrcp_message_t* pMrcpMessage) const
+{
+        apr_xml_elem* pInterpret;
+        apr_xml_elem* pInstance;
+        apr_xml_elem* pInput;
+        apr_xml_doc* pDoc = nlsml_doc_load(&amp;pMrcpMessage-&gt;body,pMrcpMessage-&gt;pool);
+        if(!pDoc)
+                return false;
+        
+        /* walk through interpreted results */
+        pInterpret = nlsml_first_interpret_get(pDoc);
+        for(; pInterpret; pInterpret = nlsml_next_interpret_get(pInterpret)) 
+        {
+                /* get instance and input */
+                nlsml_interpret_results_get(pInterpret,&amp;pInstance,&amp;pInput);
+                if(pInstance) 
+                {
+                        /* process instance */
+                        if(pInstance-&gt;first_cdata.first) 
+                        {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Interpreted Instance [%s]&quot;,pInstance-&gt;first_cdata.first-&gt;text);
+                        }
+                }
+                if(pInput) 
+                {
+                        /* process input */
+                        if(pInput-&gt;first_cdata.first)
+                        {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Interpreted Input [%s]&quot;,pInput-&gt;first_cdata.first-&gt;text);
+                        }
+                }
+        }
+        return true;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcmaincpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/main.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/main.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/main.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,24 @@
</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;umcconsole.h&quot;
+
+int main(int argc, const char * const *argv)
+{
+        UmcConsole console;
+        console.Run(argc,argv);
+        return 0;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcrecogscenariocpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogscenario.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogscenario.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogscenario.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,113 @@
</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 &lt;stdlib.h&gt;
+#include &quot;recogscenario.h&quot;
+#include &quot;recogsession.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_recog_header.h&quot;
+#include &quot;mrcp_recog_resource.h&quot;
+#include &quot;apt_log.h&quot;
+
+RecogScenario::RecogScenario() :
+        m_DefineGrammar(true),
+        m_Recognize(true),
+        m_ContentType(&quot;application/srgs+xml&quot;),
+        m_Content(NULL),
+        m_AudioSource(NULL)
+{
+}
+
+RecogScenario::~RecogScenario()
+{
+}
+
+void RecogScenario::Destroy()
+{
+}
+
+bool RecogScenario::LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        if(UmcScenario::LoadElement(pElem,pool))
+                return true;
+        
+        if(strcasecmp(pElem-&gt;name,&quot;define-grammar&quot;) == 0)
+        {
+                LoadDefineGrammar(pElem,pool);
+                return true;
+        }
+        else if(strcasecmp(pElem-&gt;name,&quot;recognize&quot;) == 0)
+        {
+                LoadRecognize(pElem,pool);
+                return true;
+        }
+                
+        return false;
+}
+
+bool RecogScenario::LoadRecognize(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_attr* pAttr;
+        for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+        {
+                if(strcasecmp(pAttr-&gt;name,&quot;enable&quot;) == 0)
+                {
+                        m_Recognize = atoi(pAttr-&gt;value) &gt; 0;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;content-type&quot;) == 0)
+                {
+                        m_ContentType = pAttr-&gt;value;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;content-location&quot;) == 0)
+                {
+                        m_Content = LoadFileContent(pAttr-&gt;value,pool);
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;audio-source&quot;) == 0)
+                {
+                        m_AudioSource = pAttr-&gt;value;
+                }
+        }
+
+        return true;
+}
+
+bool RecogScenario::LoadDefineGrammar(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_attr* pAttr;
+        for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+        {
+                if(strcasecmp(pAttr-&gt;name,&quot;enable&quot;) == 0)
+                {
+                        m_DefineGrammar = atoi(pAttr-&gt;value) &gt; 0;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;content-type&quot;) == 0)
+                {
+                        m_ContentType = pAttr-&gt;value;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;content-location&quot;) == 0)
+                {
+                        m_Content = LoadFileContent(pAttr-&gt;value,pool);
+                }
+        }
+        return true;
+}
+
+
+UmcSession* RecogScenario::CreateSession()
+{
+        return new RecogSession(this);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcrecogsessioncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogsession.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogsession.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/recogsession.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,450 @@
</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;recogsession.h&quot;
+#include &quot;recogscenario.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_recog_header.h&quot;
+#include &quot;mrcp_recog_resource.h&quot;
+#include &quot;apt_nlsml_doc.h&quot;
+#include &quot;apt_log.h&quot;
+
+struct RecogChannel
+{
+        /** MRCP control channel */
+        mrcp_channel_t* m_pMrcpChannel;
+        /** Streaming is in-progress */
+        bool            m_Streaming;
+        /** File to read audio stream from */
+        FILE*           m_pAudioIn;
+        /** Estimated time to complete (used if no audio_in available) */
+        apr_size_t      m_TimeToComplete;
+};
+
+RecogSession::RecogSession(const RecogScenario* pScenario) :
+        UmcSession(pScenario),
+        m_pRecogChannel(NULL),
+        m_ContentId(&quot;request1@form-level&quot;)
+{
+}
+
+RecogSession::~RecogSession()
+{
+}
+
+bool RecogSession::Start()
+{
+        const RecogScenario* pScenario = GetScenario();
+        if(!pScenario-&gt;IsDefineGrammarEnabled() &amp;&amp; !pScenario-&gt;IsRecognizeEnabled())
+                return false;
+        
+        /* create channel and associate all the required data */
+        m_pRecogChannel = CreateRecogChannel();
+        if(!m_pRecogChannel) 
+                return false;
+
+        /* add channel to session (send asynchronous request) */
+        if(!AddMrcpChannel(m_pRecogChannel-&gt;m_pMrcpChannel))
+        {
+                delete m_pRecogChannel;
+                m_pRecogChannel = NULL;
+                return false;
+        }
+        return true;
+}
+
+bool RecogSession::OnSessionTerminate(mrcp_sig_status_code_e status)
+{
+        if(m_pRecogChannel)
+        {
+                FILE* pAudioIn = m_pRecogChannel-&gt;m_pAudioIn;
+                if(pAudioIn)
+                {
+                        m_pRecogChannel-&gt;m_pAudioIn = NULL;
+                        fclose(pAudioIn);
+                }
+                
+                delete m_pRecogChannel;
+                m_pRecogChannel = NULL;
+        }
+        return UmcSession::OnSessionTerminate(status);
+}
+
+static apt_bool_t ReadStream(mpf_audio_stream_t* pStream, mpf_frame_t* pFrame)
+{
+        RecogChannel* pRecogChannel = (RecogChannel*) pStream-&gt;obj;
+        if(pRecogChannel &amp;&amp; pRecogChannel-&gt;m_Streaming) 
+        {
+                if(pRecogChannel-&gt;m_pAudioIn) 
+                {
+                        if(fread(pFrame-&gt;codec_frame.buffer,1,pFrame-&gt;codec_frame.size,pRecogChannel-&gt;m_pAudioIn) == pFrame-&gt;codec_frame.size) 
+                        {
+                                /* normal read */
+                                pFrame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+                        }
+                        else 
+                        {
+                                /* file is over */
+                                pRecogChannel-&gt;m_Streaming = false;
+                        }
+                }
+                else 
+                {
+                        /* fill with silence in case no file available */
+                        if(pRecogChannel-&gt;m_TimeToComplete &gt;= CODEC_FRAME_TIME_BASE) 
+                        {
+                                pFrame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+                                memset(pFrame-&gt;codec_frame.buffer,0,pFrame-&gt;codec_frame.size);
+                                pRecogChannel-&gt;m_TimeToComplete -= CODEC_FRAME_TIME_BASE;
+                        }
+                        else 
+                        {
+                                pRecogChannel-&gt;m_Streaming = false;
+                        }
+                }
+        }
+        return TRUE;
+}
+
+RecogChannel* RecogSession::CreateRecogChannel()
+{
+        mrcp_channel_t* pChannel;
+        mpf_termination_t* pTermination;
+        mpf_stream_capabilities_t* pCapabilities;
+        apr_pool_t* pool = GetSessionPool();
+
+        /* create channel */
+        RecogChannel *pRecogChannel = new RecogChannel;
+        pRecogChannel-&gt;m_pMrcpChannel = NULL;
+        pRecogChannel-&gt;m_Streaming = false;
+        pRecogChannel-&gt;m_pAudioIn = NULL;
+        pRecogChannel-&gt;m_TimeToComplete = 0;
+
+        /* create source stream capabilities */
+        pCapabilities = mpf_source_stream_capabilities_create(pool);
+        GetScenario()-&gt;InitCapabilities(pCapabilities);
+
+        static const mpf_audio_stream_vtable_t audio_stream_vtable = 
+        {
+                NULL,
+                NULL,
+                NULL,
+                ReadStream,
+                NULL,
+                NULL,
+                NULL
+        };
+
+        pTermination = CreateAudioTermination(
+                        &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
+                        pCapabilities,             /* capabilities of audio stream */
+                        pRecogChannel);            /* object to associate */
+
+        pChannel = CreateMrcpChannel(
+                        MRCP_RECOGNIZER_RESOURCE,  /* MRCP resource identifier */
+                        pTermination,              /* media termination, used to terminate audio stream */
+                        NULL,                      /* RTP descriptor, used to create RTP termination (NULL by default) */
+                        pRecogChannel);            /* object to associate */
+        if(!pChannel)
+        {
+                delete pRecogChannel;
+                return NULL;
+        }
+        
+        pRecogChannel-&gt;m_pMrcpChannel = pChannel;
+        return pRecogChannel;
+}
+
+bool RecogSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelAdd(pMrcpChannel,status))
+                return false;
+
+        if(status != MRCP_SIG_STATUS_CODE_SUCCESS)
+        {
+                /* error case, just terminate the demo */
+                return Terminate();
+        }
+
+        if(GetScenario()-&gt;IsDefineGrammarEnabled())
+        {
+                mrcp_message_t* pMrcpMessage = CreateDefineGrammarRequest(pMrcpChannel);
+                if(pMrcpMessage)
+                        SendMrcpRequest(pMrcpChannel,pMrcpMessage);
+                return true;
+        }
+
+        return StartRecognition(pMrcpChannel);
+}
+
+bool RecogSession::OnChannelRemove(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelRemove(pMrcpChannel,status))
+                return false;
+
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pRecogChannel)
+        {
+                FILE* pAudioIn = pRecogChannel-&gt;m_pAudioIn;
+                if(pAudioIn)
+                {
+                        pRecogChannel-&gt;m_pAudioIn = NULL;
+                        fclose(pAudioIn);
+                }
+        }
+        
+        /* terminate the demo */
+        return Terminate();
+}
+
+bool RecogSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
+{
+        if(!UmcSession::OnMessageReceive(pMrcpChannel,pMrcpMessage))
+                return false;
+
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) 
+        {
+                /* received MRCP response */
+                if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_DEFINE_GRAMMAR) 
+                {
+                        /* received the response to DEFINE-GRAMMAR request */
+                        if(pMrcpMessage-&gt;start_line.request_state == MRCP_REQUEST_STATE_COMPLETE) 
+                        {
+                                OnDefineGrammar(pMrcpChannel);
+                        }
+                        else 
+                        {
+                                /* received unexpected response, remove channel */
+                                RemoveMrcpChannel(pMrcpChannel);
+                        }
+                }
+                else if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_RECOGNIZE)
+                {
+                        /* received the response to RECOGNIZE request */
+                        if(pMrcpMessage-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
+                        {
+                                /* start to stream the speech to recognize */
+                                if(pRecogChannel) 
+                                {
+                                        pRecogChannel-&gt;m_Streaming = true;
+                                }
+                        }
+                        else 
+                        {
+                                /* received unexpected response, remove channel */
+                                RemoveMrcpChannel(pMrcpChannel);
+                        }
+                }
+                else 
+                {
+                        /* received unexpected response */
+                }
+        }
+        else if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) 
+        {
+                if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) 
+                {
+                        ParseNLSMLResult(pMrcpMessage);
+                        if(pRecogChannel) 
+                        {
+                                pRecogChannel-&gt;m_Streaming = false;
+                        }
+                        RemoveMrcpChannel(pMrcpChannel);
+                }
+                else if(pMrcpMessage-&gt;start_line.method_id == RECOGNIZER_START_OF_INPUT) 
+                {
+                        /* received start-of-input, do whatever you need here */
+                }
+        }
+        return true;
+}
+
+bool RecogSession::OnDefineGrammar(mrcp_channel_t* pMrcpChannel)
+{
+        if(GetScenario()-&gt;IsRecognizeEnabled())
+        {
+                return StartRecognition(pMrcpChannel);
+        }
+
+        return Terminate();
+}
+
+bool RecogSession::StartRecognition(mrcp_channel_t* pMrcpChannel)
+{
+        RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        /* create and send RECOGNIZE request */
+        mrcp_message_t* pMrcpMessage = CreateRecognizeRequest(pMrcpChannel);
+        if(pMrcpMessage)
+        {
+                SendMrcpRequest(pRecogChannel-&gt;m_pMrcpChannel,pMrcpMessage);
+        }
+
+        const mpf_codec_descriptor_t* pDescriptor = mrcp_application_source_descriptor_get(pMrcpChannel);
+        pRecogChannel-&gt;m_pAudioIn = GetAudioIn(pDescriptor,GetSessionPool());
+        if(!pRecogChannel-&gt;m_pAudioIn)
+        {
+                /* no audio input availble, set some estimated time to complete instead */
+                pRecogChannel-&gt;m_TimeToComplete = 5000; // 5 sec
+        }
+        return true;
+}
+
+mrcp_message_t* RecogSession::CreateDefineGrammarRequest(mrcp_channel_t* pMrcpChannel)
+{
+        mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,RECOGNIZER_DEFINE_GRAMMAR);
+        if(!pMrcpMessage)
+                return NULL;
+
+        const RecogScenario* pScenario = GetScenario();
+
+        mrcp_generic_header_t* pGenericHeader;
+        /* get/allocate generic header */
+        pGenericHeader = (mrcp_generic_header_t*) mrcp_generic_header_prepare(pMrcpMessage);
+        if(pGenericHeader) 
+        {
+                /* set generic header fields */
+                if(pScenario-&gt;GetContentType())
+                {
+                        apt_string_assign(&amp;pGenericHeader-&gt;content_type,pScenario-&gt;GetContentType(),pMrcpMessage-&gt;pool);
+                        mrcp_generic_header_property_add(pMrcpMessage,GENERIC_HEADER_CONTENT_TYPE);
+                }
+                apt_string_assign(&amp;pGenericHeader-&gt;content_id,m_ContentId,pMrcpMessage-&gt;pool);
+                mrcp_generic_header_property_add(pMrcpMessage,GENERIC_HEADER_CONTENT_ID);
+        }
+
+        /* set message body */
+        if(pScenario-&gt;GetContent())
+                apt_string_assign(&amp;pMrcpMessage-&gt;body,pScenario-&gt;GetContent(),pMrcpMessage-&gt;pool);
+        return pMrcpMessage;
+}
+
+mrcp_message_t* RecogSession::CreateRecognizeRequest(mrcp_channel_t* pMrcpChannel)
+{
+        mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,RECOGNIZER_RECOGNIZE);
+        if(!pMrcpMessage)
+                return NULL;
+
+        const RecogScenario* pScenario = GetScenario();
+
+        mrcp_generic_header_t* pGenericHeader;
+        mrcp_recog_header_t* pRecogHeader;
+
+        /* get/allocate generic header */
+        pGenericHeader = (mrcp_generic_header_t*) mrcp_generic_header_prepare(pMrcpMessage);
+        if(pGenericHeader)
+        {
+                /* set generic header fields */
+                if(pScenario-&gt;IsDefineGrammarEnabled())
+                {
+                        apt_string_assign(&amp;pGenericHeader-&gt;content_type,&quot;text/uri-list&quot;,pMrcpMessage-&gt;pool);
+                        /* set message body */
+                        const char* pContent = apr_pstrcat(pMrcpMessage-&gt;pool,&quot;session:&quot;,m_ContentId,NULL);
+                        apt_string_set(&amp;pMrcpMessage-&gt;body,pContent);
+                }
+                else
+                {
+                        apt_string_assign(&amp;pGenericHeader-&gt;content_type,pScenario-&gt;GetContentType(),pMrcpMessage-&gt;pool);
+                        /* set content-id */
+                        apt_string_assign(&amp;pGenericHeader-&gt;content_id,m_ContentId,pMrcpMessage-&gt;pool);
+                        mrcp_generic_header_property_add(pMrcpMessage,GENERIC_HEADER_CONTENT_ID);
+                        /* set message body */
+                        if(pScenario-&gt;GetContent())
+                                apt_string_assign(&amp;pMrcpMessage-&gt;body,pScenario-&gt;GetContent(),pMrcpMessage-&gt;pool);
+                }
+                mrcp_generic_header_property_add(pMrcpMessage,GENERIC_HEADER_CONTENT_TYPE);
+        }
+        /* get/allocate recognizer header */
+        pRecogHeader = (mrcp_recog_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
+        if(pRecogHeader)
+        {
+                /* set recognizer header fields */
+                if(pMrcpMessage-&gt;start_line.version == MRCP_VERSION_2)
+                {
+                        pRecogHeader-&gt;cancel_if_queue = FALSE;
+                        mrcp_resource_header_property_add(pMrcpMessage,RECOGNIZER_HEADER_CANCEL_IF_QUEUE);
+                }
+                pRecogHeader-&gt;no_input_timeout = 5000;
+                mrcp_resource_header_property_add(pMrcpMessage,RECOGNIZER_HEADER_NO_INPUT_TIMEOUT);
+                pRecogHeader-&gt;recognition_timeout = 10000;
+                mrcp_resource_header_property_add(pMrcpMessage,RECOGNIZER_HEADER_RECOGNITION_TIMEOUT);
+                pRecogHeader-&gt;start_input_timers = TRUE;
+                mrcp_resource_header_property_add(pMrcpMessage,RECOGNIZER_HEADER_START_INPUT_TIMERS);
+                pRecogHeader-&gt;confidence_threshold = 0.87f;
+                mrcp_resource_header_property_add(pMrcpMessage,RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD);
+        }
+        return pMrcpMessage;
+}
+
+bool RecogSession::ParseNLSMLResult(mrcp_message_t* pMrcpMessage) const
+{
+        apr_xml_elem* pInterpret;
+        apr_xml_elem* pInstance;
+        apr_xml_elem* pInput;
+        apr_xml_doc* pDoc = nlsml_doc_load(&amp;pMrcpMessage-&gt;body,pMrcpMessage-&gt;pool);
+        if(!pDoc)
+                return false;
+        
+        /* walk through interpreted results */
+        pInterpret = nlsml_first_interpret_get(pDoc);
+        for(; pInterpret; pInterpret = nlsml_next_interpret_get(pInterpret)) 
+        {
+                /* get instance and input */
+                nlsml_interpret_results_get(pInterpret,&amp;pInstance,&amp;pInput);
+                if(pInstance) 
+                {
+                        /* process instance */
+                        if(pInstance-&gt;first_cdata.first) 
+                        {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Interpreted Instance [%s]&quot;,pInstance-&gt;first_cdata.first-&gt;text);
+                        }
+                }
+                if(pInput) 
+                {
+                        /* process input */
+                        if(pInput-&gt;first_cdata.first)
+                        {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Interpreted Input [%s]&quot;,pInput-&gt;first_cdata.first-&gt;text);
+                        }
+                }
+        }
+        return true;
+}
+
+FILE* RecogSession::GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const
+{
+        const char* pFileName = GetScenario()-&gt;GetAudioSource();
+        if(!pFileName)
+        {
+                pFileName = apr_psprintf(pool,&quot;one-%dkHz.pcm&quot;,
+                        pDescriptor ? pDescriptor-&gt;sampling_rate/1000 : 8);
+        }
+        apt_dir_layout_t* pDirLayout = GetScenario()-&gt;GetDirLayout();
+        const char* pFilePath = apt_datadir_filepath_get(pDirLayout,pFileName,pool);
+        if(!pFilePath)
+                return NULL;
+        
+        FILE* pFile = fopen(pFilePath,&quot;rb&quot;);
+        if(!pFile)
+        {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Cannot Find [%s]&quot;,pFilePath);
+                return NULL;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Set [%s] as Speech Source&quot;,pFilePath);
+        return pFile;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcrecorderscenariocpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/recorderscenario.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/recorderscenario.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/recorderscenario.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,70 @@
</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 &lt;stdlib.h&gt;
+#include &quot;recorderscenario.h&quot;
+#include &quot;recordersession.h&quot;
+
+RecorderScenario::RecorderScenario() :
+        m_Record(true),
+        m_AudioSource(NULL)
+{
+}
+
+RecorderScenario::~RecorderScenario()
+{
+}
+
+void RecorderScenario::Destroy()
+{
+}
+
+bool RecorderScenario::LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        if(UmcScenario::LoadElement(pElem,pool))
+                return true;
+        
+        if(strcasecmp(pElem-&gt;name,&quot;record&quot;) == 0)
+        {
+                LoadRecord(pElem,pool);
+                return true;
+        }
+                
+        return false;
+}
+
+bool RecorderScenario::LoadRecord(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_attr* pAttr;
+        for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+        {
+                if(strcasecmp(pAttr-&gt;name,&quot;enable&quot;) == 0)
+                {
+                        m_Record = atoi(pAttr-&gt;value) &gt; 0;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;audio-source&quot;) == 0)
+                {
+                        m_AudioSource = pAttr-&gt;value;
+                }
+        }
+
+        return true;
+}
+
+UmcSession* RecorderScenario::CreateSession()
+{
+        return new RecorderSession(this);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcrecordersessioncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/recordersession.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/recordersession.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/recordersession.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,298 @@
</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;recordersession.h&quot;
+#include &quot;recorderscenario.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_recorder_header.h&quot;
+#include &quot;mrcp_recorder_resource.h&quot;
+#include &quot;apt_log.h&quot;
+
+struct RecorderChannel
+{
+        /** MRCP control channel */
+        mrcp_channel_t* m_pMrcpChannel;
+        /** Streaming is in-progress */
+        bool            m_Streaming;
+        /** File to read audio stream from */
+        FILE*           m_pAudioIn;
+};
+
+RecorderSession::RecorderSession(const RecorderScenario* pScenario) :
+        UmcSession(pScenario),
+        m_pRecorderChannel(NULL)
+{
+}
+
+RecorderSession::~RecorderSession()
+{
+}
+
+bool RecorderSession::Start()
+{
+        const RecorderScenario* pScenario = GetScenario();
+        if(!pScenario-&gt;IsRecordEnabled())
+                return false;
+        
+        /* create channel and associate all the required data */
+        m_pRecorderChannel = CreateRecorderChannel();
+        if(!m_pRecorderChannel) 
+                return false;
+
+        /* add channel to session (send asynchronous request) */
+        if(!AddMrcpChannel(m_pRecorderChannel-&gt;m_pMrcpChannel))
+        {
+                delete m_pRecorderChannel;
+                m_pRecorderChannel = NULL;
+                return false;
+        }
+        return true;
+}
+
+bool RecorderSession::OnSessionTerminate(mrcp_sig_status_code_e status)
+{
+        if(m_pRecorderChannel)
+        {
+                FILE* pAudioIn = m_pRecorderChannel-&gt;m_pAudioIn;
+                if(pAudioIn)
+                {
+                        m_pRecorderChannel-&gt;m_pAudioIn = NULL;
+                        fclose(pAudioIn);
+                }
+                
+                delete m_pRecorderChannel;
+                m_pRecorderChannel = NULL;
+        }
+        return UmcSession::OnSessionTerminate(status);
+}
+
+static apt_bool_t ReadStream(mpf_audio_stream_t* pStream, mpf_frame_t* pFrame)
+{
+        RecorderChannel* pRecorderChannel = (RecorderChannel*) pStream-&gt;obj;
+        if(pRecorderChannel &amp;&amp; pRecorderChannel-&gt;m_Streaming) 
+        {
+                if(pRecorderChannel-&gt;m_pAudioIn) 
+                {
+                        if(fread(pFrame-&gt;codec_frame.buffer,1,pFrame-&gt;codec_frame.size,pRecorderChannel-&gt;m_pAudioIn) == pFrame-&gt;codec_frame.size) 
+                        {
+                                /* normal read */
+                                pFrame-&gt;type |= MEDIA_FRAME_TYPE_AUDIO;
+                        }
+                        else 
+                        {
+                                /* file is over */
+                                pRecorderChannel-&gt;m_Streaming = false;
+                        }
+                }
+        }
+        return TRUE;
+}
+
+RecorderChannel* RecorderSession::CreateRecorderChannel()
+{
+        mrcp_channel_t* pChannel;
+        mpf_termination_t* pTermination;
+        mpf_stream_capabilities_t* pCapabilities;
+        apr_pool_t* pool = GetSessionPool();
+
+        /* create channel */
+        RecorderChannel *pRecorderChannel = new RecorderChannel;
+        pRecorderChannel-&gt;m_pMrcpChannel = NULL;
+        pRecorderChannel-&gt;m_Streaming = false;
+        pRecorderChannel-&gt;m_pAudioIn = NULL;
+
+        /* create source stream capabilities */
+        pCapabilities = mpf_source_stream_capabilities_create(pool);
+        GetScenario()-&gt;InitCapabilities(pCapabilities);
+
+        static const mpf_audio_stream_vtable_t audio_stream_vtable = 
+        {
+                NULL,
+                NULL,
+                NULL,
+                ReadStream,
+                NULL,
+                NULL,
+                NULL
+        };
+
+        pTermination = CreateAudioTermination(
+                        &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
+                        pCapabilities,             /* capabilities of audio stream */
+                        pRecorderChannel);         /* object to associate */
+
+        pChannel = CreateMrcpChannel(
+                        MRCP_RECORDER_RESOURCE,    /* MRCP resource identifier */
+                        pTermination,              /* media termination, used to terminate audio stream */
+                        NULL,                      /* RTP descriptor, used to create RTP termination (NULL by default) */
+                        pRecorderChannel);         /* object to associate */
+        if(!pChannel)
+        {
+                delete pRecorderChannel;
+                return NULL;
+        }
+        
+        pRecorderChannel-&gt;m_pMrcpChannel = pChannel;
+        return pRecorderChannel;
+}
+
+bool RecorderSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelAdd(pMrcpChannel,status))
+                return false;
+
+        if(status != MRCP_SIG_STATUS_CODE_SUCCESS)
+        {
+                /* error case, just terminate the demo */
+                return Terminate();
+        }
+
+        return StartRecorder(pMrcpChannel);
+}
+
+bool RecorderSession::OnChannelRemove(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelRemove(pMrcpChannel,status))
+                return false;
+
+        RecorderChannel* pRecorderChannel = (RecorderChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pRecorderChannel)
+        {
+                FILE* pAudioIn = pRecorderChannel-&gt;m_pAudioIn;
+                if(pAudioIn)
+                {
+                        pRecorderChannel-&gt;m_pAudioIn = NULL;
+                        fclose(pAudioIn);
+                }
+        }
+        
+        /* terminate the demo */
+        return Terminate();
+}
+
+bool RecorderSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
+{
+        if(!UmcSession::OnMessageReceive(pMrcpChannel,pMrcpMessage))
+                return false;
+
+        RecorderChannel* pRecorderChannel = (RecorderChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) 
+        {
+                /* received MRCP response */
+                if(pMrcpMessage-&gt;start_line.method_id == RECORDER_RECORD)
+                {
+                        /* received the response to RECORD request */
+                        if(pMrcpMessage-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
+                        {
+                                /* start to stream the speech to record */
+                                if(pRecorderChannel)
+                                {
+                                        pRecorderChannel-&gt;m_Streaming = true;
+                                }
+                        }
+                        else 
+                        {
+                                /* received unexpected response, remove channel */
+                                RemoveMrcpChannel(pMrcpChannel);
+                        }
+                }
+                else 
+                {
+                        /* received unexpected response */
+                }
+        }
+        else if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) 
+        {
+                if(pMrcpMessage-&gt;start_line.method_id == RECORDER_RECORD_COMPLETE) 
+                {
+                        if(pRecorderChannel) 
+                        {
+                                pRecorderChannel-&gt;m_Streaming = false;
+                        }
+                        RemoveMrcpChannel(pMrcpChannel);
+                }
+                else if(pMrcpMessage-&gt;start_line.method_id == RECORDER_START_OF_INPUT) 
+                {
+                        /* received start-of-input, do whatever you need here */
+                }
+        }
+        return true;
+}
+
+bool RecorderSession::StartRecorder(mrcp_channel_t* pMrcpChannel)
+{
+        RecorderChannel* pRecorderChannel = (RecorderChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        /* create and send RECORD request */
+        mrcp_message_t* pMrcpMessage = CreateRecordRequest(pMrcpChannel);
+        if(pMrcpMessage)
+        {
+                SendMrcpRequest(pRecorderChannel-&gt;m_pMrcpChannel,pMrcpMessage);
+        }
+
+        const mpf_codec_descriptor_t* pDescriptor = mrcp_application_source_descriptor_get(pMrcpChannel);
+        pRecorderChannel-&gt;m_pAudioIn = GetAudioIn(pDescriptor,GetSessionPool());
+        return true;
+}
+
+mrcp_message_t* RecorderSession::CreateRecordRequest(mrcp_channel_t* pMrcpChannel)
+{
+        mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,RECORDER_RECORD);
+        if(!pMrcpMessage)
+                return NULL;
+
+        mrcp_recorder_header_t* pRecorderHeader;
+
+        /* get/allocate recorder header */
+        pRecorderHeader = (mrcp_recorder_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
+        if(pRecorderHeader)
+        {
+                /* set recorder header fields */
+                pRecorderHeader-&gt;no_input_timeout = 5000;
+                mrcp_resource_header_property_add(pMrcpMessage,RECORDER_HEADER_NO_INPUT_TIMEOUT);
+
+                pRecorderHeader-&gt;final_silence = 300;
+                mrcp_resource_header_property_add(pMrcpMessage,RECORDER_HEADER_FINAL_SILENCE);
+
+                pRecorderHeader-&gt;max_time = 10000;
+                mrcp_resource_header_property_add(pMrcpMessage,RECORDER_HEADER_MAX_TIME);
+        }
+        return pMrcpMessage;
+}
+
+FILE* RecorderSession::GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const
+{
+        const char* pFileName = GetScenario()-&gt;GetAudioSource();
+        if(!pFileName)
+        {
+                pFileName = apr_psprintf(pool,&quot;demo-%dkHz.pcm&quot;,
+                        pDescriptor ? pDescriptor-&gt;sampling_rate/1000 : 8);
+        }
+        apt_dir_layout_t* pDirLayout = GetScenario()-&gt;GetDirLayout();
+        const char* pFilePath = apt_datadir_filepath_get(pDirLayout,pFileName,pool);
+        if(!pFilePath)
+                return NULL;
+        
+        FILE* pFile = fopen(pFilePath,&quot;rb&quot;);
+        if(!pFile)
+        {
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Cannot Find [%s]&quot;,pFilePath);
+                return NULL;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Set [%s] as Speech Source&quot;,pFilePath);
+        return pFile;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcsynthscenariocpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthscenario.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthscenario.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthscenario.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,80 @@
</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 &lt;stdlib.h&gt;
+#include &quot;synthscenario.h&quot;
+#include &quot;synthsession.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_synth_header.h&quot;
+#include &quot;mrcp_synth_resource.h&quot;
+
+
+SynthScenario::SynthScenario() :
+        m_Speak(true),
+        m_ContentType(&quot;application/synthesis+ssml&quot;),
+        m_Content(NULL)
+{
+}
+
+SynthScenario::~SynthScenario()
+{
+}
+
+void SynthScenario::Destroy()
+{
+}
+
+bool SynthScenario::LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        if(UmcScenario::LoadElement(pElem,pool))
+                return true;
+        
+        if(strcasecmp(pElem-&gt;name,&quot;speak&quot;) == 0)
+        {
+                LoadSpeak(pElem,pool);
+                return true;
+        }
+                
+        return false;
+}
+
+bool SynthScenario::LoadSpeak(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_attr* pAttr;
+        for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+        {
+                if(strcasecmp(pAttr-&gt;name,&quot;enable&quot;) == 0)
+                {
+                        m_Speak = atoi(pAttr-&gt;value) &gt; 0;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;content-type&quot;) == 0)
+                {
+                        m_ContentType = pAttr-&gt;value;
+                }
+                else if(strcasecmp(pAttr-&gt;name,&quot;content-location&quot;) == 0)
+                {
+                        m_Content = LoadFileContent(pAttr-&gt;value,pool);
+                }
+        }
+
+        return true;
+}
+
+UmcSession* SynthScenario::CreateSession()
+{
+        return new SynthSession(this);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcsynthsessioncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthsession.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthsession.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/synthsession.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,261 @@
</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;synthsession.h&quot;
+#include &quot;synthscenario.h&quot;
+#include &quot;mrcp_message.h&quot;
+#include &quot;mrcp_generic_header.h&quot;
+#include &quot;mrcp_synth_header.h&quot;
+#include &quot;mrcp_synth_resource.h&quot;
+
+struct SynthChannel
+{
+        mrcp_channel_t* m_pMrcpChannel;
+        /** File to write audio stream to */
+        FILE*           m_pAudioOut;
+};
+
+SynthSession::SynthSession(const SynthScenario* pScenario) :
+        UmcSession(pScenario),
+        m_pSynthChannel(NULL)
+{
+}
+
+SynthSession::~SynthSession()
+{
+}
+
+bool SynthSession::Start()
+{
+        if(!GetScenario()-&gt;IsSpeakEnabled())
+                return false;
+        
+        /* create channel and associate all the required data */
+        m_pSynthChannel = CreateSynthChannel();
+        if(!m_pSynthChannel) 
+                return false;
+
+        /* add channel to session (send asynchronous request) */
+        if(!AddMrcpChannel(m_pSynthChannel-&gt;m_pMrcpChannel))
+        {
+                delete m_pSynthChannel;
+                m_pSynthChannel = NULL;
+                return false;
+        }
+        return true;
+}
+
+bool SynthSession::OnSessionTerminate(mrcp_sig_status_code_e status)
+{
+        if(m_pSynthChannel)
+        {
+                FILE* pAudioOut = m_pSynthChannel-&gt;m_pAudioOut;
+                if(pAudioOut) 
+                {
+                        m_pSynthChannel-&gt;m_pAudioOut = NULL;
+                        fclose(pAudioOut);
+                }
+
+                delete m_pSynthChannel;
+                m_pSynthChannel = NULL;
+        }
+        return UmcSession::OnSessionTerminate(status);
+}
+
+static apt_bool_t WriteStream(mpf_audio_stream_t* pStream, const mpf_frame_t* pFrame)
+{
+        SynthChannel* pSynthChannel = (SynthChannel*) pStream-&gt;obj;
+        if(pSynthChannel &amp;&amp; pSynthChannel-&gt;m_pAudioOut) 
+        {
+                fwrite(pFrame-&gt;codec_frame.buffer,1,pFrame-&gt;codec_frame.size,pSynthChannel-&gt;m_pAudioOut);
+        }
+        return TRUE;
+}
+
+SynthChannel* SynthSession::CreateSynthChannel()
+{
+        mrcp_channel_t* pChannel;
+        mpf_termination_t* pTermination;
+        mpf_stream_capabilities_t* pCapabilities;
+        apr_pool_t* pool = GetSessionPool();
+
+        /* create channel */
+        SynthChannel *pSynthChannel = new SynthChannel;
+        pSynthChannel-&gt;m_pMrcpChannel = NULL;
+
+        /* create sink stream capabilities */
+        pCapabilities = mpf_sink_stream_capabilities_create(pool);
+        GetScenario()-&gt;InitCapabilities(pCapabilities);
+
+        static const mpf_audio_stream_vtable_t audio_stream_vtable = 
+        {
+                NULL,
+                NULL,
+                NULL,
+                NULL,
+                NULL,
+                NULL,
+                WriteStream
+        };
+
+        pTermination = CreateAudioTermination(
+                        &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
+                        pCapabilities,             /* capabilities of audio stream */
+                        pSynthChannel);            /* object to associate */
+        
+        pChannel = CreateMrcpChannel(
+                        MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
+                        pTermination,              /* media termination, used to terminate audio stream */
+                        NULL,                      /* RTP descriptor, used to create RTP termination (NULL by default) */
+                        pSynthChannel);            /* object to associate */
+        if(!pChannel)
+        {
+                delete pSynthChannel;
+                return NULL;
+        }
+
+        pSynthChannel-&gt;m_pMrcpChannel = pChannel;
+        pSynthChannel-&gt;m_pAudioOut = NULL;
+        return pSynthChannel;
+}
+
+bool SynthSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelAdd(pMrcpChannel,status))
+                return false;
+
+        SynthChannel* pSynthChannel = (SynthChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(status != MRCP_SIG_STATUS_CODE_SUCCESS)
+        {
+                /* error case, just terminate the demo */
+                return Terminate();
+        }
+
+        /* create MRCP message */
+        mrcp_message_t* pMrcpMessage = CreateSpeakRequest(pMrcpChannel);
+        if(pMrcpMessage) 
+        {
+                SendMrcpRequest(pSynthChannel-&gt;m_pMrcpChannel,pMrcpMessage);
+        }
+
+        const mpf_codec_descriptor_t* pDescriptor = mrcp_application_sink_descriptor_get(pMrcpChannel);
+        pSynthChannel-&gt;m_pAudioOut = GetAudioOut(pDescriptor,GetSessionPool());
+        return true;
+}
+
+bool SynthSession::OnChannelRemove(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+        if(!UmcSession::OnChannelRemove(pMrcpChannel,status))
+                return false;
+
+        SynthChannel* pSynthChannel = (SynthChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+        if(pSynthChannel) 
+        {
+                FILE* pAudioOut = pSynthChannel-&gt;m_pAudioOut;
+                if(pAudioOut) 
+                {
+                        pSynthChannel-&gt;m_pAudioOut = NULL;
+                        fclose(pAudioOut);
+                }
+        }
+
+        /* terminate the demo */
+        return Terminate();
+}
+
+bool SynthSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
+{
+        if(!UmcSession::OnMessageReceive(pMrcpChannel,pMrcpMessage))
+                return false;
+
+        if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) 
+        {
+                /* received MRCP response */
+                if(pMrcpMessage-&gt;start_line.method_id == SYNTHESIZER_SPEAK) 
+                {
+                        /* received the response to SPEAK request */
+                        if(pMrcpMessage-&gt;start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) 
+                        {
+                                /* waiting for SPEAK-COMPLETE event */
+                        }
+                        else 
+                        {
+                                /* received unexpected response, remove channel */
+                                RemoveMrcpChannel(pMrcpChannel);
+                        }
+                }
+                else 
+                {
+                        /* received unexpected response */
+                }
+        }
+        else if(pMrcpMessage-&gt;start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) 
+        {
+                /* received MRCP event */
+                if(pMrcpMessage-&gt;start_line.method_id == SYNTHESIZER_SPEAK_COMPLETE) 
+                {
+                        /* received SPEAK-COMPLETE event, remove channel */
+                        RemoveMrcpChannel(pMrcpChannel);
+                }
+        }
+        return true;
+}
+
+mrcp_message_t* SynthSession::CreateSpeakRequest(mrcp_channel_t* pMrcpChannel)
+{
+        mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,SYNTHESIZER_SPEAK);
+        if(!pMrcpMessage)
+                return NULL;
+
+        const SynthScenario* pScenario = GetScenario();
+
+        mrcp_generic_header_t* pGenericHeader;
+        mrcp_synth_header_t* pSynthHeader;
+        /* get/allocate generic header */
+        pGenericHeader = (mrcp_generic_header_t*) mrcp_generic_header_prepare(pMrcpMessage);
+        if(pGenericHeader) 
+        {
+                /* set generic header fields */
+                apt_string_assign(&amp;pGenericHeader-&gt;content_type,pScenario-&gt;GetContentType(),pMrcpMessage-&gt;pool);
+                mrcp_generic_header_property_add(pMrcpMessage,GENERIC_HEADER_CONTENT_TYPE);
+
+                /* set message body */
+                if(pScenario-&gt;GetContent())
+                        apt_string_assign(&amp;pMrcpMessage-&gt;body,pScenario-&gt;GetContent(),pMrcpMessage-&gt;pool);
+        }
+        /* get/allocate synthesizer header */
+        pSynthHeader = (mrcp_synth_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
+        if(pSynthHeader) 
+        {
+                /* set synthesizer header fields */
+                pSynthHeader-&gt;voice_param.age = 28;
+                mrcp_resource_header_property_add(pMrcpMessage,SYNTHESIZER_HEADER_VOICE_AGE);
+        }
+
+        return pMrcpMessage;
+}
+
+FILE* SynthSession::GetAudioOut(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const
+{
+        char* pFileName = apr_psprintf(pool,&quot;synth-%dkHz-%s.pcm&quot;,
+                pDescriptor ? pDescriptor-&gt;sampling_rate/1000 : 8, GetMrcpSessionId());
+        apt_dir_layout_t* pDirLayout = GetScenario()-&gt;GetDirLayout();
+        char* pFilePath = apt_datadir_filepath_get(pDirLayout,pFileName,pool);
+        if(!pFilePath) 
+                return NULL;
+
+        return fopen(pFilePath,&quot;wb&quot;);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcumcconsolecpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcconsole.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcconsole.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcconsole.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,280 @@
</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 &lt;stdio.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;apr_getopt.h&gt;
+#include &quot;umcconsole.h&quot;
+#include &quot;umcframework.h&quot;
+#include &quot;apt_pool.h&quot;
+
+
+UmcConsole::UmcConsole() :
+        m_pFramework(NULL)
+{
+        m_pFramework = new UmcFramework;
+}
+
+UmcConsole::~UmcConsole()
+{
+        delete m_pFramework;
+}
+
+bool UmcConsole::Run(int argc, const char * const *argv)
+{
+        apr_pool_t* pool = NULL;
+        apt_dir_layout_t* pDirLayout = NULL;
+
+        /* APR global initialization */
+        if(apr_initialize() != APR_SUCCESS) 
+        {
+                apr_terminate();
+                return false;
+        }
+
+        /* create APR pool */
+        pool = apt_pool_create();
+        if(!pool) 
+        {
+                apr_terminate();
+                return false;
+        }
+
+        /* load options */
+        if(!LoadOptions(argc,argv,pool))
+        {
+                apr_pool_destroy(pool);
+                apr_terminate();
+                return false;
+        }
+
+        /* create the structure of default directories layout */
+        pDirLayout = apt_default_dir_layout_create(m_Options.m_RootDirPath,pool);
+        /* create singleton logger */
+        apt_log_instance_create(m_Options.m_LogOutput,m_Options.m_LogPriority,pool);
+
+        if((m_Options.m_LogOutput &amp; APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) 
+        {
+                /* open the log file */
+                apt_log_file_open(pDirLayout-&gt;log_dir_path,&quot;unimrcpclient&quot;,MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
+        }
+
+        /* create demo framework */
+        if(m_pFramework-&gt;Create(pDirLayout,pool))
+        {
+                /* run command line  */
+                RunCmdLine();
+                /* destroy demo framework */
+                m_pFramework-&gt;Destroy();
+        }
+
+        /* destroy singleton logger */
+        apt_log_instance_destroy();
+        /* destroy APR pool */
+        apr_pool_destroy(pool);
+        /* APR global termination */
+        apr_terminate();
+        return true;
+}
+
+bool UmcConsole::ProcessCmdLine(char* pCmdLine)
+{
+        bool running = true;
+        char *name;
+        char *last;
+        name = apr_strtok(pCmdLine, &quot; &quot;, &amp;last);
+
+        if(strcasecmp(name,&quot;run&quot;) == 0)
+        {
+                char* pScenarioName = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                if(pScenarioName) 
+                {
+                        char* pProfileName = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                        if(!pProfileName) 
+                        {
+                                pProfileName = &quot;MRCPv2-Default&quot;;
+                        }
+                        m_pFramework-&gt;RunSession(pScenarioName,pProfileName);
+                }
+        }
+        else if(strcasecmp(name,&quot;kill&quot;) == 0)
+        {
+                char* pID = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                if(pID) 
+                {
+                        m_pFramework-&gt;KillSession(pID);
+                }
+        }
+        else if(strcasecmp(name,&quot;show&quot;) == 0)
+        {
+                char* pWhat = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                if(pWhat) 
+                {
+                        if(strcasecmp(pWhat,&quot;sessions&quot;) == 0)
+                                m_pFramework-&gt;ShowSessions();
+                        else if(strcasecmp(pWhat,&quot;scenarios&quot;) == 0)
+                                m_pFramework-&gt;ShowScenarios();
+                }
+        }
+        else if(strcasecmp(name,&quot;loglevel&quot;) == 0) 
+        {
+                char* pPriority = apr_strtok(NULL, &quot; &quot;, &amp;last);
+                if(pPriority) 
+                {
+                        apt_log_priority_set((apt_log_priority_e)atol(pPriority));
+                }
+        }
+        else if(strcasecmp(name,&quot;exit&quot;) == 0 || strcmp(name,&quot;quit&quot;) == 0) 
+        {
+                running = false;
+        }
+        else if(strcasecmp(name,&quot;help&quot;) == 0) 
+        {
+                printf(&quot;usage:\n&quot;
+                       &quot;\n- run [scenario] [profile] (run new session)\n&quot;
+                           &quot;       scenario is one of 'synth', 'recog', ... (use 'show scenarios')\n&quot;
+                           &quot;       profile is one of 'MRCPv2-Default', 'MRCPv1-Default', ... (see unimrcpclient.xml)\n&quot;
+                           &quot;\n       examples: \n&quot;
+                           &quot;           run synth\n&quot;
+                           &quot;           run recog\n&quot;
+                           &quot;           run synth MRCPv1-Default\n&quot;
+                           &quot;           run recog MRCPv1-Default\n&quot;
+                       &quot;\n- kill [id] (kill session)\n&quot;
+                           &quot;       id is a session identifier: 1, 2, ... (use 'show sessions')\n&quot;
+                           &quot;\n       example: \n&quot;
+                           &quot;           kill 1\n&quot;
+                       &quot;\n- show [what] (show either available scenarios or in-progress sessions)\n&quot;
+                           &quot;\n       examples: \n&quot;
+                           &quot;           show scenarios\n&quot;
+                           &quot;           show sessions\n&quot;
+                       &quot;\n- loglevel [level] (set loglevel, one of 0,1...7)\n&quot;
+                       &quot;\n- quit, exit\n&quot;);
+        }
+        else 
+        {
+                printf(&quot;unknown command: %s (input help for usage)\n&quot;,name);
+        }
+        return running;
+}
+
+bool UmcConsole::RunCmdLine()
+{
+        apt_bool_t running = true;
+        char cmdline[1024];
+        int i;
+        do 
+        {
+                printf(&quot;&gt;&quot;);
+                memset(&amp;cmdline, 0, sizeof(cmdline));
+                for(i = 0; i &lt; sizeof(cmdline); i++) 
+                {
+                        cmdline[i] = (char) getchar();
+                        if(cmdline[i] == '\n') 
+                        {
+                                cmdline[i] = '\0';
+                                break;
+                        }
+                }
+                if(*cmdline) 
+                {
+                        running = ProcessCmdLine(cmdline);
+                }
+        }
+        while(running != 0);
+        return true;
+}
+
+void UmcConsole::Usage() const
+{
+        printf(
+                &quot;\n&quot;
+                &quot;Usage:\n&quot;
+                &quot;\n&quot;
+                &quot;  umc [options]\n&quot;
+                &quot;\n&quot;
+                &quot;  Available options:\n&quot;
+                &quot;\n&quot;
+                &quot;   -r [--root-dir] path     : Set the project root directory path.\n&quot;
+                &quot;\n&quot;
+                &quot;   -l [--log-prio] priority : Set the log priority.\n&quot;
+                &quot;                              (0-emergency, ..., 7-debug)\n&quot;
+                &quot;\n&quot;
+                &quot;   -o [--log-output] mode   : Set the log output mode.\n&quot;
+                &quot;                              (0-none, 1-console only, 2-file only, 3-both)\n&quot;
+                &quot;\n&quot;
+                &quot;   -h [--help]              : Show the help.\n&quot;
+                &quot;\n&quot;);
+}
+
+bool UmcConsole::LoadOptions(int argc, const char * const *argv, apr_pool_t *pool)
+{
+        apr_status_t rv;
+        apr_getopt_t* opt = NULL;
+        int optch;
+        const char* optarg;
+
+        const apr_getopt_option_t opt_option[] = 
+        {
+                /* long-option, short-option, has-arg flag, description */
+                { &quot;root-dir&quot;,    'r', TRUE,  &quot;path to root dir&quot; },  /* -r arg or --root-dir arg */
+                { &quot;log-prio&quot;,    'l', TRUE,  &quot;log priority&quot; },      /* -l arg or --log-prio arg */
+                { &quot;log-output&quot;,  'o', TRUE,  &quot;log output mode&quot; },   /* -o arg or --log-output arg */
+                { &quot;help&quot;,        'h', FALSE, &quot;show help&quot; },         /* -h or --help */
+                { NULL, 0, 0, NULL },                               /* end */
+        };
+
+        /* set the default options */
+        m_Options.m_RootDirPath = &quot;../&quot;;
+        m_Options.m_LogPriority = APT_PRIO_INFO;
+        m_Options.m_LogOutput = APT_LOG_OUTPUT_CONSOLE;
+
+        rv = apr_getopt_init(&amp;opt, pool , argc, argv);
+        if(rv != APR_SUCCESS)
+                return false;
+
+        while((rv = apr_getopt_long(opt, opt_option, &amp;optch, &amp;optarg)) == APR_SUCCESS) 
+        {
+                switch(optch) 
+                {
+                        case 'r':
+                                m_Options.m_RootDirPath = optarg;
+                                break;
+                        case 'l':
+                                if(optarg) 
+                                {
+                                        m_Options.m_LogPriority = (apt_log_priority_e) atoi(optarg);
+                                }
+                                break;
+                        case 'o':
+                                if(optarg) 
+                                {
+                                        m_Options.m_LogOutput = (apt_log_output_e) atoi(optarg);
+                                }
+                                break;
+                        case 'h':
+                                Usage();
+                                return FALSE;
+                }
+        }
+
+        if(rv != APR_EOF) 
+        {
+                Usage();
+                return false;
+        }
+
+        return true;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcumcframeworkcpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcframework.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcframework.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcframework.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,605 @@
</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;umcframework.h&quot;
+#include &quot;umcsession.h&quot;
+#include &quot;synthscenario.h&quot;
+#include &quot;recogscenario.h&quot;
+#include &quot;recorderscenario.h&quot;
+#include &quot;dtmfscenario.h&quot;
+#include &quot;unimrcp_client.h&quot;
+#include &quot;apt_log.h&quot;
+
+typedef struct
+{
+        char                      m_SessionId[10];
+        char                      m_ScenarioName[128];
+        char                      m_ProfileName[128];
+        const mrcp_app_message_t* m_pAppMessage;
+} UmcTaskMsg;
+
+enum UmcTaskMsgType
+{
+        UMC_TASK_CLIENT_MSG,
+        UMC_TASK_RUN_SESSION_MSG,
+        UMC_TASK_KILL_SESSION_MSG,
+        UMC_TASK_SHOW_SCENARIOS_MSG,
+        UMC_TASK_SHOW_SESSIONS_MSG
+};
+
+apt_bool_t UmcProcessMsg(apt_task_t* pTask, apt_task_msg_t* pMsg);
+void UmcOnStartComplete(apt_task_t* pTask);
+void UmcOnTerminateComplete(apt_task_t* pTask);
+apt_bool_t AppMessageHandler(const mrcp_app_message_t* pAppMessage);
+
+
+UmcFramework::UmcFramework() :
+        m_pPool(NULL),
+        m_pDirLayout(NULL),
+        m_pTask(NULL),
+        m_pMrcpClient(NULL),
+        m_pMrcpApplication(NULL),
+        m_Ready(false),
+        m_pScenarioTable(NULL),
+        m_pSessionTable(NULL)
+{
+}
+
+UmcFramework::~UmcFramework()
+{
+}
+
+bool UmcFramework::Create(apt_dir_layout_t* pDirLayout, apr_pool_t* pool)
+{
+        m_pDirLayout = pDirLayout;
+        m_pPool = pool;
+
+        m_pSessionTable = apr_hash_make(m_pPool);
+        m_pScenarioTable = apr_hash_make(m_pPool);
+        if(!CreateTask())
+                return false;
+
+        /* wait for READY state,
+           preferably cond wait object should be used */
+        int attempts = 0;
+        while(!m_Ready &amp;&amp; attempts &lt; 10)
+        {
+                attempts++;
+                apr_sleep(500000);
+        }
+
+        return true;
+}
+
+void UmcFramework::Destroy()
+{
+        DestroyTask();
+
+        m_pScenarioTable = NULL;
+        m_pSessionTable = NULL;
+}
+
+bool UmcFramework::CreateMrcpClient()
+{
+        /* create MRCP client stack first */
+        m_pMrcpClient = unimrcp_client_create(m_pDirLayout);
+        if(!m_pMrcpClient)
+                return false;
+
+        /* create MRCP application to send/get requests to/from MRCP client stack */
+        m_pMrcpApplication = mrcp_application_create(AppMessageHandler,this,m_pPool);
+        if(!m_pMrcpApplication)
+        {
+                mrcp_client_destroy(m_pMrcpClient);
+                m_pMrcpClient = NULL;
+                return false;
+        }
+
+        /* register MRCP application to MRCP client */
+        mrcp_client_application_register(m_pMrcpClient,m_pMrcpApplication,&quot;UMC&quot;);
+        /* start MRCP client stack processing */
+        if(mrcp_client_start(m_pMrcpClient) == FALSE)
+        {
+                mrcp_client_destroy(m_pMrcpClient);
+                m_pMrcpClient = NULL;
+                m_pMrcpApplication = NULL;
+                return false;
+        }
+        return true;
+}
+
+void UmcFramework::DestroyMrcpClient()
+{
+        if(m_pMrcpClient)
+        {
+                /* shutdown MRCP client stack processing first (blocking call) */
+                mrcp_client_shutdown(m_pMrcpClient);
+                /* destroy MRCP client stack */
+                mrcp_client_destroy(m_pMrcpClient);
+                m_pMrcpClient = NULL;
+                m_pMrcpApplication = NULL;
+        }
+}
+
+bool UmcFramework::CreateTask()
+{
+        apt_task_t* pTask;
+        apt_task_vtable_t* pVtable;
+        apt_task_msg_pool_t* pMsgPool;
+
+        pMsgPool = apt_task_msg_pool_create_dynamic(sizeof(UmcTaskMsg),m_pPool);
+        m_pTask = apt_consumer_task_create(this,pMsgPool,m_pPool);
+        if(!m_pTask)
+                return false;
+
+        pTask = apt_consumer_task_base_get(m_pTask);
+        apt_task_name_set(pTask,&quot;Framework Task&quot;);
+        pVtable = apt_consumer_task_vtable_get(m_pTask);
+        if(pVtable) 
+        {
+                pVtable-&gt;process_msg = UmcProcessMsg;
+                pVtable-&gt;on_start_complete = UmcOnStartComplete;
+                pVtable-&gt;on_terminate_complete = UmcOnTerminateComplete;
+        }
+
+        m_Ready = false;
+        apt_task_start(pTask);
+        return true;
+}
+
+void UmcFramework::DestroyTask()
+{
+        if(m_pTask)
+        {
+                apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
+                if(pTask)
+                {
+                        apt_task_terminate(pTask,TRUE);
+                        apt_task_destroy(pTask);
+                }
+                m_pTask = NULL;
+        }
+}
+
+UmcScenario* UmcFramework::CreateScenario(const char* pType)
+{
+        if(pType)
+        {
+                if(strcasecmp(pType,&quot;Synthesizer&quot;) == 0)
+                        return new SynthScenario();
+                else if(strcasecmp(pType,&quot;Recognizer&quot;) == 0)
+                        return new RecogScenario();
+                else if(strcasecmp(pType,&quot;Recorder&quot;) == 0)
+                        return new RecorderScenario();
+                else if(strcasecmp(pType,&quot;DtmfRecognizer&quot;) == 0)
+                        return new DtmfScenario();
+        }
+        return NULL;
+}
+
+apr_xml_doc* UmcFramework::LoadDocument()
+{
+        apr_xml_parser* pParser = NULL;
+        apr_xml_doc* pDoc = NULL;
+        apr_file_t* pFD = NULL;
+        apr_status_t rv;
+        const char* pFilePath;
+
+        pFilePath = apr_psprintf(m_pPool,&quot;%s/%s&quot;,m_pDirLayout-&gt;conf_dir_path,&quot;umcscenarios.xml&quot;);
+
+        apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Open Config File [%s]&quot;,pFilePath);
+        rv = apr_file_open(&amp;pFD,pFilePath,APR_READ|APR_BINARY,0,m_pPool);
+        if(rv != APR_SUCCESS) 
+        {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Open Config File [%s]&quot;,pFilePath);
+                return NULL;
+        }
+
+        rv = apr_xml_parse_file(m_pPool,&amp;pParser,&amp;pDoc,pFD,2000);
+        if(rv != APR_SUCCESS) 
+        {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Parse Config File [%s]&quot;,pFilePath);
+                pDoc = NULL;
+        }
+
+        apr_file_close(pFD);
+        return pDoc;
+}
+
+bool UmcFramework::LoadScenarios()
+{
+        apr_xml_doc* pDoc = LoadDocument();
+        if(!pDoc)
+                return false;
+
+        const apr_xml_attr* pAttr;
+        const apr_xml_elem* pElem;
+        const apr_xml_elem* pRoot = pDoc-&gt;root;
+        if(!pRoot || strcasecmp(pRoot-&gt;name,&quot;umcscenarios&quot;) != 0)
+        {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Document&quot;);
+                return FALSE;
+        }
+        for(pElem = pRoot-&gt;first_child; pElem; pElem = pElem-&gt;next)
+        {
+                if(strcasecmp(pElem-&gt;name,&quot;scenario&quot;) != 0)
+                {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Unknown Element &lt;%s&gt;&quot;,pElem-&gt;name);
+                        continue;
+                }
+                
+                const char* pName = NULL;
+                const char* pClass = NULL;
+                const char* pMrcpProfile = NULL;
+                for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+                {
+                        if(strcasecmp(pAttr-&gt;name,&quot;name&quot;) == 0) 
+                        {
+                                pName = pAttr-&gt;value;
+                        }
+                        else if(strcasecmp(pAttr-&gt;name,&quot;class&quot;) == 0) 
+                        {
+                                pClass = pAttr-&gt;value;
+                        }
+                        else if(strcasecmp(pAttr-&gt;name,&quot;profile&quot;) == 0) 
+                        {
+                                pMrcpProfile = pAttr-&gt;value;
+                        }
+                }
+
+                if(pName &amp;&amp; pClass)
+                {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Load Scenario name [%s] class [%s]&quot;,pName,pClass);
+                        UmcScenario* pScenario = CreateScenario(pClass);
+                        if(pScenario)
+                        {
+                                pScenario-&gt;SetDirLayout(m_pDirLayout);
+                                pScenario-&gt;SetName(pName);
+                                pScenario-&gt;SetMrcpProfile(pMrcpProfile);
+                                if(pScenario-&gt;Load(pElem,m_pPool))
+                                        apr_hash_set(m_pScenarioTable,pScenario-&gt;GetName(),APR_HASH_KEY_STRING,pScenario);
+                                else
+                                        delete pScenario;
+                        }
+                        else
+                        {
+                                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No such scenario &lt;%s&gt;&quot;,pClass);
+                        }
+                }
+                else
+                {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Missing either name or class of the scenario&quot;);
+                }
+        }
+        return true;
+}
+
+void UmcFramework::DestroyScenarios()
+{
+        UmcScenario* pScenario;
+        void* pVal;
+        apr_hash_index_t* it = apr_hash_first(m_pPool,m_pScenarioTable);
+        for(; it; it = apr_hash_next(it)) 
+        {
+                apr_hash_this(it,NULL,NULL,&amp;pVal);
+                pScenario = (UmcScenario*) pVal;
+                if(pScenario)
+                {
+                        pScenario-&gt;Destroy();
+                        delete pScenario;
+                }
+        }
+        apr_hash_clear(m_pScenarioTable);
+}
+
+bool UmcFramework::AddSession(UmcSession* pSession)
+{
+        if(!pSession)
+                return false;
+
+        apr_hash_set(m_pSessionTable,pSession-&gt;GetId(),APR_HASH_KEY_STRING,pSession);
+        return true;
+}
+
+bool UmcFramework::RemoveSession(UmcSession* pSession)
+{
+        if(!pSession)
+                return false;
+
+        apr_hash_set(m_pSessionTable,pSession-&gt;GetId(),APR_HASH_KEY_STRING,NULL);
+        return true;
+}
+
+bool UmcFramework::ProcessRunRequest(const char* pScenarioName, const char* pProfileName)
+{
+        UmcScenario* pScenario = (UmcScenario*) apr_hash_get(m_pScenarioTable,pScenarioName,APR_HASH_KEY_STRING);
+        if(!pScenario)
+                return false;
+
+        UmcSession* pSession = pScenario-&gt;CreateSession();
+        if(!pSession)
+                return false;
+
+        printf(&quot;[%s]\n&quot;,pSession-&gt;GetId());
+        pSession-&gt;SetMrcpProfile(pProfileName);
+        pSession-&gt;SetMrcpApplication(m_pMrcpApplication);
+        if(!pSession-&gt;Run())
+        {
+                delete pSession;
+                return false;
+        }
+
+        AddSession(pSession);
+        return true;
+}
+
+void UmcFramework::ProcessKillRequest(const char* id)
+{
+        UmcSession* pSession;
+        void* pVal;
+        apr_hash_index_t* it = apr_hash_first(m_pPool,m_pSessionTable);
+        for(; it; it = apr_hash_next(it)) 
+        {
+                apr_hash_this(it,NULL,NULL,&amp;pVal);
+                pSession = (UmcSession*) pVal;
+                if(pSession &amp;&amp; strcasecmp(pSession-&gt;GetId(),id) == 0)
+                {
+                        /* first, terminate session */
+                        pSession-&gt;Terminate();
+                        return;
+                }
+        }
+}
+
+void UmcFramework::ProcessShowScenarios()
+{
+        UmcScenario* pScenario;
+        void* pVal;
+        printf(&quot;%d Scenario(s)\n&quot;, apr_hash_count(m_pScenarioTable));
+        apr_hash_index_t* it = apr_hash_first(m_pPool,m_pScenarioTable);
+        for(; it; it = apr_hash_next(it))
+        {
+                apr_hash_this(it,NULL,NULL,&amp;pVal);
+                pScenario = (UmcScenario*) pVal;
+                if(pScenario)
+                {
+                        printf(&quot;[%s]\n&quot;, pScenario-&gt;GetName());
+                }
+        }
+}
+
+void UmcFramework::ProcessShowSessions()
+{
+        UmcSession* pSession;
+        void* pVal;
+        printf(&quot;%d Session(s)\n&quot;, apr_hash_count(m_pSessionTable));
+        apr_hash_index_t* it = apr_hash_first(m_pPool,m_pSessionTable);
+        for(; it; it = apr_hash_next(it)) 
+        {
+                apr_hash_this(it,NULL,NULL,&amp;pVal);
+                pSession = (UmcSession*) pVal;
+                if(pSession)
+                {
+                        printf(&quot;[%s] - %s\n&quot;, pSession-&gt;GetId(), pSession-&gt;GetScenario()-&gt;GetName());
+                }
+        }
+}
+
+void UmcFramework::RunSession(const char* pScenarioName, const char* pProfileName)
+{
+        apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
+        apt_task_msg_t* pTaskMsg = apt_task_msg_get(pTask);
+        if(!pTaskMsg) 
+                return;
+
+        pTaskMsg-&gt;type = TASK_MSG_USER;
+        pTaskMsg-&gt;sub_type = UMC_TASK_RUN_SESSION_MSG;
+        UmcTaskMsg* pUmcMsg = (UmcTaskMsg*) pTaskMsg-&gt;data;
+        strncpy(pUmcMsg-&gt;m_ScenarioName,pScenarioName,sizeof(pUmcMsg-&gt;m_ScenarioName)-1);
+        strncpy(pUmcMsg-&gt;m_ProfileName,pProfileName,sizeof(pUmcMsg-&gt;m_ProfileName)-1);
+        pUmcMsg-&gt;m_pAppMessage = NULL;
+        apt_task_msg_signal(pTask,pTaskMsg);
+}
+
+void UmcFramework::KillSession(const char* id)
+{
+        apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
+        apt_task_msg_t* pTaskMsg = apt_task_msg_get(pTask);
+        if(!pTaskMsg) 
+                return;
+
+        pTaskMsg-&gt;type = TASK_MSG_USER;
+        pTaskMsg-&gt;sub_type = UMC_TASK_KILL_SESSION_MSG;
+        
+        UmcTaskMsg* pUmcMsg = (UmcTaskMsg*) pTaskMsg-&gt;data;
+        strncpy(pUmcMsg-&gt;m_SessionId,id,sizeof(pUmcMsg-&gt;m_SessionId)-1);
+        pUmcMsg-&gt;m_pAppMessage = NULL;
+        apt_task_msg_signal(pTask,pTaskMsg);
+}
+
+void UmcFramework::ShowScenarios()
+{
+        apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
+        apt_task_msg_t* pTaskMsg = apt_task_msg_get(pTask);
+        if(!pTaskMsg) 
+                return;
+
+        pTaskMsg-&gt;type = TASK_MSG_USER;
+        pTaskMsg-&gt;sub_type = UMC_TASK_SHOW_SCENARIOS_MSG;
+        apt_task_msg_signal(pTask,pTaskMsg);
+}
+
+void UmcFramework::ShowSessions()
+{
+        apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
+        apt_task_msg_t* pTaskMsg = apt_task_msg_get(pTask);
+        if(!pTaskMsg) 
+                return;
+
+        pTaskMsg-&gt;type = TASK_MSG_USER;
+        pTaskMsg-&gt;sub_type = UMC_TASK_SHOW_SESSIONS_MSG;
+        apt_task_msg_signal(pTask,pTaskMsg);
+}
+
+apt_bool_t AppMessageHandler(const mrcp_app_message_t* pMessage)
+{
+        UmcFramework* pFramework = (UmcFramework*) mrcp_application_object_get(pMessage-&gt;application);
+        if(!pFramework)
+                return FALSE;
+
+        apt_task_t* pTask = apt_consumer_task_base_get(pFramework-&gt;m_pTask);
+        apt_task_msg_t* pTaskMsg = apt_task_msg_get(pTask);
+        if(pTaskMsg) 
+        {
+                pTaskMsg-&gt;type = TASK_MSG_USER;
+                pTaskMsg-&gt;sub_type = UMC_TASK_CLIENT_MSG;
+                
+                UmcTaskMsg* pUmcMsg = (UmcTaskMsg*) pTaskMsg-&gt;data;
+                pUmcMsg-&gt;m_pAppMessage = pMessage;
+                apt_task_msg_signal(pTask,pTaskMsg);
+        }
+        
+        return TRUE;
+}
+
+
+apt_bool_t AppOnSessionUpdate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        return pSession-&gt;OnSessionUpdate(status);
+}
+
+apt_bool_t AppOnSessionTerminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        if(!pSession-&gt;OnSessionTerminate(status))
+                return false;
+
+        UmcFramework* pFramework = (UmcFramework*) mrcp_application_object_get(application);
+        pFramework-&gt;RemoveSession(pSession);
+        delete pSession;
+        return true;
+}
+
+apt_bool_t AppOnChannelAdd(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        return pSession-&gt;OnChannelAdd(channel,status);
+}
+
+apt_bool_t AppOnChannelRemove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        return pSession-&gt;OnChannelRemove(channel,status);
+}
+
+apt_bool_t AppOnMessageReceive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        return pSession-&gt;OnMessageReceive(channel,message);
+}
+
+apt_bool_t AppOnTerminateEvent(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        return pSession-&gt;OnTerminateEvent(channel);
+}
+
+apt_bool_t AppOnResourceDiscover(mrcp_application_t *application, mrcp_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_sig_status_code_e status)
+{
+        UmcSession* pSession = (UmcSession*) mrcp_application_session_object_get(session);
+        return pSession-&gt;OnResourceDiscover(descriptor,status);
+}
+
+apt_bool_t AppOnReady(mrcp_application_t *application, mrcp_sig_status_code_e status)
+{
+        UmcFramework* pFramework = (UmcFramework*) mrcp_application_object_get(application);
+        pFramework-&gt;m_Ready = true;
+        return TRUE;
+}
+
+void UmcOnStartComplete(apt_task_t* pTask)
+{
+        apt_consumer_task_t* pConsumerTask = (apt_consumer_task_t*) apt_task_object_get(pTask);
+        UmcFramework* pFramework = (UmcFramework*) apt_consumer_task_object_get(pConsumerTask);
+        
+        pFramework-&gt;CreateMrcpClient();
+        pFramework-&gt;LoadScenarios();
+}
+
+void UmcOnTerminateComplete(apt_task_t* pTask)
+{
+        apt_consumer_task_t* pConsumerTask = (apt_consumer_task_t*) apt_task_object_get(pTask);
+        UmcFramework* pFramework = (UmcFramework*) apt_consumer_task_object_get(pConsumerTask);
+
+        pFramework-&gt;DestroyMrcpClient();
+        pFramework-&gt;DestroyScenarios();
+}
+
+apt_bool_t UmcProcessMsg(apt_task_t *pTask, apt_task_msg_t *pMsg)
+{
+        if(pMsg-&gt;type != TASK_MSG_USER)
+                return FALSE;
+
+        apt_consumer_task_t* pConsumerTask = (apt_consumer_task_t*) apt_task_object_get(pTask);
+        UmcFramework* pFramework = (UmcFramework*) apt_consumer_task_object_get(pConsumerTask);
+        UmcTaskMsg* pUmcMsg = (UmcTaskMsg*) pMsg-&gt;data;
+        switch(pMsg-&gt;sub_type) 
+        {
+                case UMC_TASK_CLIENT_MSG:
+                {
+                        static const mrcp_app_message_dispatcher_t applicationDispatcher = 
+                        {
+                                AppOnSessionUpdate,
+                                AppOnSessionTerminate,
+                                AppOnChannelAdd,
+                                AppOnChannelRemove,
+                                AppOnMessageReceive,
+                                AppOnReady,
+                                AppOnTerminateEvent,
+                                AppOnResourceDiscover
+                        };
+
+                        mrcp_application_message_dispatch(&amp;applicationDispatcher,pUmcMsg-&gt;m_pAppMessage);
+                        break;
+                }
+                case UMC_TASK_RUN_SESSION_MSG:
+                {
+                        if(pFramework-&gt;m_Ready)
+                                pFramework-&gt;ProcessRunRequest(pUmcMsg-&gt;m_ScenarioName,pUmcMsg-&gt;m_ProfileName);
+                        break;
+                }
+                case UMC_TASK_KILL_SESSION_MSG:
+                {
+                        if(pFramework-&gt;m_Ready)
+                                pFramework-&gt;ProcessKillRequest(pUmcMsg-&gt;m_SessionId);
+                        break;
+                }
+                case UMC_TASK_SHOW_SCENARIOS_MSG:
+                {
+                        if(pFramework-&gt;m_Ready)
+                                pFramework-&gt;ProcessShowScenarios();
+                        break;
+                }
+                case UMC_TASK_SHOW_SESSIONS_MSG:
+                {
+                        if(pFramework-&gt;m_Ready)
+                                pFramework-&gt;ProcessShowSessions();
+                        break;
+                }
+        }
+        return TRUE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcumcscenariocpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcscenario.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcscenario.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcscenario.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,213 @@
</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 &lt;stdlib.h&gt;
+#include &quot;umcscenario.h&quot;
+
+UmcScenario::UmcScenario() :
+        m_pName(NULL),
+        m_pMrcpProfile(&quot;MRCPv2-Default&quot;),
+        m_pDirLayout(NULL),
+        m_ResourceDiscovery(false),
+        m_pCapabilities(NULL),
+        m_pRtpDescriptor(NULL)
+{
+}
+
+UmcScenario::~UmcScenario()
+{
+}
+
+bool UmcScenario::Load(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_elem* pChildElem;
+        /* Load Child Elements */
+        for(pChildElem = pElem-&gt;first_child; pChildElem; pChildElem = pChildElem-&gt;next)
+        {
+                LoadElement(pChildElem,pool);
+        }
+        return true;
+}
+
+void UmcScenario::Destroy()
+{
+}
+
+bool UmcScenario::LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        if(strcasecmp(pElem-&gt;name,&quot;resource-discovery&quot;) == 0)
+        {
+                LoadDiscovery(pElem,pool);
+                return true;
+        }
+        else if(strcasecmp(pElem-&gt;name,&quot;termination&quot;) == 0)
+        {
+                LoadTermination(pElem,pool);
+                return true;
+        }
+        else if(strcasecmp(pElem-&gt;name,&quot;rtp-termination&quot;) == 0)
+        {
+                LoadRtpTermination(pElem,pool);
+                return true;
+        }
+
+        return false;
+}
+
+bool UmcScenario::LoadDiscovery(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        m_ResourceDiscovery = IsElementEnabled(pElem);
+        return true;
+}
+
+bool UmcScenario::LoadTermination(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        if(!IsElementEnabled(pElem))
+                return true;
+
+        const apr_xml_elem* pChildElem;
+        /* Load Child Elements */
+        for(pChildElem = pElem-&gt;first_child; pChildElem; pChildElem = pChildElem-&gt;next)
+        {
+                if(strcasecmp(pChildElem-&gt;name,&quot;capabilities&quot;) == 0)
+                        return LoadCapabilities(pChildElem,pool);
+        }
+        return true;
+}
+
+bool UmcScenario::LoadCapabilities(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        const apr_xml_elem* pChildElem;
+        /* Load Child Elements */
+        m_pCapabilities = (mpf_codec_capabilities_t*) apr_palloc(pool,sizeof(mpf_codec_capabilities_t*));
+        mpf_codec_capabilities_init(m_pCapabilities,1,pool);
+        for(pChildElem = pElem-&gt;first_child; pChildElem; pChildElem = pChildElem-&gt;next)
+        {
+                if(strcasecmp(pChildElem-&gt;name,&quot;codec&quot;) != 0)
+                        continue;
+
+                const char* pName = NULL;
+                const char* pRates = NULL; 
+                const apr_xml_attr* pAttr;
+                for(pAttr = pChildElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+                {
+                        if(strcasecmp(pAttr-&gt;name,&quot;name&quot;) == 0)
+                        {
+                                pName = pAttr-&gt;value;
+                        }
+                        else if(strcasecmp(pAttr-&gt;name,&quot;rates&quot;) == 0)
+                        {
+                                pRates = pAttr-&gt;value;
+                        }
+                }
+
+                if(pName)
+                {
+                        int rates = ParseRates(pRates,pool);
+                        mpf_codec_capabilities_add(m_pCapabilities,rates,pName);
+                }
+        }
+        return true;
+}
+
+int UmcScenario::ParseRates(const char* pStr, apr_pool_t* pool) const
+{
+        int rates = 0;
+        if(pStr)
+        {
+                char* pRateStr;
+                char* pState;
+                char* pRateListStr = apr_pstrdup(pool,pStr);
+                do 
+                {
+                        pRateStr = apr_strtok(pRateListStr, &quot; &quot;, &amp;pState);
+                        if(pRateStr) 
+                        {
+                                apr_uint16_t rate = (apr_uint16_t)atoi(pRateStr);
+                                rates |= mpf_sample_rate_mask_get(rate);
+                        }
+                        pRateListStr = NULL; /* make sure we pass NULL on subsequent calls of apr_strtok() */
+                } 
+                while(pRateStr);
+        }
+        return rates;
+}
+
+bool UmcScenario::LoadRtpTermination(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+        return true;
+}
+
+bool UmcScenario::InitCapabilities(mpf_stream_capabilities_t* pCapabilities) const
+{
+        if(m_pCapabilities)
+        {
+                int i;
+                mpf_codec_attribs_t *pAttribs;
+                for(i=0; i&lt;m_pCapabilities-&gt;attrib_arr-&gt;nelts; i++)
+                {
+                        pAttribs = &amp;APR_ARRAY_IDX(m_pCapabilities-&gt;attrib_arr,i,mpf_codec_attribs_t);
+                        mpf_codec_capabilities_add(
+                                        &amp;pCapabilities-&gt;codecs,
+                                        pAttribs-&gt;sample_rates,
+                                        pAttribs-&gt;name.buf);
+                }
+        }
+        else
+        {
+                /* add default codec capabilities (Linear PCM) */
+                mpf_codec_capabilities_add(
+                                &amp;pCapabilities-&gt;codecs,
+                                MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                                &quot;LPCM&quot;);
+        }
+
+        return true;
+}
+
+bool UmcScenario::IsElementEnabled(const apr_xml_elem* pElem) const
+{
+        const apr_xml_attr* pAttr;
+        for(pAttr = pElem-&gt;attr; pAttr; pAttr = pAttr-&gt;next) 
+        {
+                if(strcasecmp(pAttr-&gt;name,&quot;enable&quot;) == 0)
+                {
+                        return atoi(pAttr-&gt;value) &gt; 0;
+                }
+        }
+        return true;
+}
+
+const char* UmcScenario::LoadFileContent(const char* pFileName, apr_pool_t* pool) const
+{
+        if(!m_pDirLayout || !pFileName)
+                return NULL;
+
+        char* pFilePath = apt_datadir_filepath_get(m_pDirLayout,pFileName,pool);
+        if(!pFilePath)
+                return NULL;
+
+        FILE* pFile = fopen(pFilePath,&quot;r&quot;);
+        if(!pFile)
+                return NULL;
+
+        char text[1024];
+        apr_size_t size;
+        size = fread(text,1,sizeof(text)-1,pFile);
+        text[size] = '\0';
+        fclose(pFile);
+        return apr_pstrdup(pool,text);
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcsrcumcsessioncpp"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcsession.cpp (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcsession.cpp                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/src/umcsession.cpp        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,226 @@
</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;umcsession.h&quot;
+#include &quot;umcscenario.h&quot;
+
+UmcSession::UmcSession(const UmcScenario* pScenario) :
+        m_pScenario(pScenario),
+        m_pMrcpProfile(NULL),
+        m_pMrcpApplication(NULL),
+        m_pMrcpSession(NULL),
+        m_Running(false),
+        m_Terminating(false)
+{
+        static int id = 0;
+        if(id == INT_MAX)
+                id = 0;
+        id++;
+
+        int size = apr_snprintf(m_Id,sizeof(m_Id)-1,&quot;%d&quot;,id);
+        m_Id[size] = '\0';
+}
+
+UmcSession::~UmcSession()
+{
+}
+
+bool UmcSession::Run()
+{
+        if(m_Running)
+                return false;
+
+        if(!m_pMrcpProfile)
+                m_pMrcpProfile = m_pScenario-&gt;GetMrcpProfile();
+
+        if(!m_pMrcpProfile || !m_pMrcpApplication)
+                return false;
+
+        /* create session */
+        if(!CreateMrcpSession(m_pMrcpProfile))
+                return false;
+        
+        m_Running = true;
+        
+        bool ret = false;
+        if(m_pScenario-&gt;IsDiscoveryEnabled())
+                ret = ResourceDiscover();
+        else
+                ret = Start();
+        
+        if(!ret)
+        {
+                m_Running = false;
+                DestroyMrcpSession();
+        }
+        return ret;
+}
+
+bool UmcSession::Terminate()
+{
+        if(m_Terminating)
+                return false;
+
+        m_Running = false;
+        m_Terminating = true;
+        return (mrcp_application_session_terminate(m_pMrcpSession) == TRUE);
+}
+
+bool UmcSession::OnSessionTerminate(mrcp_sig_status_code_e status)
+{
+        if(!m_Terminating)
+                return false;
+
+        m_Terminating = false;
+        return DestroyMrcpSession();
+}
+
+bool UmcSession::OnSessionUpdate(mrcp_sig_status_code_e status) 
+{
+        return m_Running;
+}
+
+bool UmcSession::OnChannelAdd(mrcp_channel_t *channel, mrcp_sig_status_code_e status) 
+{
+        return m_Running;
+}
+
+bool UmcSession::OnChannelRemove(mrcp_channel_t *channel, mrcp_sig_status_code_e status) 
+{
+        return m_Running;
+}
+
+bool UmcSession::OnMessageReceive(mrcp_channel_t *channel, mrcp_message_t *message) 
+{
+        return m_Running;
+}
+
+bool UmcSession::OnTerminateEvent(mrcp_channel_t *channel)
+{
+        if(!m_Running)
+                return false;
+
+        return Terminate();
+}
+
+bool UmcSession::OnResourceDiscover(mrcp_session_descriptor_t* descriptor, mrcp_sig_status_code_e status)
+{
+        if(!m_Running)
+                return false;
+
+        if(!Start())
+                Terminate();
+        return true;
+}
+
+bool UmcSession::CreateMrcpSession(const char* pProfileName)
+{
+        m_pMrcpSession = mrcp_application_session_create(m_pMrcpApplication,pProfileName,this);
+        return (m_pMrcpSession != NULL);
+}
+
+bool UmcSession::DestroyMrcpSession()
+{
+        if(!m_pMrcpSession)
+                return false;
+
+        mrcp_application_session_destroy(m_pMrcpSession);
+        m_pMrcpSession = NULL;
+        return true;
+}
+
+bool UmcSession::AddMrcpChannel(mrcp_channel_t* pMrcpChannel)
+{
+        if(!m_Running)
+                return false;
+
+        return (mrcp_application_channel_add(m_pMrcpSession,pMrcpChannel) == TRUE);
+}
+
+bool UmcSession::RemoveMrcpChannel(mrcp_channel_t* pMrcpChannel)
+{
+        if(!m_Running)
+                return false;
+
+        return (mrcp_application_channel_remove(m_pMrcpSession,pMrcpChannel) == TRUE);
+}
+
+bool UmcSession::SendMrcpRequest(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
+{
+        if(!m_Running)
+                return false;
+
+        return (mrcp_application_message_send(m_pMrcpSession,pMrcpChannel,pMrcpMessage) == TRUE);
+}
+
+bool UmcSession::ResourceDiscover()
+{
+        if(!m_Running)
+                return false;
+
+        return (mrcp_application_resource_discover(m_pMrcpSession) == TRUE);
+}
+
+mrcp_channel_t* UmcSession::CreateMrcpChannel(
+                                                mrcp_resource_id resource_id, 
+                                                mpf_termination_t* pTermination, 
+                                                mpf_rtp_termination_descriptor_t* pRtpDescriptor, 
+                                                void* pObj)
+{
+        return mrcp_application_channel_create(
+                        m_pMrcpSession,            /* session, channel belongs to */
+                        resource_id,               /* MRCP resource identifier */
+                        pTermination,              /* media termination, used to terminate audio stream */
+                        NULL,                      /* RTP descriptor, used to create RTP termination (NULL by default) */
+                        pObj);                     /* object to associate */
+}
+
+mpf_termination_t* UmcSession::CreateAudioTermination(
+                                                const mpf_audio_stream_vtable_t* pStreamVtable,
+                                                mpf_stream_capabilities_t* pCapabilities,
+                                                void* pObj)
+{
+        return mrcp_application_audio_termination_create(
+                        m_pMrcpSession,  /* session, termination belongs to */
+                        pStreamVtable,   /* virtual methods table of audio stream */
+                        pCapabilities,   /* capabilities of audio stream */
+                        pObj);           /* object to associate */
+}
+
+mrcp_message_t* UmcSession::CreateMrcpMessage(
+                mrcp_channel_t* pMrcpChannel, 
+                mrcp_method_id method_id)
+{
+        return mrcp_application_message_create(m_pMrcpSession,pMrcpChannel,method_id);
+}
+
+
+
+apr_pool_t* UmcSession::GetSessionPool() const
+{
+        if(!m_pMrcpSession)
+                return NULL;
+        return mrcp_application_session_pool_get(m_pMrcpSession);
+}
+
+const char* UmcSession::GetMrcpSessionId() const
+{
+        if(!m_pMrcpSession)
+                return NULL;
+
+        const apt_str_t *pId = mrcp_application_session_id_get(m_pMrcpSession);
+        return pId-&gt;buf;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsumcumcvcproj"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/platforms/umc/umc.vcproj (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/umc/umc.vcproj                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/platforms/umc/umc.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,261 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;windows-1251&quot;?&gt;
+&lt;VisualStudioProject
+        ProjectType=&quot;Visual C++&quot;
+        Version=&quot;8.00&quot;
+        Name=&quot;umc&quot;
+        ProjectGUID=&quot;{CD1C52C1-D8E1-4654-AE65-6CCAB38DE894}&quot;
+        RootNamespace=&quot;umc&quot;
+        &gt;
+        &lt;Platforms&gt;
+                &lt;Platform
+                        Name=&quot;Win32&quot;
+                /&gt;
+        &lt;/Platforms&gt;
+        &lt;ToolFiles&gt;
+        &lt;/ToolFiles&gt;
+        &lt;Configurations&gt;
+                &lt;Configuration
+                        Name=&quot;Debug|Win32&quot;
+                        ConfigurationType=&quot;1&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unidebug.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpclient.vsprops&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalDependencies=&quot;$(UniMRCPClientLibs)&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+                &lt;Configuration
+                        Name=&quot;Release|Win32&quot;
+                        ConfigurationType=&quot;1&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unirelease.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpclient.vsprops&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                                AdditionalDependencies=&quot;$(UniMRCPClientLibs)&quot;
+                                LinkTimeCodeGeneration=&quot;1&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+        &lt;/Configurations&gt;
+        &lt;References&gt;
+        &lt;/References&gt;
+        &lt;Files&gt;
+                &lt;Filter
+                        Name=&quot;src&quot;
+                        Filter=&quot;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx&quot;
+                        UniqueIdentifier=&quot;{4FC737F1-C7A5-4376-A066-2A32D752A2FF}&quot;
+                        &gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\dtmfscenario.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\dtmfsession.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\main.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\recogscenario.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\recogsession.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\recorderscenario.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\recordersession.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\synthscenario.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\synthsession.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\umcconsole.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\umcframework.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\umcscenario.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\umcsession.cpp&quot;
+                                &gt;
+                        &lt;/File&gt;
+                &lt;/Filter&gt;
+                &lt;Filter
+                        Name=&quot;include&quot;
+                        Filter=&quot;h;hpp;hxx;hm;inl;inc;xsd&quot;
+                        UniqueIdentifier=&quot;{93995380-89BD-4b04-88EB-625FBE52EBFB}&quot;
+                        &gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\dtmfscenario.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\dtmfsession.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\recogscenario.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\recogsession.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\recorderscenario.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\recordersession.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\synthscenario.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\synthsession.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\umcconsole.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\umcframework.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\umcscenario.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                        &lt;File
+                                RelativePath=&quot;.\include\umcsession.h&quot;
+                                &gt;
+                        &lt;/File&gt;
+                &lt;/Filter&gt;
+        &lt;/Files&gt;
+        &lt;Globals&gt;
+        &lt;/Globals&gt;
+&lt;/VisualStudioProject&gt;
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_bypass_applicationc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -31,7 +31,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;demo_application.h&quot;
</span><span class="cx"> #include &quot;demo_util.h&quot;
</span><del>-#include &quot;mrcp_session.h&quot;
</del><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><span class="cx"> #include &quot;mrcp_synth_header.h&quot;
</span><span class="lines">@@ -80,9 +79,10 @@
</span><span class="cx"> static mrcp_channel_t* demo_application_channel_create(mrcp_session_t *session)
</span><span class="cx"> {
</span><span class="cx">         mrcp_channel_t *channel;
</span><ins>+        apr_pool_t *pool = mrcp_application_session_pool_get(session);
</ins><span class="cx">         /* create channel */
</span><del>-        demo_app_channel_t *demo_channel = apr_palloc(session-&gt;pool,sizeof(demo_app_channel_t));
-        mpf_rtp_termination_descriptor_t *rtp_descriptor = demo_rtp_descriptor_create(session-&gt;pool);
</del><ins>+        demo_app_channel_t *demo_channel = apr_palloc(pool,sizeof(demo_app_channel_t));
+        mpf_rtp_termination_descriptor_t *rtp_descriptor = demo_rtp_descriptor_create(pool);
</ins><span class="cx">         channel = mrcp_application_channel_create(
</span><span class="cx">                         session,                     /* session, channel belongs to */
</span><span class="cx">                         MRCP_SYNTHESIZER_RESOURCE,   /* MRCP resource identifier */
</span><span class="lines">@@ -163,10 +163,10 @@
</span><span class="cx">                         mpf_rtp_media_descriptor_t *remote_media = rtp_descriptor-&gt;audio.remote;
</span><span class="cx">                         if(local_media &amp;&amp; remote_media) {
</span><span class="cx">                                 apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Media Attributes: L[%s/%d] R[%s/%d]&quot;,
</span><del>-                                        local_media-&gt;base.ip.buf,
-                                        local_media-&gt;base.port,
-                                        remote_media-&gt;base.ip.buf,
-                                        remote_media-&gt;base.port);
</del><ins>+                                        local_media-&gt;ip.buf,
+                                        local_media-&gt;port,
+                                        remote_media-&gt;ip.buf,
+                                        remote_media-&gt;port);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_recog_applicationc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -32,15 +32,12 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;demo_application.h&quot;
</span><span class="cx"> #include &quot;demo_util.h&quot;
</span><del>-#include &quot;mrcp_session.h&quot;
</del><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><span class="cx"> #include &quot;mrcp_recog_header.h&quot;
</span><span class="cx"> #include &quot;mrcp_recog_resource.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><del>-#define DEMO_SPEECH_SOURCE_FILE &quot;one.pcm&quot;
-
</del><span class="cx"> typedef struct recog_app_channel_t recog_app_channel_t;
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of recognizer application channel */
</span><span class="lines">@@ -77,7 +74,7 @@
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of recognizer audio stream methods */
</span><span class="cx"> static apt_bool_t recog_app_stream_destroy(mpf_audio_stream_t *stream);
</span><del>-static apt_bool_t recog_app_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t recog_app_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t recog_app_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t recog_app_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="lines">@@ -108,27 +105,36 @@
</span><span class="cx"> {
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         mpf_termination_t *termination;
</span><del>-        mpf_codec_descriptor_t *codec_descriptor = NULL;
</del><ins>+        mpf_stream_capabilities_t *capabilities;
+        apr_pool_t *pool = mrcp_application_session_pool_get(session);
</ins><span class="cx"> 
</span><span class="cx">         /* create channel */
</span><del>-        recog_app_channel_t *recog_channel = apr_palloc(session-&gt;pool,sizeof(recog_app_channel_t));
</del><ins>+        recog_app_channel_t *recog_channel = apr_palloc(pool,sizeof(recog_app_channel_t));
</ins><span class="cx">         recog_channel-&gt;streaming = FALSE;
</span><span class="cx">         recog_channel-&gt;audio_in = NULL;
</span><span class="cx">         recog_channel-&gt;time_to_complete = 0;
</span><span class="cx"> 
</span><del>-#if 0 /* in case your audio source isn't in linear PCM, create appropriate codec descriptor below */
-        codec_descriptor = apr_palloc(session-&gt;pool,sizeof(mpf_codec_descriptor_t));
-        mpf_codec_descriptor_init(codec_descriptor);
-        codec_descriptor-&gt;channel_count = 1;
-        codec_descriptor-&gt;payload_type = 0;
-        apt_string_set(&amp;codec_descriptor-&gt;name,&quot;PCMU&quot;);
-        codec_descriptor-&gt;sampling_rate = 8000;
</del><ins>+        /* create source stream capabilities */
+        capabilities = mpf_source_stream_capabilities_create(pool);
+
+        /* add codec capabilities (Linear PCM) */
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);
+
+#if 0
+        /* more capabilities can be added or replaced */
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;PCMU&quot;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-        termination = mrcp_application_source_termination_create(
</del><ins>+        termination = mrcp_application_audio_termination_create(
</ins><span class="cx">                         session,                   /* session, termination belongs to */
</span><span class="cx">                         &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
</span><del>-                        codec_descriptor,          /* codec descriptor of audio stream (NULL by default) */
</del><ins>+                        capabilities,              /* capabilities of audio stream */
</ins><span class="cx">                         recog_channel);            /* object to associate */
</span><span class="cx">         
</span><span class="cx">         channel = mrcp_application_channel_create(
</span><span class="lines">@@ -235,13 +241,17 @@
</span><span class="cx">         recog_app_channel_t *recog_channel = mrcp_application_channel_object_get(channel);
</span><span class="cx">         mrcp_message_t *mrcp_message;
</span><span class="cx">         const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application);
</span><ins>+        apr_pool_t *pool = mrcp_application_session_pool_get(session);
</ins><span class="cx">         /* create and send RECOGNIZE request */
</span><span class="cx">         mrcp_message = demo_recognize_message_create(session,channel,dir_layout);
</span><span class="cx">         if(mrcp_message) {
</span><span class="cx">                 mrcp_application_message_send(session,channel,mrcp_message);
</span><span class="cx">         }
</span><span class="cx">         if(recog_channel) {
</span><del>-                char *file_path = apt_datadir_filepath_get(dir_layout,DEMO_SPEECH_SOURCE_FILE,session-&gt;pool);
</del><ins>+                const mpf_codec_descriptor_t *descriptor = mrcp_application_source_descriptor_get(channel);
+                char *file_name = apr_psprintf(pool,&quot;one-%dkHz.pcm&quot;,
+                        descriptor ? descriptor-&gt;sampling_rate/1000 : 8);
+                char *file_path = apt_datadir_filepath_get(dir_layout,file_name,pool);
</ins><span class="cx">                 if(file_path) {
</span><span class="cx">                         recog_channel-&gt;audio_in = fopen(file_path,&quot;rb&quot;);
</span><span class="cx">                         if(recog_channel-&gt;audio_in) {
</span><span class="lines">@@ -311,7 +321,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Callback is called from MPF engine context to perform application stream specific action before open */
</span><del>-static apt_bool_t recog_app_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t recog_app_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_synth_applicationc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -31,7 +31,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;demo_application.h&quot;
</span><span class="cx"> #include &quot;demo_util.h&quot;
</span><del>-#include &quot;mrcp_session.h&quot;
</del><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><span class="cx"> #include &quot;mrcp_synth_header.h&quot;
</span><span class="lines">@@ -68,7 +67,7 @@
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of synthesizer audio stream methods */
</span><span class="cx"> static apt_bool_t synth_app_stream_destroy(mpf_audio_stream_t *stream);
</span><del>-static apt_bool_t synth_app_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t synth_app_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t synth_app_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t synth_app_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="lines">@@ -99,25 +98,34 @@
</span><span class="cx"> {
</span><span class="cx">         mrcp_channel_t *channel;
</span><span class="cx">         mpf_termination_t *termination;
</span><del>-        mpf_codec_descriptor_t *codec_descriptor = NULL;
</del><ins>+        mpf_stream_capabilities_t *capabilities;
+        apr_pool_t *pool = mrcp_application_session_pool_get(session);
</ins><span class="cx"> 
</span><span class="cx">         /* create channel */
</span><del>-        synth_app_channel_t *synth_channel = apr_palloc(session-&gt;pool,sizeof(synth_app_channel_t));
</del><ins>+        synth_app_channel_t *synth_channel = apr_palloc(pool,sizeof(synth_app_channel_t));
</ins><span class="cx">         synth_channel-&gt;audio_out = NULL;
</span><span class="cx"> 
</span><ins>+        /* create sink stream capabilities */
+        capabilities = mpf_sink_stream_capabilities_create(pool);
+
+        /* add codec capabilities (Linear PCM) */
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);
+
</ins><span class="cx"> #if 0
</span><del>-        codec_descriptor = apr_palloc(session-&gt;pool,sizeof(mpf_codec_descriptor_t));
-        mpf_codec_descriptor_init(codec_descriptor);
-        codec_descriptor-&gt;channel_count = 1;
-        codec_descriptor-&gt;payload_type = 0;
-        apt_string_set(&amp;codec_descriptor-&gt;name,&quot;PCMU&quot;);
-        codec_descriptor-&gt;sampling_rate = 8000;
</del><ins>+        /* more capabilities can be added or replaced */
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;PCMU&quot;);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-        termination = mrcp_application_sink_termination_create(
</del><ins>+        termination = mrcp_application_audio_termination_create(
</ins><span class="cx">                         session,                   /* session, termination belongs to */
</span><span class="cx">                         &amp;audio_stream_vtable,      /* virtual methods table of audio stream */
</span><del>-                        codec_descriptor,          /* codec descriptor of audio stream (NULL by default) */
</del><ins>+                        capabilities,              /* capabilities of audio stream */
</ins><span class="cx">                         synth_channel);            /* object to associate */
</span><span class="cx">         
</span><span class="cx">         channel = mrcp_application_channel_create(
</span><span class="lines">@@ -187,6 +195,7 @@
</span><span class="cx"> static apt_bool_t synth_application_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
</span><span class="cx"> {
</span><span class="cx">         synth_app_channel_t *synth_channel = mrcp_application_channel_object_get(channel);
</span><ins>+        apr_pool_t *pool = mrcp_application_session_pool_get(session);
</ins><span class="cx">         if(status == MRCP_SIG_STATUS_CODE_SUCCESS) {
</span><span class="cx">                 mrcp_message_t *mrcp_message;
</span><span class="cx">                 const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application);
</span><span class="lines">@@ -197,8 +206,12 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if(synth_channel &amp;&amp; session) {
</span><del>-                        char *file_name = apr_pstrcat(session-&gt;pool,&quot;synth-&quot;,session-&gt;id.buf,&quot;.pcm&quot;,NULL);
-                        char *file_path = apt_datadir_filepath_get(dir_layout,file_name,session-&gt;pool);
</del><ins>+                        const apt_str_t *id = mrcp_application_session_id_get(session);
+                        const mpf_codec_descriptor_t *descriptor = mrcp_application_sink_descriptor_get(channel);
+                        char *file_name = apr_psprintf(pool,&quot;synth-%dkHz-%s.pcm&quot;,
+                                descriptor ? descriptor-&gt;sampling_rate/1000 : 8,
+                                id-&gt;buf);
+                        char *file_path = apt_datadir_filepath_get(dir_layout,file_name,pool);
</ins><span class="cx">                         if(file_path) {
</span><span class="cx">                                 synth_channel-&gt;audio_out = fopen(file_path,&quot;wb&quot;);
</span><span class="cx">                         }
</span><span class="lines">@@ -266,7 +279,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Callback is called from MPF engine context to perform application stream specific action before open */
</span><del>-static apt_bool_t synth_app_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t synth_app_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpplatformsunimrcpclientsrcdemo_utilc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -16,7 +16,6 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;demo_util.h&quot;
</span><span class="cx"> /* common includes */
</span><del>-#include &quot;mrcp_session.h&quot;
</del><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><span class="cx"> /* synthesizer includes */
</span><span class="lines">@@ -183,10 +182,10 @@
</span><span class="cx">         /* create rtp local media */
</span><span class="cx">         media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">         mpf_rtp_media_descriptor_init(media);
</span><del>-        apt_string_assign(&amp;media-&gt;base.ip,&quot;127.0.0.1&quot;,pool);
-        media-&gt;base.port = 6000;
-        media-&gt;base.state = MPF_MEDIA_ENABLED;
-        media-&gt;mode = STREAM_MODE_RECEIVE;
</del><ins>+        apt_string_assign(&amp;media-&gt;ip,&quot;127.0.0.1&quot;,pool);
+        media-&gt;port = 6000;
+        media-&gt;state = MPF_MEDIA_ENABLED;
+        media-&gt;direction = STREAM_DIRECTION_RECEIVE;
</ins><span class="cx"> 
</span><span class="cx">         /* initialize codec list */
</span><span class="cx">         mpf_codec_list_init(&amp;media-&gt;codec_list,2,pool);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -10,6 +10,10 @@
</span><span class="cx"> SUBDIRS               += demo-recog
</span><span class="cx"> endif
</span><span class="cx"> 
</span><ins>+if RECORDER_PLUGIN
+SUBDIRS               += mrcp-recorder
+endif
+
</ins><span class="cx"> if CEPSTRAL_PLUGIN
</span><span class="cx"> SUBDIRS               += mrcp-cepstral
</span><span class="cx"> endif
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsdemorecogsrcdemo_recog_enginec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,20 +15,19 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /* 
</span><del>- * Some mandatory rules for plugin implementation.
- * 1. Each plugin MUST contain the following function as an entry point of the plugin
- *        MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
- * 2. One and only one response MUST be sent back to the received request.
- * 3. Methods (callbacks) of the MRCP engine channel MUST not block.
- *   (asynch response can be sent from the context of other thread)
- * 4. Methods (callbacks) of the MPF engine stream MUST not block.
</del><ins>+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ *    with the exact signature and name (the main entry point)
+ *        MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ *        MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ *   (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
-#include &quot;mrcp_recog_resource.h&quot;
-#include &quot;mrcp_recog_header.h&quot;
-#include &quot;mrcp_generic_header.h&quot;
-#include &quot;mrcp_message.h&quot;
</del><ins>+#include &quot;mrcp_recog_engine.h&quot;
</ins><span class="cx"> #include &quot;mpf_activity_detector.h&quot;
</span><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="lines">@@ -40,10 +39,10 @@
</span><span class="cx"> typedef struct demo_recog_msg_t demo_recog_msg_t;
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of recognizer engine methods */
</span><del>-static apt_bool_t demo_recog_engine_destroy(mrcp_resource_engine_t *engine);
-static apt_bool_t demo_recog_engine_open(mrcp_resource_engine_t *engine);
-static apt_bool_t demo_recog_engine_close(mrcp_resource_engine_t *engine);
-static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool);
</del><ins>+static apt_bool_t demo_recog_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t demo_recog_engine_open(mrcp_engine_t *engine);
+static apt_bool_t demo_recog_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> static const struct mrcp_engine_method_vtable_t engine_vtable = {
</span><span class="cx">         demo_recog_engine_destroy,
</span><span class="lines">@@ -68,7 +67,7 @@
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of recognizer audio stream methods */
</span><span class="cx"> static apt_bool_t demo_recog_stream_destroy(mpf_audio_stream_t *stream);
</span><del>-static apt_bool_t demo_recog_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t demo_recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t demo_recog_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t demo_recog_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="lines">@@ -122,11 +121,14 @@
</span><span class="cx"> static apt_bool_t demo_recog_msg_signal(demo_recog_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request);
</span><span class="cx"> static apt_bool_t demo_recog_msg_process(apt_task_t *task, apt_task_msg_t *msg);
</span><span class="cx"> 
</span><ins>+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
</ins><span class="cx"> /** Declare this macro to use log routine of the server, plugin is loaded from */
</span><span class="cx"> MRCP_PLUGIN_LOGGER_IMPLEMENT
</span><span class="cx"> 
</span><span class="cx"> /** Create demo recognizer engine */
</span><del>-MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</del><ins>+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         demo_recog_engine_t *demo_engine = apr_palloc(pool,sizeof(demo_recog_engine_t));
</span><span class="cx">         apt_task_t *task;
</span><span class="lines">@@ -145,16 +147,16 @@
</span><span class="cx">                 vtable-&gt;process_msg = demo_recog_msg_process;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* create resource engine base */
-        return mrcp_resource_engine_create(
-                                        MRCP_RECOGNIZER_RESOURCE,  /* MRCP resource identifier */
-                                        demo_engine,               /* object to associate */
-                                        &amp;engine_vtable,            /* virtual methods table of resource engine */
-                                        pool);                     /* pool to allocate memory from */
</del><ins>+        /* create engine base */
+        return mrcp_engine_create(
+                                MRCP_RECOGNIZER_RESOURCE,  /* MRCP resource identifier */
+                                demo_engine,               /* object to associate */
+                                &amp;engine_vtable,            /* virtual methods table of engine */
+                                pool);                     /* pool to allocate memory from */
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Destroy recognizer engine */
</span><del>-static apt_bool_t demo_recog_engine_destroy(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t demo_recog_engine_destroy(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         demo_recog_engine_t *demo_engine = engine-&gt;obj;
</span><span class="cx">         if(demo_engine-&gt;task) {
</span><span class="lines">@@ -166,7 +168,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Open recognizer engine */
</span><del>-static apt_bool_t demo_recog_engine_open(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t demo_recog_engine_open(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         demo_recog_engine_t *demo_engine = engine-&gt;obj;
</span><span class="cx">         if(demo_engine-&gt;task) {
</span><span class="lines">@@ -177,7 +179,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Close recognizer engine */
</span><del>-static apt_bool_t demo_recog_engine_close(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t demo_recog_engine_close(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         demo_recog_engine_t *demo_engine = engine-&gt;obj;
</span><span class="cx">         if(demo_engine-&gt;task) {
</span><span class="lines">@@ -187,8 +189,11 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
</del><ins>+static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
</ins><span class="cx"> {
</span><ins>+        mpf_stream_capabilities_t *capabilities;
+        mpf_termination_t *termination; 
+
</ins><span class="cx">         /* create demo recog channel */
</span><span class="cx">         demo_recog_channel_t *recog_channel = apr_palloc(pool,sizeof(demo_recog_channel_t));
</span><span class="cx">         recog_channel-&gt;demo_engine = engine-&gt;obj;
</span><span class="lines">@@ -196,26 +201,35 @@
</span><span class="cx">         recog_channel-&gt;stop_response = NULL;
</span><span class="cx">         recog_channel-&gt;detector = mpf_activity_detector_create(pool);
</span><span class="cx">         recog_channel-&gt;audio_out = NULL;
</span><ins>+
+        capabilities = mpf_sink_stream_capabilities_create(pool);
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);
+
+        /* create media termination */
+        termination = mrcp_engine_audio_termination_create(
+                        recog_channel,        /* object to associate */
+                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
</ins><span class="cx">         /* create engine channel base */
</span><del>-        recog_channel-&gt;channel = mrcp_engine_sink_channel_create(
-                        engine,               /* resource engine */
</del><ins>+        recog_channel-&gt;channel = mrcp_engine_channel_create(
+                        engine,               /* engine */
</ins><span class="cx">                         &amp;channel_vtable,      /* virtual methods table of engine channel */
</span><del>-                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
</del><span class="cx">                         recog_channel,        /* object to associate */
</span><del>-                        NULL,                 /* codec descriptor might be NULL by default */
</del><ins>+                        termination,          /* associated media termination */
</ins><span class="cx">                         pool);                /* pool to allocate memory from */
</span><ins>+
</ins><span class="cx">         return recog_channel-&gt;channel;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Destroy engine channel */
</span><span class="cx"> static apt_bool_t demo_recog_channel_destroy(mrcp_engine_channel_t *channel)
</span><span class="cx"> {
</span><del>-        demo_recog_channel_t *recog_channel = channel-&gt;method_obj;
-        if(recog_channel-&gt;audio_out) {
-                fclose(recog_channel-&gt;audio_out);
-                recog_channel-&gt;audio_out = NULL;
-        }
-
</del><ins>+        /* nothing to destrtoy */
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -255,13 +269,16 @@
</span><span class="cx">                         mpf_activity_detector_noinput_timeout_set(recog_channel-&gt;detector,recog_header-&gt;no_input_timeout);
</span><span class="cx">                 }
</span><span class="cx">                 if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_SPEECH_COMPLETE_TIMEOUT) == TRUE) {
</span><del>-                        mpf_activity_detector_complete_timeout_set(recog_channel-&gt;detector,recog_header-&gt;speech_complete_timeout);
</del><ins>+                        mpf_activity_detector_silence_timeout_set(recog_channel-&gt;detector,recog_header-&gt;speech_complete_timeout);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(!recog_channel-&gt;audio_out) {
</span><span class="cx">                 const apt_dir_layout_t *dir_layout = channel-&gt;engine-&gt;dir_layout;
</span><del>-                char *file_name = apr_pstrcat(channel-&gt;pool,&quot;utter-&quot;,request-&gt;channel_id.session_id.buf,&quot;.pcm&quot;,NULL);
</del><ins>+                const mpf_codec_descriptor_t *descriptor = mrcp_engine_sink_stream_codec_get(channel);
+                char *file_name = apr_psprintf(channel-&gt;pool,&quot;utter-%dkHz-%s.pcm&quot;,
+                        descriptor ? descriptor-&gt;sampling_rate/1000 : 8,
+                        request-&gt;channel_id.session_id.buf);
</ins><span class="cx">                 char *file_path = apt_datadir_filepath_get(dir_layout,file_name,channel-&gt;pool);
</span><span class="cx">                 if(file_path) {
</span><span class="cx">                         recog_channel-&gt;audio_out = fopen(file_path,&quot;wb&quot;);
</span><span class="lines">@@ -333,7 +350,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Callback is called from MPF engine context to perform any action before open */
</span><del>-static apt_bool_t demo_recog_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t demo_recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -459,6 +476,18 @@
</span><span class="cx">                                 break;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><ins>+                if((frame-&gt;type &amp; MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
+                        if(frame-&gt;marker == MPF_MARKER_START_OF_EVENT) {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Detected Start of Event: id [%d]&quot;,
+                                        frame-&gt;event_frame.event_id);
+                        }
+                        else if(frame-&gt;marker == MPF_MARKER_END_OF_EVENT) {
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Detected End of Event: id [%d] duration [%d ts]&quot;,
+                                        frame-&gt;event_frame.event_id,
+                                        frame-&gt;event_frame.duration);
+                        }
+                }
+
</ins><span class="cx">                 if(recog_channel-&gt;audio_out) {
</span><span class="cx">                         fwrite(frame-&gt;codec_frame.buffer,1,frame-&gt;codec_frame.size,recog_channel-&gt;audio_out);
</span><span class="cx">                 }
</span><span class="lines">@@ -495,9 +524,17 @@
</span><span class="cx">                         mrcp_engine_channel_open_respond(demo_msg-&gt;channel,TRUE);
</span><span class="cx">                         break;
</span><span class="cx">                 case DEMO_RECOG_MSG_CLOSE_CHANNEL:
</span><ins>+                {
</ins><span class="cx">                         /* close channel, make sure there is no activity and send asynch response */
</span><ins>+                        demo_recog_channel_t *recog_channel = demo_msg-&gt;channel-&gt;method_obj;
+                        if(recog_channel-&gt;audio_out) {
+                                fclose(recog_channel-&gt;audio_out);
+                                recog_channel-&gt;audio_out = NULL;
+                        }
+
</ins><span class="cx">                         mrcp_engine_channel_close_respond(demo_msg-&gt;channel);
</span><span class="cx">                         break;
</span><ins>+                }
</ins><span class="cx">                 case DEMO_RECOG_MSG_REQUEST_PROCESS:
</span><span class="cx">                         demo_recog_channel_request_dispatch(demo_msg-&gt;channel,demo_msg-&gt;request);
</span><span class="cx">                         break;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsdemosynthsrcdemo_synth_enginec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,20 +15,19 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /* 
</span><del>- * Some mandatory rules for plugin implementation.
- * 1. Each plugin MUST contain the following function as an entry point of the plugin
- *        MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
- * 2. One and only one response MUST be sent back to the received request.
- * 3. Methods (callbacks) of the MRCP engine channel MUST not block.
- *   (asynch response can be sent from the context of other thread)
- * 4. Methods (callbacks) of the MPF engine stream MUST not block.
</del><ins>+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ *    with the exact signature and name (the main entry point)
+ *        MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ *        MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ *   (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
-#include &quot;mrcp_synth_resource.h&quot;
-#include &quot;mrcp_synth_header.h&quot;
-#include &quot;mrcp_generic_header.h&quot;
-#include &quot;mrcp_message.h&quot;
</del><ins>+#include &quot;mrcp_synth_engine.h&quot;
</ins><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -39,10 +38,10 @@
</span><span class="cx"> typedef struct demo_synth_msg_t demo_synth_msg_t;
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of synthesizer engine methods */
</span><del>-static apt_bool_t demo_synth_engine_destroy(mrcp_resource_engine_t *engine);
-static apt_bool_t demo_synth_engine_open(mrcp_resource_engine_t *engine);
-static apt_bool_t demo_synth_engine_close(mrcp_resource_engine_t *engine);
-static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool);
</del><ins>+static apt_bool_t demo_synth_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t demo_synth_engine_open(mrcp_engine_t *engine);
+static apt_bool_t demo_synth_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> static const struct mrcp_engine_method_vtable_t engine_vtable = {
</span><span class="cx">         demo_synth_engine_destroy,
</span><span class="lines">@@ -67,7 +66,7 @@
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of synthesizer audio stream methods */
</span><span class="cx"> static apt_bool_t demo_synth_stream_destroy(mpf_audio_stream_t *stream);
</span><del>-static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t demo_synth_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t demo_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="lines">@@ -119,15 +118,17 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-#define DEMO_SPEECH_SOURCE_FILE &quot;demo.pcm&quot;
</del><span class="cx"> static apt_bool_t demo_synth_msg_signal(demo_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request);
</span><span class="cx"> static apt_bool_t demo_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg);
</span><span class="cx"> 
</span><ins>+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
</ins><span class="cx"> /** Declare this macro to use log routine of the server, plugin is loaded from */
</span><span class="cx"> MRCP_PLUGIN_LOGGER_IMPLEMENT
</span><span class="cx"> 
</span><span class="cx"> /** Create demo synthesizer engine */
</span><del>-MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</del><ins>+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         /* create demo engine */
</span><span class="cx">         demo_synth_engine_t *demo_engine = apr_palloc(pool,sizeof(demo_synth_engine_t));
</span><span class="lines">@@ -148,16 +149,16 @@
</span><span class="cx">                 vtable-&gt;process_msg = demo_synth_msg_process;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        /* create resource engine base */
-        return mrcp_resource_engine_create(
-                                        MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
-                                        demo_engine,               /* object to associate */
-                                        &amp;engine_vtable,            /* virtual methods table of resource engine */
-                                        pool);                     /* pool to allocate memory from */
</del><ins>+        /* create engine base */
+        return mrcp_engine_create(
+                                MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
+                                demo_engine,               /* object to associate */
+                                &amp;engine_vtable,            /* virtual methods table of engine */
+                                pool);                     /* pool to allocate memory from */
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Destroy synthesizer engine */
</span><del>-static apt_bool_t demo_synth_engine_destroy(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t demo_synth_engine_destroy(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         demo_synth_engine_t *demo_engine = engine-&gt;obj;
</span><span class="cx">         if(demo_engine-&gt;task) {
</span><span class="lines">@@ -169,7 +170,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Open synthesizer engine */
</span><del>-static apt_bool_t demo_synth_engine_open(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t demo_synth_engine_open(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         demo_synth_engine_t *demo_engine = engine-&gt;obj;
</span><span class="cx">         if(demo_engine-&gt;task) {
</span><span class="lines">@@ -180,7 +181,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Close synthesizer engine */
</span><del>-static apt_bool_t demo_synth_engine_close(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t demo_synth_engine_close(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         demo_synth_engine_t *demo_engine = engine-&gt;obj;
</span><span class="cx">         if(demo_engine-&gt;task) {
</span><span class="lines">@@ -191,8 +192,11 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create demo synthesizer channel derived from engine channel base */
</span><del>-static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
</del><ins>+static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
</ins><span class="cx"> {
</span><ins>+        mpf_stream_capabilities_t *capabilities;
+        mpf_termination_t *termination; 
+
</ins><span class="cx">         /* create demo synth channel */
</span><span class="cx">         demo_synth_channel_t *synth_channel = apr_palloc(pool,sizeof(demo_synth_channel_t));
</span><span class="cx">         synth_channel-&gt;demo_engine = engine-&gt;obj;
</span><span class="lines">@@ -201,14 +205,28 @@
</span><span class="cx">         synth_channel-&gt;time_to_complete = 0;
</span><span class="cx">         synth_channel-&gt;paused = FALSE;
</span><span class="cx">         synth_channel-&gt;audio_file = NULL;
</span><ins>+        
+        capabilities = mpf_source_stream_capabilities_create(pool);
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);
+
+        /* create media termination */
+        termination = mrcp_engine_audio_termination_create(
+                        synth_channel,        /* object to associate */
+                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
</ins><span class="cx">         /* create engine channel base */
</span><del>-        synth_channel-&gt;channel = mrcp_engine_source_channel_create(
-                        engine,               /* resource engine */
</del><ins>+        synth_channel-&gt;channel = mrcp_engine_channel_create(
+                        engine,               /* engine */
</ins><span class="cx">                         &amp;channel_vtable,      /* virtual methods table of engine channel */
</span><del>-                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
</del><span class="cx">                         synth_channel,        /* object to associate */
</span><del>-                        NULL,                 /* codec descriptor might be NULL by default */
</del><ins>+                        termination,          /* associated media termination */
</ins><span class="cx">                         pool);                /* pool to allocate memory from */
</span><ins>+
</ins><span class="cx">         return synth_channel-&gt;channel;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -244,7 +262,10 @@
</span><span class="cx">         demo_synth_channel_t *synth_channel = channel-&gt;method_obj;
</span><span class="cx">         synth_channel-&gt;time_to_complete = 0;
</span><span class="cx">         if(channel-&gt;engine) {
</span><del>-                file_path = apt_datadir_filepath_get(channel-&gt;engine-&gt;dir_layout,DEMO_SPEECH_SOURCE_FILE,channel-&gt;pool);
</del><ins>+                const mpf_codec_descriptor_t *descriptor = mrcp_engine_source_stream_codec_get(channel);
+                char *file_name = apr_psprintf(channel-&gt;pool,&quot;demo-%dkHz.pcm&quot;,
+                        descriptor ? descriptor-&gt;sampling_rate/1000 : 8);
+                file_path = apt_datadir_filepath_get(channel-&gt;engine-&gt;dir_layout,file_name,channel-&gt;pool);
</ins><span class="cx">         }
</span><span class="cx">         if(file_path) {
</span><span class="cx">                 synth_channel-&gt;audio_file = fopen(file_path,&quot;rb&quot;);
</span><span class="lines">@@ -394,7 +415,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Callback is called from MPF engine context to perform any action before open */
</span><del>-static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpcepstralsrcmrcp_swiftc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,29 +15,29 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /* 
</span><del>- * Some mandatory rules concerning plugin implementation.
- * 1. Each plugin MUST contain the following function as an entry point of the plugin
- *        MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
- * 2. One and only one response MUST be sent back to the received request.
- * 3. Methods (callbacks) of the MRCP engine channel MUST not block.
- *   (asynch response can be sent from the context of other thread)
- * 4. Methods (callbacks) of the MPF engine stream MUST not block.
</del><ins>+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ *    with the exact signature and name (the main entry point)
+ *        MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ *        MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ *   (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#include &lt;stdlib.h&gt;
</ins><span class="cx"> #include &lt;swift.h&gt;
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
-#include &quot;mrcp_synth_resource.h&quot;
-#include &quot;mrcp_synth_header.h&quot;
-#include &quot;mrcp_generic_header.h&quot;
-#include &quot;mrcp_message.h&quot;
</del><ins>+#include &quot;mrcp_synth_engine.h&quot;
</ins><span class="cx"> #include &quot;mpf_buffer.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of synthesizer engine methods */
</span><del>-static apt_bool_t mrcp_swift_engine_destroy(mrcp_resource_engine_t *engine);
-static apt_bool_t mrcp_swift_engine_open(mrcp_resource_engine_t *engine);
-static apt_bool_t mrcp_swift_engine_close(mrcp_resource_engine_t *engine);
-static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool);
</del><ins>+static apt_bool_t mrcp_swift_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t mrcp_swift_engine_open(mrcp_engine_t *engine);
+static apt_bool_t mrcp_swift_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> static const struct mrcp_engine_method_vtable_t engine_vtable = {
</span><span class="cx">         mrcp_swift_engine_destroy,
</span><span class="lines">@@ -62,7 +62,7 @@
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of synthesizer audio stream methods */
</span><span class="cx"> static apt_bool_t synth_stream_destroy(mpf_audio_stream_t *stream);
</span><del>-static apt_bool_t synth_stream_open(mpf_audio_stream_t *stream);
</del><ins>+static apt_bool_t synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
</ins><span class="cx"> static apt_bool_t synth_stream_close(mpf_audio_stream_t *stream);
</span><span class="cx"> static apt_bool_t synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
</span><span class="cx"> 
</span><span class="lines">@@ -76,6 +76,18 @@
</span><span class="cx">         NULL
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+typedef struct mrcp_swift_engine_t mrcp_swift_engine_t;
+/** Declaration of Swift synthesizer engine */
+struct mrcp_swift_engine_t {
+        /** Swift synthesizer engine */
+        swift_engine *swift;
+        /** Speech language mapping */
+        apr_table_t  *language_table;
+        /** Sampling rates (bitmask of mpf_sample_rates_e)
+        installed voices support */
+        int           sample_rates;
+};
+
</ins><span class="cx"> typedef struct mrcp_swift_channel_t mrcp_swift_channel_t;
</span><span class="cx"> /** Declaration of Swift synthesizer channel */
</span><span class="cx"> struct mrcp_swift_channel_t {
</span><span class="lines">@@ -118,123 +130,120 @@
</span><span class="cx">         170  /* PROSODY_RATE_DEFAULT */
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-static apr_table_t *swift_speech_language_table;
</del><span class="cx"> 
</span><span class="cx"> static apr_table_t* mrcp_swift_language_table_create(apr_pool_t *pool);
</span><del>-static void mrcp_swift_voices_show(swift_engine *engine);
</del><ins>+static apt_bool_t mrcp_swift_voices_scan(mrcp_swift_engine_t *engine);
</ins><span class="cx"> static swift_result_t mrcp_swift_write_audio(swift_event *event, swift_event_t type, void *udata);
</span><span class="cx"> static apt_bool_t mrcp_swift_channel_voice_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message);
</span><span class="cx"> static apt_bool_t mrcp_swift_channel_params_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message);
</span><span class="cx"> 
</span><ins>+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
</ins><span class="cx"> /** Declare this macro to use log routine of the server, plugin is loaded from */
</span><span class="cx"> MRCP_PLUGIN_LOGGER_IMPLEMENT
</span><span class="cx"> 
</span><span class="cx"> /** Create Swift synthesizer engine */
</span><del>-MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</del><ins>+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        swift_engine *synth_engine;
-        mrcp_resource_engine_t *engine;
-        /* open swift engine */
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open Swift Engine [%s]&quot;,swift_version);
-        if((synth_engine = swift_engine_open(NULL)) ==  NULL) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Open Swift Engine&quot;);
-                return NULL;
-        }
-        swift_speech_language_table = mrcp_swift_language_table_create(pool);
-        mrcp_swift_voices_show(synth_engine);
</del><ins>+        mrcp_swift_engine_t *synth_engine = apr_palloc(pool,sizeof(mrcp_swift_engine_t));
+        synth_engine-&gt;swift = NULL;
+        synth_engine-&gt;language_table = mrcp_swift_language_table_create(pool);
+        synth_engine-&gt;sample_rates = MPF_SAMPLE_RATE_NONE;
</ins><span class="cx"> 
</span><del>-        /* create resource engine base */
-        engine = mrcp_resource_engine_create(
-                                        MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
-                                        synth_engine,              /* object to associate */
-                                        &amp;engine_vtable,            /* virtual methods table of resource engine */
-                                        pool);                     /* pool to allocate memory from */
-        if(!engine) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Engine&quot;);
-                swift_engine_close(synth_engine);
-        }
-        return engine;
</del><ins>+        /* create engine base */
+        return mrcp_engine_create(
+                                MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
+                                synth_engine,              /* object to associate */
+                                &amp;engine_vtable,            /* virtual methods table of engine */
+                                pool);                     /* pool to allocate memory from */
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Destroy synthesizer engine */
</span><del>-static apt_bool_t mrcp_swift_engine_destroy(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t mrcp_swift_engine_destroy(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><del>-        swift_engine *synth_engine = engine-&gt;obj;
-        /* close swift engine */
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close Swift Engine&quot;);
-        if(synth_engine) {
-                swift_engine_close(synth_engine);
-                engine-&gt;obj = NULL;
-        }
</del><ins>+        /* nothing to destroy */
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Open synthesizer engine */
</span><del>-static apt_bool_t mrcp_swift_engine_open(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t mrcp_swift_engine_open(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><ins>+        mrcp_swift_engine_t *synth_engine = engine-&gt;obj;
+        
+        /* open swift engine */
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open Swift Engine [%s]&quot;,swift_version);
+        if((synth_engine-&gt;swift = swift_engine_open(NULL)) ==  NULL) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Open Swift Engine&quot;);
+                return FALSE;
+        }
+
+        if(mrcp_swift_voices_scan(synth_engine) == FALSE) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Scan Swift Voices&quot;);
+                swift_engine_close(synth_engine-&gt;swift);
+                synth_engine-&gt;swift = NULL;
+                return FALSE;
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Close synthesizer engine */
</span><del>-static apt_bool_t mrcp_swift_engine_close(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t mrcp_swift_engine_close(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><ins>+        mrcp_swift_engine_t *synth_engine = engine-&gt;obj;
+
+        /* close swift engine */
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close Swift Engine&quot;);
+        if(synth_engine-&gt;swift) {
+                swift_engine_close(synth_engine-&gt;swift);
+                synth_engine-&gt;swift = NULL;
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create demo synthesizer channel derived from engine channel base */
</span><del>-static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
</del><ins>+static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
</ins><span class="cx"> {
</span><del>-        swift_engine *synth_engine = engine-&gt;obj;
-        mrcp_swift_channel_t *synth_channel;
</del><ins>+        mrcp_swift_engine_t *synth_engine = engine-&gt;obj;
+
+        mpf_stream_capabilities_t *capabilities;
+        mpf_termination_t *termination; 
</ins><span class="cx">         mrcp_engine_channel_t *channel;
</span><del>-        swift_params *params;
-        swift_port *port;
-        mpf_codec_descriptor_t *codec_descriptor;
</del><span class="cx"> 
</span><del>-        codec_descriptor = 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 = 8000;
-
-        params = swift_params_new(NULL);
-        swift_params_set_string(params, &quot;audio/encoding&quot;, &quot;pcm16&quot;);
-        swift_params_set_int(params, &quot;audio/sampling-rate&quot;, codec_descriptor-&gt;sampling_rate);
-        /* open swift port */ 
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open Swift Port&quot;);
-        if((port = swift_port_open(synth_engine,params)) == NULL) {
-                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Open Swift Port&quot;);
-                return NULL;
-        }
-
</del><span class="cx">         /* create swift synth channel */
</span><del>-        synth_channel = apr_palloc(pool,sizeof(mrcp_swift_channel_t));
</del><ins>+        mrcp_swift_channel_t *synth_channel = apr_palloc(pool,sizeof(mrcp_swift_channel_t));
+        synth_channel-&gt;port = NULL;
+        synth_channel-&gt;tts_stream = 0;
+        synth_channel-&gt;channel = NULL;
+        synth_channel-&gt;audio_buffer = NULL;
</ins><span class="cx">         synth_channel-&gt;speak_request = NULL;
</span><span class="cx">         synth_channel-&gt;stop_response = NULL;
</span><span class="cx">         synth_channel-&gt;paused = FALSE;
</span><del>-        synth_channel-&gt;channel = NULL;
-        synth_channel-&gt;port = port;
-        synth_channel-&gt;tts_stream = 0;
</del><ins>+
+        capabilities = mpf_source_stream_capabilities_create(pool);
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        synth_engine-&gt;sample_rates,
+                        &quot;LPCM&quot;);
+
+        /* create media termination */
+        termination = mrcp_engine_audio_termination_create(
+                        synth_channel,        /* object to associate */
+                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
</ins><span class="cx">         /* create engine channel base */
</span><del>-        channel = mrcp_engine_source_channel_create(
-                        engine,               /* resource engine */
</del><ins>+        channel = mrcp_engine_channel_create(
+                        engine,               /* engine */
</ins><span class="cx">                         &amp;channel_vtable,      /* virtual methods table of engine channel */
</span><del>-                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
</del><span class="cx">                         synth_channel,        /* object to associate */
</span><del>-                        codec_descriptor,     /* codec descriptor might be NULL by default */
</del><ins>+                        termination,          /* associated media termination */
</ins><span class="cx">                         pool);                /* pool to allocate memory from */
</span><span class="cx"> 
</span><del>-        if(!channel) {
-                swift_port_close(port);
-                synth_channel-&gt;port = NULL;
-                return NULL;
</del><ins>+        if(channel) {
+                synth_channel-&gt;audio_buffer = mpf_buffer_create(pool);
</ins><span class="cx">         }
</span><del>-
-        synth_channel-&gt;audio_buffer = mpf_buffer_create(pool);
-
-        /* set swift_write_audio as a callback, with the output file as its param */
-        swift_port_set_callback(port, &amp;mrcp_swift_write_audio, SWIFT_EVENT_AUDIO | SWIFT_EVENT_END, synth_channel);
</del><span class="cx">         synth_channel-&gt;channel = channel;
</span><span class="cx">         return channel;
</span><span class="cx"> }
</span><span class="lines">@@ -242,13 +251,7 @@
</span><span class="cx"> /** Destroy engine channel */
</span><span class="cx"> static apt_bool_t mrcp_swift_channel_destroy(mrcp_engine_channel_t *channel)
</span><span class="cx"> {
</span><del>-        mrcp_swift_channel_t *synth_channel = channel-&gt;method_obj;
-        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close Swift Port&quot;);
-        if(synth_channel-&gt;port) {
-                /* close swift port */ 
-                swift_port_close(synth_channel-&gt;port);
-                synth_channel-&gt;port = NULL;
-        }
</del><ins>+        /* nothing to destroy */
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -256,13 +259,46 @@
</span><span class="cx"> static apt_bool_t mrcp_swift_channel_open(mrcp_engine_channel_t *channel)
</span><span class="cx"> {
</span><span class="cx">         /* open channel and send asynch response */
</span><del>-        return mrcp_engine_channel_open_respond(channel,TRUE);
</del><ins>+        apt_bool_t status = FALSE;
+        mrcp_swift_channel_t *synth_channel = channel-&gt;method_obj;
+        mrcp_swift_engine_t *synth_engine = channel-&gt;engine-&gt;obj;
+        const mpf_codec_descriptor_t *descriptor = mrcp_engine_source_stream_codec_get(synth_channel-&gt;channel);
+        if(descriptor) {
+                swift_params *params;
+                swift_port *port;
+
+                params = swift_params_new(NULL);
+                swift_params_set_string(params, &quot;audio/encoding&quot;, &quot;pcm16&quot;);
+                swift_params_set_int(params, &quot;audio/sampling-rate&quot;, descriptor-&gt;sampling_rate);
+                /* open swift port */ 
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Open Swift Port&quot;);
+                port = swift_port_open(synth_engine-&gt;swift,params);
+                if(port) {
+                        /* set swift_write_audio as a callback, with the output file as its param */
+                        swift_port_set_callback(port, &amp;mrcp_swift_write_audio, SWIFT_EVENT_AUDIO | SWIFT_EVENT_END, synth_channel);
+                        synth_channel-&gt;port = port;
+                        status = TRUE;
+                }
+                else {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Open Swift Port&quot;);
+                }
+        }
+
+        return mrcp_engine_channel_open_respond(channel,status);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Close engine channel (asynchronous response MUST be sent)*/
</span><span class="cx"> static apt_bool_t mrcp_swift_channel_close(mrcp_engine_channel_t *channel)
</span><span class="cx"> {
</span><span class="cx">         /* close channel, make sure there is no activity and send asynch response */
</span><ins>+        mrcp_swift_channel_t *synth_channel = channel-&gt;method_obj;
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Close Swift Port&quot;);
+        if(synth_channel-&gt;port) {
+                /* close swift port */ 
+                swift_port_close(synth_channel-&gt;port);
+                synth_channel-&gt;port = NULL;
+        }
+
</ins><span class="cx">         return mrcp_engine_channel_close_respond(channel);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -379,7 +415,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Callback is called from MPF engine context to perform any action before open */
</span><del>-static apt_bool_t synth_stream_open(mpf_audio_stream_t *stream)
</del><ins>+static apt_bool_t synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="lines">@@ -525,8 +561,10 @@
</span><span class="cx">         }
</span><span class="cx">         if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_SPEECH_LANGUAGE) == TRUE) {
</span><span class="cx">                 const char *swift_lang_name = NULL;
</span><del>-                if(swift_speech_language_table) {
-                        swift_lang_name = apr_table_get(swift_speech_language_table,synth_header-&gt;speech_language.buf);
</del><ins>+                mrcp_engine_t *engine = synth_channel-&gt;channel-&gt;engine;
+                mrcp_swift_engine_t *synth_engine = engine-&gt;obj;
+                if(synth_engine &amp;&amp; synth_engine-&gt;language_table) {
+                        swift_lang_name = apr_table_get(synth_engine-&gt;language_table,synth_header-&gt;speech_language.buf);
</ins><span class="cx">                 }
</span><span class="cx">                 if(!swift_lang_name) {
</span><span class="cx">                         swift_lang_name = synth_header-&gt;speech_language.buf;
</span><span class="lines">@@ -536,21 +574,29 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if(offset &gt; 0) {
</span><del>-                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Find Voices Matching the Criteria [%s]&quot;,search_criteria);
-                if((voice = swift_port_find_first_voice(synth_channel-&gt;port,search_criteria,NULL)) == NULL) {
</del><ins>+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Find Swift Voice Matching the Criteria [%s]&quot;, search_criteria);
+                voice = swift_port_find_first_voice(synth_channel-&gt;port,search_criteria,NULL);
+                if(!voice) {
</ins><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;No Swift Voice Available Matching the Criteria [%s]&quot;,search_criteria);
</span><ins>+                        /* find the first available one */
</ins><span class="cx">                         voice = swift_port_find_first_voice(synth_channel-&gt;port,NULL,NULL);
</span><span class="cx">                 }
</span><del>-                if(SWIFT_FAILED(res = swift_port_set_voice(synth_channel-&gt;port,voice)) ) {
-                        const char *error_string = swift_strerror(res);
-                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,error_string);
-                        return FALSE;
-                } 
</del><ins>+
+                if(voice) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Set Swift Voice [%s]&quot;,
+                                swift_voice_get_attribute(voice, &quot;name&quot;));
+                        if(SWIFT_FAILED(res = swift_port_set_voice(synth_channel-&gt;port,voice)) ) {
+                                const char *error_string = swift_strerror(res);
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,error_string);
+                                return FALSE;
+                        }
+                }
</ins><span class="cx">         }
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-apt_bool_t swift_prosody_volume_get(const mrcp_prosody_volume_t *prosody_volume, int *volume)
</del><ins>+/** Get volume by prosody params */
+static apt_bool_t swift_prosody_volume_get(const mrcp_prosody_volume_t *prosody_volume, int *volume)
</ins><span class="cx"> {
</span><span class="cx">         apt_bool_t res = FALSE;
</span><span class="cx">         if(prosody_volume-&gt;type == PROSODY_VOLUME_TYPE_LABEL) {
</span><span class="lines">@@ -571,7 +617,8 @@
</span><span class="cx">         return res;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-apt_bool_t swift_prosody_rate_get(const mrcp_prosody_rate_t *prosody_rate, int *rate)
</del><ins>+/** Get rate by prosody params */
+static apt_bool_t swift_prosody_rate_get(const mrcp_prosody_rate_t *prosody_rate, int *rate)
</ins><span class="cx"> {
</span><span class="cx">         apt_bool_t res = FALSE;
</span><span class="cx">         if(prosody_rate-&gt;type == PROSODY_RATE_TYPE_LABEL) {
</span><span class="lines">@@ -643,24 +690,45 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Show Swift available voices */
-static void mrcp_swift_voices_show(swift_engine *engine) 
</del><ins>+static void mrcp_swift_sample_rates_set(mrcp_swift_engine_t *engine, const char *str)
</ins><span class="cx"> {
</span><ins>+        if(str) {
+                int value = atoi(str);
+                if(value == 8000) {
+                        engine-&gt;sample_rates |= MPF_SAMPLE_RATE_8000;
+                }
+                else if(value == 16000) {
+                        engine-&gt;sample_rates |= MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000;
+                }
+        }
+}
+
+/** Scan Swift available voices */
+static apt_bool_t mrcp_swift_voices_scan(mrcp_swift_engine_t *engine)
+{
</ins><span class="cx">         swift_port *port;
</span><span class="cx">         swift_voice *voice;
</span><span class="cx">         const char *license_status;
</span><ins>+        const char *sample_rate;
</ins><span class="cx"> 
</span><ins>+        if(!engine-&gt;swift) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Invalid Swift Engine&quot;);
+                return FALSE;
+        }
+
</ins><span class="cx">         /* open swift port*/
</span><del>-        if((port = swift_port_open(engine, NULL)) == NULL) {
</del><ins>+        if((port = swift_port_open(engine-&gt;swift, NULL)) == NULL) {
</ins><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Open Swift Port&quot;);
</span><del>-                return;    
</del><ins>+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        engine-&gt;sample_rates = MPF_SAMPLE_RATE_NONE;
+
</ins><span class="cx">         /* find the first voice on the system */
</span><span class="cx">         if((voice = swift_port_find_first_voice(port, NULL, NULL)) == NULL) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;No Swift Voice Available&quot;);
</span><span class="cx">                 swift_port_close(port);
</span><del>-                return;
</del><ins>+                return FALSE;
</ins><span class="cx">         }
</span><span class="cx">         /* go through all of the voices on the system and print some info about each */
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Swift Available Voices:&quot;);
</span><span class="lines">@@ -671,16 +739,21 @@
</span><span class="cx">                 else {
</span><span class="cx">                         license_status = &quot;unlicensed&quot;;
</span><span class="cx">                 }
</span><del>-                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;%s: %s, age %s, %s, %sHz, %s&quot;,
</del><ins>+                sample_rate = swift_voice_get_attribute(voice, &quot;sample-rate&quot;);
+                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;%s: %s, age %s, %s, %sHz, %s, %s&quot;,
</ins><span class="cx">                         swift_voice_get_attribute(voice, &quot;name&quot;),
</span><span class="cx">                         swift_voice_get_attribute(voice, &quot;speaker/gender&quot;),
</span><span class="cx">                         swift_voice_get_attribute(voice, &quot;speaker/age&quot;),
</span><span class="cx">                         swift_voice_get_attribute(voice, &quot;language/name&quot;),
</span><del>-                        swift_voice_get_attribute(voice, &quot;sample-rate&quot;),
</del><ins>+                        sample_rate,
+                        swift_voice_get_attribute(voice, &quot;version&quot;),
</ins><span class="cx">                         license_status);
</span><ins>+
+                mrcp_swift_sample_rates_set(engine,sample_rate);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         swift_port_close(port);
</span><ins>+        return TRUE;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create speech language lookup table */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpfliteincludeflite_voicesh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -29,11 +29,15 @@
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+/** Opaque Flite voice declaration */
</ins><span class="cx"> typedef struct flite_voices_t flite_voices_t;
</span><span class="cx"> 
</span><ins>+/** Load Flite voices */
</ins><span class="cx"> flite_voices_t* flite_voices_load(apr_pool_t *pool);
</span><ins>+/** Unload Flite voices */
</ins><span class="cx"> void flite_voices_unload(flite_voices_t *voices);
</span><span class="cx"> 
</span><ins>+/** Get best matched voice */
</ins><span class="cx"> cst_voice* flite_voices_best_match_get(flite_voices_t *voices, mrcp_message_t *message);
</span><span class="cx"> 
</span><span class="cx"> APT_END_EXTERN_C
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcpflitesrcmrcp_flitec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,21 +15,20 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /* 
</span><del>- * Some mandatory rules for plugin implementation.
- * 1. Each plugin MUST contain the following function as an entry point of the plugin
- *        MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
- * 2. One and only one response MUST be sent back to the received request.
- * 3. Methods (callbacks) of the MRCP engine channel MUST not block.
- *   (asynch response can be sent from the context of other thread)
- * 4. Methods (callbacks) of the MPF engine stream MUST not block.
</del><ins>+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ *    with the exact signature and name (the main entry point)
+ *        MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ *        MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ *   (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &quot;flite_voices.h&quot;
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
-#include &quot;mrcp_synth_resource.h&quot;
-#include &quot;mrcp_synth_header.h&quot;
-#include &quot;mrcp_generic_header.h&quot;
-#include &quot;mrcp_message.h&quot;
</del><ins>+#include &quot;mrcp_synth_engine.h&quot;
</ins><span class="cx"> #include &quot;mpf_buffer.h&quot;
</span><span class="cx"> #include &quot;apr_time.h&quot;
</span><span class="cx"> #include &quot;apt_consumer_task.h&quot;
</span><span class="lines">@@ -39,10 +38,10 @@
</span><span class="cx"> typedef struct flite_synth_channel_t flite_synth_channel_t;
</span><span class="cx"> 
</span><span class="cx"> /** Declaration of synthesizer engine methods */
</span><del>-static apt_bool_t flite_synth_engine_destroy(mrcp_resource_engine_t *engine);
-static apt_bool_t flite_synth_engine_open(mrcp_resource_engine_t *engine);
-static apt_bool_t flite_synth_engine_close(mrcp_resource_engine_t *engine);
-static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool);
</del><ins>+static apt_bool_t flite_synth_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t flite_synth_engine_open(mrcp_engine_t *engine);
+static apt_bool_t flite_synth_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> static const struct mrcp_engine_method_vtable_t engine_vtable = {
</span><span class="cx">         flite_synth_engine_destroy,
</span><span class="lines">@@ -119,36 +118,39 @@
</span><span class="cx"> /* we have a special task for the actual synthesis - 
</span><span class="cx">    the task is created when a mrcp speak message is received */
</span><span class="cx"> static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg);
</span><del>-static apt_bool_t flite_on_start(apt_task_t *task);
-static apt_bool_t flite_on_terminate(apt_task_t *task);
</del><ins>+static void flite_on_start(apt_task_t *task);
+static void flite_on_terminate(apt_task_t *task);
</ins><span class="cx"> 
</span><ins>+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
</ins><span class="cx"> /** Declare this macro to use log routine of the server where the plugin is loaded from */
</span><span class="cx"> MRCP_PLUGIN_LOGGER_IMPLEMENT
</span><span class="cx"> 
</span><span class="cx"> /** Create flite synthesizer engine */
</span><del>-MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</del><ins>+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</ins><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><span class="cx">         flite_engine-&gt;iChannels = 0;
</span><span class="cx"> 
</span><del>-        /* create resource engine base */
-        return mrcp_resource_engine_create(
-                                        MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
-                                        flite_engine,              /* object to associate */
-                                        &amp;engine_vtable,            /* virtual methods table of resource engine */
-                                        pool);                     /* pool to allocate memory from */
</del><ins>+        /* create engine base */
+        return mrcp_engine_create(
+                                MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
+                                flite_engine,              /* object to associate */
+                                &amp;engine_vtable,            /* virtual methods table of engine */
+                                pool);                     /* pool to allocate memory from */
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Destroy synthesizer engine */
</span><del>-static apt_bool_t flite_synth_engine_destroy(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t flite_synth_engine_destroy(mrcp_engine_t *engine)
</ins><span class="cx"> {
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_engine_destroy&quot;);
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Open synthesizer engine */
</span><del>-static apt_bool_t flite_synth_engine_open(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t flite_synth_engine_open(mrcp_engine_t *engine)
</ins><span class="cx"> {
</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_open&quot;);
</span><span class="lines">@@ -162,7 +164,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Close synthesizer engine */
</span><del>-static apt_bool_t flite_synth_engine_close(mrcp_resource_engine_t *engine)
</del><ins>+static apt_bool_t flite_synth_engine_close(mrcp_engine_t *engine)
</ins><span class="cx"> {
</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="lines">@@ -200,10 +202,12 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create flite synthesizer channel derived from engine channel base */
</span><del>-static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
</del><ins>+static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
</ins><span class="cx"> {
</span><ins>+        mpf_stream_capabilities_t *capabilities;
+        mpf_termination_t *termination; 
+
</ins><span class="cx">         /* create flite synth channel */
</span><del>-        mpf_codec_descriptor_t *codec_descriptor = NULL;
</del><span class="cx">         flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) apr_palloc(pool,sizeof(flite_synth_channel_t));
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;flite_synth_engine_channel_create&quot;);
</span><span class="lines">@@ -223,30 +227,33 @@
</span><span class="cx">                 return NULL;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-#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
-
-        /* create engine channel base */
-        synth_channel-&gt;channel = mrcp_engine_source_channel_create(
-                        engine,               /* resource engine */
-                        &amp;channel_vtable,      /* virtual methods table of engine channel */
</del><ins>+        capabilities = mpf_source_stream_capabilities_create(pool);
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);

+        /* create media termination */
+        termination = mrcp_engine_audio_termination_create(
+                        synth_channel,        /* object to associate */
</ins><span class="cx">                         &amp;audio_stream_vtable, /* virtual methods table of audio stream */
</span><del>-                        synth_channel,        /* object to associate */
-                        codec_descriptor,     /* codec descriptor might be NULL by default */
</del><ins>+                        capabilities,         /* stream capabilities */
</ins><span class="cx">                         pool);                /* pool to allocate memory from */
</span><del>-        
-        if(!synth_channel-&gt;channel) {
-                apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;flite_synth_engine_channel_create failed&quot;);
-                apt_task_destroy(synth_channel-&gt;task);
-                return NULL;                
-        }
</del><span class="cx"> 
</span><ins>+        /* create engine channel base */
+        synth_channel-&gt;channel = mrcp_engine_channel_create(
+                         engine,               /* engine */
+                         &amp;channel_vtable,      /* virtual methods table of engine channel */
+                         synth_channel,        /* object to associate */
+                        termination,          /* associated media termination */
+                         pool);                /* pool to allocate memory from */
+         
+         if(!synth_channel-&gt;channel) {
+                 apt_log(APT_LOG_MARK, APT_PRIO_WARNING, &quot;flite_synth_engine_channel_create failed&quot;);
+                 apt_task_destroy(synth_channel-&gt;task);
+                 return NULL;                
+         } 
+
</ins><span class="cx">         synth_channel-&gt;audio_buffer = mpf_buffer_create(pool);
</span><span class="cx">         synth_channel-&gt;iId = ++synth_channel-&gt;flite_engine-&gt;iChannels;
</span><span class="cx"> 
</span><span class="lines">@@ -423,8 +430,11 @@
</span><span class="cx">         apt_str_t *body;
</span><span class="cx">         mrcp_message_t *response;
</span><span class="cx"> 
</span><del>-        mpf_codec_t * codec = mrcp_engine_source_stream_codec_get(synth_channel-&gt;channel);
-        apr_uint16_t rate = codec-&gt;descriptor-&gt;sampling_rate;
</del><ins>+        apr_uint16_t rate = 8000;
+        const mpf_codec_descriptor_t * descriptor = mrcp_engine_source_stream_codec_get(synth_channel-&gt;channel);
+        if(descriptor) {
+                rate = descriptor-&gt;sampling_rate;
+        }
</ins><span class="cx">         body = &amp;synth_channel-&gt;speak_request-&gt;body;
</span><span class="cx"> 
</span><span class="cx">         response = synth_channel-&gt;speak_response;
</span><span class="lines">@@ -498,18 +508,18 @@
</span><span class="cx">         return apt_consumer_task_object_get(consumer_task);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t flite_on_start(apt_task_t *task)
</del><ins>+static void flite_on_start(apt_task_t *task)
</ins><span class="cx"> {
</span><span class="cx">         flite_synth_channel_t *synth_channel = flite_synth_channel_get(task);
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Speak task started - channel %d&quot;, synth_channel-&gt;iId);
</span><del>-        return mrcp_engine_channel_open_respond(synth_channel-&gt;channel,TRUE);
</del><ins>+        mrcp_engine_channel_open_respond(synth_channel-&gt;channel,TRUE);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static apt_bool_t flite_on_terminate(apt_task_t *task)
</del><ins>+static void flite_on_terminate(apt_task_t *task)
</ins><span class="cx"> {
</span><span class="cx">         flite_synth_channel_t *synth_channel = flite_synth_channel_get(task);
</span><span class="cx">         apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, &quot;Speak task terminated - channel %d&quot;, synth_channel-&gt;iId);
</span><del>-        return mrcp_engine_channel_close_respond(synth_channel-&gt;channel);
</del><ins>+        mrcp_engine_channel_close_respond(synth_channel-&gt;channel);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Process STOP request */
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcppocketsphinxMakefileam"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/Makefile.am (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/Makefile.am        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -21,9 +21,16 @@
</span><span class="cx"> mrcppocketsphinx_la_LIBADD  = $(UNIMRCP_POCKETSPHINX_LIBS) $(UNIMRCP_SPHINXBASE_LIBS) -lm
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+dictionary:
+        !(test -f $(UNIMRCP_POCKETSPHINX_MODELS)/lm/cmudict.0.6d) || \
+                $(INSTALL) -m 644 $(UNIMRCP_POCKETSPHINX_MODELS)/lm/cmudict.0.6d $(datadir)/default.dic
+
+model:
+        !(test -d $(UNIMRCP_POCKETSPHINX_MODELS)/hmm/wsj1/) || ($(mkinstalldirs) $(datadir)/wsj1; \
+                $(INSTALL) -m 644 $(UNIMRCP_POCKETSPHINX_MODELS)/hmm/wsj1/* $(datadir)/wsj1)
+
</ins><span class="cx"> install-data-local:
</span><span class="cx">         test -d $(confdir) || $(mkinstalldirs) $(confdir)
</span><span class="cx">         test -f $(confdir)/pocketsphinx.xml || $(INSTALL) -m 644 conf/pocketsphinx.xml $(confdir)
</span><del>-        test -d $(datadir)/wsj1 || $(mkinstalldirs) $(datadir)/wsj1; \
-                        $(INSTALL) -m 644 $(UNIMRCP_POCKETSPHINX_MODELS)/hmm/wsj1/* $(datadir)/wsj1; \
-                        $(INSTALL) -m 644 $(UNIMRCP_POCKETSPHINX_MODELS)/lm/cmudict.0.6d $(datadir)/default.dic
</del><ins>+        test -f $(datadir)/default.dic || $(MAKE) dictionary
+        test -d $(datadir)/wsj1 || $(MAKE) model
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcppocketsphinxincludepocketsphinx_propertiesh"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/include/pocketsphinx_properties.h (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/include/pocketsphinx_properties.h        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/include/pocketsphinx_properties.h        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -26,34 +26,47 @@
</span><span class="cx"> 
</span><span class="cx"> APT_BEGIN_EXTERN_C
</span><span class="cx"> 
</span><ins>+/** Enumeration of PocketSphinx models */
</ins><span class="cx"> typedef enum {
</span><del>-        POCKETSPHINX_MODEL_NARROWBAND,
-        POCKETSPHINX_MODEL_WIDEBAND
-
</del><ins>+        POCKETSPHINX_MODEL_NARROWBAND, /**&lt; narrowband model */
+        POCKETSPHINX_MODEL_WIDEBAND    /**&lt; wideband model */
</ins><span class="cx"> } pocketsphinx_model_e;
</span><span class="cx"> 
</span><del>-/** Declaration of pocketsphinx properties */
</del><ins>+/** Declaration of PocketSphinx properties */
</ins><span class="cx"> typedef struct pocketsphinx_properties_t pocketsphinx_properties_t;
</span><span class="cx"> 
</span><del>-/** Pocketsphinx properties */
</del><ins>+/** PocketSphinx properties */
</ins><span class="cx"> struct pocketsphinx_properties_t {
</span><ins>+        /** Data directory */
</ins><span class="cx">         const char          *data_dir;
</span><ins>+        /** Path to dictionary file */
</ins><span class="cx">         const char          *dictionary;
</span><ins>+        /** Path to narrowband model */
</ins><span class="cx">         const char          *model_8k;
</span><ins>+        /** Path to wideband model */
</ins><span class="cx">         const char          *model_16k;
</span><ins>+        /** Preferred (default) model */
</ins><span class="cx">         pocketsphinx_model_e preferred_model;
</span><span class="cx"> 
</span><ins>+        /** Sensitivity level */
</ins><span class="cx">         apr_size_t           sensitivity_level;
</span><ins>+        /** Sensitivity timeout */
</ins><span class="cx">         apr_size_t           sensitivity_timeout;
</span><span class="cx"> 
</span><ins>+        /** Noinput timeout */
</ins><span class="cx">         apr_size_t           no_input_timeout;
</span><ins>+        /** Recognition timeout */
</ins><span class="cx">         apr_size_t           recognition_timeout;
</span><ins>+        /** Partial result checking timeout */
</ins><span class="cx">         apr_size_t           partial_result_timeout;
</span><span class="cx"> 
</span><ins>+        /** Whether to save waveform or not */
</ins><span class="cx">         apt_bool_t           save_waveform;
</span><ins>+        /** Directory to save waveform in */
</ins><span class="cx">         const char          *save_waveform_dir;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+/** Load PocketSphinx properties */
</ins><span class="cx"> apt_bool_t pocketsphinx_properties_load(pocketsphinx_properties_t *properties, 
</span><span class="cx">                                                                                 const char *file_path, 
</span><span class="cx">                                                                                 const apt_dir_layout_t *dir_layout,
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcppocketsphinxsrcmrcp_pocketsphinxc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,13 +15,16 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> /* 
</span><del>- * Some mandatory rules for plugin implementation.
- * 1. Each plugin MUST contain the following function as an entry point of the plugin
- *        MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
- * 2. One and only one response MUST be sent back to the received request.
- * 3. Methods (callbacks) of the MRCP engine channel MUST not block.
- *   (asynch response can be sent from the context of other thread)
- * 4. Methods (callbacks) of the MPF engine stream MUST not block.
</del><ins>+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ *    with the exact signature and name (the main entry point)
+ *        MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ *        MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ *   (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
</ins><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &lt;pocketsphinx.h&gt;
</span><span class="lines">@@ -29,11 +32,7 @@
</span><span class="cx"> #include &lt;apr_thread_proc.h&gt;
</span><span class="cx"> #include &lt;apr_tables.h&gt;
</span><span class="cx"> #include &lt;apr_file_io.h&gt;
</span><del>-#include &quot;mrcp_resource_engine.h&quot;
-#include &quot;mrcp_recog_resource.h&quot;
-#include &quot;mrcp_recog_header.h&quot;
-#include &quot;mrcp_generic_header.h&quot;
-#include &quot;mrcp_message.h&quot;
</del><ins>+#include &quot;mrcp_recog_engine.h&quot;
</ins><span class="cx"> #include &quot;mpf_activity_detector.h&quot;
</span><span class="cx"> #include &quot;pocketsphinx_properties.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="lines">@@ -46,10 +45,10 @@
</span><span class="cx"> typedef struct pocketsphinx_recognizer_t pocketsphinx_recognizer_t;
</span><span class="cx"> 
</span><span class="cx"> /** Methods of recognition engine */
</span><del>-static apt_bool_t pocketsphinx_engine_destroy(mrcp_resource_engine_t *engine);
-static apt_bool_t pocketsphinx_engine_open(mrcp_resource_engine_t *engine);
-static apt_bool_t pocketsphinx_engine_close(mrcp_resource_engine_t *engine);
-static mrcp_engine_channel_t* pocketsphinx_engine_recognizer_create(mrcp_resource_engine_t *engine, apr_pool_t *pool);
</del><ins>+static apt_bool_t pocketsphinx_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t pocketsphinx_engine_open(mrcp_engine_t *engine);
+static apt_bool_t pocketsphinx_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* pocketsphinx_engine_recognizer_create(mrcp_engine_t *engine, apr_pool_t *pool);
</ins><span class="cx"> 
</span><span class="cx"> static const struct mrcp_engine_method_vtable_t engine_vtable = {
</span><span class="cx">         pocketsphinx_engine_destroy,
</span><span class="lines">@@ -87,8 +86,8 @@
</span><span class="cx"> 
</span><span class="cx"> /** Pocketsphinx engine (engine is an aggregation of recognizers) */
</span><span class="cx"> struct pocketsphinx_engine_t {
</span><del>-        /* Resource engine base */
-        mrcp_resource_engine_t   *base;
</del><ins>+        /* Engine base */
+        mrcp_engine_t   *base;
</ins><span class="cx">         /** Properties loaded from config file */
</span><span class="cx">         pocketsphinx_properties_t properties;
</span><span class="cx"> };
</span><span class="lines">@@ -102,7 +101,7 @@
</span><span class="cx">         ps_decoder_t             *decoder;
</span><span class="cx">         /** Configuration */
</span><span class="cx">         cmd_ln_t                 *config;
</span><del>-        /** Recognizer properties coppied from defualt engine properties */
</del><ins>+        /** Recognizer properties coppied from default engine properties */
</ins><span class="cx">         pocketsphinx_properties_t properties;
</span><span class="cx">         /** Is input timer started */
</span><span class="cx">         apt_bool_t                is_input_timer_on;
</span><span class="lines">@@ -141,60 +140,68 @@
</span><span class="cx">         mrcp_message_t           *stop_response;
</span><span class="cx">         /** Is recognition channel being closed */
</span><span class="cx">         apt_bool_t                close_requested;
</span><ins>+        /** Flag to prevent race condition when checking if a message is present */
+        apt_bool_t                message_waiting;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+static void* APR_THREAD_FUNC pocketsphinx_recognizer_run(apr_thread_t *thread, void *data);
+
+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
</ins><span class="cx"> /** Declare this macro to use log routine of the server, plugin is loaded from */
</span><span class="cx"> MRCP_PLUGIN_LOGGER_IMPLEMENT
</span><span class="cx"> 
</span><del>-static void* APR_THREAD_FUNC pocketsphinx_recognizer_run(apr_thread_t *thread, void *data);
-
</del><span class="cx"> /** Create pocketsphinx engine (engine is an aggregation of recognizers) */
</span><del>-MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</del><ins>+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
</ins><span class="cx"> {
</span><span class="cx">         pocketsphinx_engine_t *engine = apr_palloc(pool,sizeof(pocketsphinx_engine_t));
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create PocketSphinx Engine&quot;);
</span><span class="cx">         
</span><del>-        /* create resource engine base */
-        engine-&gt;base = mrcp_resource_engine_create(
</del><ins>+        /* create engine base */
+        engine-&gt;base = mrcp_engine_create(
</ins><span class="cx">                                         MRCP_RECOGNIZER_RESOURCE,  /* MRCP resource identifier */
</span><span class="cx">                                         engine,                    /* object to associate */
</span><del>-                                        &amp;engine_vtable,            /* virtual methods table of resource engine */
</del><ins>+                                        &amp;engine_vtable,            /* virtual methods table of engine */
</ins><span class="cx">                                         pool);                     /* pool to allocate memory from */
</span><span class="cx">         return engine-&gt;base;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Destroy pocketsphinx engine */
</span><del>-static apt_bool_t pocketsphinx_engine_destroy(mrcp_resource_engine_t *resource_engine)
</del><ins>+static apt_bool_t pocketsphinx_engine_destroy(mrcp_engine_t *engine_base)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Open pocketsphinx engine */
</span><del>-static apt_bool_t pocketsphinx_engine_open(mrcp_resource_engine_t *resource_engine)
</del><ins>+static apt_bool_t pocketsphinx_engine_open(mrcp_engine_t *engine_base)
</ins><span class="cx"> {
</span><del>-        pocketsphinx_engine_t *engine = resource_engine-&gt;obj;
-        const apt_dir_layout_t *dir_layout = resource_engine-&gt;dir_layout;
</del><ins>+        pocketsphinx_engine_t *engine = engine_base-&gt;obj;
+        const apt_dir_layout_t *dir_layout = engine_base-&gt;dir_layout;
</ins><span class="cx"> 
</span><span class="cx">         char *file_path = NULL;
</span><del>-        apr_filepath_merge(&amp;file_path,dir_layout-&gt;conf_dir_path,POCKETSPHINX_CONFFILE_NAME,0,resource_engine-&gt;pool);
</del><ins>+        apr_filepath_merge(&amp;file_path,dir_layout-&gt;conf_dir_path,POCKETSPHINX_CONFFILE_NAME,0,engine_base-&gt;pool);
</ins><span class="cx"> 
</span><span class="cx">         /* load properties */
</span><del>-        pocketsphinx_properties_load(&amp;engine-&gt;properties,file_path,dir_layout,resource_engine-&gt;pool);
</del><ins>+        pocketsphinx_properties_load(&amp;engine-&gt;properties,file_path,dir_layout,engine_base-&gt;pool);
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Close pocketsphinx engine */
</span><del>-static apt_bool_t pocketsphinx_engine_close(mrcp_resource_engine_t *resource_engine)
</del><ins>+static apt_bool_t pocketsphinx_engine_close(mrcp_engine_t *engine_base)
</ins><span class="cx"> {
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create pocketsphinx recognizer */
</span><del>-static mrcp_engine_channel_t* pocketsphinx_engine_recognizer_create(mrcp_resource_engine_t *resource_engine, apr_pool_t *pool)
</del><ins>+static mrcp_engine_channel_t* pocketsphinx_engine_recognizer_create(mrcp_engine_t *engine_base, apr_pool_t *pool)
</ins><span class="cx"> {
</span><ins>+        mpf_stream_capabilities_t *capabilities;
+        mpf_termination_t *termination; 
</ins><span class="cx">         mrcp_engine_channel_t *channel;
</span><del>-        mpf_codec_descriptor_t *codec_descriptor;
-        pocketsphinx_engine_t *engine = resource_engine-&gt;obj;
</del><ins>+        pocketsphinx_engine_t *engine = engine_base-&gt;obj;
+
+        /* create pocketsphinx recognizer */
</ins><span class="cx">         pocketsphinx_recognizer_t *recognizer = apr_palloc(pool,sizeof(pocketsphinx_recognizer_t));
</span><span class="cx">         recognizer-&gt;decoder = NULL;
</span><span class="cx">         recognizer-&gt;config = NULL;
</span><span class="lines">@@ -215,27 +222,30 @@
</span><span class="cx">         recognizer-&gt;grammar_id = NULL;
</span><span class="cx">         recognizer-&gt;grammar_table = apr_table_make(pool,1);
</span><span class="cx">         recognizer-&gt;waveform = NULL;
</span><ins>+        recognizer-&gt;message_waiting = FALSE;
</ins><span class="cx"> 
</span><span class="cx">         /* copy default properties loaded from config */
</span><span class="cx">         recognizer-&gt;properties = engine-&gt;properties;
</span><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 = 8000;
-        if(recognizer-&gt;properties.preferred_model == POCKETSPHINX_MODEL_WIDEBAND) {
-                codec_descriptor-&gt;sampling_rate = 16000;
-        }
</del><ins>+        capabilities = mpf_sink_stream_capabilities_create(pool);
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);
</ins><span class="cx"> 
</span><ins>+        /* create media termination */
+        termination = mrcp_engine_audio_termination_create(
+                        recognizer,           /* object to associate */
+                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
</ins><span class="cx">         /* create engine channel base */
</span><del>-        channel = mrcp_engine_sink_channel_create(
-                        resource_engine,      /* resource engine */
</del><ins>+        channel = mrcp_engine_channel_create(
+                        engine_base,          /* engine */
</ins><span class="cx">                         &amp;channel_vtable,      /* virtual methods table of engine channel */
</span><del>-                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
</del><span class="cx">                         recognizer,           /* object to associate */
</span><del>-                        NULL,                 /* codec descriptor might be NULL by default */
</del><ins>+                        termination,          /* associated media termination */
</ins><span class="cx">                         pool);                /* pool to allocate memory from */
</span><span class="cx"> 
</span><span class="cx">         apr_thread_mutex_create(&amp;recognizer-&gt;mutex,APR_THREAD_MUTEX_DEFAULT,channel-&gt;pool);
</span><span class="lines">@@ -290,6 +300,7 @@
</span><span class="cx">         /* Signal recognition thread to terminate */
</span><span class="cx">         apr_thread_mutex_lock(recognizer-&gt;mutex);
</span><span class="cx">         recognizer-&gt;close_requested = TRUE;
</span><ins>+        recognizer-&gt;message_waiting = TRUE;
</ins><span class="cx">         apr_thread_cond_signal(recognizer-&gt;wait_object);
</span><span class="cx">         apr_thread_mutex_unlock(recognizer-&gt;mutex);
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -303,6 +314,7 @@
</span><span class="cx">         /* Store request and signal recognition thread to process the request */
</span><span class="cx">         apr_thread_mutex_lock(recognizer-&gt;mutex);
</span><span class="cx">         recognizer-&gt;request = request;
</span><ins>+        recognizer-&gt;message_waiting = TRUE;
</ins><span class="cx">         apr_thread_cond_signal(recognizer-&gt;wait_object);
</span><span class="cx">         apr_thread_mutex_unlock(recognizer-&gt;mutex);
</span><span class="cx">         return TRUE;
</span><span class="lines">@@ -311,9 +323,10 @@
</span><span class="cx"> /** Initialize pocketsphinx decoder [RECOG] */
</span><span class="cx"> static apt_bool_t pocketsphinx_decoder_init(pocketsphinx_recognizer_t *recognizer, const char *grammar)
</span><span class="cx"> {
</span><ins>+        const mpf_codec_descriptor_t *descriptor = mrcp_engine_sink_stream_codec_get(recognizer-&gt;channel);
</ins><span class="cx">         const char *model = recognizer-&gt;properties.model_8k;
</span><span class="cx">         const char *rate = &quot;8000&quot;;
</span><del>-        if(recognizer-&gt;properties.preferred_model == POCKETSPHINX_MODEL_WIDEBAND) {
</del><ins>+        if(descriptor &amp;&amp; descriptor-&gt;sampling_rate == 16000) {
</ins><span class="cx">                 model = recognizer-&gt;properties.model_16k;
</span><span class="cx">                 rate = &quot;16000&quot;;
</span><span class="cx">         }
</span><span class="lines">@@ -375,7 +388,6 @@
</span><span class="cx">                 recognizer-&gt;grammar_id,
</span><span class="cx">                 recognizer-&gt;grammar_id,
</span><span class="cx">                 99,
</span><del>-                recognizer-&gt;last_result,
</del><span class="cx">                 recognizer-&gt;last_result);
</span><span class="cx">         if(body-&gt;buf) {
</span><span class="cx">                 mrcp_generic_header_t *generic_header;
</span><span class="lines">@@ -409,16 +421,75 @@
</span><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+/** Load pocketsphinx grammar [RECOG] */
+static mrcp_status_code_e pocketsphinx_grammar_load(pocketsphinx_recognizer_t *recognizer, const char *content_id, const char *content_type, const apt_str_t *content)
+{
+        /* load grammar */
+        mrcp_engine_channel_t *channel = recognizer-&gt;channel;
+        const apt_dir_layout_t *dir_layout = channel-&gt;engine-&gt;dir_layout;
+        const char *grammar_file_path = NULL;
+        const char *grammar_file_name = NULL;
+        apr_file_t *fd = NULL;
+        apr_status_t rv;
+        apr_size_t size;
+
+        /* only JSGF grammar is supported */
+        if(strstr(content_type,&quot;jsgf&quot;) == NULL) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Not Supported Content-Type [%s] &quot;APT_SIDRES_FMT,
+                        content_type,RECOGNIZER_SIDRES(recognizer));
+                return MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE;
+        }
+
+        grammar_file_name = apr_psprintf(channel-&gt;pool,&quot;%s-%s.gram&quot;,channel-&gt;id.buf,content_id);
+        grammar_file_path = apt_datadir_filepath_get(dir_layout,grammar_file_name,channel-&gt;pool);
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create Grammar File [%s] &quot;APT_SIDRES_FMT,
+                grammar_file_path,RECOGNIZER_SIDRES(recognizer));
+        rv = apr_file_open(&amp;fd,grammar_file_path,APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY,
+                APR_OS_DEFAULT,channel-&gt;pool);
+        if(rv != APR_SUCCESS) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot Open Grammar File to Write [%s] &quot;APT_SIDRES_FMT,
+                        grammar_file_path,RECOGNIZER_SIDRES(recognizer));
+                return MRCP_STATUS_CODE_METHOD_FAILED;
+        }
+
+        size = content-&gt;length;
+        apr_file_write(fd,content-&gt;buf,&amp;size);
+        apr_file_close(fd);
+
+        /* init pocketsphinx decoder */
+        if(pocketsphinx_decoder_init(recognizer,grammar_file_path) != TRUE) {
+                apr_file_remove(grammar_file_path,channel-&gt;pool);
+                return MRCP_STATUS_CODE_METHOD_FAILED;
+        }
+        recognizer-&gt;grammar_id = content_id;
+        apr_table_setn(recognizer-&gt;grammar_table,content_id,grammar_file_path);
+        return MRCP_STATUS_CODE_SUCCESS;
+}
+
+/** Unload pocketsphinx grammar [RECOG] */
+static mrcp_status_code_e pocketsphinx_grammar_unload(pocketsphinx_recognizer_t *recognizer, const char *content_id)
+{
+        /* unload grammar */
+        const char *grammar_file_path = apr_table_get(recognizer-&gt;grammar_table,content_id);
+        if(!grammar_file_path) {
+                return MRCP_STATUS_CODE_ILLEGAL_PARAM_VALUE;
+        }
+
+        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove Grammar File [%s] &quot;APT_SIDRES_FMT,
+                grammar_file_path,RECOGNIZER_SIDRES(recognizer));
+        apr_file_remove(grammar_file_path,recognizer-&gt;channel-&gt;pool);
+        apr_table_unset(recognizer-&gt;grammar_table,content_id);
+        return MRCP_STATUS_CODE_SUCCESS;
+}
+
</ins><span class="cx"> /** Process DEFINE-GRAMMAR request [RECOG] */
</span><span class="cx"> static apt_bool_t pocketsphinx_define_grammar(pocketsphinx_recognizer_t *recognizer, mrcp_message_t *request, mrcp_message_t *response)
</span><span class="cx"> {
</span><span class="cx">         const char *content_type = NULL;
</span><span class="cx">         const char *content_id = NULL;
</span><del>-        apt_str_t *grammar = NULL;
-
</del><span class="cx">         mrcp_engine_channel_t *channel = recognizer-&gt;channel;
</span><span class="cx"> 
</span><del>-        /* get recognizer header */
</del><span class="cx">         mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request);
</span><span class="cx">         mrcp_recog_header_t *recog_header = mrcp_resource_header_prepare(response);
</span><span class="cx">         if(!generic_header || !recog_header) {
</span><span class="lines">@@ -427,7 +498,7 @@
</span><span class="cx"> 
</span><span class="cx">         recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS;
</span><span class="cx">         mrcp_resource_header_property_add(response,RECOGNIZER_HEADER_COMPLETION_CAUSE);
</span><del>-        
</del><ins>+
</ins><span class="cx">         /* content-id must be specified */
</span><span class="cx">         if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_ID) == TRUE) {
</span><span class="cx">                 content_id = generic_header-&gt;content_id.buf;
</span><span class="lines">@@ -439,80 +510,33 @@
</span><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
-                grammar = &amp;request-&gt;body;
-        }
-
-        if(grammar) {
-                /* load grammar */
-                const apt_dir_layout_t *dir_layout = channel-&gt;engine-&gt;dir_layout;
-                const char *grammar_file_path = NULL;
-                const char *grammar_file_name = NULL;
-                apr_file_t *fd = NULL;
-                apr_status_t rv;
-                apr_size_t size;
-
</del><ins>+        if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE &amp;&amp;
+                generic_header-&gt;content_length) {
</ins><span class="cx">                 /* content-type must be specified */
</span><span class="cx">                 if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_TYPE) == TRUE) {
</span><span class="cx">                         content_type = generic_header-&gt;content_type.buf;
</span><span class="cx">                 }
</span><ins>+
</ins><span class="cx">                 if(!content_type) {
</span><span class="cx">                         apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Missing Content-Type &quot;APT_SIDRES_FMT,RECOGNIZER_SIDRES(recognizer));
</span><span class="cx">                         response-&gt;start_line.status_code = MRCP_STATUS_CODE_MISSING_PARAM;
</span><span class="cx">                         recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><del>-        
-                /* only JSGF grammar is supported */
-                if(strstr(content_type,&quot;jsgf&quot;) == NULL) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Not Supported Content-Type [%s] &quot;APT_SIDRES_FMT,
-                                content_type,RECOGNIZER_SIDRES(recognizer));
-                        response-&gt;start_line.status_code = MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE;
-                        recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
-                        return FALSE;
-                }
</del><span class="cx"> 
</span><del>-                grammar_file_name = apr_psprintf(channel-&gt;pool,&quot;%s-%s.gram&quot;,channel-&gt;id.buf,content_id);
-                grammar_file_path = apt_datadir_filepath_get(dir_layout,grammar_file_name,channel-&gt;pool);
-
-                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create Grammar File [%s] &quot;APT_SIDRES_FMT,
-                        grammar_file_path,RECOGNIZER_SIDRES(recognizer));
-                rv = apr_file_open(&amp;fd,grammar_file_path,APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY,
-                        APR_OS_DEFAULT,channel-&gt;pool);
-                if(rv != APR_SUCCESS) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Cannot Open Grammar File to Write [%s] &quot;APT_SIDRES_FMT,
-                                grammar_file_path,RECOGNIZER_SIDRES(recognizer));
-                        response-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
</del><ins>+                response-&gt;start_line.status_code = pocketsphinx_grammar_load(recognizer,content_id,content_type,&amp;request-&gt;body);
+                if(response-&gt;start_line.status_code != MRCP_STATUS_CODE_SUCCESS) {
</ins><span class="cx">                         recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
</span><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><del>-
-                size = grammar-&gt;length;
-                apr_file_write(fd,grammar-&gt;buf,&amp;size);
-                apr_file_close(fd);
-
-                /* init pocketsphinx decoder */
-                if(pocketsphinx_decoder_init(recognizer,grammar_file_path) == TRUE) {
-                        recognizer-&gt;grammar_id = content_id;
-                        apr_table_setn(recognizer-&gt;grammar_table,content_id,grammar_file_path);
-                }
-                else {
-                        response-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
</del><ins>+        }
+        else {
+                response-&gt;start_line.status_code = pocketsphinx_grammar_unload(recognizer,content_id);
+                if(response-&gt;start_line.status_code != MRCP_STATUS_CODE_SUCCESS) {
</ins><span class="cx">                         recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
</span><del>-                        apr_file_remove(grammar_file_path,channel-&gt;pool);
</del><span class="cx">                         return FALSE;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><del>-        else {
-                /* unload grammar */
-                const char *grammar_file_path = apr_table_get(recognizer-&gt;grammar_table,content_id);
-                if(grammar_file_path) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Remove Grammar File [%s] &quot;APT_SIDRES_FMT,
-                                grammar_file_path,RECOGNIZER_SIDRES(recognizer));
-                        apr_file_remove(grammar_file_path,channel-&gt;pool);
-                        apr_table_unset(recognizer-&gt;grammar_table,content_id);
-                }
-        }
</del><span class="cx"> 
</span><span class="cx">         /* send asynchronous response */
</span><span class="cx">         mrcp_engine_channel_message_send(channel,response);
</span><span class="lines">@@ -522,13 +546,49 @@
</span><span class="cx"> /** Process RECOGNIZE request [RECOG] */
</span><span class="cx"> static apt_bool_t pocketsphinx_recognize(pocketsphinx_recognizer_t *recognizer, mrcp_message_t *request, mrcp_message_t *response)
</span><span class="cx"> {
</span><ins>+        const char *content_type = NULL;
</ins><span class="cx">         mrcp_engine_channel_t *channel = recognizer-&gt;channel;
</span><span class="cx">         mrcp_recog_header_t *request_recog_header;
</span><span class="cx">         mrcp_recog_header_t *response_recog_header = mrcp_resource_header_prepare(response);
</span><del>-        if(!response_recog_header) {
</del><ins>+        mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request);
+        if(!generic_header || !response_recog_header) {
</ins><span class="cx">                 return FALSE;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        /* 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;
+        }
+        if(!content_type) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Missing Content-Type &quot;APT_SIDRES_FMT,RECOGNIZER_SIDRES(recognizer));
+                response-&gt;start_line.status_code = MRCP_STATUS_CODE_MISSING_PARAM;
+                response_recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
+                return FALSE;
+        }
+
+        if(strcmp(content_type,&quot;text/uri-list&quot;) == 0) {
+                /* assume the uri-list contains last defined (active) grammar for now */
+        }
+        else {
+                const char *content_id = NULL;
+                /* content-id must be specified */
+                if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_ID) == TRUE) {
+                        content_id = generic_header-&gt;content_id.buf;
+                }
+                if(!content_id) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Missing Content-Id &quot;APT_SIDRES_FMT,RECOGNIZER_SIDRES(recognizer));
+                        response-&gt;start_line.status_code = MRCP_STATUS_CODE_MISSING_PARAM;
+                        response_recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
+                        return FALSE;
+                }
+
+                response-&gt;start_line.status_code = pocketsphinx_grammar_load(recognizer,content_id,content_type,&amp;request-&gt;body);
+                if(response-&gt;start_line.status_code != MRCP_STATUS_CODE_SUCCESS) {
+                        response_recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_GRAM_LOAD_FAILURE;
+                        return FALSE;
+                }
+        }
+
</ins><span class="cx">         if(!recognizer-&gt;decoder || ps_start_utt(recognizer-&gt;decoder, NULL) &lt; 0) {
</span><span class="cx">                 response-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
</span><span class="cx">                 response_recog_header-&gt;completion_cause = RECOGNIZER_COMPLETION_CAUSE_ERROR;
</span><span class="lines">@@ -557,8 +617,9 @@
</span><span class="cx">         /* check if waveform (utterance) should be saved */
</span><span class="cx">         if(recognizer-&gt;properties.save_waveform == TRUE) {
</span><span class="cx">                 apr_status_t rv;
</span><del>-                const char *waveform_file_name = apr_psprintf(channel-&gt;pool,&quot;utter-%s-%d.pcm&quot;,
-                        channel-&gt;id.buf,request-&gt;start_line.request_id);
</del><ins>+                const char *waveform_file_name = apr_psprintf(channel-&gt;pool,&quot;utter-%s-%&quot;MRCP_REQUEST_ID_FMT&quot;.pcm&quot;,
+                        channel-&gt;id.buf,
+                        request-&gt;start_line.request_id);
</ins><span class="cx">                 char *waveform_file_path = NULL;
</span><span class="cx">                 apr_filepath_merge(&amp;waveform_file_path,recognizer-&gt;properties.save_waveform_dir,
</span><span class="cx">                         waveform_file_name,0,channel-&gt;pool);
</span><span class="lines">@@ -730,11 +791,13 @@
</span><span class="cx">         mrcp_engine_channel_open_respond(recognizer-&gt;channel,TRUE);
</span><span class="cx"> 
</span><span class="cx">         do {
</span><ins>+                apr_thread_mutex_lock(recognizer-&gt;mutex);
</ins><span class="cx">                 /** Wait for MRCP requests */
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Wait for incoming messages &quot;APT_SIDRES_FMT, RECOGNIZER_SIDRES(recognizer));
</span><del>-                apr_thread_mutex_lock(recognizer-&gt;mutex);
-                apr_thread_cond_wait(recognizer-&gt;wait_object,recognizer-&gt;mutex);
-                apr_thread_mutex_unlock(recognizer-&gt;mutex);
</del><ins>+                if (!recognizer-&gt;message_waiting) {
+                        apr_thread_cond_wait(recognizer-&gt;wait_object,recognizer-&gt;mutex);
+                }
+                recognizer-&gt;message_waiting = FALSE;
</ins><span class="cx"> 
</span><span class="cx">                 if(recognizer-&gt;request) {
</span><span class="cx">                         /* store request message and further dispatch it */
</span><span class="lines">@@ -746,6 +809,7 @@
</span><span class="cx">                         /* end of input detected, get recognition result and raise recognition complete event */
</span><span class="cx">                         pocketsphinx_recognition_complete(recognizer,recognizer-&gt;complete_event);
</span><span class="cx">                 }
</span><ins>+                apr_thread_mutex_unlock(recognizer-&gt;mutex);
</ins><span class="cx">         }
</span><span class="cx">         while(recognizer-&gt;close_requested == FALSE);
</span><span class="cx"> 
</span><span class="lines">@@ -814,6 +878,7 @@
</span><span class="cx">         /* signal recognition thread first */
</span><span class="cx">         apr_thread_mutex_lock(recognizer-&gt;mutex);
</span><span class="cx">         recognizer-&gt;complete_event = message;
</span><ins>+        recognizer-&gt;message_waiting = TRUE;
</ins><span class="cx">         apr_thread_cond_signal(recognizer-&gt;wait_object);
</span><span class="cx">         apr_thread_mutex_unlock(recognizer-&gt;mutex);
</span><span class="cx">         return TRUE;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcppocketsphinxsrcpocketsphinx_propertiesc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/pocketsphinx_properties.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/pocketsphinx_properties.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-pocketsphinx/src/pocketsphinx_properties.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -14,6 +14,7 @@
</span><span class="cx">  * limitations under the License.
</span><span class="cx">  */
</span><span class="cx"> 
</span><ins>+#include &lt;stdlib.h&gt;
</ins><span class="cx"> #include &lt;apr_xml.h&gt;
</span><span class="cx"> #include &quot;pocketsphinx_properties.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcprecorderMakefileam"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/Makefile.am (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/Makefile.am                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/Makefile.am        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+MAINTAINERCLEANFILES            = Makefile.in
+
+INCLUDES                   = -Iinclude \
+                             -I$(top_srcdir)/libs/mrcp-engine/include \
+                             -I$(top_srcdir)/libs/mrcp/include \
+                             -I$(top_srcdir)/libs/mrcp/message/include \
+                             -I$(top_srcdir)/libs/mrcp/control/include \
+                             -I$(top_srcdir)/libs/mrcp/resources/include \
+                             -I$(top_srcdir)/libs/mpf/include \
+                             -I$(top_srcdir)/libs/apr-toolkit/include \
+                             $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
+
+plugin_LTLIBRARIES         = mrcprecorder.la
+
+mrcprecorder_la_SOURCES    = src/mrcp_recorder_engine.c
+mrcprecorder_la_LDFLAGS    = -module $(PLUGIN_LT_VERSION)
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcprecordermrcprecordervcproj"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/mrcprecorder.vcproj (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/mrcprecorder.vcproj                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/mrcprecorder.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,165 @@
</span><ins>+&lt;?xml version=&quot;1.0&quot; encoding=&quot;Windows-1252&quot;?&gt;
+&lt;VisualStudioProject
+        ProjectType=&quot;Visual C++&quot;
+        Version=&quot;8.00&quot;
+        Name=&quot;mrcprecorder&quot;
+        ProjectGUID=&quot;{5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2}&quot;
+        RootNamespace=&quot;mrcprecorder&quot;
+        Keyword=&quot;Win32Proj&quot;
+        &gt;
+        &lt;Platforms&gt;
+                &lt;Platform
+                        Name=&quot;Win32&quot;
+                /&gt;
+        &lt;/Platforms&gt;
+        &lt;ToolFiles&gt;
+        &lt;/ToolFiles&gt;
+        &lt;Configurations&gt;
+                &lt;Configuration
+                        Name=&quot;Debug|Win32&quot;
+                        ConfigurationType=&quot;2&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unidebug.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpplugin.vsprops&quot;
+                        CharacterSet=&quot;1&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+                &lt;Configuration
+                        Name=&quot;Release|Win32&quot;
+                        ConfigurationType=&quot;2&quot;
+                        InheritedPropertySheets=&quot;$(ProjectDir)..\..\build\vsprops\unirelease.vsprops;$(ProjectDir)..\..\build\vsprops\unimrcpplugin.vsprops&quot;
+                        CharacterSet=&quot;1&quot;
+                        WholeProgramOptimization=&quot;1&quot;
+                        &gt;
+                        &lt;Tool
+                                Name=&quot;VCPreBuildEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCustomBuildTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXMLDataGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebServiceProxyGeneratorTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCMIDLTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCCLCompilerTool&quot;
+                                AdditionalIncludeDirectories=&quot;include&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManagedResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCResourceCompilerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPreLinkEventTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCLinkerTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCALinkTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCManifestTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCXDCMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCBscMakeTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCFxCopTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCAppVerifierTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCWebDeploymentTool&quot;
+                        /&gt;
+                        &lt;Tool
+                                Name=&quot;VCPostBuildEventTool&quot;
+                        /&gt;
+                &lt;/Configuration&gt;
+        &lt;/Configurations&gt;
+        &lt;References&gt;
+        &lt;/References&gt;
+        &lt;Files&gt;
+                &lt;Filter
+                        Name=&quot;include&quot;
+                        Filter=&quot;h;hpp;hxx;hm;inl;inc;xsd&quot;
+                        UniqueIdentifier=&quot;{93995380-89BD-4b04-88EB-625FBE52EBFB}&quot;
+                        &gt;
+                &lt;/Filter&gt;
+                &lt;Filter
+                        Name=&quot;src&quot;
+                        Filter=&quot;cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx&quot;
+                        &gt;
+                        &lt;File
+                                RelativePath=&quot;.\src\mrcp_recorder_engine.c&quot;
+                                &gt;
+                        &lt;/File&gt;
+                &lt;/Filter&gt;
+        &lt;/Files&gt;
+        &lt;Globals&gt;
+        &lt;/Globals&gt;
+&lt;/VisualStudioProject&gt;
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcppluginsmrcprecordersrcmrcp_recorder_enginec"></a>
<div class="addfile"><h4>Added: freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/src/mrcp_recorder_engine.c (0 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/src/mrcp_recorder_engine.c                                (rev 0)
+++ freeswitch/trunk/libs/unimrcp/plugins/mrcp-recorder/src/mrcp_recorder_engine.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -0,0 +1,463 @@
</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.
+ */
+
+/* 
+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ *    with the exact signature and name (the main entry point)
+ *        MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ *        MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ *   (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
+ */
+
+#include &quot;mrcp_recorder_engine.h&quot;
+#include &quot;mpf_activity_detector.h&quot;
+#include &quot;apt_log.h&quot;
+
+#define RECORDER_ENGINE_TASK_NAME &quot;Recorder Engine&quot;
+
+typedef struct recorder_channel_t recorder_channel_t;
+
+/** Declaration of recorder engine methods */
+static apt_bool_t recorder_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t recorder_engine_open(mrcp_engine_t *engine);
+static apt_bool_t recorder_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* recorder_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
+
+static const struct mrcp_engine_method_vtable_t engine_vtable = {
+        recorder_engine_destroy,
+        recorder_engine_open,
+        recorder_engine_close,
+        recorder_engine_channel_create
+};
+
+
+/** Declaration of recorder channel methods */
+static apt_bool_t recorder_channel_destroy(mrcp_engine_channel_t *channel);
+static apt_bool_t recorder_channel_open(mrcp_engine_channel_t *channel);
+static apt_bool_t recorder_channel_close(mrcp_engine_channel_t *channel);
+static apt_bool_t recorder_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
+
+static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
+        recorder_channel_destroy,
+        recorder_channel_open,
+        recorder_channel_close,
+        recorder_channel_request_process
+};
+
+/** Declaration of recorder audio stream methods */
+static apt_bool_t recorder_stream_destroy(mpf_audio_stream_t *stream);
+static apt_bool_t recorder_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
+static apt_bool_t recorder_stream_close(mpf_audio_stream_t *stream);
+static apt_bool_t recorder_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
+
+static const mpf_audio_stream_vtable_t audio_stream_vtable = {
+        recorder_stream_destroy,
+        NULL,
+        NULL,
+        NULL,
+        recorder_stream_open,
+        recorder_stream_close,
+        recorder_stream_write
+};
+
+/** Declaration of recorder channel */
+struct recorder_channel_t {
+        /** Engine channel base */
+        mrcp_engine_channel_t   *channel;
+
+        /** Active (in-progress) record request */
+        mrcp_message_t          *record_request;
+        /** Pending stop response */
+        mrcp_message_t          *stop_response;
+        /** Indicates whether input timers are started */
+        apt_bool_t               timers_started;
+        /** Voice activity detector */
+        mpf_activity_detector_t *detector;
+        /** Max length of the recording in msec */
+        apr_size_t               max_time;
+        /** Elapsed time of the recording in msec */
+        apr_size_t               cur_time;
+        /** Written size of the recording in bytes */
+        apr_size_t               cur_size;
+        /** File name of the recording */
+        const char              *file_name;
+        /** File to write to */
+        FILE                    *audio_out;
+};
+
+
+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
+/** Declare this macro to use log routine of the server, plugin is loaded from */
+MRCP_PLUGIN_LOGGER_IMPLEMENT
+
+/** Create recorder engine */
+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+{
+        /* create engine base */
+        return mrcp_engine_create(
+                                MRCP_RECORDER_RESOURCE,    /* MRCP resource identifier */
+                                NULL,                      /* object to associate */
+                                &amp;engine_vtable,            /* virtual methods table of engine */
+                                pool);                     /* pool to allocate memory from */
+}
+
+/** Destroy recorder engine */
+static apt_bool_t recorder_engine_destroy(mrcp_engine_t *engine)
+{
+        return TRUE;
+}
+
+/** Open recorder engine */
+static apt_bool_t recorder_engine_open(mrcp_engine_t *engine)
+{
+        return TRUE;
+}
+
+/** Close recorder engine */
+static apt_bool_t recorder_engine_close(mrcp_engine_t *engine)
+{
+        return TRUE;
+}
+
+static mrcp_engine_channel_t* recorder_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
+{
+        mpf_stream_capabilities_t *capabilities;
+        mpf_termination_t *termination; 
+
+        /* create recorder channel */
+        recorder_channel_t *recorder_channel = apr_palloc(pool,sizeof(recorder_channel_t));
+        recorder_channel-&gt;record_request = NULL;
+        recorder_channel-&gt;stop_response = NULL;
+        recorder_channel-&gt;detector = mpf_activity_detector_create(pool);
+        recorder_channel-&gt;max_time = 0;
+        recorder_channel-&gt;cur_time = 0;
+        recorder_channel-&gt;cur_size = 0;
+        recorder_channel-&gt;file_name = NULL;
+        recorder_channel-&gt;audio_out = NULL;
+
+        capabilities = mpf_sink_stream_capabilities_create(pool);
+        mpf_codec_capabilities_add(
+                        &amp;capabilities-&gt;codecs,
+                        MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+                        &quot;LPCM&quot;);
+
+        /* create media termination */
+        termination = mrcp_engine_audio_termination_create(
+                        recorder_channel,     /* object to associate */
+                        &amp;audio_stream_vtable, /* virtual methods table of audio stream */
+                        capabilities,         /* stream capabilities */
+                        pool);                /* pool to allocate memory from */
+
+        /* create engine channel base */
+        recorder_channel-&gt;channel = mrcp_engine_channel_create(
+                        engine,               /* engine */
+                        &amp;channel_vtable,      /* virtual methods table of engine channel */
+                        recorder_channel,     /* object to associate */
+                        termination,          /* associated media termination */
+                        pool);                /* pool to allocate memory from */
+
+        return recorder_channel-&gt;channel;
+}
+
+/** Destroy engine channel */
+static apt_bool_t recorder_channel_destroy(mrcp_engine_channel_t *channel)
+{
+        /* nothing to destrtoy */
+        return TRUE;
+}
+
+/** Open engine channel (asynchronous response MUST be sent)*/
+static apt_bool_t recorder_channel_open(mrcp_engine_channel_t *channel)
+{
+        /* open channel and send asynch response */
+        return mrcp_engine_channel_open_respond(channel,TRUE);
+}
+
+/** Close engine channel (asynchronous response MUST be sent)*/
+static apt_bool_t recorder_channel_close(mrcp_engine_channel_t *channel)
+{
+        /* close channel, make sure there is no activity and send asynch response */
+        return mrcp_engine_channel_close_respond(channel);
+}
+
+/** Open file to record */
+static apt_bool_t recorder_file_open(recorder_channel_t *recorder_channel, mrcp_message_t *request)
+{
+        mrcp_engine_channel_t *channel = recorder_channel-&gt;channel;
+        const apt_dir_layout_t *dir_layout = channel-&gt;engine-&gt;dir_layout;
+        const mpf_codec_descriptor_t *descriptor = mrcp_engine_sink_stream_codec_get(channel);
+        char *file_name = apr_psprintf(channel-&gt;pool,&quot;rec-%dkHz-%s-%&quot;MRCP_REQUEST_ID_FMT&quot;.pcm&quot;,
+                descriptor ? descriptor-&gt;sampling_rate/1000 : 8,
+                request-&gt;channel_id.session_id.buf,
+                request-&gt;start_line.request_id);
+        char *file_path = apt_datadir_filepath_get(dir_layout,file_name,channel-&gt;pool);
+        if(!file_path) {
+                return FALSE;
+        }
+
+        if(recorder_channel-&gt;audio_out) {
+                fclose(recorder_channel-&gt;audio_out);
+                recorder_channel-&gt;audio_out = NULL;
+        }
+
+        recorder_channel-&gt;audio_out = fopen(file_path,&quot;wb&quot;);
+        if(!recorder_channel-&gt;audio_out) {
+                return FALSE;
+        }
+
+        recorder_channel-&gt;file_name = file_name;
+        return TRUE;
+}
+
+/** Set Record-URI header field */
+static apt_bool_t recorder_channel_uri_set(recorder_channel_t *recorder_channel, mrcp_message_t *message)
+{
+        char *record_uri;
+        /* get/allocate recorder header */
+        mrcp_recorder_header_t *recorder_header = mrcp_resource_header_prepare(message);
+        if(!recorder_header) {
+                return FALSE;
+        }
+        
+        record_uri = apr_psprintf(message-&gt;pool,&quot;&lt;file://mediaserver/data/%s&gt;;size=%d;duration=%d&quot;,
+                                recorder_channel-&gt;file_name,
+                                recorder_channel-&gt;cur_size,
+                                recorder_channel-&gt;cur_time);
+
+        apt_string_set(&amp;recorder_header-&gt;record_uri,record_uri);
+        mrcp_resource_header_property_add(message,RECORDER_HEADER_RECORD_URI);
+        return TRUE;
+}
+
+/** Process RECORD request */
+static apt_bool_t recorder_channel_record(recorder_channel_t *recorder_channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+        /* process RECORD request */
+        mrcp_recorder_header_t *recorder_header;
+        recorder_channel-&gt;timers_started = TRUE;
+
+        /* get recorder header */
+        recorder_header = mrcp_resource_header_get(request);
+        if(recorder_header) {
+                if(mrcp_resource_header_property_check(request,RECORDER_HEADER_START_INPUT_TIMERS) == TRUE) {
+                        recorder_channel-&gt;timers_started = recorder_header-&gt;start_input_timers;
+                }
+                if(mrcp_resource_header_property_check(request,RECORDER_HEADER_NO_INPUT_TIMEOUT) == TRUE) {
+                        mpf_activity_detector_noinput_timeout_set(recorder_channel-&gt;detector,recorder_header-&gt;no_input_timeout);
+                }
+                if(mrcp_resource_header_property_check(request,RECORDER_HEADER_FINAL_SILENCE) == TRUE) {
+                        mpf_activity_detector_silence_timeout_set(recorder_channel-&gt;detector,recorder_header-&gt;final_silence);
+                }
+                if(mrcp_resource_header_property_check(request,RECORDER_HEADER_MAX_TIME) == TRUE) {
+                        recorder_channel-&gt;max_time = recorder_header-&gt;max_time;
+                }
+        }
+
+        /* open file to record */
+        if(recorder_file_open(recorder_channel,request) == FALSE) {
+                response-&gt;start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
+                response-&gt;start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
+                /* send asynchronous response */
+                mrcp_engine_channel_message_send(recorder_channel-&gt;channel,response);
+                return TRUE;
+        }
+
+        recorder_channel-&gt;cur_time = 0;
+        recorder_channel-&gt;cur_size = 0;
+        response-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        /* send asynchronous response */
+        mrcp_engine_channel_message_send(recorder_channel-&gt;channel,response);
+        recorder_channel-&gt;record_request = request;
+        return TRUE;
+}
+
+/** Process STOP request */
+static apt_bool_t recorder_channel_stop(recorder_channel_t *recorder_channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+        /* store STOP request, make sure there is no more activity and only then send the response */
+        recorder_channel-&gt;stop_response = response;
+        return TRUE;
+}
+
+/** Process START-INPUT-TIMERS request */
+static apt_bool_t recorder_channel_timers_start(recorder_channel_t *recorder_channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+        recorder_channel-&gt;timers_started = TRUE;
+        return mrcp_engine_channel_message_send(recorder_channel-&gt;channel,response);
+}
+
+/** Process MRCP channel request (asynchronous response MUST be sent)*/
+static apt_bool_t recorder_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request)
+{
+        apt_bool_t processed = FALSE;
+        recorder_channel_t *recorder_channel = channel-&gt;method_obj;
+        mrcp_message_t *response = mrcp_response_create(request,request-&gt;pool);
+        switch(request-&gt;start_line.method_id) {
+                case RECORDER_SET_PARAMS:
+                        break;
+                case RECORDER_GET_PARAMS:
+                        break;
+                case RECORDER_RECORD:
+                        processed = recorder_channel_record(recorder_channel,request,response);
+                        break;
+                case RECORDER_STOP:
+                        processed = recorder_channel_stop(recorder_channel,request,response);
+                        break;
+                case RECORDER_START_INPUT_TIMERS:
+                        processed = recorder_channel_timers_start(recorder_channel,request,response);
+                        break;
+                default:
+                        break;
+        }
+        if(processed == FALSE) {
+                /* send asynchronous response for not handled request */
+                mrcp_engine_channel_message_send(channel,response);
+        }
+        return TRUE;
+}
+
+/* Raise START-OF-INPUT event */
+static apt_bool_t recorder_start_of_input(recorder_channel_t *recorder_channel)
+{
+        /* create START-OF-INPUT event */
+        mrcp_message_t *message = mrcp_event_create(
+                                                recorder_channel-&gt;record_request,
+                                                RECORDER_START_OF_INPUT,
+                                                recorder_channel-&gt;record_request-&gt;pool);
+        if(!message) {
+                return FALSE;
+        }
+
+        /* set request state */
+        message-&gt;start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+        /* send asynch event */
+        return mrcp_engine_channel_message_send(recorder_channel-&gt;channel,message);
+}
+
+/* Raise RECORD-COMPLETE event */
+static apt_bool_t recorder_record_complete(recorder_channel_t *recorder_channel, mrcp_recorder_completion_cause_e cause)
+{
+        mrcp_recorder_header_t *recorder_header;
+        /* create RECORD-COMPLETE event */
+        mrcp_message_t *message = mrcp_event_create(
+                                                recorder_channel-&gt;record_request,
+                                                RECORDER_RECORD_COMPLETE,
+                                                recorder_channel-&gt;record_request-&gt;pool);
+        if(!message) {
+                return FALSE;
+        }
+
+        if(recorder_channel-&gt;audio_out) {
+                fclose(recorder_channel-&gt;audio_out);
+                recorder_channel-&gt;audio_out = NULL;
+        }
+
+        /* get/allocate recorder header */
+        recorder_header = mrcp_resource_header_prepare(message);
+        if(recorder_header) {
+                /* set completion cause */
+                recorder_header-&gt;completion_cause = cause;
+                mrcp_resource_header_property_add(message,RECORDER_HEADER_COMPLETION_CAUSE);
+        }
+        /* set record-uri */
+        recorder_channel_uri_set(recorder_channel,message);
+        /* set request state */
+        message-&gt;start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
+
+        recorder_channel-&gt;record_request = NULL;
+        /* send asynch event */
+        return mrcp_engine_channel_message_send(recorder_channel-&gt;channel,message);
+}
+
+/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
+static apt_bool_t recorder_stream_destroy(mpf_audio_stream_t *stream)
+{
+        return TRUE;
+}
+
+/** Callback is called from MPF engine context to perform any action before open */
+static apt_bool_t recorder_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
+{
+        return TRUE;
+}
+
+/** Callback is called from MPF engine context to perform any action after close */
+static apt_bool_t recorder_stream_close(mpf_audio_stream_t *stream)
+{
+        return TRUE;
+}
+
+/** Callback is called from MPF engine context to write/send new frame */
+static apt_bool_t recorder_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
+{
+        recorder_channel_t *recorder_channel = stream-&gt;obj;
+        if(recorder_channel-&gt;stop_response) {
+                if(recorder_channel-&gt;audio_out) {
+                        fclose(recorder_channel-&gt;audio_out);
+                        recorder_channel-&gt;audio_out = NULL;
+                }
+                
+                if(recorder_channel-&gt;record_request){
+                        /* set record-uri */
+                        recorder_channel_uri_set(recorder_channel,recorder_channel-&gt;stop_response);
+                }
+                /* send asynchronous response to STOP request */
+                mrcp_engine_channel_message_send(recorder_channel-&gt;channel,recorder_channel-&gt;stop_response);
+                recorder_channel-&gt;stop_response = NULL;
+                recorder_channel-&gt;record_request = NULL;
+                return TRUE;
+        }
+
+        if(recorder_channel-&gt;record_request) {
+                mpf_detector_event_e det_event = mpf_activity_detector_process(recorder_channel-&gt;detector,frame);
+                switch(det_event) {
+                        case MPF_DETECTOR_EVENT_ACTIVITY:
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Detected Voice Activity&quot;);
+                                recorder_start_of_input(recorder_channel);
+                                break;
+                        case MPF_DETECTOR_EVENT_INACTIVITY:
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Detected Voice Inactivity&quot;);
+                                recorder_record_complete(recorder_channel,RECORDER_COMPLETION_CAUSE_SUCCESS_SILENCE);
+                                break;
+                        case MPF_DETECTOR_EVENT_NOINPUT:
+                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Detected Noinput&quot;);
+                                if(recorder_channel-&gt;timers_started == TRUE) {
+                                        recorder_record_complete(recorder_channel,RECORDER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
+                                }
+                                break;
+                        default:
+                                break;
+                }
+
+                if(recorder_channel-&gt;audio_out) {
+                        fwrite(frame-&gt;codec_frame.buffer,1,frame-&gt;codec_frame.size,recorder_channel-&gt;audio_out);
+                        
+                        recorder_channel-&gt;cur_size += frame-&gt;codec_frame.size;
+                        recorder_channel-&gt;cur_time += CODEC_FRAME_TIME_BASE;
+                        if(recorder_channel-&gt;max_time &amp;&amp; recorder_channel-&gt;cur_time &gt;= recorder_channel-&gt;max_time) {
+                                recorder_record_complete(recorder_channel,RECORDER_COMPLETION_CAUSE_SUCCESS_MAXTIME);
+                        }
+                }
+        }
+        return TRUE;
+}
</ins></span></pre></div>
<a id="freeswitchtrunklibsunimrcptestsmpftestsrcmpf_suitec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/tests/mpftest/src/mpf_suite.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/tests/mpftest/src/mpf_suite.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/tests/mpftest/src/mpf_suite.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -17,8 +17,6 @@
</span><span class="cx"> #include &lt;apr_thread_cond.h&gt;
</span><span class="cx"> #include &quot;apt_test_suite.h&quot;
</span><span class="cx"> #include &quot;mpf_engine.h&quot;
</span><del>-#include &quot;mpf_user.h&quot;
-#include &quot;mpf_termination.h&quot;
</del><span class="cx"> #include &quot;mpf_rtp_termination_factory.h&quot;
</span><span class="cx"> #include &quot;mpf_file_termination_factory.h&quot;
</span><span class="cx"> #include &quot;mpf_audio_file_descriptor.h&quot;
</span><span class="lines">@@ -51,8 +49,8 @@
</span><span class="cx">         /** The main task of the test engine, which sends messages to MPF engine and 
</span><span class="cx">          * processes responses and events sent back from MPF engine */
</span><span class="cx">         apt_consumer_task_t       *consumer_task;
</span><del>-        /** MPF engine task */
-        apt_task_t                *engine_task;
</del><ins>+        /** MPF engine */
+        mpf_engine_t              *engine;
</ins><span class="cx">         /** RTP termination factory */
</span><span class="cx">         mpf_termination_factory_t *rtp_termination_factory;
</span><span class="cx">         /** File termination factory */
</span><span class="lines">@@ -68,7 +66,7 @@
</span><span class="cx"> 
</span><span class="cx"> static void mpf_suite_on_start_complete(apt_task_t *task);
</span><span class="cx"> static void mpf_suite_on_terminate_complete(apt_task_t *task);
</span><del>-static apt_bool_t mpf_suite_msg_process(apt_task_t *task, apt_task_msg_t *msg);
</del><ins>+static apt_bool_t mpf_suite_task_msg_process(apt_task_t *task, apt_task_msg_t *msg);
</ins><span class="cx"> 
</span><span class="cx"> static mpf_audio_file_descriptor_t* mpf_file_reader_descriptor_create(mpf_suite_session_t *session);
</span><span class="cx"> static mpf_audio_file_descriptor_t* mpf_file_writer_descriptor_create(mpf_suite_session_t *session);
</span><span class="lines">@@ -97,7 +95,7 @@
</span><span class="cx"> 
</span><span class="cx">         suite_engine = apr_palloc(suite-&gt;pool,sizeof(mpf_suite_engine_t));
</span><span class="cx"> 
</span><del>-        engine = mpf_engine_create(suite-&gt;pool);
</del><ins>+        engine = mpf_engine_create(1,suite-&gt;pool);
</ins><span class="cx">         if(!engine) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create MPF Engine&quot;);
</span><span class="cx">                 return FALSE;
</span><span class="lines">@@ -106,7 +104,7 @@
</span><span class="cx">         if(codec_manager) {
</span><span class="cx">                 mpf_engine_codec_manager_register(engine,codec_manager);
</span><span class="cx">         }
</span><del>-        suite_engine-&gt;engine_task = mpf_task_get(engine);
</del><ins>+        suite_engine-&gt;engine = engine;
</ins><span class="cx"> 
</span><span class="cx">         config = mpf_rtp_config_create(suite-&gt;pool);
</span><span class="cx">         apt_string_set(&amp;config-&gt;ip,&quot;127.0.0.1&quot;);
</span><span class="lines">@@ -126,12 +124,12 @@
</span><span class="cx">         task = apt_consumer_task_base_get(suite_engine-&gt;consumer_task);
</span><span class="cx">         vtable = apt_task_vtable_get(task);
</span><span class="cx">         if(vtable) {
</span><del>-                vtable-&gt;process_msg = mpf_suite_msg_process;
</del><ins>+                vtable-&gt;process_msg = mpf_suite_task_msg_process;
</ins><span class="cx">                 vtable-&gt;on_start_complete = mpf_suite_on_start_complete;
</span><span class="cx">                 vtable-&gt;on_terminate_complete = mpf_suite_on_terminate_complete;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        apt_task_add(task,suite_engine-&gt;engine_task);
</del><ins>+        apt_task_add(task,mpf_task_get(engine));
</ins><span class="cx"> 
</span><span class="cx">         apr_thread_mutex_create(&amp;suite_engine-&gt;wait_object_mutex,APR_THREAD_MUTEX_UNNESTED,suite-&gt;pool);
</span><span class="cx">         apr_thread_cond_create(&amp;suite_engine-&gt;wait_object,suite-&gt;pool);
</span><span class="lines">@@ -163,8 +161,8 @@
</span><span class="cx">         mpf_suite_session_t *session;
</span><span class="cx">         apt_task_t *consumer_task;
</span><span class="cx">         mpf_suite_engine_t *suite_engine;
</span><del>-        apt_task_msg_t *msg;
-        mpf_message_t *mpf_message;
</del><ins>+        mpf_task_msg_t *task_msg = NULL;
+        void *descriptor;
</ins><span class="cx">         apr_pool_t *pool = NULL;
</span><span class="cx"> 
</span><span class="cx">         consumer_task = apt_task_object_get(task);
</span><span class="lines">@@ -180,23 +178,18 @@
</span><span class="cx">         session-&gt;rtp_mode = TRUE;
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create MPF Context&quot;);
</span><del>-        session-&gt;context = mpf_context_create(session,2,pool);
</del><ins>+        session-&gt;context = mpf_engine_context_create(suite_engine-&gt;engine,session,2,pool);
</ins><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create Termination [1]&quot;);
</span><span class="cx">         session-&gt;termination1 = mpf_termination_create(suite_engine-&gt;file_termination_factory,session,session-&gt;pool);
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Add Termination [1]&quot;);
</span><del>-        msg = apt_task_msg_get(task);
-        msg-&gt;type = TASK_MSG_USER;
-        mpf_message = (mpf_message_t*) msg-&gt;data;
</del><ins>+        descriptor = mpf_file_reader_descriptor_create(session);
+        mpf_engine_termination_message_add(
+                        suite_engine-&gt;engine,
+                        MPF_ADD_TERMINATION,session-&gt;context,session-&gt;termination1,descriptor,
+                        &amp;task_msg);
</ins><span class="cx"> 
</span><del>-        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-        mpf_message-&gt;command_id = MPF_COMMAND_ADD;
-        mpf_message-&gt;context = session-&gt;context;
-        mpf_message-&gt;termination = session-&gt;termination1;
-        mpf_message-&gt;descriptor = mpf_file_reader_descriptor_create(session);
-        apt_task_msg_signal(suite_engine-&gt;engine_task,msg);
-
</del><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Create Termination [2]&quot;);
</span><span class="cx">         if(session-&gt;rtp_mode == TRUE) {
</span><span class="cx">                 session-&gt;termination2 = mpf_termination_create(suite_engine-&gt;rtp_termination_factory,session,session-&gt;pool);
</span><span class="lines">@@ -206,21 +199,20 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Add Termination [2]&quot;);
</span><del>-        msg = apt_task_msg_get(task);
-        msg-&gt;type = TASK_MSG_USER;
-        mpf_message = (mpf_message_t*) msg-&gt;data;
-
-        mpf_message-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-        mpf_message-&gt;command_id = MPF_COMMAND_ADD;
-        mpf_message-&gt;context = session-&gt;context;
-        mpf_message-&gt;termination = session-&gt;termination2;
</del><ins>+        descriptor = NULL;
</ins><span class="cx">         if(session-&gt;rtp_mode == TRUE) {
</span><del>-                mpf_message-&gt;descriptor = mpf_rtp_local_descriptor_create(session);
</del><ins>+                descriptor = mpf_rtp_local_descriptor_create(session);
</ins><span class="cx">         }
</span><span class="cx">         else {
</span><del>-                mpf_message-&gt;descriptor = mpf_file_writer_descriptor_create(session);
</del><ins>+                descriptor = mpf_file_writer_descriptor_create(session);
</ins><span class="cx">         }
</span><del>-        apt_task_msg_signal(suite_engine-&gt;engine_task,msg);
</del><ins>+
+        mpf_engine_termination_message_add(
+                        suite_engine-&gt;engine,
+                        MPF_ADD_TERMINATION,session-&gt;context,session-&gt;termination2,descriptor,
+                        &amp;task_msg);
+
+        mpf_engine_message_send(suite_engine-&gt;engine,&amp;task_msg);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Execution of MPF test suite scenario is terminated  */
</span><span class="lines">@@ -229,147 +221,118 @@
</span><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;On MPF Suite Terminate&quot;);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-/** Process task messages  */
-static apt_bool_t mpf_suite_msg_process(apt_task_t *task, apt_task_msg_t *msg)
</del><ins>+/** Process MPF response  */
+static apt_bool_t mpf_suite_response_process(mpf_suite_engine_t *suite_engine, const mpf_message_t *mpf_message)
</ins><span class="cx"> {
</span><del>-        const mpf_message_t *mpf_message = (const mpf_message_t*) msg-&gt;data;
-        if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_RESPONSE) {
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Response&quot;);
-                if(mpf_message-&gt;command_id == MPF_COMMAND_ADD) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Add Termination&quot;);
-                        if(mpf_message-&gt;termination) {
-                                mpf_suite_session_t *session;
-                                session = mpf_termination_object_get(mpf_message-&gt;termination);
-                                if(session-&gt;termination2 == mpf_message-&gt;termination &amp;&amp; session-&gt;rtp_mode == TRUE) {
-                                        apt_task_msg_t *msg;
-                                        mpf_message_t *request;
-                                        apt_task_t *consumer_task;
-                                        mpf_suite_engine_t *suite_engine;
-
-                                        consumer_task = apt_task_object_get(task);
-                                        suite_engine = apt_task_object_get(consumer_task);
-
-                                        msg = apt_task_msg_get(task);
-                                        msg-&gt;type = TASK_MSG_USER;
-                                        request = (mpf_message_t*) msg-&gt;data;
-
-                                        request-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-                                        request-&gt;command_id = MPF_COMMAND_MODIFY;
-                                        request-&gt;context = session-&gt;context;
-                                        request-&gt;termination = session-&gt;termination2;
-                                        request-&gt;descriptor = mpf_rtp_remote_descriptor_create(session);
-                                        apt_task_msg_signal(suite_engine-&gt;engine_task,msg);
-                                }
</del><ins>+        mpf_task_msg_t *task_msg = NULL;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Response&quot;);
+        if(mpf_message-&gt;command_id == MPF_ADD_TERMINATION) {
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Add Termination&quot;);
+                if(mpf_message-&gt;termination) {
+                        mpf_suite_session_t *session;
+                        session = mpf_termination_object_get(mpf_message-&gt;termination);
+                        if(session-&gt;termination2 == mpf_message-&gt;termination &amp;&amp; session-&gt;rtp_mode == TRUE) {
+                                void *descriptor = mpf_rtp_remote_descriptor_create(session);
+                                mpf_engine_termination_message_add(
+                                        suite_engine-&gt;engine,
+                                        MPF_MODIFY_TERMINATION,session-&gt;context,session-&gt;termination2,descriptor,
+                                        &amp;task_msg);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><del>-                else if(mpf_message-&gt;command_id == MPF_COMMAND_SUBTRACT) {
-                        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Subtract Termination&quot;);
-                        if(mpf_message-&gt;termination) {
-                                mpf_suite_session_t *session;
-                                session = mpf_termination_object_get(mpf_message-&gt;termination);
-                                if(session-&gt;termination1 == mpf_message-&gt;termination) {
-                                        session-&gt;termination1 = NULL;
-                                }
-                                if(session-&gt;termination2 == mpf_message-&gt;termination) {
-                                        session-&gt;termination2 = NULL;
-                                }
-                                mpf_termination_destroy(mpf_message-&gt;termination);
-
-                                if(!session-&gt;termination1 &amp;&amp; !session-&gt;termination2) {
-                                        apt_task_t *consumer_task;
-                                        mpf_suite_engine_t *suite_engine;
-
-                                        mpf_context_destroy(session-&gt;context);
-                                        session-&gt;context = NULL;
-                                        apr_pool_destroy(session-&gt;pool);
-
-                                        consumer_task = apt_task_object_get(task);
-                                        suite_engine = apt_task_object_get(consumer_task);
-
-                                        apr_thread_mutex_lock(suite_engine-&gt;wait_object_mutex);
-                                        apr_thread_cond_signal(suite_engine-&gt;wait_object);
-                                        apr_thread_mutex_unlock(suite_engine-&gt;wait_object_mutex);
-                                }
-                        }
-                }
</del><span class="cx">         }
</span><del>-        else if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_EVENT) {
-                apt_task_t *consumer_task;
-                mpf_suite_engine_t *suite_engine;
-                apt_task_msg_t *msg;
-                mpf_message_t *request;
-                mpf_suite_session_t *session;
-                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Event&quot;);
</del><ins>+        else if(mpf_message-&gt;command_id == MPF_SUBTRACT_TERMINATION) {
+                apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;On Subtract Termination&quot;);
</ins><span class="cx">                 if(mpf_message-&gt;termination) {
</span><ins>+                        mpf_suite_session_t *session;
</ins><span class="cx">                         session = mpf_termination_object_get(mpf_message-&gt;termination);
</span><del>-                        if(session-&gt;termination1) {
-                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Subtract Termination [1]&quot;);
-                                msg = apt_task_msg_get(task);
-                                msg-&gt;type = TASK_MSG_USER;
-                                request = (mpf_message_t*) msg-&gt;data;
-
-                                request-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-                                request-&gt;command_id = MPF_COMMAND_SUBTRACT;
-                                request-&gt;context = session-&gt;context;
-                                request-&gt;termination = session-&gt;termination1;
-
-                                consumer_task = apt_task_object_get(task);
-                                suite_engine = apt_task_object_get(consumer_task);
-                                apt_task_msg_signal(suite_engine-&gt;engine_task,msg);
</del><ins>+                        if(session-&gt;termination1 == mpf_message-&gt;termination) {
+                                session-&gt;termination1 = NULL;
</ins><span class="cx">                         }
</span><del>-                        if(session-&gt;termination2) {
-                                apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Subtract Termination [2]&quot;);
-                                msg = apt_task_msg_get(task);
-                                msg-&gt;type = TASK_MSG_USER;
-                                request = (mpf_message_t*) msg-&gt;data;
</del><ins>+                        if(session-&gt;termination2 == mpf_message-&gt;termination) {
+                                session-&gt;termination2 = NULL;
+                        }
+                        mpf_termination_destroy(mpf_message-&gt;termination);
</ins><span class="cx"> 
</span><del>-                                request-&gt;message_type = MPF_MESSAGE_TYPE_REQUEST;
-                                request-&gt;command_id = MPF_COMMAND_SUBTRACT;
-                                request-&gt;context = session-&gt;context;
-                                request-&gt;termination = session-&gt;termination2;
</del><ins>+                        if(!session-&gt;termination1 &amp;&amp; !session-&gt;termination2) {
+                                mpf_engine_context_destroy(session-&gt;context);
+                                session-&gt;context = NULL;
+                                apr_pool_destroy(session-&gt;pool);
</ins><span class="cx"> 
</span><del>-                                consumer_task = apt_task_object_get(task);
-                                suite_engine = apt_task_object_get(consumer_task);
-                                apt_task_msg_signal(suite_engine-&gt;engine_task,msg);
</del><ins>+                                apr_thread_mutex_lock(suite_engine-&gt;wait_object_mutex);
+                                apr_thread_cond_signal(suite_engine-&gt;wait_object);
+                                apr_thread_mutex_unlock(suite_engine-&gt;wait_object_mutex);
</ins><span class="cx">                         }
</span><span class="cx">                 }
</span><span class="cx">         }
</span><ins>+        return mpf_engine_message_send(suite_engine-&gt;engine,&amp;task_msg);
+}
</ins><span class="cx"> 
</span><ins>+/** Process MPF event  */
+static apt_bool_t mpf_suite_event_process(mpf_suite_engine_t *suite_engine, const mpf_message_t *mpf_message)
+{
+        mpf_task_msg_t *task_msg = NULL;
+        mpf_suite_session_t *session;
+        apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,&quot;Process MPF Event&quot;);
+        if(mpf_message-&gt;termination) {
+                session = mpf_termination_object_get(mpf_message-&gt;termination);
+                if(session-&gt;termination1) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Subtract Termination [1]&quot;);
+                        mpf_engine_termination_message_add(
+                                suite_engine-&gt;engine,
+                                MPF_SUBTRACT_TERMINATION,session-&gt;context,session-&gt;termination1,NULL,
+                                &amp;task_msg);
+                }
+                if(session-&gt;termination2) {
+                        apt_log(APT_LOG_MARK,APT_PRIO_INFO,&quot;Subtract Termination [2]&quot;);
+                        mpf_engine_termination_message_add(
+                                suite_engine-&gt;engine,
+                                MPF_SUBTRACT_TERMINATION,session-&gt;context,session-&gt;termination2,NULL,
+                                &amp;task_msg);
+                }
+        }
+        return mpf_engine_message_send(suite_engine-&gt;engine,&amp;task_msg);
+}
+
+/** Process task messages */
+static apt_bool_t mpf_suite_task_msg_process(apt_task_t *task, apt_task_msg_t *msg)
+{
+        apr_size_t i;
+        const mpf_message_t *mpf_message;
+        apt_task_t *consumer_task = apt_task_object_get(task);
+        mpf_suite_engine_t *suite_engine = apt_task_object_get(consumer_task);
+        const mpf_message_container_t *container = (const mpf_message_container_t*) msg-&gt;data;
+        for(i=0; i&lt;container-&gt;count; i++) {
+                mpf_message = &amp;container-&gt;messages[i];
+                if(mpf_message-&gt;message_type == MPF_MESSAGE_TYPE_RESPONSE) {
+                        mpf_suite_response_process(suite_engine,mpf_message);
+                }
+                else {
+                        mpf_suite_event_process(suite_engine,mpf_message);
+                }
+        }
</ins><span class="cx">         return TRUE;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create sample file reader descriptor */
</span><span class="cx"> static mpf_audio_file_descriptor_t* mpf_file_reader_descriptor_create(mpf_suite_session_t *session)
</span><span class="cx"> {
</span><del>-        mpf_codec_descriptor_t *codec_descriptor;
</del><span class="cx">         mpf_audio_file_descriptor_t *descriptor = apr_palloc(session-&gt;pool,sizeof(mpf_audio_file_descriptor_t));
</span><span class="cx">         descriptor-&gt;mask = FILE_READER;
</span><span class="cx">         descriptor-&gt;read_handle = fopen(&quot;demo.pcm&quot;,&quot;rb&quot;);
</span><span class="cx">         descriptor-&gt;write_handle = NULL;
</span><del>-
-        codec_descriptor = &amp;descriptor-&gt;codec_descriptor;
-        codec_descriptor-&gt;payload_type = 96;
-        apt_string_set(&amp;codec_descriptor-&gt;name,&quot;LPCM&quot;);
-        codec_descriptor-&gt;sampling_rate = 8000;
-        codec_descriptor-&gt;channel_count = 1;
</del><ins>+        descriptor-&gt;codec_descriptor = mpf_codec_lpcm_descriptor_create(8000,1,session-&gt;pool);
</ins><span class="cx">         return descriptor;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /** Create sample file writer descriptor */
</span><span class="cx"> static mpf_audio_file_descriptor_t* mpf_file_writer_descriptor_create(mpf_suite_session_t *session)
</span><span class="cx"> {
</span><del>-        mpf_codec_descriptor_t *codec_descriptor;
</del><span class="cx">         mpf_audio_file_descriptor_t *descriptor = apr_palloc(session-&gt;pool,sizeof(mpf_audio_file_descriptor_t));
</span><span class="cx">         descriptor-&gt;mask = FILE_WRITER;
</span><span class="cx">         descriptor-&gt;max_write_size = 500000; /* 500Kb */
</span><span class="cx">         descriptor-&gt;write_handle = fopen(&quot;demo_out.pcm&quot;,&quot;wb&quot;);
</span><span class="cx">         descriptor-&gt;read_handle = NULL;
</span><del>-
-        codec_descriptor = &amp;descriptor-&gt;codec_descriptor;
-        codec_descriptor-&gt;payload_type = 96;
-        apt_string_set(&amp;codec_descriptor-&gt;name,&quot;LPCM&quot;);
-        codec_descriptor-&gt;sampling_rate = 8000;
-        codec_descriptor-&gt;channel_count = 1;
</del><ins>+        descriptor-&gt;codec_descriptor = mpf_codec_lpcm_descriptor_create(8000,1,session-&gt;pool);
</ins><span class="cx">         return descriptor;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -380,9 +343,9 @@
</span><span class="cx">         mpf_rtp_stream_descriptor_init(descriptor);
</span><span class="cx">         descriptor-&gt;local = apr_palloc(session-&gt;pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">         mpf_rtp_media_descriptor_init(descriptor-&gt;local);
</span><del>-        descriptor-&gt;local-&gt;mode = STREAM_MODE_NONE;
-        apt_string_set(&amp;descriptor-&gt;local-&gt;base.ip,&quot;127.0.0.1&quot;);
-        descriptor-&gt;local-&gt;base.port = 5000;
</del><ins>+        descriptor-&gt;local-&gt;direction = STREAM_DIRECTION_NONE;
+        apt_string_set(&amp;descriptor-&gt;local-&gt;ip,&quot;127.0.0.1&quot;);
+        descriptor-&gt;local-&gt;port = 5000;
</ins><span class="cx">         return descriptor;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -395,9 +358,9 @@
</span><span class="cx">         mpf_rtp_stream_descriptor_init(descriptor);
</span><span class="cx">         descriptor-&gt;remote = apr_palloc(session-&gt;pool,sizeof(mpf_rtp_media_descriptor_t));
</span><span class="cx">         mpf_rtp_media_descriptor_init(descriptor-&gt;remote);
</span><del>-        descriptor-&gt;remote-&gt;mode = STREAM_MODE_SEND_RECEIVE;
-        apt_string_set(&amp;descriptor-&gt;remote-&gt;base.ip,&quot;127.0.0.1&quot;);
-        descriptor-&gt;remote-&gt;base.port = 5002;
</del><ins>+        descriptor-&gt;remote-&gt;direction = STREAM_DIRECTION_DUPLEX;
+        apt_string_set(&amp;descriptor-&gt;remote-&gt;ip,&quot;127.0.0.1&quot;);
+        descriptor-&gt;remote-&gt;port = 5002;
</ins><span class="cx">         codec_list = &amp;descriptor-&gt;remote-&gt;codec_list;
</span><span class="cx">         mpf_codec_list_init(codec_list,2,session-&gt;pool);
</span><span class="cx">         codec_descriptor = mpf_codec_list_add(codec_list);
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcptestsmrcptestmrcptestvcproj"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/tests/mrcptest/mrcptest.vcproj (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/tests/mrcptest/mrcptest.vcproj        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/tests/mrcptest/mrcptest.vcproj        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> &lt;?xml version=&quot;1.0&quot; encoding=&quot;windows-1251&quot;?&gt;
</span><span class="cx"> &lt;VisualStudioProject
</span><span class="cx">         ProjectType=&quot;Visual C++&quot;
</span><del>-        Version=&quot;8,00&quot;
</del><ins>+        Version=&quot;8.00&quot;
</ins><span class="cx">         Name=&quot;mrcptest&quot;
</span><span class="cx">         ProjectGUID=&quot;{3CA97077-6210-4362-998A-D15A35EEAA08}&quot;
</span><span class="cx">         RootNamespace=&quot;mrcptest&quot;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcptestsmrcptestsrcparse_gen_suitec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/parse_gen_suite.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/parse_gen_suite.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/parse_gen_suite.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -18,7 +18,8 @@
</span><span class="cx"> #include &lt;apr_file_io.h&gt;
</span><span class="cx"> #include &quot;apt_test_suite.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><del>-#include &quot;mrcp_default_factory.h&quot;
</del><ins>+#include &quot;mrcp_resource_loader.h&quot;
+#include &quot;mrcp_resource_factory.h&quot;
</ins><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_stream.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -173,7 +174,15 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t parse_gen_test_run(apt_test_suite_t *suite, int argc, const char * const *argv)
</span><span class="cx"> {
</span><del>-        mrcp_resource_factory_t *factory = mrcp_default_factory_create(suite-&gt;pool);
</del><ins>+        mrcp_resource_factory_t *factory;
+        mrcp_resource_loader_t *resource_loader;
+        resource_loader = mrcp_resource_loader_create(TRUE,suite-&gt;pool);
+        if(!resource_loader) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Loader&quot;);
+                return FALSE;
+        }
+        
+        factory = mrcp_resource_factory_get(resource_loader);
</ins><span class="cx">         if(!factory) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Factory&quot;);
</span><span class="cx">                 return FALSE;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcptestsmrcptestsrcset_get_suitec"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/set_get_suite.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/set_get_suite.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/tests/mrcptest/src/set_get_suite.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -17,7 +17,8 @@
</span><span class="cx"> #include &quot;apt_test_suite.h&quot;
</span><span class="cx"> #include &quot;apt_log.h&quot;
</span><span class="cx"> /* common includes */
</span><del>-#include &quot;mrcp_default_factory.h&quot;
</del><ins>+#include &quot;mrcp_resource_loader.h&quot;
+#include &quot;mrcp_resource_factory.h&quot;
</ins><span class="cx"> #include &quot;mrcp_message.h&quot;
</span><span class="cx"> #include &quot;mrcp_generic_header.h&quot;
</span><span class="cx"> /* synthesizer includes */
</span><span class="lines">@@ -38,9 +39,12 @@
</span><span class="cx"> static mrcp_message_t* speak_request_create(mrcp_resource_factory_t *factory, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mrcp_message_t *message;
</span><ins>+        mrcp_resource_t *resource = mrcp_resource_get(factory,MRCP_SYNTHESIZER_RESOURCE);
+        if(!resource) {
+                return NULL;
+        }
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Create SPEAK Request&quot;);
</span><del>-        message = mrcp_request_create(MRCP_SYNTHESIZER_RESOURCE,SYNTHESIZER_SPEAK,pool);
-        mrcp_message_resourcify_by_id(factory,message);
</del><ins>+        message = mrcp_request_create(resource,MRCP_VERSION_2,SYNTHESIZER_SPEAK,pool);
</ins><span class="cx">         if(message) {
</span><span class="cx">                 mrcp_generic_header_t *generic_header;
</span><span class="cx">                 mrcp_synth_header_t *synth_header;
</span><span class="lines">@@ -156,9 +160,12 @@
</span><span class="cx"> static mrcp_message_t* get_params_request_create(mrcp_resource_factory_t *factory, apr_pool_t *pool)
</span><span class="cx"> {
</span><span class="cx">         mrcp_message_t *message;
</span><ins>+        mrcp_resource_t *resource = mrcp_resource_get(factory,MRCP_SYNTHESIZER_RESOURCE);
+        if(!resource) {
+                return NULL;
+        }
</ins><span class="cx">         apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,&quot;Create GET-PARAMS Request&quot;);
</span><del>-        message = mrcp_request_create(MRCP_SYNTHESIZER_RESOURCE,SYNTHESIZER_GET_PARAMS,pool);
-        mrcp_message_resourcify_by_id(factory,message);
</del><ins>+        message = mrcp_request_create(resource,MRCP_VERSION_2,SYNTHESIZER_GET_PARAMS,pool);
</ins><span class="cx">         if(message) {
</span><span class="cx">                 apt_str_t param_name;
</span><span class="cx">                 apt_str_t param_value;
</span><span class="lines">@@ -289,7 +296,15 @@
</span><span class="cx"> 
</span><span class="cx"> static apt_bool_t set_get_test_run(apt_test_suite_t *suite, int argc, const char * const *argv)
</span><span class="cx"> {
</span><del>-        mrcp_resource_factory_t *factory = mrcp_default_factory_create(suite-&gt;pool);
</del><ins>+        mrcp_resource_factory_t *factory;
+        mrcp_resource_loader_t *resource_loader;
+        resource_loader = mrcp_resource_loader_create(TRUE,suite-&gt;pool);
+        if(!resource_loader) {
+                apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Loader&quot;);
+                return FALSE;
+        }
+        
+        factory = mrcp_resource_factory_get(resource_loader);
</ins><span class="cx">         if(!factory) {
</span><span class="cx">                 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,&quot;Failed to Create Resource Factory&quot;);
</span><span class="cx">                 return FALSE;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcptestsstrtablegensrcmainc"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/tests/strtablegen/src/main.c (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/tests/strtablegen/src/main.c        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/tests/strtablegen/src/main.c        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -15,6 +15,7 @@
</span><span class="cx">  */
</span><span class="cx"> 
</span><span class="cx"> #include &lt;stdio.h&gt;
</span><ins>+#include &lt;ctype.h&gt;
</ins><span class="cx"> #include &quot;apt_pool.h&quot;
</span><span class="cx"> #include &quot;apt_string_table.h&quot;
</span><span class="cx"> #include &quot;apt_text_stream.h&quot;
</span></span></pre></div>
<a id="freeswitchtrunklibsunimrcpunimrcpsln"></a>
<div class="modfile"><h4>Modified: freeswitch/trunk/libs/unimrcp/unimrcp.sln (15579 => 15580)</h4>
<pre class="diff"><span>
<span class="info">--- freeswitch/trunk/libs/unimrcp/unimrcp.sln        2009-11-20 21:32:09 UTC (rev 15579)
+++ freeswitch/trunk/libs/unimrcp/unimrcp.sln        2009-11-20 22:00:51 UTC (rev 15580)
</span><span class="lines">@@ -27,27 +27,27 @@
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcpsignaling&quot;, &quot;libs\mrcp-signaling\mrcpsignaling.vcproj&quot;, &quot;{12A49562-BAB9-43A3-A21D-15B60BBB4C31}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {B5A00BFA-6083-4FAE-A097-71642D6473B5} = {B5A00BFA-6083-4FAE-A097-71642D6473B5}
</ins><span class="cx">                 {1C320193-46A6-4B34-9C56-8AB584FC1B56} = {1C320193-46A6-4B34-9C56-8AB584FC1B56}
</span><del>-                {B5A00BFA-6083-4FAE-A097-71642D6473B5} = {B5A00BFA-6083-4FAE-A097-71642D6473B5}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcpserver&quot;, &quot;libs\mrcp-server\mrcpserver.vcproj&quot;, &quot;{18B1F35A-10F8-4287-9B37-2D10501B0B38}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {12A49562-BAB9-43A3-A21D-15B60BBB4C31} = {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
</ins><span class="cx">                 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA} = {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}
</span><del>-                {12A49562-BAB9-43A3-A21D-15B60BBB4C31} = {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;libunimrcpserver&quot;, &quot;platforms\libunimrcp-server\libunimrcpserver.vcproj&quot;, &quot;{C98AF157-352E-4737-BD30-A24E2647F5AE}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {DEB01ACB-D65F-4A62-AED9-58C1054499E9} = {DEB01ACB-D65F-4A62-AED9-58C1054499E9}
+                {18B1F35A-10F8-4287-9B37-2D10501B0B38} = {18B1F35A-10F8-4287-9B37-2D10501B0B38}
</ins><span class="cx">                 {746F3632-5BB2-4570-9453-31D6D58A7D8E} = {746F3632-5BB2-4570-9453-31D6D58A7D8E}
</span><del>-                {18B1F35A-10F8-4287-9B37-2D10501B0B38} = {18B1F35A-10F8-4287-9B37-2D10501B0B38}
-                {DEB01ACB-D65F-4A62-AED9-58C1054499E9} = {DEB01ACB-D65F-4A62-AED9-58C1054499E9}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcpsofiasip&quot;, &quot;modules\mrcp-sofiasip\mrcpsofiasip.vcproj&quot;, &quot;{746F3632-5BB2-4570-9453-31D6D58A7D8E}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {12A49562-BAB9-43A3-A21D-15B60BBB4C31} = {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
</ins><span class="cx">                 {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA} = {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}
</span><del>-                {12A49562-BAB9-43A3-A21D-15B60BBB4C31} = {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcpclient&quot;, &quot;libs\mrcp-client\mrcpclient.vcproj&quot;, &quot;{72782932-37CC-46AE-8C7F-9A7B1A6EE108}&quot;
</span><span class="lines">@@ -57,9 +57,9 @@
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;libunimrcpclient&quot;, &quot;platforms\libunimrcp-client\libunimrcpclient.vcproj&quot;, &quot;{EE157390-1E85-416C-946E-620E32C9AD33}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {DEB01ACB-D65F-4A62-AED9-58C1054499E9} = {DEB01ACB-D65F-4A62-AED9-58C1054499E9}
+                {746F3632-5BB2-4570-9453-31D6D58A7D8E} = {746F3632-5BB2-4570-9453-31D6D58A7D8E}
</ins><span class="cx">                 {72782932-37CC-46AE-8C7F-9A7B1A6EE108} = {72782932-37CC-46AE-8C7F-9A7B1A6EE108}
</span><del>-                {746F3632-5BB2-4570-9453-31D6D58A7D8E} = {746F3632-5BB2-4570-9453-31D6D58A7D8E}
-                {DEB01ACB-D65F-4A62-AED9-58C1054499E9} = {DEB01ACB-D65F-4A62-AED9-58C1054499E9}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;unimrcpclient&quot;, &quot;platforms\unimrcp-client\unimrcpclient.vcproj&quot;, &quot;{57FAF32E-49FD-491F-895D-132D0D5EFE0A}&quot;
</span><span class="lines">@@ -74,8 +74,8 @@
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcpengine&quot;, &quot;libs\mrcp-engine\mrcpengine.vcproj&quot;, &quot;{843425BE-9A9A-44F4-A4E3-4B57D6ABD53C}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {B5A00BFA-6083-4FAE-A097-71642D6473B5} = {B5A00BFA-6083-4FAE-A097-71642D6473B5}
</ins><span class="cx">                 {1C320193-46A6-4B34-9C56-8AB584FC1B56} = {1C320193-46A6-4B34-9C56-8AB584FC1B56}
</span><del>-                {B5A00BFA-6083-4FAE-A097-71642D6473B5} = {B5A00BFA-6083-4FAE-A097-71642D6473B5}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;demosynth&quot;, &quot;plugins\demo-synth\demosynth.vcproj&quot;, &quot;{92BFA534-C419-4EB2-AAA3-510653F38F08}&quot;
</span><span class="lines">@@ -127,8 +127,8 @@
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcpunirtsp&quot;, &quot;modules\mrcp-unirtsp\mrcpunirtsp.vcproj&quot;, &quot;{DEB01ACB-D65F-4A62-AED9-58C1054499E9}&quot;
</span><span class="cx">         ProjectSection(ProjectDependencies) = postProject
</span><ins>+                {12A49562-BAB9-43A3-A21D-15B60BBB4C31} = {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
</ins><span class="cx">                 {504B3154-7A4F-459D-9877-B951021C3F1F} = {504B3154-7A4F-459D-9877-B951021C3F1F}
</span><del>-                {12A49562-BAB9-43A3-A21D-15B60BBB4C31} = {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
</del><span class="cx">         EndProjectSection
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;prepare&quot;, &quot;build\tools\prepare.vcproj&quot;, &quot;{01D63BF5-7798-4746-852A-4B45229BB735}&quot;
</span><span class="lines">@@ -150,6 +150,26 @@
</span><span class="cx"> EndProject
</span><span class="cx"> Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;preparesphinx&quot;, &quot;build\tools\preparesphinx.vcproj&quot;, &quot;{71D62A04-8EF6-4C6B-AC12-0C15A875E53A}&quot;
</span><span class="cx"> EndProject
</span><ins>+Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;asrclient&quot;, &quot;platforms\asr-client\asrclient.vcproj&quot;, &quot;{6B83AC6D-01CE-4E1C-81CE-02AD8116C684}&quot;
+        ProjectSection(ProjectDependencies) = postProject
+                {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3} = {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}
+        EndProjectSection
+EndProject
+Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;libasrclient&quot;, &quot;platforms\libasr-client\libasrclient.vcproj&quot;, &quot;{272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}&quot;
+        ProjectSection(ProjectDependencies) = postProject
+                {EE157390-1E85-416C-946E-620E32C9AD33} = {EE157390-1E85-416C-946E-620E32C9AD33}
+        EndProjectSection
+EndProject
+Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;umc&quot;, &quot;platforms\umc\umc.vcproj&quot;, &quot;{CD1C52C1-D8E1-4654-AE65-6CCAB38DE894}&quot;
+        ProjectSection(ProjectDependencies) = postProject
+                {EE157390-1E85-416C-946E-620E32C9AD33} = {EE157390-1E85-416C-946E-620E32C9AD33}
+        EndProjectSection
+EndProject
+Project(&quot;{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}&quot;) = &quot;mrcprecorder&quot;, &quot;plugins\mrcp-recorder\mrcprecorder.vcproj&quot;, &quot;{5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2}&quot;
+        ProjectSection(ProjectDependencies) = postProject
+                {843425BE-9A9A-44F4-A4E3-4B57D6ABD53C} = {843425BE-9A9A-44F4-A4E3-4B57D6ABD53C}
+        EndProjectSection
+EndProject
</ins><span class="cx"> Global
</span><span class="cx">         GlobalSection(SolutionConfigurationPlatforms) = preSolution
</span><span class="cx">                 Debug|Win32 = Debug|Win32
</span><span class="lines">@@ -256,6 +276,22 @@
</span><span class="cx">                 {56F6FB96-2BC7-4CAE-A8BF-6A0FAEC90556}.Release|Win32.ActiveCfg = Release|Win32
</span><span class="cx">                 {71D62A04-8EF6-4C6B-AC12-0C15A875E53A}.Debug|Win32.ActiveCfg = Debug|Win32
</span><span class="cx">                 {71D62A04-8EF6-4C6B-AC12-0C15A875E53A}.Release|Win32.ActiveCfg = Release|Win32
</span><ins>+                {6B83AC6D-01CE-4E1C-81CE-02AD8116C684}.Debug|Win32.ActiveCfg = Debug|Win32
+                {6B83AC6D-01CE-4E1C-81CE-02AD8116C684}.Debug|Win32.Build.0 = Debug|Win32
+                {6B83AC6D-01CE-4E1C-81CE-02AD8116C684}.Release|Win32.ActiveCfg = Release|Win32
+                {6B83AC6D-01CE-4E1C-81CE-02AD8116C684}.Release|Win32.Build.0 = Release|Win32
+                {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}.Debug|Win32.ActiveCfg = Debug|Win32
+                {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}.Debug|Win32.Build.0 = Debug|Win32
+                {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}.Release|Win32.ActiveCfg = Release|Win32
+                {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3}.Release|Win32.Build.0 = Release|Win32
+                {CD1C52C1-D8E1-4654-AE65-6CCAB38DE894}.Debug|Win32.ActiveCfg = Debug|Win32
+                {CD1C52C1-D8E1-4654-AE65-6CCAB38DE894}.Debug|Win32.Build.0 = Debug|Win32
+                {CD1C52C1-D8E1-4654-AE65-6CCAB38DE894}.Release|Win32.ActiveCfg = Release|Win32
+                {CD1C52C1-D8E1-4654-AE65-6CCAB38DE894}.Release|Win32.Build.0 = Release|Win32
+                {5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2}.Debug|Win32.ActiveCfg = Debug|Win32
+                {5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2}.Debug|Win32.Build.0 = Debug|Win32
+                {5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2}.Release|Win32.ActiveCfg = Release|Win32
+                {5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2}.Release|Win32.Build.0 = Release|Win32
</ins><span class="cx">         EndGlobalSection
</span><span class="cx">         GlobalSection(SolutionProperties) = preSolution
</span><span class="cx">                 HideSolutionNode = FALSE
</span><span class="lines">@@ -276,11 +312,15 @@
</span><span class="cx">                 {C98AF157-352E-4737-BD30-A24E2647F5AE} = {8E282AE2-038C-49FE-AC67-BC9615AFD800}
</span><span class="cx">                 {EE157390-1E85-416C-946E-620E32C9AD33} = {8E282AE2-038C-49FE-AC67-BC9615AFD800}
</span><span class="cx">                 {57FAF32E-49FD-491F-895D-132D0D5EFE0A} = {8E282AE2-038C-49FE-AC67-BC9615AFD800}
</span><ins>+                {6B83AC6D-01CE-4E1C-81CE-02AD8116C684} = {8E282AE2-038C-49FE-AC67-BC9615AFD800}
+                {272FAFA8-2B2F-4716-B95F-3B37CF2E0CB3} = {8E282AE2-038C-49FE-AC67-BC9615AFD800}
+                {CD1C52C1-D8E1-4654-AE65-6CCAB38DE894} = {8E282AE2-038C-49FE-AC67-BC9615AFD800}
</ins><span class="cx">                 {92BFA534-C419-4EB2-AAA3-510653F38F08} = {09BABD45-8F30-4F99-B8B8-8DD78F6804DB}
</span><span class="cx">                 {B495B6D9-AF84-479D-B30A-313C16EF8BFD} = {09BABD45-8F30-4F99-B8B8-8DD78F6804DB}
</span><span class="cx">                 {729EF28E-38C9-40DE-A138-87785F021411} = {09BABD45-8F30-4F99-B8B8-8DD78F6804DB}
</span><span class="cx">                 {3C614AE8-B611-4D43-A9AF-1CAA440A9F69} = {09BABD45-8F30-4F99-B8B8-8DD78F6804DB}
</span><span class="cx">                 {56F6FB96-2BC7-4CAE-A8BF-6A0FAEC90556} = {09BABD45-8F30-4F99-B8B8-8DD78F6804DB}
</span><ins>+                {5AFB8B04-AEB9-408C-B53E-AFBC44B5F3F2} = {09BABD45-8F30-4F99-B8B8-8DD78F6804DB}
</ins><span class="cx">                 {79EF9F1D-E211-4ED1-91D2-FC935AB3A872} = {AC4356E8-48A1-4D2D-AFB1-11CF30B974CD}
</span><span class="cx">                 {429C907B-97D1-4B2D-9B0E-A14A5BFDAD15} = {AC4356E8-48A1-4D2D-AFB1-11CF30B974CD}
</span><span class="cx">                 {DCF01B1C-5268-44F3-9130-D647FABFB663} = {AC4356E8-48A1-4D2D-AFB1-11CF30B974CD}
</span></span></pre>
</div>
</div>
<div id="footer">See you at ClueCon</div>

</body>
</html>