mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-02-25 02:51:30 +00:00
522 lines
18 KiB
C
522 lines
18 KiB
C
|
/*
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* Some mandatory rules for plugin implementation.
|
||
|
* 1. Each plugin MUST contain the following function as an entry point of the plugin
|
||
|
* MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
|
||
|
* 2. One and only one response MUST be sent back to the received request.
|
||
|
* 3. Methods (callbacks) of the MRCP engine channel MUST not block.
|
||
|
* (asynch response can be sent from the context of other thread)
|
||
|
* 4. Methods (callbacks) of the MPF engine stream MUST not block.
|
||
|
*/
|
||
|
|
||
|
#include "mrcp_resource_engine.h"
|
||
|
#include "mrcp_synth_resource.h"
|
||
|
#include "mrcp_synth_header.h"
|
||
|
#include "mrcp_generic_header.h"
|
||
|
#include "mrcp_message.h"
|
||
|
#include "apt_consumer_task.h"
|
||
|
#include "apt_log.h"
|
||
|
|
||
|
#define SYNTH_ENGINE_TASK_NAME "Demo Synth Engine"
|
||
|
|
||
|
typedef struct demo_synth_engine_t demo_synth_engine_t;
|
||
|
typedef struct demo_synth_channel_t demo_synth_channel_t;
|
||
|
typedef struct demo_synth_msg_t demo_synth_msg_t;
|
||
|
|
||
|
/** Declaration of synthesizer engine methods */
|
||
|
static apt_bool_t demo_synth_engine_destroy(mrcp_resource_engine_t *engine);
|
||
|
static apt_bool_t demo_synth_engine_open(mrcp_resource_engine_t *engine);
|
||
|
static apt_bool_t demo_synth_engine_close(mrcp_resource_engine_t *engine);
|
||
|
static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool);
|
||
|
|
||
|
static const struct mrcp_engine_method_vtable_t engine_vtable = {
|
||
|
demo_synth_engine_destroy,
|
||
|
demo_synth_engine_open,
|
||
|
demo_synth_engine_close,
|
||
|
demo_synth_engine_channel_create
|
||
|
};
|
||
|
|
||
|
|
||
|
/** Declaration of synthesizer channel methods */
|
||
|
static apt_bool_t demo_synth_channel_destroy(mrcp_engine_channel_t *channel);
|
||
|
static apt_bool_t demo_synth_channel_open(mrcp_engine_channel_t *channel);
|
||
|
static apt_bool_t demo_synth_channel_close(mrcp_engine_channel_t *channel);
|
||
|
static apt_bool_t demo_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
|
||
|
|
||
|
static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
|
||
|
demo_synth_channel_destroy,
|
||
|
demo_synth_channel_open,
|
||
|
demo_synth_channel_close,
|
||
|
demo_synth_channel_request_process
|
||
|
};
|
||
|
|
||
|
/** Declaration of synthesizer audio stream methods */
|
||
|
static apt_bool_t demo_synth_stream_destroy(mpf_audio_stream_t *stream);
|
||
|
static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream);
|
||
|
static apt_bool_t demo_synth_stream_close(mpf_audio_stream_t *stream);
|
||
|
static apt_bool_t demo_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
|
||
|
|
||
|
static const mpf_audio_stream_vtable_t audio_stream_vtable = {
|
||
|
demo_synth_stream_destroy,
|
||
|
demo_synth_stream_open,
|
||
|
demo_synth_stream_close,
|
||
|
demo_synth_stream_read,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
/** Declaration of demo synthesizer engine */
|
||
|
struct demo_synth_engine_t {
|
||
|
apt_consumer_task_t *task;
|
||
|
};
|
||
|
|
||
|
/** Declaration of demo synthesizer channel */
|
||
|
struct demo_synth_channel_t {
|
||
|
/** Back pointer to engine */
|
||
|
demo_synth_engine_t *demo_engine;
|
||
|
/** Engine channel base */
|
||
|
mrcp_engine_channel_t *channel;
|
||
|
|
||
|
/** Active (in-progress) speak request */
|
||
|
mrcp_message_t *speak_request;
|
||
|
/** Pending stop response */
|
||
|
mrcp_message_t *stop_response;
|
||
|
/** Estimated time to complete */
|
||
|
apr_size_t time_to_complete;
|
||
|
/** Is paused */
|
||
|
apt_bool_t paused;
|
||
|
/** Speech source (used instead of actual synthesizing) */
|
||
|
FILE *audio_file;
|
||
|
};
|
||
|
|
||
|
typedef enum {
|
||
|
DEMO_SYNTH_MSG_OPEN_CHANNEL,
|
||
|
DEMO_SYNTH_MSG_CLOSE_CHANNEL,
|
||
|
DEMO_SYNTH_MSG_REQUEST_PROCESS
|
||
|
} demo_synth_msg_type_e;
|
||
|
|
||
|
/** Declaration of demo synthesizer task message */
|
||
|
struct demo_synth_msg_t {
|
||
|
demo_synth_msg_type_e type;
|
||
|
mrcp_engine_channel_t *channel;
|
||
|
mrcp_message_t *request;
|
||
|
};
|
||
|
|
||
|
|
||
|
#define DEMO_SPEECH_SOURCE_FILE "demo.pcm"
|
||
|
static apt_bool_t demo_synth_msg_signal(demo_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request);
|
||
|
static apt_bool_t demo_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg);
|
||
|
|
||
|
/** Declare this macro to use log routine of the server, plugin is loaded from */
|
||
|
MRCP_PLUGIN_LOGGER_IMPLEMENT
|
||
|
|
||
|
/** Create demo synthesizer engine */
|
||
|
MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
|
||
|
{
|
||
|
/* create demo engine */
|
||
|
demo_synth_engine_t *demo_engine = apr_palloc(pool,sizeof(demo_synth_engine_t));
|
||
|
apt_task_t *task;
|
||
|
apt_task_vtable_t *vtable;
|
||
|
apt_task_msg_pool_t *msg_pool;
|
||
|
|
||
|
/* create task/thread to run demo engine in the context of this task */
|
||
|
msg_pool = apt_task_msg_pool_create_dynamic(sizeof(demo_synth_msg_t),pool);
|
||
|
demo_engine->task = apt_consumer_task_create(demo_engine,msg_pool,pool);
|
||
|
if(!demo_engine->task) {
|
||
|
return NULL;
|
||
|
}
|
||
|
task = apt_consumer_task_base_get(demo_engine->task);
|
||
|
apt_task_name_set(task,SYNTH_ENGINE_TASK_NAME);
|
||
|
vtable = apt_task_vtable_get(task);
|
||
|
if(vtable) {
|
||
|
vtable->process_msg = demo_synth_msg_process;
|
||
|
}
|
||
|
|
||
|
/* create resource engine base */
|
||
|
return mrcp_resource_engine_create(
|
||
|
MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
|
||
|
demo_engine, /* object to associate */
|
||
|
&engine_vtable, /* virtual methods table of resource engine */
|
||
|
pool); /* pool to allocate memory from */
|
||
|
}
|
||
|
|
||
|
/** Destroy synthesizer engine */
|
||
|
static apt_bool_t demo_synth_engine_destroy(mrcp_resource_engine_t *engine)
|
||
|
{
|
||
|
demo_synth_engine_t *demo_engine = engine->obj;
|
||
|
if(demo_engine->task) {
|
||
|
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
|
||
|
apt_task_destroy(task);
|
||
|
demo_engine->task = NULL;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Open synthesizer engine */
|
||
|
static apt_bool_t demo_synth_engine_open(mrcp_resource_engine_t *engine)
|
||
|
{
|
||
|
demo_synth_engine_t *demo_engine = engine->obj;
|
||
|
if(demo_engine->task) {
|
||
|
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
|
||
|
apt_task_start(task);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Close synthesizer engine */
|
||
|
static apt_bool_t demo_synth_engine_close(mrcp_resource_engine_t *engine)
|
||
|
{
|
||
|
demo_synth_engine_t *demo_engine = engine->obj;
|
||
|
if(demo_engine->task) {
|
||
|
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
|
||
|
apt_task_terminate(task,TRUE);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Create demo synthesizer channel derived from engine channel base */
|
||
|
static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
|
||
|
{
|
||
|
/* create demo synth channel */
|
||
|
demo_synth_channel_t *synth_channel = apr_palloc(pool,sizeof(demo_synth_channel_t));
|
||
|
synth_channel->demo_engine = engine->obj;
|
||
|
synth_channel->speak_request = NULL;
|
||
|
synth_channel->stop_response = NULL;
|
||
|
synth_channel->time_to_complete = 0;
|
||
|
synth_channel->paused = FALSE;
|
||
|
synth_channel->audio_file = NULL;
|
||
|
/* create engine channel base */
|
||
|
synth_channel->channel = mrcp_engine_source_channel_create(
|
||
|
engine, /* resource engine */
|
||
|
&channel_vtable, /* virtual methods table of engine channel */
|
||
|
&audio_stream_vtable, /* virtual methods table of audio stream */
|
||
|
synth_channel, /* object to associate */
|
||
|
NULL, /* codec descriptor might be NULL by default */
|
||
|
pool); /* pool to allocate memory from */
|
||
|
return synth_channel->channel;
|
||
|
}
|
||
|
|
||
|
/** Destroy engine channel */
|
||
|
static apt_bool_t demo_synth_channel_destroy(mrcp_engine_channel_t *channel)
|
||
|
{
|
||
|
/* nothing to destroy */
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Open engine channel (asynchronous response MUST be sent)*/
|
||
|
static apt_bool_t demo_synth_channel_open(mrcp_engine_channel_t *channel)
|
||
|
{
|
||
|
return demo_synth_msg_signal(DEMO_SYNTH_MSG_OPEN_CHANNEL,channel,NULL);
|
||
|
}
|
||
|
|
||
|
/** Close engine channel (asynchronous response MUST be sent)*/
|
||
|
static apt_bool_t demo_synth_channel_close(mrcp_engine_channel_t *channel)
|
||
|
{
|
||
|
return demo_synth_msg_signal(DEMO_SYNTH_MSG_CLOSE_CHANNEL,channel,NULL);
|
||
|
}
|
||
|
|
||
|
/** Process MRCP channel request (asynchronous response MUST be sent)*/
|
||
|
static apt_bool_t demo_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request)
|
||
|
{
|
||
|
return demo_synth_msg_signal(DEMO_SYNTH_MSG_REQUEST_PROCESS,channel,request);
|
||
|
}
|
||
|
|
||
|
/** Process SPEAK request */
|
||
|
static apt_bool_t demo_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
|
||
|
{
|
||
|
char *file_path = NULL;
|
||
|
demo_synth_channel_t *synth_channel = channel->method_obj;
|
||
|
synth_channel->time_to_complete = 0;
|
||
|
if(channel->engine) {
|
||
|
file_path = apt_datadir_filepath_get(channel->engine->dir_layout,DEMO_SPEECH_SOURCE_FILE,channel->pool);
|
||
|
}
|
||
|
if(file_path) {
|
||
|
synth_channel->audio_file = fopen(file_path,"rb");
|
||
|
if(synth_channel->audio_file) {
|
||
|
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source",file_path);
|
||
|
}
|
||
|
else {
|
||
|
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"No Speech Source [%s] Found",file_path);
|
||
|
/* calculate estimated time to complete */
|
||
|
if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
|
||
|
mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request);
|
||
|
if(generic_header) {
|
||
|
synth_channel->time_to_complete = generic_header->content_length * 10; /* 10 msec per character */
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
|
||
|
/* send asynchronous response */
|
||
|
mrcp_engine_channel_message_send(channel,response);
|
||
|
synth_channel->speak_request = request;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Process STOP request */
|
||
|
static apt_bool_t demo_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
|
||
|
{
|
||
|
demo_synth_channel_t *synth_channel = channel->method_obj;
|
||
|
/* store the request, make sure there is no more activity and only then send the response */
|
||
|
synth_channel->stop_response = response;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Process PAUSE request */
|
||
|
static apt_bool_t demo_synth_channel_pause(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
|
||
|
{
|
||
|
demo_synth_channel_t *synth_channel = channel->method_obj;
|
||
|
synth_channel->paused = TRUE;
|
||
|
/* send asynchronous response */
|
||
|
mrcp_engine_channel_message_send(channel,response);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Process RESUME request */
|
||
|
static apt_bool_t demo_synth_channel_resume(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
|
||
|
{
|
||
|
demo_synth_channel_t *synth_channel = channel->method_obj;
|
||
|
synth_channel->paused = FALSE;
|
||
|
/* send asynchronous response */
|
||
|
mrcp_engine_channel_message_send(channel,response);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Process SET-PARAMS request */
|
||
|
static apt_bool_t demo_synth_channel_set_params(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
|
||
|
{
|
||
|
mrcp_synth_header_t *req_synth_header;
|
||
|
/* get synthesizer header */
|
||
|
req_synth_header = mrcp_resource_header_get(request);
|
||
|
if(req_synth_header) {
|
||
|
/* check voice age header */
|
||
|
if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) {
|
||
|
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Voice Age [%d]",req_synth_header->voice_param.age);
|
||
|
}
|
||
|
/* check voice name header */
|
||
|
if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) {
|
||
|
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Voice Name [%s]",req_synth_header->voice_param.name);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* send asynchronous response */
|
||
|
mrcp_engine_channel_message_send(channel,response);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Process GET-PARAMS request */
|
||
|
static apt_bool_t demo_synth_channel_get_params(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
|
||
|
{
|
||
|
mrcp_synth_header_t *req_synth_header;
|
||
|
/* get synthesizer header */
|
||
|
req_synth_header = mrcp_resource_header_get(request);
|
||
|
if(req_synth_header) {
|
||
|
mrcp_synth_header_t *res_synth_header = mrcp_resource_header_prepare(response);
|
||
|
/* check voice age header */
|
||
|
if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) {
|
||
|
res_synth_header->voice_param.age = 25;
|
||
|
mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_VOICE_AGE);
|
||
|
}
|
||
|
/* check voice name header */
|
||
|
if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) {
|
||
|
apt_string_set(&res_synth_header->voice_param.name,"David");
|
||
|
mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_VOICE_NAME);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* send asynchronous response */
|
||
|
mrcp_engine_channel_message_send(channel,response);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Dispatch MRCP request */
|
||
|
static apt_bool_t demo_synth_channel_request_dispatch(mrcp_engine_channel_t *channel, mrcp_message_t *request)
|
||
|
{
|
||
|
apt_bool_t processed = FALSE;
|
||
|
mrcp_message_t *response = mrcp_response_create(request,request->pool);
|
||
|
switch(request->start_line.method_id) {
|
||
|
case SYNTHESIZER_SET_PARAMS:
|
||
|
processed = demo_synth_channel_set_params(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_GET_PARAMS:
|
||
|
processed = demo_synth_channel_get_params(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_SPEAK:
|
||
|
processed = demo_synth_channel_speak(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_STOP:
|
||
|
processed = demo_synth_channel_stop(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_PAUSE:
|
||
|
processed = demo_synth_channel_pause(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_RESUME:
|
||
|
processed = demo_synth_channel_resume(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_BARGE_IN_OCCURRED:
|
||
|
processed = demo_synth_channel_stop(channel,request,response);
|
||
|
break;
|
||
|
case SYNTHESIZER_CONTROL:
|
||
|
break;
|
||
|
case SYNTHESIZER_DEFINE_LEXICON:
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
if(processed == FALSE) {
|
||
|
/* send asynchronous response for not handled request */
|
||
|
mrcp_engine_channel_message_send(channel,response);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
|
||
|
static apt_bool_t demo_synth_stream_destroy(mpf_audio_stream_t *stream)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Callback is called from MPF engine context to perform any action before open */
|
||
|
static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Callback is called from MPF engine context to perform any action after close */
|
||
|
static apt_bool_t demo_synth_stream_close(mpf_audio_stream_t *stream)
|
||
|
{
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/** Callback is called from MPF engine context to read/get new frame */
|
||
|
static apt_bool_t demo_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
|
||
|
{
|
||
|
demo_synth_channel_t *synth_channel = stream->obj;
|
||
|
/* check if STOP was requested */
|
||
|
if(synth_channel->stop_response) {
|
||
|
/* send asynchronous response to STOP request */
|
||
|
mrcp_engine_channel_message_send(synth_channel->channel,synth_channel->stop_response);
|
||
|
synth_channel->stop_response = NULL;
|
||
|
synth_channel->speak_request = NULL;
|
||
|
synth_channel->paused = FALSE;
|
||
|
if(synth_channel->audio_file) {
|
||
|
fclose(synth_channel->audio_file);
|
||
|
synth_channel->audio_file = NULL;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
/* check if there is active SPEAK request and it isn't in paused state */
|
||
|
if(synth_channel->speak_request && synth_channel->paused == FALSE) {
|
||
|
/* normal processing */
|
||
|
apt_bool_t completed = FALSE;
|
||
|
if(synth_channel->audio_file) {
|
||
|
/* read speech from file */
|
||
|
apr_size_t size = frame->codec_frame.size;
|
||
|
if(fread(frame->codec_frame.buffer,1,size,synth_channel->audio_file) == size) {
|
||
|
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
|
||
|
}
|
||
|
else {
|
||
|
completed = TRUE;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
/* fill with silence in case no file available */
|
||
|
if(synth_channel->time_to_complete >= CODEC_FRAME_TIME_BASE) {
|
||
|
memset(frame->codec_frame.buffer,0,frame->codec_frame.size);
|
||
|
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
|
||
|
synth_channel->time_to_complete -= CODEC_FRAME_TIME_BASE;
|
||
|
}
|
||
|
else {
|
||
|
completed = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if(completed) {
|
||
|
/* raise SPEAK-COMPLETE event */
|
||
|
mrcp_message_t *message = mrcp_event_create(
|
||
|
synth_channel->speak_request,
|
||
|
SYNTHESIZER_SPEAK_COMPLETE,
|
||
|
synth_channel->speak_request->pool);
|
||
|
if(message) {
|
||
|
/* get/allocate synthesizer header */
|
||
|
mrcp_synth_header_t *synth_header = mrcp_resource_header_prepare(message);
|
||
|
if(synth_header) {
|
||
|
/* set completion cause */
|
||
|
synth_header->completion_cause = SYNTHESIZER_COMPLETION_CAUSE_NORMAL;
|
||
|
mrcp_resource_header_property_add(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE);
|
||
|
}
|
||
|
/* set request state */
|
||
|
message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
|
||
|
|
||
|
synth_channel->speak_request = NULL;
|
||
|
if(synth_channel->audio_file) {
|
||
|
fclose(synth_channel->audio_file);
|
||
|
synth_channel->audio_file = NULL;
|
||
|
}
|
||
|
/* send asynch event */
|
||
|
mrcp_engine_channel_message_send(synth_channel->channel,message);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static apt_bool_t demo_synth_msg_signal(demo_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request)
|
||
|
{
|
||
|
apt_bool_t status = FALSE;
|
||
|
demo_synth_channel_t *demo_channel = channel->method_obj;
|
||
|
demo_synth_engine_t *demo_engine = demo_channel->demo_engine;
|
||
|
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
|
||
|
apt_task_msg_t *msg = apt_task_msg_get(task);
|
||
|
if(msg) {
|
||
|
demo_synth_msg_t *demo_msg;
|
||
|
msg->type = TASK_MSG_USER;
|
||
|
demo_msg = (demo_synth_msg_t*) msg->data;
|
||
|
|
||
|
demo_msg->type = type;
|
||
|
demo_msg->channel = channel;
|
||
|
demo_msg->request = request;
|
||
|
status = apt_task_msg_signal(task,msg);
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
static apt_bool_t demo_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg)
|
||
|
{
|
||
|
demo_synth_msg_t *demo_msg = (demo_synth_msg_t*)msg->data;
|
||
|
switch(demo_msg->type) {
|
||
|
case DEMO_SYNTH_MSG_OPEN_CHANNEL:
|
||
|
/* open channel and send asynch response */
|
||
|
mrcp_engine_channel_open_respond(demo_msg->channel,TRUE);
|
||
|
break;
|
||
|
case DEMO_SYNTH_MSG_CLOSE_CHANNEL:
|
||
|
/* close channel, make sure there is no activity and send asynch response */
|
||
|
mrcp_engine_channel_close_respond(demo_msg->channel);
|
||
|
break;
|
||
|
case DEMO_SYNTH_MSG_REQUEST_PROCESS:
|
||
|
demo_synth_channel_request_dispatch(demo_msg->channel,demo_msg->request);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|