mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-11-15 05:48:33 +00:00
inital checkin of unimrcp svn revision 985 from http://unimrcp.googlecode.com/svn/trunk/
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13790 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
ec90221783
commit
da925bddf8
349 files changed
+47866
No files matched your search
@@ -0,0 +1,4 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
SUBDIRS = libunimrcp-server unimrcp-server \
|
||||
libunimrcp-client unimrcp-client
|
||||
@@ -0,0 +1,34 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/platforms/libunimrcp-client/include \
|
||||
-I$(top_srcdir)/modules/mrcp-sofiasip/include \
|
||||
-I$(top_srcdir)/modules/mrcp-unirtsp/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 \
|
||||
-I$(top_srcdir)/build \
|
||||
$(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
|
||||
|
||||
lib_LTLIBRARIES = libunimrcpclient.la
|
||||
|
||||
include_HEADERS = include/unimrcp_client.h
|
||||
|
||||
libunimrcpclient_la_SOURCES = src/unimrcp_client.c
|
||||
|
||||
libunimrcpclient_la_LIBADD = $(top_builddir)/modules/mrcp-sofiasip/libmrcpsofiasip.la \
|
||||
$(top_builddir)/modules/mrcp-unirtsp/libmrcpunirtsp.la \
|
||||
$(top_builddir)/libs/mrcpv2-transport/libmrcpv2transport.la \
|
||||
$(top_builddir)/libs/mrcp-client/libmrcpclient.la \
|
||||
$(top_builddir)/libs/mrcp-signaling/libmrcpsignaling.la \
|
||||
$(top_builddir)/libs/mrcp/libmrcp.la \
|
||||
$(top_builddir)/libs/mpf/libmpf.la \
|
||||
$(top_builddir)/libs/apr-toolkit/libaprtoolkit.la \
|
||||
$(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS) $(UNIMRCP_SOFIA_LIBS)
|
||||
|
||||
libunimrcpclient_la_LDFLAGS = $(UNI_LT_VERSION)
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __UNIMRCP_CLIENT_H__
|
||||
#define __UNIMRCP_CLIENT_H__
|
||||
|
||||
/**
|
||||
* @file unimrcp_client.h
|
||||
* @brief UniMRCP Client
|
||||
*/
|
||||
|
||||
#include "mrcp_client.h"
|
||||
|
||||
APT_BEGIN_EXTERN_C
|
||||
|
||||
/**
|
||||
* Create UniMRCP client.
|
||||
* @param dir_layout the dir layout structure
|
||||
*/
|
||||
MRCP_DECLARE(mrcp_client_t*) unimrcp_client_create(apt_dir_layout_t *dir_layout);
|
||||
|
||||
|
||||
APT_END_EXTERN_C
|
||||
|
||||
#endif /*__UNIMRCP_CLIENT_H__*/
|
||||
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="libunimrcpclient"
|
||||
ProjectGUID="{EE157390-1E85-416C-946E-620E32C9AD33}"
|
||||
RootNamespace="libunimrcpclient"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unidebug.vsprops;$(SolutionDir)build\vsprops\unimrcpclient.vsprops"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(ProjectRootDir)modules\mrcp-sofiasip\include";"$(ProjectRootDir)modules\mrcp-unirtsp\include""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unirelease.vsprops;$(SolutionDir)build\vsprops\unimrcpclient.vsprops"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(ProjectRootDir)modules\mrcp-sofiasip\include";"$(ProjectRootDir)modules\mrcp-unirtsp\include""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="include"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\build\uni_version.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\unimrcp_client.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\unimrcp_client.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,596 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <apr_xml.h>
|
||||
#include "unimrcp_client.h"
|
||||
#include "uni_version.h"
|
||||
#include "mrcp_default_factory.h"
|
||||
#include "mpf_engine.h"
|
||||
#include "mpf_codec_manager.h"
|
||||
#include "mpf_rtp_termination_factory.h"
|
||||
#include "mrcp_sofiasip_client_agent.h"
|
||||
#include "mrcp_unirtsp_client_agent.h"
|
||||
#include "mrcp_client_connection.h"
|
||||
#include "apt_net.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
#define CONF_FILE_NAME "unimrcpclient.xml"
|
||||
#define DEFAULT_CONF_DIR_PATH "../conf"
|
||||
|
||||
#define DEFAULT_LOCAL_IP_ADDRESS "127.0.0.1"
|
||||
#define DEFAULT_REMOTE_IP_ADDRESS "127.0.0.1"
|
||||
#define DEFAULT_SIP_LOCAL_PORT 8062
|
||||
#define DEFAULT_SIP_REMOTE_PORT 8060
|
||||
#define DEFAULT_RTP_PORT_MIN 4000
|
||||
#define DEFAULT_RTP_PORT_MAX 5000
|
||||
|
||||
#define DEFAULT_SOFIASIP_UA_NAME "UniMRCP SofiaSIP"
|
||||
#define DEFAULT_SDP_ORIGIN "UniMRCPClient"
|
||||
#define DEFAULT_RESOURCE_LOCATION "media"
|
||||
|
||||
#define XML_FILE_BUFFER_LENGTH 2000
|
||||
|
||||
static apr_xml_doc* unimrcp_client_config_parse(const char *path, apr_pool_t *pool);
|
||||
static apt_bool_t unimrcp_client_config_load(mrcp_client_t *client, const apr_xml_doc *doc, apr_pool_t *pool);
|
||||
|
||||
/** Start UniMRCP client */
|
||||
MRCP_DECLARE(mrcp_client_t*) unimrcp_client_create(apt_dir_layout_t *dir_layout)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
apr_xml_doc *doc;
|
||||
mrcp_resource_factory_t *resource_factory;
|
||||
mpf_codec_manager_t *codec_manager;
|
||||
mrcp_client_t *client;
|
||||
|
||||
if(!dir_layout) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"UniMRCP Client ["UNI_VERSION_STRING"]");
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"APR ["APR_VERSION_STRING"]");
|
||||
client = mrcp_client_create(dir_layout);
|
||||
if(!client) {
|
||||
return NULL;
|
||||
}
|
||||
pool = mrcp_client_memory_pool_get(client);
|
||||
if(!pool) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
doc = unimrcp_client_config_parse(dir_layout->conf_dir_path,pool);
|
||||
if(doc) {
|
||||
unimrcp_client_config_load(client,doc,pool);
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
/** Parse config file */
|
||||
static apr_xml_doc* unimrcp_client_config_parse(const char *dir_path, apr_pool_t *pool)
|
||||
{
|
||||
apr_xml_parser *parser = NULL;
|
||||
apr_xml_doc *doc = NULL;
|
||||
apr_file_t *fd = NULL;
|
||||
apr_status_t rv;
|
||||
const char *file_path;
|
||||
|
||||
if(!dir_path) {
|
||||
dir_path = DEFAULT_CONF_DIR_PATH;
|
||||
}
|
||||
if(*dir_path == '\0') {
|
||||
file_path = CONF_FILE_NAME;
|
||||
}
|
||||
else {
|
||||
file_path = apr_psprintf(pool,"%s/%s",dir_path,CONF_FILE_NAME);
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Open Config File [%s]",file_path);
|
||||
rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
|
||||
if(rv != APR_SUCCESS) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Config File [%s]",file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = apr_xml_parse_file(pool,&parser,&doc,fd,XML_FILE_BUFFER_LENGTH);
|
||||
if(rv != APR_SUCCESS) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse Config File [%s]",file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apr_file_close(fd);
|
||||
return doc;
|
||||
}
|
||||
|
||||
static apt_bool_t param_name_value_get(const apr_xml_elem *elem, const apr_xml_attr **name, const apr_xml_attr **value)
|
||||
{
|
||||
const apr_xml_attr *attr;
|
||||
if(!name || !value) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*name = NULL;
|
||||
*value = NULL;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
*name = attr;
|
||||
}
|
||||
else if(strcasecmp(attr->name,"value") == 0) {
|
||||
*value = attr;
|
||||
}
|
||||
}
|
||||
return (*name && *value) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static char* ip_addr_get(const char *value, apr_pool_t *pool)
|
||||
{
|
||||
if(!value || strcasecmp(value,"auto") == 0) {
|
||||
char *addr = DEFAULT_LOCAL_IP_ADDRESS;
|
||||
apt_ip_get(&addr,pool);
|
||||
return addr;
|
||||
}
|
||||
return apr_pstrdup(pool,value);
|
||||
}
|
||||
|
||||
/** Load map of MRCP resource names */
|
||||
static apt_bool_t resource_map_load(apr_table_t *resource_map, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
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,"Loading Resource Map");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
apr_table_set(resource_map,attr_name->value,attr_value->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load SofiaSIP signaling agent */
|
||||
static mrcp_sig_agent_t* unimrcp_client_sofiasip_agent_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
mrcp_sofia_client_config_t *config = mrcp_sofiasip_client_config_alloc(pool);
|
||||
config->local_ip = DEFAULT_LOCAL_IP_ADDRESS;
|
||||
config->local_port = DEFAULT_SIP_LOCAL_PORT;
|
||||
config->remote_ip = DEFAULT_REMOTE_IP_ADDRESS;
|
||||
config->remote_port = DEFAULT_SIP_REMOTE_PORT;
|
||||
config->ext_ip = NULL;
|
||||
config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
|
||||
config->origin = DEFAULT_SDP_ORIGIN;
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SofiaSIP Agent");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"client-ip") == 0) {
|
||||
config->local_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"client-ext-ip") == 0) {
|
||||
config->ext_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"client-port") == 0) {
|
||||
config->local_port = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"server-ip") == 0) {
|
||||
config->remote_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"server-port") == 0) {
|
||||
config->remote_port = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"server-username") == 0) {
|
||||
config->remote_user_name = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"force-destination") == 0) {
|
||||
config->force_destination = atoi(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sip-transport") == 0) {
|
||||
config->transport = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"ua-name") == 0) {
|
||||
config->user_agent_name = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
|
||||
config->origin = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mrcp_sofiasip_client_agent_create(config,pool);
|
||||
}
|
||||
|
||||
/** Load UniRTSP signaling agent */
|
||||
static mrcp_sig_agent_t* unimrcp_client_rtsp_agent_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
rtsp_client_config_t *config = mrcp_unirtsp_client_config_alloc(pool);
|
||||
config->origin = DEFAULT_SDP_ORIGIN;
|
||||
config->resource_location = DEFAULT_RESOURCE_LOCATION;
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading UniRTSP Agent");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"server-ip") == 0) {
|
||||
config->server_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"server-port") == 0) {
|
||||
config->server_port = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"resource-location") == 0) {
|
||||
config->resource_location = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
|
||||
config->origin = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
|
||||
config->max_connection_count = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"force-destination") == 0) {
|
||||
config->force_destination = atoi(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(elem->name,"resourcemap") == 0) {
|
||||
resource_map_load(config->resource_map,elem,pool);
|
||||
}
|
||||
}
|
||||
return mrcp_unirtsp_client_agent_create(config,pool);
|
||||
}
|
||||
|
||||
/** Load signaling agents */
|
||||
static apt_bool_t unimrcp_client_signaling_agents_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Signaling Agents");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"agent") == 0) {
|
||||
mrcp_sig_agent_t *sig_agent = NULL;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else if(strcasecmp(attr->name,"class") == 0) {
|
||||
if(strcasecmp(attr->value,"SofiaSIP") == 0) {
|
||||
sig_agent = unimrcp_client_sofiasip_agent_load(client,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(attr->value,"UniRTSP") == 0) {
|
||||
sig_agent = unimrcp_client_rtsp_agent_load(client,elem,pool);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
if(sig_agent) {
|
||||
mrcp_client_signaling_agent_register(client,sig_agent,name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load MRCPv2 connection agent */
|
||||
static mrcp_connection_agent_t* unimrcp_client_connection_agent_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apr_size_t max_connection_count = 100;
|
||||
apt_bool_t offer_new_connection = FALSE;
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Agent");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
|
||||
max_connection_count = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"offer-new-connection") == 0) {
|
||||
offer_new_connection = atoi(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mrcp_client_connection_agent_create(max_connection_count,offer_new_connection,pool);
|
||||
}
|
||||
|
||||
/** Load MRCPv2 conection agents */
|
||||
static apt_bool_t unimrcp_client_connection_agents_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Connection Agents");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"agent") == 0) {
|
||||
mrcp_connection_agent_t *connection_agent;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
connection_agent = unimrcp_client_connection_agent_load(client,elem,pool);
|
||||
if(connection_agent) {
|
||||
mrcp_client_connection_agent_register(client,connection_agent,name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load RTP termination factory */
|
||||
static mpf_termination_factory_t* unimrcp_client_rtp_factory_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
char *rtp_ip = DEFAULT_LOCAL_IP_ADDRESS;
|
||||
char *rtp_ext_ip = NULL;
|
||||
mpf_rtp_config_t *rtp_config = mpf_rtp_config_create(pool);
|
||||
rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
|
||||
rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Termination Factory");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"rtp-ip") == 0) {
|
||||
rtp_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-ext-ip") == 0) {
|
||||
rtp_ext_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-port-min") == 0) {
|
||||
rtp_config->rtp_port_min = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-port-max") == 0) {
|
||||
rtp_config->rtp_port_max = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"playout-delay") == 0) {
|
||||
rtp_config->jb_config.initial_playout_delay = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"min-playout-delay") == 0) {
|
||||
rtp_config->jb_config.min_playout_delay = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"max-playout-delay") == 0) {
|
||||
rtp_config->jb_config.max_playout_delay = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"codecs") == 0) {
|
||||
const mpf_codec_manager_t *codec_manager = mrcp_client_codec_manager_get(client);
|
||||
if(codec_manager) {
|
||||
mpf_codec_manager_codec_list_load(codec_manager,&rtp_config->codec_list,attr_value->value,pool);
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"ptime") == 0) {
|
||||
rtp_config->ptime = (apr_uint16_t)atol(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
apt_string_set(&rtp_config->ip,rtp_ip);
|
||||
if(rtp_ext_ip) {
|
||||
apt_string_set(&rtp_config->ext_ip,rtp_ext_ip);
|
||||
}
|
||||
return mpf_rtp_termination_factory_create(rtp_config,pool);
|
||||
}
|
||||
|
||||
/** Load media engines */
|
||||
static apt_bool_t unimrcp_client_media_engines_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engines");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"engine") == 0) {
|
||||
mpf_engine_t *media_engine;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engine");
|
||||
media_engine = mpf_engine_create(pool);
|
||||
if(media_engine) {
|
||||
mrcp_client_media_engine_register(client,media_engine,name);
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(elem->name,"rtp") == 0) {
|
||||
mpf_termination_factory_t *rtp_factory;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
rtp_factory = unimrcp_client_rtp_factory_load(client,elem,pool);
|
||||
if(rtp_factory) {
|
||||
mrcp_client_rtp_factory_register(client,rtp_factory,name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load settings */
|
||||
static apt_bool_t unimrcp_client_settings_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Settings");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"signaling") == 0) {
|
||||
unimrcp_client_signaling_agents_load(client,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"connection") == 0) {
|
||||
unimrcp_client_connection_agents_load(client,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"media") == 0) {
|
||||
unimrcp_client_media_engines_load(client,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load profile */
|
||||
static apt_bool_t unimrcp_client_profile_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const char *name = NULL;
|
||||
mrcp_profile_t *profile;
|
||||
mrcp_sig_agent_t *sig_agent = NULL;
|
||||
mrcp_connection_agent_t *cnt_agent = NULL;
|
||||
mpf_engine_t *media_engine = NULL;
|
||||
mpf_termination_factory_t *rtp_factory = NULL;
|
||||
const apr_xml_elem *elem;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = root->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profile [%s]",name);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
if(!name) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load Profile: no profile name specified");
|
||||
return FALSE;
|
||||
}
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Loading Profile %s [%s]",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"signaling-agent") == 0) {
|
||||
sig_agent = mrcp_client_signaling_agent_get(client,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"connection-agent") == 0) {
|
||||
cnt_agent = mrcp_client_connection_agent_get(client,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"media-engine") == 0) {
|
||||
media_engine = mrcp_client_media_engine_get(client,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-factory") == 0) {
|
||||
rtp_factory = mrcp_client_rtp_factory_get(client,attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Profile [%s]",name);
|
||||
profile = mrcp_client_profile_create(NULL,sig_agent,cnt_agent,media_engine,rtp_factory,pool);
|
||||
return mrcp_client_profile_register(client,profile,name);
|
||||
}
|
||||
|
||||
/** Load profiles */
|
||||
static apt_bool_t unimrcp_client_profiles_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profiles");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"profile") == 0) {
|
||||
unimrcp_client_profile_load(client,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load configuration (settings and profiles) */
|
||||
static apt_bool_t unimrcp_client_config_load(mrcp_client_t *client, const apr_xml_doc *doc, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
const apr_xml_elem *root = doc->root;
|
||||
if(!root || strcasecmp(root->name,"unimrcpclient") != 0) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Document");
|
||||
return FALSE;
|
||||
}
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"settings") == 0) {
|
||||
unimrcp_client_settings_load(client,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"profiles") == 0) {
|
||||
unimrcp_client_profiles_load(client,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/platforms/libunimrcp-server/include \
|
||||
-I$(top_srcdir)/modules/mrcp-sofiasip/include \
|
||||
-I$(top_srcdir)/modules/mrcp-unirtsp/include \
|
||||
-I$(top_srcdir)/libs/mrcp-server/include \
|
||||
-I$(top_srcdir)/libs/mrcp-engine/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 \
|
||||
-I$(top_srcdir)/build \
|
||||
$(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
|
||||
|
||||
lib_LTLIBRARIES = libunimrcpserver.la
|
||||
|
||||
include_HEADERS = include/unimrcp_server.h
|
||||
|
||||
libunimrcpserver_la_SOURCES = src/unimrcp_server.c
|
||||
|
||||
libunimrcpserver_la_LIBADD = $(top_builddir)/modules/mrcp-sofiasip/libmrcpsofiasip.la \
|
||||
$(top_builddir)/modules/mrcp-unirtsp/libmrcpunirtsp.la \
|
||||
$(top_builddir)/libs/mrcp-server/libmrcpserver.la \
|
||||
$(top_builddir)/libs/mrcp-signaling/libmrcpsignaling.la \
|
||||
$(top_builddir)/libs/mrcpv2-transport/libmrcpv2transport.la \
|
||||
$(top_builddir)/libs/mrcp-engine/libmrcpengine.la \
|
||||
$(top_builddir)/libs/mrcp/libmrcp.la \
|
||||
$(top_builddir)/libs/mpf/libmpf.la \
|
||||
$(top_builddir)/libs/apr-toolkit/libaprtoolkit.la \
|
||||
$(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS) $(UNIMRCP_SOFIA_LIBS)
|
||||
|
||||
libunimrcpserver_la_LDFLAGS = $(UNI_LT_VERSION)
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __UNIMRCP_SERVER_H__
|
||||
#define __UNIMRCP_SERVER_H__
|
||||
|
||||
/**
|
||||
* @file unimrcp_server.h
|
||||
* @brief UniMRCP Server
|
||||
*/
|
||||
|
||||
#include "mrcp_server.h"
|
||||
|
||||
APT_BEGIN_EXTERN_C
|
||||
|
||||
/**
|
||||
* Start UniMRCP server.
|
||||
* @param dir_layout the dir layout structure
|
||||
*/
|
||||
MRCP_DECLARE(mrcp_server_t*) unimrcp_server_start(apt_dir_layout_t *dir_layout);
|
||||
|
||||
/**
|
||||
* Shutdown UniMRCP server.
|
||||
* @param server the MRCP server to shutdown
|
||||
*/
|
||||
MRCP_DECLARE(apt_bool_t) unimrcp_server_shutdown(mrcp_server_t *server);
|
||||
|
||||
APT_END_EXTERN_C
|
||||
|
||||
#endif /*__UNIMRCP_SERVER_H__*/
|
||||
@@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="libunimrcpserver"
|
||||
ProjectGUID="{C98AF157-352E-4737-BD30-A24E2647F5AE}"
|
||||
RootNamespace="libunimrcpserver"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unidebug.vsprops;$(SolutionDir)build\vsprops\unimrcpserver.vsprops"
|
||||
CharacterSet="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(ProjectRootDir)modules\mrcp-sofiasip\include";"$(ProjectRootDir)modules\mrcp-unirtsp\include""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unirelease.vsprops;$(SolutionDir)build\vsprops\unimrcpserver.vsprops"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""$(ProjectRootDir)modules\mrcp-sofiasip\include";"$(ProjectRootDir)modules\mrcp-unirtsp\include""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="include"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\build\uni_version.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\unimrcp_server.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\unimrcp_server.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,701 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <apr_xml.h>
|
||||
#include "unimrcp_server.h"
|
||||
#include "uni_version.h"
|
||||
#include "mrcp_default_factory.h"
|
||||
#include "mpf_engine.h"
|
||||
#include "mpf_codec_manager.h"
|
||||
#include "mpf_rtp_termination_factory.h"
|
||||
#include "mrcp_sofiasip_server_agent.h"
|
||||
#include "mrcp_unirtsp_server_agent.h"
|
||||
#include "mrcp_server_connection.h"
|
||||
#include "apt_net.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
#define CONF_FILE_NAME "unimrcpserver.xml"
|
||||
#define DEFAULT_CONF_DIR_PATH "../conf"
|
||||
#define DEFAULT_PLUGIN_DIR_PATH "../plugin"
|
||||
#ifdef WIN32
|
||||
#define DEFAULT_PLUGIN_EXT "dll"
|
||||
#else
|
||||
#define DEFAULT_PLUGIN_EXT "so"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_IP_ADDRESS "127.0.0.1"
|
||||
#define DEFAULT_SIP_PORT 8060
|
||||
#define DEFAULT_RTSP_PORT 1554
|
||||
#define DEFAULT_MRCP_PORT 1544
|
||||
#define DEFAULT_RTP_PORT_MIN 5000
|
||||
#define DEFAULT_RTP_PORT_MAX 6000
|
||||
|
||||
#define DEFAULT_SOFIASIP_UA_NAME "UniMRCP SofiaSIP"
|
||||
#define DEFAULT_SDP_ORIGIN "UniMRCPServer"
|
||||
|
||||
#define XML_FILE_BUFFER_LENGTH 2000
|
||||
|
||||
static apr_xml_doc* unimrcp_server_config_parse(const char *path, apr_pool_t *pool);
|
||||
static apt_bool_t unimrcp_server_config_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_doc *doc, apr_pool_t *pool);
|
||||
|
||||
/** Start UniMRCP server */
|
||||
MRCP_DECLARE(mrcp_server_t*) unimrcp_server_start(apt_dir_layout_t *dir_layout)
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
apr_xml_doc *doc;
|
||||
mrcp_resource_factory_t *resource_factory;
|
||||
mpf_codec_manager_t *codec_manager;
|
||||
mrcp_server_t *server;
|
||||
|
||||
if(!dir_layout) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"UniMRCP Server ["UNI_VERSION_STRING"]");
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"APR ["APR_VERSION_STRING"]");
|
||||
server = mrcp_server_create(dir_layout);
|
||||
if(!server) {
|
||||
return NULL;
|
||||
}
|
||||
pool = mrcp_server_memory_pool_get(server);
|
||||
if(!pool) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
doc = unimrcp_server_config_parse(dir_layout->conf_dir_path,pool);
|
||||
if(doc) {
|
||||
unimrcp_server_config_load(server,dir_layout->plugin_dir_path,doc,pool);
|
||||
}
|
||||
|
||||
mrcp_server_start(server);
|
||||
return server;
|
||||
}
|
||||
|
||||
/** Shutdown UniMRCP server */
|
||||
MRCP_DECLARE(apt_bool_t) unimrcp_server_shutdown(mrcp_server_t *server)
|
||||
{
|
||||
if(mrcp_server_shutdown(server) == FALSE) {
|
||||
return FALSE;
|
||||
}
|
||||
return mrcp_server_destroy(server);
|
||||
}
|
||||
|
||||
|
||||
/** Parse config file */
|
||||
static apr_xml_doc* unimrcp_server_config_parse(const char *dir_path, apr_pool_t *pool)
|
||||
{
|
||||
apr_xml_parser *parser = NULL;
|
||||
apr_xml_doc *doc = NULL;
|
||||
apr_file_t *fd = NULL;
|
||||
apr_status_t rv;
|
||||
const char *file_path;
|
||||
|
||||
if(!dir_path) {
|
||||
dir_path = DEFAULT_CONF_DIR_PATH;
|
||||
}
|
||||
if(*dir_path == '\0') {
|
||||
file_path = CONF_FILE_NAME;
|
||||
}
|
||||
else {
|
||||
file_path = apr_psprintf(pool,"%s/%s",dir_path,CONF_FILE_NAME);
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Open Config File [%s]",file_path);
|
||||
rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
|
||||
if(rv != APR_SUCCESS) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Config File [%s]",file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = apr_xml_parse_file(pool,&parser,&doc,fd,XML_FILE_BUFFER_LENGTH);
|
||||
if(rv != APR_SUCCESS) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse Config File [%s]",file_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
apr_file_close(fd);
|
||||
return doc;
|
||||
}
|
||||
|
||||
static apt_bool_t param_name_value_get(const apr_xml_elem *elem, const apr_xml_attr **name, const apr_xml_attr **value)
|
||||
{
|
||||
const apr_xml_attr *attr;
|
||||
if(!name || !value) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*name = NULL;
|
||||
*value = NULL;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
*name = attr;
|
||||
}
|
||||
else if(strcasecmp(attr->name,"value") == 0) {
|
||||
*value = attr;
|
||||
}
|
||||
}
|
||||
return (*name && *value) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
static char* ip_addr_get(const char *value, apr_pool_t *pool)
|
||||
{
|
||||
if(!value || strcasecmp(value,"auto") == 0) {
|
||||
char *addr = DEFAULT_IP_ADDRESS;
|
||||
apt_ip_get(&addr,pool);
|
||||
return addr;
|
||||
}
|
||||
return apr_pstrdup(pool,value);
|
||||
}
|
||||
|
||||
/** Load map of MRCP resource names */
|
||||
static apt_bool_t resource_map_load(apr_table_t *resource_map, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
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,"Loading Resource Map");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
apr_table_set(resource_map,attr_name->value,attr_value->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load map of plugins */
|
||||
static apt_bool_t plugin_map_load(apr_table_t *plugin_map, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
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,"Loading Plugin Map");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
apr_table_set(plugin_map,attr_name->value,attr_value->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load SofiaSIP signaling agent */
|
||||
static mrcp_sig_agent_t* unimrcp_server_sofiasip_agent_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
mrcp_sofia_server_config_t *config = mrcp_sofiasip_server_config_alloc(pool);
|
||||
config->local_ip = DEFAULT_IP_ADDRESS;
|
||||
config->local_port = DEFAULT_SIP_PORT;
|
||||
config->ext_ip = NULL;
|
||||
config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
|
||||
config->origin = DEFAULT_SDP_ORIGIN;
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SofiaSIP Agent");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"sip-ip") == 0) {
|
||||
config->local_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sip-ext-ip") == 0) {
|
||||
config->ext_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sip-port") == 0) {
|
||||
config->local_port = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sip-transport") == 0) {
|
||||
config->transport = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"ua-name") == 0) {
|
||||
config->user_agent_name = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
|
||||
config->origin = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"force-destination") == 0) {
|
||||
config->force_destination = atoi(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mrcp_sofiasip_server_agent_create(config,pool);
|
||||
}
|
||||
|
||||
/** Load UniRTSP signaling agent */
|
||||
static mrcp_sig_agent_t* unimrcp_server_rtsp_agent_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
rtsp_server_config_t *config = mrcp_unirtsp_server_config_alloc(pool);
|
||||
config->local_ip = DEFAULT_IP_ADDRESS;
|
||||
config->local_port = DEFAULT_RTSP_PORT;
|
||||
config->origin = DEFAULT_SDP_ORIGIN;
|
||||
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading UniRTSP Agent");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"rtsp-ip") == 0) {
|
||||
config->local_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtsp-port") == 0) {
|
||||
config->local_port = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
|
||||
config->origin = apr_pstrdup(pool,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
|
||||
config->max_connection_count = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"force-destination") == 0) {
|
||||
config->force_destination = atoi(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(elem->name,"resourcemap") == 0) {
|
||||
resource_map_load(config->resource_map,elem,pool);
|
||||
}
|
||||
}
|
||||
return mrcp_unirtsp_server_agent_create(config,pool);
|
||||
}
|
||||
|
||||
/** Load signaling agents */
|
||||
static apt_bool_t unimrcp_server_signaling_agents_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Signaling Agents");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"agent") == 0) {
|
||||
mrcp_sig_agent_t *sig_agent = NULL;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else if(strcasecmp(attr->name,"class") == 0) {
|
||||
if(strcasecmp(attr->value,"SofiaSIP") == 0) {
|
||||
sig_agent = unimrcp_server_sofiasip_agent_load(server,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(attr->value,"UniRTSP") == 0) {
|
||||
sig_agent = unimrcp_server_rtsp_agent_load(server,elem,pool);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
if(sig_agent) {
|
||||
mrcp_server_signaling_agent_register(server,sig_agent,name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load MRCPv2 connection agent */
|
||||
static mrcp_connection_agent_t* unimrcp_server_connection_agent_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
char *mrcp_ip = DEFAULT_IP_ADDRESS;
|
||||
apr_port_t mrcp_port = DEFAULT_MRCP_PORT;
|
||||
apr_size_t max_connection_count = 100;
|
||||
apt_bool_t force_new_connection = FALSE;
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Agent");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"mrcp-ip") == 0) {
|
||||
mrcp_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"mrcp-port") == 0) {
|
||||
mrcp_port = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
|
||||
max_connection_count = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"force-new-connection") == 0) {
|
||||
force_new_connection = atoi(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mrcp_server_connection_agent_create(mrcp_ip,mrcp_port,max_connection_count,force_new_connection,pool);
|
||||
}
|
||||
|
||||
/** Load MRCPv2 conection agents */
|
||||
static apt_bool_t unimrcp_server_connection_agents_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Connection Agents");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"agent") == 0) {
|
||||
mrcp_connection_agent_t *connection_agent;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
connection_agent = unimrcp_server_connection_agent_load(server,elem,pool);
|
||||
if(connection_agent) {
|
||||
mrcp_server_connection_agent_register(server,connection_agent,name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load RTP termination factory */
|
||||
static mpf_termination_factory_t* unimrcp_server_rtp_factory_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
char *rtp_ip = DEFAULT_IP_ADDRESS;
|
||||
char *rtp_ext_ip = NULL;
|
||||
mpf_rtp_config_t *rtp_config = mpf_rtp_config_create(pool);
|
||||
rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
|
||||
rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Termination Factory");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"rtp-ip") == 0) {
|
||||
rtp_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-ext-ip") == 0) {
|
||||
rtp_ext_ip = ip_addr_get(attr_value->value,pool);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-port-min") == 0) {
|
||||
rtp_config->rtp_port_min = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-port-max") == 0) {
|
||||
rtp_config->rtp_port_max = (apr_port_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"playout-delay") == 0) {
|
||||
rtp_config->jb_config.initial_playout_delay = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"min-playout-delay") == 0) {
|
||||
rtp_config->jb_config.min_playout_delay = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"max-playout-delay") == 0) {
|
||||
rtp_config->jb_config.max_playout_delay = atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"codecs") == 0) {
|
||||
const mpf_codec_manager_t *codec_manager = mrcp_server_codec_manager_get(server);
|
||||
if(codec_manager) {
|
||||
mpf_codec_manager_codec_list_load(codec_manager,&rtp_config->codec_list,attr_value->value,pool);
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"ptime") == 0) {
|
||||
rtp_config->ptime = (apr_uint16_t)atol(attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"own-preference") == 0) {
|
||||
rtp_config->own_preferrence = atoi(attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
apt_string_set(&rtp_config->ip,rtp_ip);
|
||||
if(rtp_ext_ip) {
|
||||
apt_string_set(&rtp_config->ext_ip,rtp_ext_ip);
|
||||
}
|
||||
return mpf_rtp_termination_factory_create(rtp_config,pool);
|
||||
}
|
||||
|
||||
/** Load media engines */
|
||||
static apt_bool_t unimrcp_server_media_engines_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engines");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"engine") == 0) {
|
||||
mpf_engine_t *media_engine;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engine");
|
||||
media_engine = mpf_engine_create(pool);
|
||||
if(media_engine) {
|
||||
mrcp_server_media_engine_register(server,media_engine,name);
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(elem->name,"rtp") == 0) {
|
||||
mpf_termination_factory_t *rtp_factory;
|
||||
const char *name = NULL;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = elem->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
rtp_factory = unimrcp_server_rtp_factory_load(server,elem,pool);
|
||||
if(rtp_factory) {
|
||||
mrcp_server_rtp_factory_register(server,rtp_factory,name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load plugin */
|
||||
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)
|
||||
{
|
||||
const char *plugin_name = NULL;
|
||||
const char *plugin_class = NULL;
|
||||
const char *plugin_ext = NULL;
|
||||
const char *plugin_path = NULL;
|
||||
apt_bool_t plugin_enabled = TRUE;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = root->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
plugin_name = apr_pstrdup(pool,attr->value);
|
||||
}
|
||||
else if(strcasecmp(attr->name,"class") == 0) {
|
||||
plugin_class = attr->value;
|
||||
}
|
||||
else if(strcasecmp(attr->name,"ext") == 0) {
|
||||
plugin_ext = attr->value;
|
||||
}
|
||||
else if(strcasecmp(attr->name,"enable") == 0) {
|
||||
plugin_enabled = atoi(attr->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
|
||||
if(!plugin_class || !plugin_enabled) {
|
||||
return FALSE;
|
||||
}
|
||||
if(!plugin_dir_path) {
|
||||
plugin_dir_path = DEFAULT_PLUGIN_DIR_PATH;
|
||||
}
|
||||
if(!plugin_ext) {
|
||||
plugin_ext = DEFAULT_PLUGIN_EXT;
|
||||
}
|
||||
|
||||
if(*plugin_dir_path == '\0') {
|
||||
plugin_path = apr_psprintf(pool,"%s.%s",plugin_class,plugin_ext);
|
||||
}
|
||||
else {
|
||||
plugin_path = apr_psprintf(pool,"%s/%s.%s",plugin_dir_path,plugin_class,plugin_ext);
|
||||
}
|
||||
|
||||
return mrcp_server_plugin_register(server,plugin_path,plugin_name);
|
||||
}
|
||||
|
||||
/** Load plugins */
|
||||
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)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Plugins (Resource Engines)");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"engine") == 0) {
|
||||
unimrcp_server_plugin_load(server,plugin_dir_path,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/** Load settings */
|
||||
static apt_bool_t unimrcp_server_settings_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Settings");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"signaling") == 0) {
|
||||
unimrcp_server_signaling_agents_load(server,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"connection") == 0) {
|
||||
unimrcp_server_connection_agents_load(server,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"media") == 0) {
|
||||
unimrcp_server_media_engines_load(server,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"plugin") == 0) {
|
||||
unimrcp_server_plugins_load(server,plugin_dir_path,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load profile */
|
||||
static apt_bool_t unimrcp_server_profile_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const char *name = NULL;
|
||||
mrcp_profile_t *profile;
|
||||
mrcp_sig_agent_t *sig_agent = NULL;
|
||||
mrcp_connection_agent_t *cnt_agent = NULL;
|
||||
mpf_engine_t *media_engine = NULL;
|
||||
mpf_termination_factory_t *rtp_factory = NULL;
|
||||
apr_table_t *plugin_map = NULL;
|
||||
const apr_xml_elem *elem;
|
||||
const apr_xml_attr *attr;
|
||||
for(attr = root->attr; attr; attr = attr->next) {
|
||||
if(strcasecmp(attr->name,"name") == 0) {
|
||||
name = apr_pstrdup(pool,attr->value);
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profile [%s]",name);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
|
||||
}
|
||||
}
|
||||
if(!name) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load Profile: no profile name specified");
|
||||
return FALSE;
|
||||
}
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"param") == 0) {
|
||||
const apr_xml_attr *attr_name;
|
||||
const apr_xml_attr *attr_value;
|
||||
if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Loading Profile %s [%s]",attr_name->value,attr_value->value);
|
||||
if(strcasecmp(attr_name->value,"signaling-agent") == 0) {
|
||||
sig_agent = mrcp_server_signaling_agent_get(server,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"connection-agent") == 0) {
|
||||
cnt_agent = mrcp_server_connection_agent_get(server,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"media-engine") == 0) {
|
||||
media_engine = mrcp_server_media_engine_get(server,attr_value->value);
|
||||
}
|
||||
else if(strcasecmp(attr_name->value,"rtp-factory") == 0) {
|
||||
rtp_factory = mrcp_server_rtp_factory_get(server,attr_value->value);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(elem->name,"pluginmap") == 0) {
|
||||
plugin_map = apr_table_make(pool,2);
|
||||
plugin_map_load(plugin_map,elem,pool);
|
||||
}
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Profile [%s]",name);
|
||||
profile = mrcp_server_profile_create(NULL,sig_agent,cnt_agent,media_engine,rtp_factory,pool);
|
||||
return mrcp_server_profile_register(server,profile,plugin_map,name);
|
||||
}
|
||||
|
||||
/** Load profiles */
|
||||
static apt_bool_t unimrcp_server_profiles_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profiles");
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"profile") == 0) {
|
||||
unimrcp_server_profile_load(server,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Load configuration (settings and profiles) */
|
||||
static apt_bool_t unimrcp_server_config_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_doc *doc, apr_pool_t *pool)
|
||||
{
|
||||
const apr_xml_elem *elem;
|
||||
const apr_xml_elem *root = doc->root;
|
||||
if(!root || strcasecmp(root->name,"unimrcpserver") != 0) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Document");
|
||||
return FALSE;
|
||||
}
|
||||
for(elem = root->first_child; elem; elem = elem->next) {
|
||||
if(strcasecmp(elem->name,"settings") == 0) {
|
||||
unimrcp_server_settings_load(server,plugin_dir_path,elem,pool);
|
||||
}
|
||||
else if(strcasecmp(elem->name,"profiles") == 0) {
|
||||
unimrcp_server_profiles_load(server,elem,pool);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
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 = unimrcpclient
|
||||
unimrcpclient_SOURCES = src/main.c \
|
||||
src/demo_framework.c \
|
||||
src/demo_synth_application.c \
|
||||
src/demo_recog_application.c \
|
||||
src/demo_bypass_application.c \
|
||||
src/demo_discover_application.c \
|
||||
src/demo_util.c
|
||||
unimrcpclient_LDADD = $(top_builddir)/platforms/libunimrcp-client/libunimrcpclient.la
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DEMO_APPLICATION_H__
|
||||
#define __DEMO_APPLICATION_H__
|
||||
|
||||
/**
|
||||
* @file demo_application.h
|
||||
* @brief Demo MRCP Application
|
||||
*/
|
||||
|
||||
#include "mrcp_application.h"
|
||||
|
||||
APT_BEGIN_EXTERN_C
|
||||
|
||||
/** Demo application declaration */
|
||||
typedef struct demo_application_t demo_application_t;
|
||||
|
||||
/** Demo application */
|
||||
struct demo_application_t {
|
||||
/** MRCP application */
|
||||
mrcp_application_t *application;
|
||||
/** Demo framework */
|
||||
void *framework;
|
||||
|
||||
/** Virtual run method */
|
||||
apt_bool_t (*run)(demo_application_t *application, const char *profile);
|
||||
/** Virtual app_message handler */
|
||||
apt_bool_t (*handler)(demo_application_t *application, const mrcp_app_message_t *app_message);
|
||||
};
|
||||
|
||||
|
||||
/** Create demo synthesizer application */
|
||||
demo_application_t* demo_synth_application_create(apr_pool_t *pool);
|
||||
|
||||
/** Create demo recognizer application */
|
||||
demo_application_t* demo_recog_application_create(apr_pool_t *pool);
|
||||
|
||||
/** Create demo bypass media application */
|
||||
demo_application_t* demo_bypass_application_create(apr_pool_t *pool);
|
||||
|
||||
/** Create demo resource discover application */
|
||||
demo_application_t* demo_discover_application_create(apr_pool_t *pool);
|
||||
|
||||
|
||||
APT_END_EXTERN_C
|
||||
|
||||
#endif /*__DEMO_APPLICATION_H__*/
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DEMO_FRAMEWORK_H__
|
||||
#define __DEMO_FRAMEWORK_H__
|
||||
|
||||
/**
|
||||
* @file demo_framework.h
|
||||
* @brief Demo MRCP Application Framework
|
||||
*/
|
||||
|
||||
#include "mrcp_types.h"
|
||||
|
||||
APT_BEGIN_EXTERN_C
|
||||
|
||||
/** Opaque demo framework declaration */
|
||||
typedef struct demo_framework_t demo_framework_t;
|
||||
|
||||
/**
|
||||
* Create demo framework.
|
||||
*/
|
||||
demo_framework_t* demo_framework_create(apt_dir_layout_t *dir_layout);
|
||||
|
||||
/**
|
||||
* Run demo application.
|
||||
* @param framework the framework to run application for
|
||||
* @param app_name the name of the application to run
|
||||
* @param profile_name the name of the profile to use
|
||||
*/
|
||||
apt_bool_t demo_framework_app_run(demo_framework_t *framework, const char *app_name, const char *profile_name);
|
||||
|
||||
/**
|
||||
* Destroy demo framework.
|
||||
* @param framework the framework to destroy
|
||||
*/
|
||||
apt_bool_t demo_framework_destroy(demo_framework_t *framework);
|
||||
|
||||
APT_END_EXTERN_C
|
||||
|
||||
#endif /*__DEMO_FRAMEWORK_H__*/
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __DEMO_UTIL_H__
|
||||
#define __DEMO_UTIL_H__
|
||||
|
||||
/**
|
||||
* @file demo_util.h
|
||||
* @brief Demo MRCP Utilities
|
||||
*/
|
||||
|
||||
#include "mrcp_application.h"
|
||||
|
||||
APT_BEGIN_EXTERN_C
|
||||
|
||||
/** Create demo MRCP message (SPEAK request) */
|
||||
mrcp_message_t* demo_speak_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout);
|
||||
|
||||
/** Create demo MRCP message (DEFINE-GRAMMAR request) */
|
||||
mrcp_message_t* demo_define_grammar_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout);
|
||||
/** Create demo MRCP message (RECOGNIZE request) */
|
||||
mrcp_message_t* demo_recognize_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout);
|
||||
|
||||
|
||||
/** Create demo RTP termination descriptor */
|
||||
mpf_rtp_termination_descriptor_t* demo_rtp_descriptor_create(apr_pool_t *pool);
|
||||
|
||||
APT_END_EXTERN_C
|
||||
|
||||
#endif /*__DEMO_UTIL_H__*/
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Demo synthesizer scenario (client stack stays out of media path).
|
||||
* C -> S: SIP INVITE or RTPS SETUP (add synthesizer channel)
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
* C -> S: MRCP SPEAK
|
||||
* S -> C: MRCP IN-PROGRESS
|
||||
* S -> X: RTP Start Transmission (RTP stream is sent directly to external endpoint bypassing client stack)
|
||||
* S -> C: MRCP SPEAK-COMPLETE
|
||||
* S -> X: RTP Stop Transmission
|
||||
* C -> S: SIP INVITE or RTPS SETUP (optionally remove synthesizer channel)
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
* C -> S: SIP BYE or RTPS TEARDOWN
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
*/
|
||||
|
||||
#include "demo_application.h"
|
||||
#include "demo_util.h"
|
||||
#include "mrcp_session.h"
|
||||
#include "mrcp_message.h"
|
||||
#include "mrcp_generic_header.h"
|
||||
#include "mrcp_synth_header.h"
|
||||
#include "mrcp_synth_resource.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
typedef struct demo_app_channel_t demo_app_channel_t;
|
||||
|
||||
/** Declaration of synthesizer application channel */
|
||||
struct demo_app_channel_t {
|
||||
/** MRCP control channel */
|
||||
mrcp_channel_t *channel;
|
||||
};
|
||||
|
||||
/** Declaration of demo application methods */
|
||||
static apt_bool_t demo_application_run(demo_application_t *demo_application, const char *profile);
|
||||
static apt_bool_t demo_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message);
|
||||
|
||||
static apt_bool_t demo_application_on_session_update(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t demo_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t demo_application_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t demo_application_on_channel_remove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t demo_application_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message);
|
||||
|
||||
static const mrcp_app_message_dispatcher_t demo_application_dispatcher = {
|
||||
demo_application_on_session_update,
|
||||
demo_application_on_session_terminate,
|
||||
demo_application_on_channel_add,
|
||||
demo_application_on_channel_remove,
|
||||
demo_application_on_message_receive
|
||||
};
|
||||
|
||||
|
||||
/** Create demo bypass media application */
|
||||
demo_application_t* demo_bypass_application_create(apr_pool_t *pool)
|
||||
{
|
||||
demo_application_t *demo_application = apr_palloc(pool,sizeof(demo_application_t));
|
||||
demo_application->application = NULL;
|
||||
demo_application->framework = NULL;
|
||||
demo_application->handler = demo_application_handler;
|
||||
demo_application->run = demo_application_run;
|
||||
return demo_application;
|
||||
}
|
||||
|
||||
/** Create demo channel */
|
||||
static mrcp_channel_t* demo_application_channel_create(mrcp_session_t *session)
|
||||
{
|
||||
mrcp_channel_t *channel;
|
||||
/* create channel */
|
||||
demo_app_channel_t *demo_channel = apr_palloc(session->pool,sizeof(demo_app_channel_t));
|
||||
mpf_rtp_termination_descriptor_t *rtp_descriptor = demo_rtp_descriptor_create(session->pool);
|
||||
channel = mrcp_application_channel_create(
|
||||
session, /* session, channel belongs to */
|
||||
MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
|
||||
NULL, /* no termination (not to use internal media processing) */
|
||||
rtp_descriptor, /* RTP descriptor, used to create RTP termination */
|
||||
demo_channel); /* object to associate */
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
/** Run demo scenario */
|
||||
static apt_bool_t demo_application_run(demo_application_t *demo_application, const char *profile)
|
||||
{
|
||||
mrcp_channel_t *channel;
|
||||
/* create session */
|
||||
mrcp_session_t *session = mrcp_application_session_create(demo_application->application,profile,NULL);
|
||||
if(!session) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* create channel and associate all the required data */
|
||||
channel = demo_application_channel_create(session);
|
||||
if(!channel) {
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* add channel to session (send asynchronous request) */
|
||||
if(mrcp_application_channel_add(session,channel) != TRUE) {
|
||||
/* session and channel are still not referenced
|
||||
and both are allocated from session pool and will
|
||||
be freed with session destroy call */
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the messages sent from the MRCP client stack */
|
||||
static apt_bool_t demo_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message)
|
||||
{
|
||||
/* app_message should be dispatched now,
|
||||
* the default dispatcher is used in demo. */
|
||||
return mrcp_application_message_dispatch(&demo_application_dispatcher,app_message);
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session update requests */
|
||||
static apt_bool_t demo_application_on_session_update(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session terminate requests */
|
||||
static apt_bool_t demo_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* received response to session termination request,
|
||||
now it's safe to destroy no more referenced session */
|
||||
mrcp_application_session_destroy(session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to channel add requests */
|
||||
static apt_bool_t demo_application_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
|
||||
{
|
||||
if(status == MRCP_SIG_STATUS_CODE_SUCCESS) {
|
||||
mpf_rtp_termination_descriptor_t *rtp_descriptor;
|
||||
mrcp_message_t *mrcp_message;
|
||||
const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application);
|
||||
/* create and send SPEAK request */
|
||||
mrcp_message = demo_speak_message_create(session,channel,dir_layout);
|
||||
if(mrcp_message) {
|
||||
mrcp_application_message_send(session,channel,mrcp_message);
|
||||
}
|
||||
rtp_descriptor = mrcp_application_rtp_descriptor_get(channel);
|
||||
if(rtp_descriptor) {
|
||||
mpf_rtp_media_descriptor_t *local_media = rtp_descriptor->audio.local;
|
||||
mpf_rtp_media_descriptor_t *remote_media = rtp_descriptor->audio.remote;
|
||||
if(local_media && remote_media) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Media Attributes: L[%s/%d] R[%s/%d]",
|
||||
local_media->base.ip.buf,
|
||||
local_media->base.port,
|
||||
remote_media->base.ip.buf,
|
||||
remote_media->base.port);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* error case, just terminate the demo */
|
||||
mrcp_application_session_terminate(session);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to channel remove requests */
|
||||
static apt_bool_t demo_application_on_channel_remove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* terminate the demo */
|
||||
mrcp_application_session_terminate(session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the MRCP responses/events */
|
||||
static apt_bool_t demo_application_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
|
||||
{
|
||||
if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
|
||||
/* received MRCP response */
|
||||
if(message->start_line.method_id == SYNTHESIZER_SPEAK) {
|
||||
/* received the response to SPEAK request,
|
||||
waiting for SPEAK-COMPLETE event */
|
||||
}
|
||||
else {
|
||||
/* received unexpected response */
|
||||
}
|
||||
}
|
||||
else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
|
||||
/* received MRCP event */
|
||||
if(message->start_line.method_id == SYNTHESIZER_SPEAK_COMPLETE) {
|
||||
/* received SPEAK-COMPLETE event, remove channel */
|
||||
mrcp_application_channel_remove(session,channel);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Demo resource discovery.
|
||||
* C -> S: SIP OPTIONS or RTPS DESCRIBE
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
*/
|
||||
|
||||
#include "demo_application.h"
|
||||
#include "mrcp_session_descriptor.h"
|
||||
#include "mrcp_control_descriptor.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
|
||||
/** Declaration of synthesizer application methods */
|
||||
static apt_bool_t discover_application_run(demo_application_t *demo_application, const char *profile);
|
||||
static apt_bool_t discover_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message);
|
||||
|
||||
/** Declaration of application message handlers */
|
||||
static apt_bool_t discover_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t discover_application_on_resource_discover(mrcp_application_t *application, mrcp_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_sig_status_code_e status);
|
||||
|
||||
static const mrcp_app_message_dispatcher_t discover_application_dispatcher = {
|
||||
NULL,
|
||||
discover_application_on_session_terminate,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
discover_application_on_resource_discover
|
||||
};
|
||||
|
||||
/** Create demo resource discover application */
|
||||
demo_application_t* demo_discover_application_create(apr_pool_t *pool)
|
||||
{
|
||||
demo_application_t *discover_application = apr_palloc(pool,sizeof(demo_application_t));
|
||||
discover_application->application = NULL;
|
||||
discover_application->framework = NULL;
|
||||
discover_application->handler = discover_application_handler;
|
||||
discover_application->run = discover_application_run;
|
||||
return discover_application;
|
||||
}
|
||||
|
||||
/** Run demo resource discover scenario */
|
||||
static apt_bool_t discover_application_run(demo_application_t *demo_application, const char *profile)
|
||||
{
|
||||
/* create session */
|
||||
mrcp_session_t *session = mrcp_application_session_create(demo_application->application,profile,NULL);
|
||||
if(!session) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* send resource discover request */
|
||||
if(mrcp_application_resource_discover(session) != TRUE) {
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the messages sent from the MRCP client stack */
|
||||
static apt_bool_t discover_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message)
|
||||
{
|
||||
/* app_message should be dispatched now,
|
||||
* the default dispatcher is used in demo. */
|
||||
return mrcp_application_message_dispatch(&discover_application_dispatcher,app_message);
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session terminate requests */
|
||||
static apt_bool_t discover_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* received response to session termination request,
|
||||
now it's safe to destroy no more referenced session */
|
||||
mrcp_application_session_destroy(session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to resource discover requests */
|
||||
static apt_bool_t discover_application_on_resource_discover(mrcp_application_t *application, mrcp_session_t *session, mrcp_session_descriptor_t *descriptor, mrcp_sig_status_code_e status)
|
||||
{
|
||||
if(descriptor && status == MRCP_SIG_STATUS_CODE_SUCCESS) {
|
||||
int i;
|
||||
int count = descriptor->control_media_arr->nelts;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"On Resource Discover [%d]", count);
|
||||
|
||||
for(i = 0; i < count; i++) {
|
||||
mrcp_control_descriptor_t *control_media = mrcp_session_control_media_get(descriptor,i);
|
||||
if(control_media) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"[%d] - %s", i,control_media->resource_name.buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Failed to Discover Resources");
|
||||
}
|
||||
|
||||
mrcp_application_session_terminate(session);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <apr_hash.h>
|
||||
#include "demo_framework.h"
|
||||
#include "demo_application.h"
|
||||
#include "unimrcp_client.h"
|
||||
#include "apt_consumer_task.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
#define FRAMEWORK_TASK_NAME "Framework Task"
|
||||
|
||||
#define MAX_APP_NAME_LENGTH 16
|
||||
#define MAX_PROFILE_NAME_LENGTH 16
|
||||
|
||||
/** Demo framework */
|
||||
struct demo_framework_t {
|
||||
/** MRCP client stack instance */
|
||||
mrcp_client_t *client;
|
||||
/** Message processing task */
|
||||
apt_consumer_task_t *task;
|
||||
/** Table of demo applications */
|
||||
apr_hash_t *application_table;
|
||||
/** Memory to allocate memory from */
|
||||
apr_pool_t *pool;
|
||||
};
|
||||
|
||||
typedef struct framework_task_data_t framework_task_data_t;
|
||||
struct framework_task_data_t {
|
||||
char app_name[MAX_APP_NAME_LENGTH];
|
||||
char profile_name[MAX_PROFILE_NAME_LENGTH];
|
||||
demo_application_t *demo_application;
|
||||
const mrcp_app_message_t *app_message;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
DEMO_APPLICATION_MSG_ID,
|
||||
DEMO_CONSOLE_MSG_ID
|
||||
} framework_msg_type_e;
|
||||
|
||||
static apt_bool_t demo_framework_message_handler(const mrcp_app_message_t *app_message);
|
||||
static apt_bool_t demo_framework_consumer_task_create(demo_framework_t *framework);
|
||||
static apt_bool_t demo_framework_app_register(demo_framework_t *framework, demo_application_t *demo_application, const char *name);
|
||||
|
||||
/** Create demo framework */
|
||||
demo_framework_t* demo_framework_create(apt_dir_layout_t *dir_layout)
|
||||
{
|
||||
demo_framework_t *framework = NULL;
|
||||
mrcp_client_t *client = unimrcp_client_create(dir_layout);
|
||||
if(client) {
|
||||
demo_application_t *demo_application;
|
||||
apr_pool_t *pool = mrcp_client_memory_pool_get(client);
|
||||
/* create demo framework */
|
||||
framework = apr_palloc(pool,sizeof(demo_framework_t));
|
||||
framework->pool = pool;
|
||||
framework->client = client;
|
||||
framework->application_table = apr_hash_make(pool);
|
||||
|
||||
/* create demo synthesizer application */
|
||||
demo_application = demo_synth_application_create(framework->pool);
|
||||
if(demo_application) {
|
||||
demo_framework_app_register(framework,demo_application,"synth");
|
||||
}
|
||||
|
||||
/* create demo recognizer application */
|
||||
demo_application = demo_recog_application_create(framework->pool);
|
||||
if(demo_application) {
|
||||
demo_framework_app_register(framework,demo_application,"recog");
|
||||
}
|
||||
|
||||
/* create demo bypass media application */
|
||||
demo_application = demo_bypass_application_create(framework->pool);
|
||||
if(demo_application) {
|
||||
demo_framework_app_register(framework,demo_application,"bypass");
|
||||
}
|
||||
|
||||
/* create demo resource discover application */
|
||||
demo_application = demo_discover_application_create(framework->pool);
|
||||
if(demo_application) {
|
||||
demo_framework_app_register(framework,demo_application,"discover");
|
||||
}
|
||||
|
||||
demo_framework_consumer_task_create(framework);
|
||||
|
||||
if(framework->task) {
|
||||
apt_task_t *task = apt_consumer_task_base_get(framework->task);
|
||||
apt_task_start(task);
|
||||
}
|
||||
|
||||
/* start client stack */
|
||||
mrcp_client_start(client);
|
||||
}
|
||||
|
||||
return framework;
|
||||
}
|
||||
|
||||
/** Run demo application */
|
||||
apt_bool_t demo_framework_app_run(demo_framework_t *framework, const char *app_name, const char *profile_name)
|
||||
{
|
||||
apt_task_t *task = apt_consumer_task_base_get(framework->task);
|
||||
apt_task_msg_t *task_msg = apt_task_msg_get(task);
|
||||
if(task_msg) {
|
||||
framework_task_data_t *framework_task_data = (framework_task_data_t*)task_msg->data;
|
||||
task_msg->type = TASK_MSG_USER;
|
||||
task_msg->sub_type = DEMO_CONSOLE_MSG_ID;
|
||||
framework_task_data = (framework_task_data_t*) task_msg->data;
|
||||
strcpy(framework_task_data->app_name,app_name);
|
||||
strcpy(framework_task_data->profile_name,profile_name);
|
||||
framework_task_data->app_message = NULL;
|
||||
framework_task_data->demo_application = NULL;
|
||||
apt_task_msg_signal(task,task_msg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Destroy demo framework */
|
||||
apt_bool_t demo_framework_destroy(demo_framework_t *framework)
|
||||
{
|
||||
if(!framework) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(framework->task) {
|
||||
apt_task_t *task = apt_consumer_task_base_get(framework->task);
|
||||
apt_task_terminate(task,TRUE);
|
||||
apt_task_destroy(task);
|
||||
framework->task = NULL;
|
||||
}
|
||||
|
||||
mrcp_client_shutdown(framework->client);
|
||||
return mrcp_client_destroy(framework->client);
|
||||
}
|
||||
|
||||
static apt_bool_t demo_framework_app_register(demo_framework_t *framework, demo_application_t *demo_application, const char *name)
|
||||
{
|
||||
apr_hash_set(framework->application_table,name,APR_HASH_KEY_STRING,demo_application);
|
||||
demo_application->framework = framework;
|
||||
demo_application->application = mrcp_application_create(
|
||||
demo_framework_message_handler,
|
||||
demo_application,
|
||||
framework->pool);
|
||||
return mrcp_client_application_register(framework->client,demo_application->application,name);
|
||||
}
|
||||
|
||||
static void demo_framework_on_start_complete(apt_task_t *task)
|
||||
{
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Run Demo Framework");
|
||||
}
|
||||
|
||||
static apt_bool_t demo_framework_console_msg_process(demo_framework_t *framework, const char *app_name, const char *profile_name)
|
||||
{
|
||||
demo_application_t *demo_application = apr_hash_get(framework->application_table,app_name,APR_HASH_KEY_STRING);
|
||||
if(!demo_application) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Demo Application [%s]",app_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Run Demo Application Scenario [%s]",app_name);
|
||||
return demo_application->run(demo_application,profile_name);
|
||||
}
|
||||
|
||||
static apt_bool_t demo_framework_msg_process(apt_task_t *task, apt_task_msg_t *msg)
|
||||
{
|
||||
if(msg->type == TASK_MSG_USER) {
|
||||
framework_task_data_t *data = (framework_task_data_t*)msg->data;
|
||||
switch(msg->sub_type) {
|
||||
case DEMO_APPLICATION_MSG_ID:
|
||||
{
|
||||
data->demo_application->handler(data->demo_application,data->app_message);
|
||||
break;
|
||||
}
|
||||
case DEMO_CONSOLE_MSG_ID:
|
||||
{
|
||||
apt_consumer_task_t *consumer_task = apt_task_object_get(task);
|
||||
demo_framework_t *framework = apt_consumer_task_object_get(consumer_task);
|
||||
demo_framework_console_msg_process(framework,data->app_name,data->profile_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static apt_bool_t demo_framework_consumer_task_create(demo_framework_t *framework)
|
||||
{
|
||||
apt_task_t *task;
|
||||
apt_task_vtable_t *vtable;
|
||||
apt_task_msg_pool_t *msg_pool;
|
||||
|
||||
msg_pool = apt_task_msg_pool_create_dynamic(sizeof(framework_task_data_t),framework->pool);
|
||||
framework->task = apt_consumer_task_create(framework,msg_pool,framework->pool);
|
||||
if(!framework->task) {
|
||||
return FALSE;
|
||||
}
|
||||
task = apt_consumer_task_base_get(framework->task);
|
||||
apt_task_name_set(task,FRAMEWORK_TASK_NAME);
|
||||
vtable = apt_consumer_task_vtable_get(framework->task);
|
||||
if(vtable) {
|
||||
vtable->process_msg = demo_framework_msg_process;
|
||||
vtable->on_start_complete = demo_framework_on_start_complete;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MRCP client stack (task) context.
|
||||
* Signal app_message to the main consumer task of the demo framework
|
||||
* for further processing (see demo_framework_msg_process).
|
||||
*/
|
||||
static apt_bool_t demo_framework_message_handler(const mrcp_app_message_t *app_message)
|
||||
{
|
||||
demo_application_t *demo_application;
|
||||
if(!app_message->application) {
|
||||
return FALSE;
|
||||
}
|
||||
demo_application = mrcp_application_object_get(app_message->application);
|
||||
if(demo_application && demo_application->framework) {
|
||||
demo_framework_t *framework = demo_application->framework;
|
||||
apt_task_t *task = apt_consumer_task_base_get(framework->task);
|
||||
apt_task_msg_t *task_msg = apt_task_msg_get(task);
|
||||
if(task_msg) {
|
||||
framework_task_data_t *framework_task_data = (framework_task_data_t*)task_msg->data;
|
||||
task_msg->type = TASK_MSG_USER;
|
||||
task_msg->sub_type = DEMO_APPLICATION_MSG_ID;
|
||||
framework_task_data = (framework_task_data_t*) task_msg->data;
|
||||
framework_task_data->app_message = app_message;
|
||||
framework_task_data->demo_application = demo_application;
|
||||
apt_task_msg_signal(task,task_msg);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Demo recognizer scenario.
|
||||
* C -> S: SIP INVITE or RTPS SETUP (add recognizer channel)
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
* C -> S: MRCP RECOGNIZE
|
||||
* S -> C: MRCP IN-PROGRESS
|
||||
* C -> S: RTP Start Transmission
|
||||
* S -> C: MRCP START-OF-INPUT
|
||||
* S -> C: MRCP RECOGNITION-COMPLETE
|
||||
* C -> S: RTP Stop Transmission
|
||||
* C -> S: SIP INVITE or RTPS SETUP (optionally remove recognizer channel)
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
* C -> S: SIP BYE or RTPS TEARDOWN
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
*/
|
||||
|
||||
#include "demo_application.h"
|
||||
#include "demo_util.h"
|
||||
#include "mrcp_session.h"
|
||||
#include "mrcp_message.h"
|
||||
#include "mrcp_generic_header.h"
|
||||
#include "mrcp_recog_header.h"
|
||||
#include "mrcp_recog_resource.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
#define DEMO_SPEECH_SOURCE_FILE "one.pcm"
|
||||
|
||||
typedef struct recog_app_channel_t recog_app_channel_t;
|
||||
|
||||
/** Declaration of recognizer application channel */
|
||||
struct recog_app_channel_t {
|
||||
/** MRCP control channel */
|
||||
mrcp_channel_t *channel;
|
||||
|
||||
/** Streaming is in-progress */
|
||||
apt_bool_t streaming;
|
||||
/** File to read audio stream from */
|
||||
FILE *audio_in;
|
||||
/** Estimated time to complete (used if no audio_in available) */
|
||||
apr_size_t time_to_complete;
|
||||
};
|
||||
|
||||
/** Declaration of recognizer application methods */
|
||||
static apt_bool_t recog_application_run(demo_application_t *demo_application, const char *profile);
|
||||
static apt_bool_t recog_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message);
|
||||
|
||||
/** Declaration of application message handlers */
|
||||
static apt_bool_t recog_application_on_session_update(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t recog_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t recog_application_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t recog_application_on_channel_remove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t recog_application_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message);
|
||||
|
||||
static const mrcp_app_message_dispatcher_t recog_application_dispatcher = {
|
||||
recog_application_on_session_update,
|
||||
recog_application_on_session_terminate,
|
||||
recog_application_on_channel_add,
|
||||
recog_application_on_channel_remove,
|
||||
recog_application_on_message_receive
|
||||
};
|
||||
|
||||
/** Declaration of recognizer audio stream methods */
|
||||
static apt_bool_t recog_app_stream_destroy(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t recog_app_stream_open(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t recog_app_stream_close(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t recog_app_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
|
||||
|
||||
static const mpf_audio_stream_vtable_t audio_stream_vtable = {
|
||||
recog_app_stream_destroy,
|
||||
recog_app_stream_open,
|
||||
recog_app_stream_close,
|
||||
recog_app_stream_read,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
/** Create demo recognizer application */
|
||||
demo_application_t* demo_recog_application_create(apr_pool_t *pool)
|
||||
{
|
||||
demo_application_t *recog_application = apr_palloc(pool,sizeof(demo_application_t));
|
||||
recog_application->application = NULL;
|
||||
recog_application->framework = NULL;
|
||||
recog_application->handler = recog_application_handler;
|
||||
recog_application->run = recog_application_run;
|
||||
return recog_application;
|
||||
}
|
||||
|
||||
/** Create demo recognizer channel */
|
||||
static mrcp_channel_t* recog_application_channel_create(mrcp_session_t *session)
|
||||
{
|
||||
mrcp_channel_t *channel;
|
||||
mpf_termination_t *termination;
|
||||
mpf_codec_descriptor_t *codec_descriptor = NULL;
|
||||
|
||||
/* create channel */
|
||||
recog_app_channel_t *recog_channel = apr_palloc(session->pool,sizeof(recog_app_channel_t));
|
||||
recog_channel->streaming = FALSE;
|
||||
recog_channel->audio_in = NULL;
|
||||
recog_channel->time_to_complete = 0;
|
||||
|
||||
#if 0 /* in case your audio source isn't in linear PCM, create appropriate codec descriptor below */
|
||||
codec_descriptor = apr_palloc(session->pool,sizeof(mpf_codec_descriptor_t));
|
||||
mpf_codec_descriptor_init(codec_descriptor);
|
||||
codec_descriptor->channel_count = 1;
|
||||
codec_descriptor->payload_type = 0;
|
||||
apt_string_set(&codec_descriptor->name,"PCMU");
|
||||
codec_descriptor->sampling_rate = 8000;
|
||||
#endif
|
||||
|
||||
termination = mrcp_application_source_termination_create(
|
||||
session, /* session, termination belongs to */
|
||||
&audio_stream_vtable, /* virtual methods table of audio stream */
|
||||
codec_descriptor, /* codec descriptor of audio stream (NULL by default) */
|
||||
recog_channel); /* 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) */
|
||||
recog_channel); /* object to associate */
|
||||
return channel;
|
||||
}
|
||||
|
||||
/** Run demo recognizer scenario */
|
||||
static apt_bool_t recog_application_run(demo_application_t *demo_application, const char *profile)
|
||||
{
|
||||
mrcp_channel_t *channel;
|
||||
/* create session */
|
||||
mrcp_session_t *session = mrcp_application_session_create(demo_application->application,profile,NULL);
|
||||
if(!session) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* create channel and associate all the required data */
|
||||
channel = recog_application_channel_create(session);
|
||||
if(!channel) {
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* add channel to session (send asynchronous request) */
|
||||
if(mrcp_application_channel_add(session,channel) != TRUE) {
|
||||
/* session and channel are still not referenced
|
||||
and both are allocated from session pool and will
|
||||
be freed with session destroy call */
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the messages sent from the MRCP client stack */
|
||||
static apt_bool_t recog_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message)
|
||||
{
|
||||
/* app_message should be dispatched now,
|
||||
* the default dispatcher is used in demo. */
|
||||
return mrcp_application_message_dispatch(&recog_application_dispatcher,app_message);
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session update requests */
|
||||
static apt_bool_t recog_application_on_session_update(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* not used in demo */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session terminate requests */
|
||||
static apt_bool_t recog_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* received response to session termination request,
|
||||
now it's safe to destroy no more referenced session */
|
||||
mrcp_application_session_destroy(session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to channel add requests */
|
||||
static apt_bool_t recog_application_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
|
||||
{
|
||||
if(status == MRCP_SIG_STATUS_CODE_SUCCESS) {
|
||||
mrcp_message_t *mrcp_message;
|
||||
const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application);
|
||||
/* create and send DEFINE-GRAMMAR request */
|
||||
mrcp_message = demo_define_grammar_message_create(session,channel,dir_layout);
|
||||
if(mrcp_message) {
|
||||
mrcp_application_message_send(session,channel,mrcp_message);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* error case, just terminate the demo */
|
||||
mrcp_application_session_terminate(session);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static apt_bool_t recog_application_on_channel_remove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
|
||||
{
|
||||
recog_app_channel_t *recog_channel = mrcp_application_channel_object_get(channel);
|
||||
|
||||
/* terminate the demo */
|
||||
mrcp_application_session_terminate(session);
|
||||
|
||||
if(recog_channel) {
|
||||
FILE *audio_in = recog_channel->audio_in;
|
||||
if(audio_in) {
|
||||
recog_channel->audio_in = NULL;
|
||||
fclose(audio_in);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the DEFINE-GRAMMAR responses */
|
||||
static apt_bool_t recog_application_on_define_grammar(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel)
|
||||
{
|
||||
recog_app_channel_t *recog_channel = mrcp_application_channel_object_get(channel);
|
||||
mrcp_message_t *mrcp_message;
|
||||
const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application);
|
||||
/* create and send RECOGNIZE request */
|
||||
mrcp_message = demo_recognize_message_create(session,channel,dir_layout);
|
||||
if(mrcp_message) {
|
||||
mrcp_application_message_send(session,channel,mrcp_message);
|
||||
}
|
||||
if(recog_channel) {
|
||||
char *file_path = apt_datadir_filepath_get(dir_layout,DEMO_SPEECH_SOURCE_FILE,session->pool);
|
||||
if(file_path) {
|
||||
recog_channel->audio_in = fopen(file_path,"rb");
|
||||
if(recog_channel->audio_in) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source",file_path);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Cannot Find [%s]",file_path);
|
||||
/* set some estimated time to complete */
|
||||
recog_channel->time_to_complete = 5000; // 5 sec
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static apt_bool_t recog_application_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
|
||||
{
|
||||
recog_app_channel_t *recog_channel = mrcp_application_channel_object_get(channel);
|
||||
if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
|
||||
/* received MRCP response */
|
||||
if(message->start_line.method_id == RECOGNIZER_DEFINE_GRAMMAR) {
|
||||
/* received the response to DEFINE-GRAMMAR request */
|
||||
if(message->start_line.request_state == MRCP_REQUEST_STATE_COMPLETE) {
|
||||
recog_application_on_define_grammar(application,session,channel);
|
||||
}
|
||||
else {
|
||||
/* received unexpected response, remove channel */
|
||||
mrcp_application_channel_remove(session,channel);
|
||||
}
|
||||
}
|
||||
else if(message->start_line.method_id == RECOGNIZER_RECOGNIZE) {
|
||||
/* received the response to RECOGNIZE request */
|
||||
if(message->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
|
||||
/* start to stream the speech to recognize */
|
||||
if(recog_channel) {
|
||||
recog_channel->streaming = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* received unexpected response, remove channel */
|
||||
mrcp_application_channel_remove(session,channel);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* received unexpected response */
|
||||
}
|
||||
}
|
||||
else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
|
||||
if(message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
|
||||
if(recog_channel) {
|
||||
recog_channel->streaming = FALSE;
|
||||
}
|
||||
mrcp_application_channel_remove(session,channel);
|
||||
}
|
||||
else if(message->start_line.method_id == RECOGNIZER_START_OF_INPUT) {
|
||||
/* received start-of-input, do whatever you need here */
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
|
||||
static apt_bool_t recog_app_stream_destroy(mpf_audio_stream_t *stream)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to perform application stream specific action before open */
|
||||
static apt_bool_t recog_app_stream_open(mpf_audio_stream_t *stream)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to perform application stream specific action after close */
|
||||
static apt_bool_t recog_app_stream_close(mpf_audio_stream_t *stream)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to read new frame */
|
||||
static apt_bool_t recog_app_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
|
||||
{
|
||||
recog_app_channel_t *recog_channel = stream->obj;
|
||||
if(recog_channel && recog_channel->streaming == TRUE) {
|
||||
if(recog_channel->audio_in) {
|
||||
if(fread(frame->codec_frame.buffer,1,frame->codec_frame.size,recog_channel->audio_in) == frame->codec_frame.size) {
|
||||
/* normal read */
|
||||
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
|
||||
}
|
||||
else {
|
||||
/* file is over */
|
||||
recog_channel->streaming = FALSE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* fill with silence in case no file available */
|
||||
if(recog_channel->time_to_complete >= CODEC_FRAME_TIME_BASE) {
|
||||
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
|
||||
memset(frame->codec_frame.buffer,0,frame->codec_frame.size);
|
||||
recog_channel->time_to_complete -= CODEC_FRAME_TIME_BASE;
|
||||
}
|
||||
else {
|
||||
recog_channel->streaming = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Demo synthesizer scenario.
|
||||
* C -> S: SIP INVITE or RTPS SETUP (add synthesizer channel)
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
* C -> S: MRCP SPEAK
|
||||
* S -> C: MRCP IN-PROGRESS
|
||||
* S -> C: RTP Start Transmission
|
||||
* S -> C: MRCP SPEAK-COMPLETE
|
||||
* S -> C: RTP Stop Transmission
|
||||
* C -> S: SIP INVITE or RTPS SETUP (optionally remove synthesizer channel)
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
* C -> S: SIP BYE or RTPS TEARDOWN
|
||||
* S -> C: SIP OK or RTPS OK
|
||||
*/
|
||||
|
||||
#include "demo_application.h"
|
||||
#include "demo_util.h"
|
||||
#include "mrcp_session.h"
|
||||
#include "mrcp_message.h"
|
||||
#include "mrcp_generic_header.h"
|
||||
#include "mrcp_synth_header.h"
|
||||
#include "mrcp_synth_resource.h"
|
||||
|
||||
typedef struct synth_app_channel_t synth_app_channel_t;
|
||||
|
||||
/** Declaration of synthesizer application channel */
|
||||
struct synth_app_channel_t {
|
||||
/** MRCP control channel */
|
||||
mrcp_channel_t *channel;
|
||||
/** File to write audio stream to */
|
||||
FILE *audio_out;
|
||||
};
|
||||
|
||||
/** Declaration of synthesizer application methods */
|
||||
static apt_bool_t synth_application_run(demo_application_t *demo_application, const char *profile);
|
||||
static apt_bool_t synth_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message);
|
||||
|
||||
/** Declaration of application message handlers */
|
||||
static apt_bool_t synth_application_on_session_update(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t synth_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status);
|
||||
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);
|
||||
static apt_bool_t synth_application_on_channel_remove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status);
|
||||
static apt_bool_t synth_application_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message);
|
||||
|
||||
static const mrcp_app_message_dispatcher_t synth_application_dispatcher = {
|
||||
synth_application_on_session_update,
|
||||
synth_application_on_session_terminate,
|
||||
synth_application_on_channel_add,
|
||||
synth_application_on_channel_remove,
|
||||
synth_application_on_message_receive
|
||||
};
|
||||
|
||||
/** Declaration of synthesizer audio stream methods */
|
||||
static apt_bool_t synth_app_stream_destroy(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t synth_app_stream_open(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t synth_app_stream_close(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t synth_app_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
|
||||
|
||||
static const mpf_audio_stream_vtable_t audio_stream_vtable = {
|
||||
synth_app_stream_destroy,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
synth_app_stream_open,
|
||||
synth_app_stream_close,
|
||||
synth_app_stream_write
|
||||
};
|
||||
|
||||
|
||||
/** Create demo synthesizer application */
|
||||
demo_application_t* demo_synth_application_create(apr_pool_t *pool)
|
||||
{
|
||||
demo_application_t *synth_application = apr_palloc(pool,sizeof(demo_application_t));
|
||||
synth_application->application = NULL;
|
||||
synth_application->framework = NULL;
|
||||
synth_application->handler = synth_application_handler;
|
||||
synth_application->run = synth_application_run;
|
||||
return synth_application;
|
||||
}
|
||||
|
||||
/** Create demo synthesizer channel */
|
||||
static mrcp_channel_t* synth_application_channel_create(mrcp_session_t *session)
|
||||
{
|
||||
mrcp_channel_t *channel;
|
||||
mpf_termination_t *termination;
|
||||
mpf_codec_descriptor_t *codec_descriptor = NULL;
|
||||
|
||||
/* create channel */
|
||||
synth_app_channel_t *synth_channel = apr_palloc(session->pool,sizeof(synth_app_channel_t));
|
||||
synth_channel->audio_out = NULL;
|
||||
|
||||
#if 0
|
||||
codec_descriptor = apr_palloc(session->pool,sizeof(mpf_codec_descriptor_t));
|
||||
mpf_codec_descriptor_init(codec_descriptor);
|
||||
codec_descriptor->channel_count = 1;
|
||||
codec_descriptor->payload_type = 0;
|
||||
apt_string_set(&codec_descriptor->name,"PCMU");
|
||||
codec_descriptor->sampling_rate = 8000;
|
||||
#endif
|
||||
|
||||
termination = mrcp_application_sink_termination_create(
|
||||
session, /* session, termination belongs to */
|
||||
&audio_stream_vtable, /* virtual methods table of audio stream */
|
||||
codec_descriptor, /* codec descriptor of audio stream (NULL by default) */
|
||||
synth_channel); /* object to associate */
|
||||
|
||||
channel = mrcp_application_channel_create(
|
||||
session, /* session, channel belongs to */
|
||||
MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
|
||||
termination, /* media termination, used to terminate audio stream */
|
||||
NULL, /* RTP descriptor, used to create RTP termination (NULL by default) */
|
||||
synth_channel); /* object to associate */
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
/** Run demo synthesizer scenario */
|
||||
static apt_bool_t synth_application_run(demo_application_t *demo_application, const char *profile)
|
||||
{
|
||||
mrcp_channel_t *channel;
|
||||
/* create session */
|
||||
mrcp_session_t *session = mrcp_application_session_create(demo_application->application,profile,NULL);
|
||||
if(!session) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* create channel and associate all the required data */
|
||||
channel = synth_application_channel_create(session);
|
||||
if(!channel) {
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* add channel to session (send asynchronous request) */
|
||||
if(mrcp_application_channel_add(session,channel) != TRUE) {
|
||||
/* session and channel are still not referenced
|
||||
and both are allocated from session pool and will
|
||||
be freed with session destroy call */
|
||||
mrcp_application_session_destroy(session);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the messages sent from the MRCP client stack */
|
||||
static apt_bool_t synth_application_handler(demo_application_t *application, const mrcp_app_message_t *app_message)
|
||||
{
|
||||
/* app_message should be dispatched now,
|
||||
* the default dispatcher is used in demo. */
|
||||
return mrcp_application_message_dispatch(&synth_application_dispatcher,app_message);
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session update requests */
|
||||
static apt_bool_t synth_application_on_session_update(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* not used in demo */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to session terminate requests */
|
||||
static apt_bool_t synth_application_on_session_terminate(mrcp_application_t *application, mrcp_session_t *session, mrcp_sig_status_code_e status)
|
||||
{
|
||||
/* received response to session termination request,
|
||||
now it's safe to destroy no more referenced session */
|
||||
mrcp_application_session_destroy(session);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to channel add requests */
|
||||
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)
|
||||
{
|
||||
synth_app_channel_t *synth_channel = mrcp_application_channel_object_get(channel);
|
||||
if(status == MRCP_SIG_STATUS_CODE_SUCCESS) {
|
||||
mrcp_message_t *mrcp_message;
|
||||
const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application);
|
||||
/* create and send SPEAK request */
|
||||
mrcp_message = demo_speak_message_create(session,channel,dir_layout);
|
||||
if(mrcp_message) {
|
||||
mrcp_application_message_send(session,channel,mrcp_message);
|
||||
}
|
||||
|
||||
if(synth_channel && session) {
|
||||
char *file_name = apr_pstrcat(session->pool,"synth-",session->id.buf,".pcm",NULL);
|
||||
char *file_path = apt_datadir_filepath_get(dir_layout,file_name,session->pool);
|
||||
if(file_path) {
|
||||
synth_channel->audio_out = fopen(file_path,"wb");
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* error case, just terminate the demo */
|
||||
mrcp_application_session_terminate(session);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the responses sent to channel remove requests */
|
||||
static apt_bool_t synth_application_on_channel_remove(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status)
|
||||
{
|
||||
synth_app_channel_t *synth_channel = mrcp_application_channel_object_get(channel);
|
||||
|
||||
/* terminate the demo */
|
||||
mrcp_application_session_terminate(session);
|
||||
|
||||
if(synth_channel) {
|
||||
FILE *audio_out = synth_channel->audio_out;
|
||||
if(audio_out) {
|
||||
synth_channel->audio_out = NULL;
|
||||
fclose(audio_out);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Handle the MRCP responses/events */
|
||||
static apt_bool_t synth_application_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
|
||||
{
|
||||
if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
|
||||
/* received MRCP response */
|
||||
if(message->start_line.method_id == SYNTHESIZER_SPEAK) {
|
||||
/* received the response to SPEAK request */
|
||||
if(message->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
|
||||
/* waiting for SPEAK-COMPLETE event */
|
||||
}
|
||||
else {
|
||||
/* received unexpected response, remove channel */
|
||||
mrcp_application_channel_remove(session,channel);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* received unexpected response */
|
||||
}
|
||||
}
|
||||
else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) {
|
||||
/* received MRCP event */
|
||||
if(message->start_line.method_id == SYNTHESIZER_SPEAK_COMPLETE) {
|
||||
/* received SPEAK-COMPLETE event, remove channel */
|
||||
mrcp_application_channel_remove(session,channel);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
|
||||
static apt_bool_t synth_app_stream_destroy(mpf_audio_stream_t *stream)
|
||||
{
|
||||
/* nothing to destroy in demo */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to perform application stream specific action before open */
|
||||
static apt_bool_t synth_app_stream_open(mpf_audio_stream_t *stream)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to perform application stream specific action after close */
|
||||
static apt_bool_t synth_app_stream_close(mpf_audio_stream_t *stream)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to make new frame available to write/send */
|
||||
static apt_bool_t synth_app_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
|
||||
{
|
||||
synth_app_channel_t *synth_channel = stream->obj;
|
||||
if(synth_channel && synth_channel->audio_out) {
|
||||
fwrite(frame->codec_frame.buffer,1,frame->codec_frame.size,synth_channel->audio_out);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "demo_util.h"
|
||||
/* common includes */
|
||||
#include "mrcp_session.h"
|
||||
#include "mrcp_message.h"
|
||||
#include "mrcp_generic_header.h"
|
||||
/* synthesizer includes */
|
||||
#include "mrcp_synth_header.h"
|
||||
#include "mrcp_synth_resource.h"
|
||||
/* recognizer includes */
|
||||
#include "mrcp_recog_header.h"
|
||||
#include "mrcp_recog_resource.h"
|
||||
|
||||
static void demo_message_body_set(mrcp_message_t *mrcp_message, const apt_dir_layout_t *dir_layout, const char *file_name)
|
||||
{
|
||||
char *file_path = apt_datadir_filepath_get(dir_layout,file_name,mrcp_message->pool);
|
||||
if(file_path) {
|
||||
FILE *file = fopen(file_path,"r");
|
||||
if(file) {
|
||||
char text[1024];
|
||||
apr_size_t size;
|
||||
size = fread(text,1,sizeof(text),file);
|
||||
apt_string_assign_n(&mrcp_message->body,text,size,mrcp_message->pool);
|
||||
fclose(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Create demo MRCP message (SPEAK request) */
|
||||
mrcp_message_t* demo_speak_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout)
|
||||
{
|
||||
/* create MRCP message */
|
||||
mrcp_message_t *mrcp_message = mrcp_application_message_create(session,channel,SYNTHESIZER_SPEAK);
|
||||
if(mrcp_message) {
|
||||
mrcp_generic_header_t *generic_header;
|
||||
mrcp_synth_header_t *synth_header;
|
||||
/* get/allocate generic header */
|
||||
generic_header = mrcp_generic_header_prepare(mrcp_message);
|
||||
if(generic_header) {
|
||||
/* set generic header fields */
|
||||
apt_string_assign(&generic_header->content_type,"application/synthesis+ssml",mrcp_message->pool);
|
||||
mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE);
|
||||
}
|
||||
/* get/allocate synthesizer header */
|
||||
synth_header = mrcp_resource_header_prepare(mrcp_message);
|
||||
if(synth_header) {
|
||||
/* set synthesizer header fields */
|
||||
synth_header->voice_param.age = 28;
|
||||
mrcp_resource_header_property_add(mrcp_message,SYNTHESIZER_HEADER_VOICE_AGE);
|
||||
}
|
||||
/* set message body */
|
||||
demo_message_body_set(mrcp_message,dir_layout,"speak.xml");
|
||||
}
|
||||
return mrcp_message;
|
||||
}
|
||||
|
||||
/** Create demo MRCP message (DEFINE-GRAMMAR request) */
|
||||
mrcp_message_t* demo_define_grammar_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout)
|
||||
{
|
||||
/* create MRCP message */
|
||||
mrcp_message_t *mrcp_message = mrcp_application_message_create(session,channel,RECOGNIZER_DEFINE_GRAMMAR);
|
||||
if(mrcp_message) {
|
||||
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 */
|
||||
if(mrcp_message->start_line.version == MRCP_VERSION_2) {
|
||||
apt_string_assign(&generic_header->content_type,"application/srgs+xml",mrcp_message->pool);
|
||||
}
|
||||
else {
|
||||
apt_string_assign(&generic_header->content_type,"application/grammar+xml",mrcp_message->pool);
|
||||
}
|
||||
mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE);
|
||||
apt_string_assign(&generic_header->content_id,"request1@form-level.store",mrcp_message->pool);
|
||||
mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_ID);
|
||||
}
|
||||
/* set message body */
|
||||
demo_message_body_set(mrcp_message,dir_layout,"grammar.xml");
|
||||
}
|
||||
return mrcp_message;
|
||||
}
|
||||
|
||||
/** Create demo MRCP message (RECOGNIZE request) */
|
||||
mrcp_message_t* demo_recognize_message_create(mrcp_session_t *session, mrcp_channel_t *channel, const apt_dir_layout_t *dir_layout)
|
||||
{
|
||||
const char text[] = "session:request1@form-level.store";
|
||||
|
||||
/* create MRCP message */
|
||||
mrcp_message_t *mrcp_message = mrcp_application_message_create(session,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(&generic_header->content_type,"text/uri-list",mrcp_message->pool);
|
||||
mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE);
|
||||
}
|
||||
/* get/allocate recognizer header */
|
||||
recog_header = mrcp_resource_header_prepare(mrcp_message);
|
||||
if(recog_header) {
|
||||
if(mrcp_message->start_line.version == MRCP_VERSION_2) {
|
||||
/* set recognizer header fields */
|
||||
recog_header->cancel_if_queue = FALSE;
|
||||
mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CANCEL_IF_QUEUE);
|
||||
}
|
||||
recog_header->no_input_timeout = 5000;
|
||||
mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_NO_INPUT_TIMEOUT);
|
||||
recog_header->recognition_timeout = 10000;
|
||||
mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_RECOGNITION_TIMEOUT);
|
||||
recog_header->start_input_timers = TRUE;
|
||||
mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_START_INPUT_TIMERS);
|
||||
}
|
||||
/* set message body */
|
||||
apt_string_assign(&mrcp_message->body,text,mrcp_message->pool);
|
||||
}
|
||||
return mrcp_message;
|
||||
}
|
||||
|
||||
|
||||
/** Create demo RTP termination descriptor */
|
||||
mpf_rtp_termination_descriptor_t* demo_rtp_descriptor_create(apr_pool_t *pool)
|
||||
{
|
||||
mpf_codec_descriptor_t *codec_descriptor;
|
||||
mpf_rtp_media_descriptor_t *media;
|
||||
/* create rtp descriptor */
|
||||
mpf_rtp_termination_descriptor_t *rtp_descriptor = apr_palloc(pool,sizeof(mpf_rtp_termination_descriptor_t));
|
||||
mpf_rtp_termination_descriptor_init(rtp_descriptor);
|
||||
/* create rtp local media */
|
||||
media = apr_palloc(pool,sizeof(mpf_rtp_media_descriptor_t));
|
||||
mpf_rtp_media_descriptor_init(media);
|
||||
apt_string_assign(&media->base.ip,"127.0.0.1",pool);
|
||||
media->base.port = 6000;
|
||||
media->base.state = MPF_MEDIA_ENABLED;
|
||||
media->mode = STREAM_MODE_RECEIVE;
|
||||
|
||||
/* initialize codec list */
|
||||
mpf_codec_list_init(&media->codec_list,2,pool);
|
||||
/* set codec descriptor */
|
||||
codec_descriptor = mpf_codec_list_add(&media->codec_list);
|
||||
if(codec_descriptor) {
|
||||
codec_descriptor->payload_type = 0;
|
||||
}
|
||||
/* set another codec descriptor */
|
||||
codec_descriptor = mpf_codec_list_add(&media->codec_list);
|
||||
if(codec_descriptor) {
|
||||
codec_descriptor->payload_type = 96;
|
||||
apt_string_set(&codec_descriptor->name,"PCMU");
|
||||
codec_descriptor->sampling_rate = 16000;
|
||||
codec_descriptor->channel_count = 1;
|
||||
}
|
||||
|
||||
rtp_descriptor->audio.local = media;
|
||||
return rtp_descriptor;
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <apr_getopt.h>
|
||||
#include <apr_file_info.h>
|
||||
#include "demo_framework.h"
|
||||
#include "apt_pool.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
typedef struct {
|
||||
const char *root_dir_path;
|
||||
apt_log_priority_e log_priority;
|
||||
apt_log_output_e log_output;
|
||||
} client_options_t;
|
||||
|
||||
static apt_bool_t demo_framework_cmdline_process(demo_framework_t *framework, char *cmdline)
|
||||
{
|
||||
apt_bool_t running = TRUE;
|
||||
char *name;
|
||||
char *last;
|
||||
name = apr_strtok(cmdline, " ", &last);
|
||||
|
||||
if(strcasecmp(name,"run") == 0) {
|
||||
char *app_name = apr_strtok(NULL, " ", &last);
|
||||
if(app_name) {
|
||||
char *profile_name = apr_strtok(NULL, " ", &last);
|
||||
if(!profile_name) {
|
||||
profile_name = "MRCPv2-Default";
|
||||
}
|
||||
demo_framework_app_run(framework,app_name,profile_name);
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(name,"loglevel") == 0) {
|
||||
char *priority = apr_strtok(NULL, " ", &last);
|
||||
if(priority) {
|
||||
apt_log_priority_set(atol(priority));
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(name,"exit") == 0 || strcmp(name,"quit") == 0) {
|
||||
running = FALSE;
|
||||
}
|
||||
else if(strcasecmp(name,"help") == 0) {
|
||||
printf("usage:\n"
|
||||
"\n- run [app_name] [profile_name] (run demo application)\n"
|
||||
" app_name is one of 'synth', 'recog', 'bypass', 'discover'\n"
|
||||
" profile_name is one of 'MRCPv2-Default', 'MRCPv1-Default', ...\n"
|
||||
"\n examples: \n"
|
||||
" run synth\n"
|
||||
" run recog\n"
|
||||
" run synth MRCPv1-Default\n"
|
||||
" run recog MRCPv1-Default\n"
|
||||
"\n- loglevel [level] (set loglevel, one of 0,1...7)\n"
|
||||
"\n- quit, exit\n");
|
||||
}
|
||||
else {
|
||||
printf("unknown command: %s (input help for usage)\n",name);
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
static apt_bool_t demo_framework_cmdline_run(demo_framework_t *framework)
|
||||
{
|
||||
apt_bool_t running = TRUE;
|
||||
char cmdline[1024];
|
||||
int i;
|
||||
do {
|
||||
printf(">");
|
||||
memset(&cmdline, 0, sizeof(cmdline));
|
||||
for(i = 0; i < sizeof(cmdline); i++) {
|
||||
cmdline[i] = (char) getchar();
|
||||
if(cmdline[i] == '\n') {
|
||||
cmdline[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*cmdline) {
|
||||
running = demo_framework_cmdline_process(framework,cmdline);
|
||||
}
|
||||
}
|
||||
while(running != 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
printf(
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
" unimrcpclient [options]\n"
|
||||
"\n"
|
||||
" Available options:\n"
|
||||
"\n"
|
||||
" -r [--root-dir] path : Set the project root directory path.\n"
|
||||
"\n"
|
||||
" -l [--log-prio] priority : Set the log priority.\n"
|
||||
" (0-emergency, ..., 7-debug)\n"
|
||||
"\n"
|
||||
" -o [--log-output] mode : Set the log output mode.\n"
|
||||
" (0-none, 1-console only, 2-file only, 3-both)\n"
|
||||
"\n"
|
||||
" -h [--help] : Show the help.\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static apt_bool_t demo_framework_options_load(client_options_t *options, 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 */
|
||||
{ "root-dir", 'r', TRUE, "path to root dir" }, /* -r arg or --root-dir arg */
|
||||
{ "log-prio", 'l', TRUE, "log priority" }, /* -l arg or --log-prio arg */
|
||||
{ "log-output", 'o', TRUE, "log output mode" }, /* -o arg or --log-output arg */
|
||||
{ "help", 'h', FALSE, "show help" }, /* -h or --help */
|
||||
{ NULL, 0, 0, NULL }, /* end */
|
||||
};
|
||||
|
||||
rv = apr_getopt_init(&opt, pool , argc, argv);
|
||||
if(rv != APR_SUCCESS) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
|
||||
switch(optch) {
|
||||
case 'r':
|
||||
options->root_dir_path = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
if(optarg) {
|
||||
options->log_priority = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if(optarg) {
|
||||
options->log_output = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'h':
|
||||
usage();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(rv != APR_EOF) {
|
||||
usage();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, const char * const *argv)
|
||||
{
|
||||
apr_pool_t *pool = NULL;
|
||||
client_options_t options;
|
||||
apt_dir_layout_t *dir_layout;
|
||||
demo_framework_t *framework;
|
||||
|
||||
/* APR global initialization */
|
||||
if(apr_initialize() != APR_SUCCESS) {
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create APR pool */
|
||||
pool = apt_pool_create();
|
||||
if(!pool) {
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the default options */
|
||||
options.root_dir_path = "../";
|
||||
options.log_priority = APT_PRIO_INFO;
|
||||
options.log_output = APT_LOG_OUTPUT_CONSOLE;
|
||||
|
||||
/* load options */
|
||||
if(demo_framework_options_load(&options,argc,argv,pool) != TRUE) {
|
||||
apr_pool_destroy(pool);
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create the structure of default directories layout */
|
||||
dir_layout = apt_default_dir_layout_create(options.root_dir_path,pool);
|
||||
/* create singleton logger */
|
||||
apt_log_instance_create(options.log_output,options.log_priority,pool);
|
||||
|
||||
if((options.log_output & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) {
|
||||
/* open the log file */
|
||||
apt_log_file_open(dir_layout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
|
||||
}
|
||||
|
||||
/* create demo framework */
|
||||
framework = demo_framework_create(dir_layout);
|
||||
if(framework) {
|
||||
/* run command line */
|
||||
demo_framework_cmdline_run(framework);
|
||||
/* destroy demo framework */
|
||||
demo_framework_destroy(framework);
|
||||
}
|
||||
|
||||
/* destroy singleton logger */
|
||||
apt_log_instance_destroy();
|
||||
/* destroy APR pool */
|
||||
apr_pool_destroy(pool);
|
||||
/* APR global termination */
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="unimrcpclient"
|
||||
ProjectGUID="{57FAF32E-49FD-491F-895D-132D0D5EFE0A}"
|
||||
RootNamespace="unimrcpclient"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unidebug.vsprops;$(SolutionDir)build\vsprops\unimrcpclient.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="include"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(UniMRCPClientLibs)"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unirelease.vsprops;$(SolutionDir)build\vsprops\unimrcpclient.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="include"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(UniMRCPClientLibs)"
|
||||
LinkTimeCodeGeneration="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\demo_bypass_application.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\demo_discover_application.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\demo_framework.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\demo_recog_application.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\demo_synth_application.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\demo_util.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\main.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="include"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\include\demo_application.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\demo_framework.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\include\demo_util.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,19 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
INCLUDES = -Iinclude \
|
||||
-I$(top_srcdir)/platforms/libunimrcp-server/include \
|
||||
-I$(top_srcdir)/libs/mrcp-server/include \
|
||||
-I$(top_srcdir)/libs/mrcp-engine/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 = unimrcpserver
|
||||
unimrcpserver_SOURCES = src/main.c src/uni_cmdline.c src/uni_daemon.c
|
||||
unimrcpserver_LDADD = $(top_builddir)/platforms/libunimrcp-server/libunimrcpserver.la
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <apr_getopt.h>
|
||||
#include <apr_file_info.h>
|
||||
#include "apt_pool.h"
|
||||
#include "apt_dir_layout.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
typedef struct {
|
||||
const char *root_dir_path;
|
||||
apt_bool_t foreground;
|
||||
apt_log_priority_e log_priority;
|
||||
apt_log_output_e log_output;
|
||||
} server_options_t;
|
||||
|
||||
#ifdef WIN32
|
||||
apt_bool_t uni_service_run(apt_dir_layout_t *dir_layout, apr_pool_t *pool);
|
||||
#else
|
||||
apt_bool_t uni_daemon_run(apt_dir_layout_t *dir_layout, apr_pool_t *pool);
|
||||
#endif
|
||||
|
||||
apt_bool_t uni_cmdline_run(apt_dir_layout_t *dir_layout, apr_pool_t *pool);
|
||||
|
||||
|
||||
static void usage()
|
||||
{
|
||||
printf(
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
" unimrcpserver [options]\n"
|
||||
"\n"
|
||||
" Available options:\n"
|
||||
"\n"
|
||||
" -r [--root-dir] path : Set the project root directory path.\n"
|
||||
"\n"
|
||||
" -l [--log-prio] priority : Set the log priority.\n"
|
||||
" (0-emergency, ..., 7-debug)\n"
|
||||
"\n"
|
||||
" -o [--log-output] mode : Set the log output mode.\n"
|
||||
" (0-none, 1-console only, 2-file only, 3-both)\n"
|
||||
"\n"
|
||||
#ifdef WIN32
|
||||
" -s [--service] : Run as the Windows service.\n"
|
||||
"\n"
|
||||
#else
|
||||
" -d [--daemon] : Run as the daemon.\n"
|
||||
"\n"
|
||||
#endif
|
||||
" -h [--help] : Show the help.\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
static apt_bool_t options_load(server_options_t *options, 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 */
|
||||
{ "root-dir", 'r', TRUE, "path to root dir" }, /* -r arg or --root-dir arg */
|
||||
{ "log-prio", 'l', TRUE, "log priority" }, /* -l arg or --log-prio arg */
|
||||
{ "log-output", 'o', TRUE, "log output mode" }, /* -o arg or --log-output arg */
|
||||
#ifdef WIN32
|
||||
{ "service", 's', FALSE, "run as service" }, /* -s or --service */
|
||||
#else
|
||||
{ "daemon", 'd', FALSE, "start as daemon" }, /* -d or --daemon */
|
||||
#endif
|
||||
{ "help", 'h', FALSE, "show help" }, /* -h or --help */
|
||||
{ NULL, 0, 0, NULL }, /* end */
|
||||
};
|
||||
|
||||
rv = apr_getopt_init(&opt, pool , argc, argv);
|
||||
if(rv != APR_SUCCESS) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while((rv = apr_getopt_long(opt, opt_option, &optch, &optarg)) == APR_SUCCESS) {
|
||||
switch(optch) {
|
||||
case 'r':
|
||||
options->root_dir_path = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
if(optarg) {
|
||||
options->log_priority = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if(optarg) {
|
||||
options->log_output = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
#ifdef WIN32
|
||||
case 's':
|
||||
options->foreground = FALSE;
|
||||
break;
|
||||
#else
|
||||
case 'd':
|
||||
options->foreground = FALSE;
|
||||
break;
|
||||
#endif
|
||||
case 'h':
|
||||
usage();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if(rv != APR_EOF) {
|
||||
usage();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main(int argc, const char * const *argv)
|
||||
{
|
||||
apr_pool_t *pool = NULL;
|
||||
server_options_t options;
|
||||
apt_dir_layout_t *dir_layout;
|
||||
|
||||
/* APR global initialization */
|
||||
if(apr_initialize() != APR_SUCCESS) {
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create APR pool */
|
||||
pool = apt_pool_create();
|
||||
if(!pool) {
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set the default options */
|
||||
options.root_dir_path = "../";
|
||||
options.foreground = TRUE;
|
||||
options.log_priority = APT_PRIO_INFO;
|
||||
options.log_output = APT_LOG_OUTPUT_CONSOLE;
|
||||
|
||||
/* load options */
|
||||
if(options_load(&options,argc,argv,pool) != TRUE) {
|
||||
apr_pool_destroy(pool);
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* create the structure of default directories layout */
|
||||
dir_layout = apt_default_dir_layout_create(options.root_dir_path,pool);
|
||||
/* create singleton logger */
|
||||
apt_log_instance_create(options.log_output,options.log_priority,pool);
|
||||
|
||||
if((options.log_output & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) {
|
||||
/* open the log file */
|
||||
apt_log_file_open(dir_layout->log_dir_path,"unimrcpserver",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
|
||||
}
|
||||
|
||||
if(options.foreground == TRUE) {
|
||||
/* run command line */
|
||||
uni_cmdline_run(dir_layout,pool);
|
||||
}
|
||||
#ifdef WIN32
|
||||
else {
|
||||
/* run as windows service */
|
||||
uni_service_run(dir_layout,pool);
|
||||
}
|
||||
#else
|
||||
else {
|
||||
/* run as daemon */
|
||||
uni_daemon_run(dir_layout,pool);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* destroy singleton logger */
|
||||
apt_log_instance_destroy();
|
||||
/* destroy APR pool */
|
||||
apr_pool_destroy(pool);
|
||||
/* APR global termination */
|
||||
apr_terminate();
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "unimrcp_server.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
static apt_bool_t cmdline_process(char *cmdline)
|
||||
{
|
||||
apt_bool_t running = TRUE;
|
||||
char *name;
|
||||
char *last;
|
||||
name = apr_strtok(cmdline, " ", &last);
|
||||
|
||||
if(strcasecmp(name,"loglevel") == 0) {
|
||||
char *priority = apr_strtok(NULL, " ", &last);
|
||||
if(priority) {
|
||||
apt_log_priority_set(atol(priority));
|
||||
}
|
||||
}
|
||||
else if(strcasecmp(name,"exit") == 0 || strcmp(name,"quit") == 0) {
|
||||
running = FALSE;
|
||||
}
|
||||
else if(strcasecmp(name,"help") == 0) {
|
||||
printf("usage:\n");
|
||||
printf("- loglevel [level] (set loglevel, one of 0,1...7)\n");
|
||||
printf("- quit, exit\n");
|
||||
}
|
||||
else {
|
||||
printf("unknown command: %s (input help for usage)\n",name);
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
apt_bool_t uni_cmdline_run(apt_dir_layout_t *dir_layout, apr_pool_t *pool)
|
||||
{
|
||||
apt_bool_t running = TRUE;
|
||||
char cmdline[1024];
|
||||
int i;
|
||||
mrcp_server_t *server;
|
||||
|
||||
/* start server */
|
||||
server = unimrcp_server_start(dir_layout);
|
||||
if(!server) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do {
|
||||
printf(">");
|
||||
memset(&cmdline, 0, sizeof(cmdline));
|
||||
for(i = 0; i < sizeof(cmdline); i++) {
|
||||
cmdline[i] = (char) getchar();
|
||||
if(cmdline[i] == '\n') {
|
||||
cmdline[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(*cmdline) {
|
||||
running = cmdline_process(cmdline);
|
||||
}
|
||||
}
|
||||
while(running != 0);
|
||||
|
||||
/* shutdown server */
|
||||
unimrcp_server_shutdown(server);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <apr_signal.h>
|
||||
#include <apr_thread_proc.h>
|
||||
#include "unimrcp_server.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
static apt_bool_t daemon_running;
|
||||
|
||||
static void sigterm_handler(int signo)
|
||||
{
|
||||
daemon_running = FALSE;
|
||||
}
|
||||
|
||||
apt_bool_t uni_daemon_run(apt_dir_layout_t *dir_layout, apr_pool_t *pool)
|
||||
{
|
||||
mrcp_server_t *server;
|
||||
|
||||
daemon_running = TRUE;
|
||||
apr_signal(SIGTERM,sigterm_handler);
|
||||
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Run as Daemon");
|
||||
apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);
|
||||
|
||||
/* start server */
|
||||
server = unimrcp_server_start(dir_layout);
|
||||
if(!server) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while(daemon_running) apr_sleep(1000000);
|
||||
|
||||
/* shutdown server */
|
||||
unimrcp_server_shutdown(server);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <apr_lib.h>
|
||||
#include "unimrcp_server.h"
|
||||
#include "apt_log.h"
|
||||
|
||||
#define WIN_SERVICE_NAME "unimrcp"
|
||||
|
||||
static SERVICE_STATUS_HANDLE win_service_status_handle = NULL;
|
||||
static SERVICE_STATUS win_service_status;
|
||||
|
||||
static mrcp_server_t *server = NULL;
|
||||
static apt_dir_layout_t *service_dir_layout = NULL;
|
||||
|
||||
/** SCM state change handler */
|
||||
static void WINAPI win_service_handler(DWORD control)
|
||||
{
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Service Handler %d",control);
|
||||
switch (control)
|
||||
{
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
break;
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL_STOP:
|
||||
if(server) {
|
||||
win_service_status.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
if(!SetServiceStatus(win_service_status_handle, &win_service_status)) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Set Service Status %d",GetLastError());
|
||||
}
|
||||
|
||||
/* shutdown server */
|
||||
unimrcp_server_shutdown(server);
|
||||
}
|
||||
win_service_status.dwCurrentState = SERVICE_STOPPED;
|
||||
win_service_status.dwCheckPoint = 0;
|
||||
win_service_status.dwWaitHint = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!SetServiceStatus(win_service_status_handle, &win_service_status)) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Set Service Status %d",GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
static void WINAPI win_service_main(DWORD argc, LPTSTR *argv)
|
||||
{
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Service Main");
|
||||
win_service_status.dwServiceType = SERVICE_WIN32;
|
||||
win_service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
win_service_status.dwWin32ExitCode = 0;
|
||||
win_service_status.dwServiceSpecificExitCode = 0;
|
||||
win_service_status.dwCheckPoint = 0;
|
||||
win_service_status.dwWaitHint = 0;
|
||||
|
||||
win_service_status_handle = RegisterServiceCtrlHandler(WIN_SERVICE_NAME, win_service_handler);
|
||||
if(win_service_status_handle == (SERVICE_STATUS_HANDLE)0) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Service Control Handler %d",GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
win_service_status.dwCurrentState = SERVICE_START_PENDING;
|
||||
if(!SetServiceStatus(win_service_status_handle, &win_service_status)) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Set Service Status %d",GetLastError());
|
||||
}
|
||||
|
||||
/* start server */
|
||||
server = unimrcp_server_start(service_dir_layout);
|
||||
|
||||
win_service_status.dwCurrentState = server ? SERVICE_RUNNING : SERVICE_STOPPED;
|
||||
if(!SetServiceStatus(win_service_status_handle, &win_service_status)) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Set Service Status %d",GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
/** Run SCM service */
|
||||
apt_bool_t uni_service_run(apt_dir_layout_t *dir_layout, apr_pool_t *pool)
|
||||
{
|
||||
SERVICE_TABLE_ENTRY win_service_table[] = {
|
||||
{ WIN_SERVICE_NAME, win_service_main },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
service_dir_layout = dir_layout;
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Run as Service");
|
||||
if(!StartServiceCtrlDispatcher(win_service_table)) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Connect to SCM %d",GetLastError());
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="windows-1251"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="unimrcpserver"
|
||||
ProjectGUID="{592CF22D-3F8F-4A77-A174-130D77B7623B}"
|
||||
RootNamespace="unimrcpserver"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unidebug.vsprops;$(SolutionDir)build\vsprops\unimrcpserver.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(UniMRCPServerLibs)"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
ConfigurationType="1"
|
||||
InheritedPropertySheets="$(SolutionDir)build\vsprops\unirelease.vsprops;$(SolutionDir)build\vsprops\unimrcpserver.vsprops"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="$(UniMRCPServerLibs)"
|
||||
LinkTimeCodeGeneration="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\main.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\uni_cmdline.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\uni_daemon.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\uni_service.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="include"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
Reference in new issue
Block a user