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:
Michael Jerris committed 2009-06-16 22:31:19 +00:00
1 parent ec90221783
commit da925bddf8
349 files changed
+47866

No files matched your search

@@ -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;
}