1 /*
2 * Copyright 2008-2014 Arsen Chaloyan
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * $Id: demo_recog_engine.c 2193 2014-10-08 03:44:33Z achaloyan@gmail.com $
17 */
18
19 /*
20 * Mandatory rules concerning plugin implementation.
21 * 1. Each plugin MUST implement a plugin/engine creator function
22 * with the exact signature and name (the main entry point)
23 * MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
24 * 2. Each plugin MUST declare its version number
25 * MRCP_PLUGIN_VERSION_DECLARE
26 * 3. One and only one response MUST be sent back to the received request.
27 * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
28 * (asynchronous response can be sent from the context of other thread)
29 * 5. Methods (callbacks) of the MPF engine stream MUST not block.
30 */
31
32 #include "mrcp_recog_engine.h"
33 #include "mpf_activity_detector.h"
34 #include "apt_consumer_task.h"
35 #include "apt_log.h"
36
37 #define RECOG_ENGINE_TASK_NAME "Demo Recog Engine"
38
39 typedef struct demo_recog_engine_t demo_recog_engine_t;
40 typedef struct demo_recog_channel_t demo_recog_channel_t;
41 typedef struct demo_recog_msg_t demo_recog_msg_t;
42
43 /** Declaration of recognizer engine methods */
44 static apt_bool_t demo_recog_engine_destroy(mrcp_engine_t *engine);
45 static apt_bool_t demo_recog_engine_open(mrcp_engine_t *engine);
46 static apt_bool_t demo_recog_engine_close(mrcp_engine_t *engine);
47 static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
48
49 static const struct mrcp_engine_method_vtable_t engine_vtable = {
50 demo_recog_engine_destroy,
51 demo_recog_engine_open,
52 demo_recog_engine_close,
53 demo_recog_engine_channel_create
54 };
55
56
57 /** Declaration of recognizer channel methods */
58 static apt_bool_t demo_recog_channel_destroy(mrcp_engine_channel_t *channel);
59 static apt_bool_t demo_recog_channel_open(mrcp_engine_channel_t *channel);
60 static apt_bool_t demo_recog_channel_close(mrcp_engine_channel_t *channel);
61 static apt_bool_t demo_recog_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
62
63 static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
64 demo_recog_channel_destroy,
65 demo_recog_channel_open,
66 demo_recog_channel_close,
67 demo_recog_channel_request_process
68 };
69
70 /** Declaration of recognizer audio stream methods */
71 static apt_bool_t demo_recog_stream_destroy(mpf_audio_stream_t *stream);
72 static apt_bool_t demo_recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
73 static apt_bool_t demo_recog_stream_close(mpf_audio_stream_t *stream);
74 static apt_bool_t demo_recog_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
75
76 static const mpf_audio_stream_vtable_t audio_stream_vtable = {
77 demo_recog_stream_destroy,
78 NULL,
79 NULL,
80 NULL,
81 demo_recog_stream_open,
82 demo_recog_stream_close,
83 demo_recog_stream_write,
84 NULL
85 };
86
87 /** Declaration of demo recognizer engine */
88 struct demo_recog_engine_t {
89 apt_consumer_task_t *task;
90 };
91
92 /** Declaration of demo recognizer channel */
93 struct demo_recog_channel_t {
94 /** Back pointer to engine */
95 demo_recog_engine_t *demo_engine;
96 /** Engine channel base */
97 mrcp_engine_channel_t *channel;
98
99 /** Active (in-progress) recognition request */
100 mrcp_message_t *recog_request;
101 /** Pending stop response */
102 mrcp_message_t *stop_response;
103 /** Indicates whether input timers are started */
104 apt_bool_t timers_started;
105 /** Voice activity detector */
106 mpf_activity_detector_t *detector;
107 /** File to write utterance to */
108 FILE *audio_out;
109 };
110
111 typedef enum {
112 DEMO_RECOG_MSG_OPEN_CHANNEL,
113 DEMO_RECOG_MSG_CLOSE_CHANNEL,
114 DEMO_RECOG_MSG_REQUEST_PROCESS
115 } demo_recog_msg_type_e;
116
117 /** Declaration of demo recognizer task message */
118 struct demo_recog_msg_t {
119 demo_recog_msg_type_e type;
120 mrcp_engine_channel_t *channel;
121 mrcp_message_t *request;
122 };
123
124 static apt_bool_t demo_recog_msg_signal(demo_recog_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request);
125 static apt_bool_t demo_recog_msg_process(apt_task_t *task, apt_task_msg_t *msg);
126
127 /** Declare this macro to set plugin version */
128 MRCP_PLUGIN_VERSION_DECLARE
129
130 /** Declare this macro to use log routine of the server, plugin is loaded from */
131 MRCP_PLUGIN_LOGGER_IMPLEMENT
132
133 /** Create demo recognizer engine */
MRCP_PLUGIN_DECLARE(mrcp_engine_t *)134 MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
135 {
136 demo_recog_engine_t *demo_engine = apr_palloc(pool,sizeof(demo_recog_engine_t));
137 apt_task_t *task;
138 apt_task_vtable_t *vtable;
139 apt_task_msg_pool_t *msg_pool;
140
141 msg_pool = apt_task_msg_pool_create_dynamic(sizeof(demo_recog_msg_t),pool);
142 demo_engine->task = apt_consumer_task_create(demo_engine,msg_pool,pool);
143 if(!demo_engine->task) {
144 return NULL;
145 }
146 task = apt_consumer_task_base_get(demo_engine->task);
147 apt_task_name_set(task,RECOG_ENGINE_TASK_NAME);
148 vtable = apt_task_vtable_get(task);
149 if(vtable) {
150 vtable->process_msg = demo_recog_msg_process;
151 }
152
153 /* create engine base */
154 return mrcp_engine_create(
155 MRCP_RECOGNIZER_RESOURCE, /* MRCP resource identifier */
156 demo_engine, /* object to associate */
157 &engine_vtable, /* virtual methods table of engine */
158 pool); /* pool to allocate memory from */
159 }
160
161 /** Destroy recognizer engine */
demo_recog_engine_destroy(mrcp_engine_t * engine)162 static apt_bool_t demo_recog_engine_destroy(mrcp_engine_t *engine)
163 {
164 demo_recog_engine_t *demo_engine = engine->obj;
165 if(demo_engine->task) {
166 apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
167 apt_task_destroy(task);
168 demo_engine->task = NULL;
169 }
170 return TRUE;
171 }
172
173 /** Open recognizer engine */
demo_recog_engine_open(mrcp_engine_t * engine)174 static apt_bool_t demo_recog_engine_open(mrcp_engine_t *engine)
175 {
176 demo_recog_engine_t *demo_engine = engine->obj;
177 if(demo_engine->task) {
178 apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
179 apt_task_start(task);
180 }
181 return mrcp_engine_open_respond(engine,TRUE);
182 }
183
184 /** Close recognizer engine */
demo_recog_engine_close(mrcp_engine_t * engine)185 static apt_bool_t demo_recog_engine_close(mrcp_engine_t *engine)
186 {
187 demo_recog_engine_t *demo_engine = engine->obj;
188 if(demo_engine->task) {
189 apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
190 apt_task_terminate(task,TRUE);
191 }
192 return mrcp_engine_close_respond(engine);
193 }
194
demo_recog_engine_channel_create(mrcp_engine_t * engine,apr_pool_t * pool)195 static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
196 {
197 mpf_stream_capabilities_t *capabilities;
198 mpf_termination_t *termination;
199
200 /* create demo recog channel */
201 demo_recog_channel_t *recog_channel = apr_palloc(pool,sizeof(demo_recog_channel_t));
202 recog_channel->demo_engine = engine->obj;
203 recog_channel->recog_request = NULL;
204 recog_channel->stop_response = NULL;
205 recog_channel->detector = mpf_activity_detector_create(pool);
206 recog_channel->audio_out = NULL;
207
208 capabilities = mpf_sink_stream_capabilities_create(pool);
209 mpf_codec_capabilities_add(
210 &capabilities->codecs,
211 MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
212 "LPCM");
213
214 /* create media termination */
215 termination = mrcp_engine_audio_termination_create(
216 recog_channel, /* object to associate */
217 &audio_stream_vtable, /* virtual methods table of audio stream */
218 capabilities, /* stream capabilities */
219 pool); /* pool to allocate memory from */
220
221 /* create engine channel base */
222 recog_channel->channel = mrcp_engine_channel_create(
223 engine, /* engine */
224 &channel_vtable, /* virtual methods table of engine channel */
225 recog_channel, /* object to associate */
226 termination, /* associated media termination */
227 pool); /* pool to allocate memory from */
228
229 return recog_channel->channel;
230 }
231
232 /** Destroy engine channel */
demo_recog_channel_destroy(mrcp_engine_channel_t * channel)233 static apt_bool_t demo_recog_channel_destroy(mrcp_engine_channel_t *channel)
234 {
235 /* nothing to destrtoy */
236 return TRUE;
237 }
238
239 /** Open engine channel (asynchronous response MUST be sent)*/
demo_recog_channel_open(mrcp_engine_channel_t * channel)240 static apt_bool_t demo_recog_channel_open(mrcp_engine_channel_t *channel)
241 {
242 return demo_recog_msg_signal(DEMO_RECOG_MSG_OPEN_CHANNEL,channel,NULL);
243 }
244
245 /** Close engine channel (asynchronous response MUST be sent)*/
demo_recog_channel_close(mrcp_engine_channel_t * channel)246 static apt_bool_t demo_recog_channel_close(mrcp_engine_channel_t *channel)
247 {
248 return demo_recog_msg_signal(DEMO_RECOG_MSG_CLOSE_CHANNEL,channel,NULL);
249 }
250
251 /** Process MRCP channel request (asynchronous response MUST be sent)*/
demo_recog_channel_request_process(mrcp_engine_channel_t * channel,mrcp_message_t * request)252 static apt_bool_t demo_recog_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request)
253 {
254 return demo_recog_msg_signal(DEMO_RECOG_MSG_REQUEST_PROCESS,channel,request);
255 }
256
257 /** Process RECOGNIZE request */
demo_recog_channel_recognize(mrcp_engine_channel_t * channel,mrcp_message_t * request,mrcp_message_t * response)258 static apt_bool_t demo_recog_channel_recognize(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
259 {
260 /* process RECOGNIZE request */
261 mrcp_recog_header_t *recog_header;
262 demo_recog_channel_t *recog_channel = channel->method_obj;
263 const mpf_codec_descriptor_t *descriptor = mrcp_engine_sink_stream_codec_get(channel);
264
265 if(!descriptor) {
266 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Get Codec Descriptor "APT_SIDRES_FMT, MRCP_MESSAGE_SIDRES(request));
267 response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
268 return FALSE;
269 }
270
271 recog_channel->timers_started = TRUE;
272
273 /* get recognizer header */
274 recog_header = mrcp_resource_header_get(request);
275 if(recog_header) {
276 if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_START_INPUT_TIMERS) == TRUE) {
277 recog_channel->timers_started = recog_header->start_input_timers;
278 }
279 if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_NO_INPUT_TIMEOUT) == TRUE) {
280 mpf_activity_detector_noinput_timeout_set(recog_channel->detector,recog_header->no_input_timeout);
281 }
282 if(mrcp_resource_header_property_check(request,RECOGNIZER_HEADER_SPEECH_COMPLETE_TIMEOUT) == TRUE) {
283 mpf_activity_detector_silence_timeout_set(recog_channel->detector,recog_header->speech_complete_timeout);
284 }
285 }
286
287 if(!recog_channel->audio_out) {
288 const apt_dir_layout_t *dir_layout = channel->engine->dir_layout;
289 char *file_name = apr_psprintf(channel->pool,"utter-%dkHz-%s.pcm",
290 descriptor->sampling_rate/1000,
291 request->channel_id.session_id.buf);
292 char *file_path = apt_vardir_filepath_get(dir_layout,file_name,channel->pool);
293 if(file_path) {
294 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Utterance Output File [%s] for Writing",file_path);
295 recog_channel->audio_out = fopen(file_path,"wb");
296 if(!recog_channel->audio_out) {
297 apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Utterance Output File [%s] for Writing",file_path);
298 }
299 }
300 }
301
302 response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
303 /* send asynchronous response */
304 mrcp_engine_channel_message_send(channel,response);
305 recog_channel->recog_request = request;
306 return TRUE;
307 }
308
309 /** Process STOP request */
demo_recog_channel_stop(mrcp_engine_channel_t * channel,mrcp_message_t * request,mrcp_message_t * response)310 static apt_bool_t demo_recog_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
311 {
312 /* process STOP request */
313 demo_recog_channel_t *recog_channel = channel->method_obj;
314 /* store STOP request, make sure there is no more activity and only then send the response */
315 recog_channel->stop_response = response;
316 return TRUE;
317 }
318
319 /** Process START-INPUT-TIMERS request */
demo_recog_channel_timers_start(mrcp_engine_channel_t * channel,mrcp_message_t * request,mrcp_message_t * response)320 static apt_bool_t demo_recog_channel_timers_start(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
321 {
322 demo_recog_channel_t *recog_channel = channel->method_obj;
323 recog_channel->timers_started = TRUE;
324 return mrcp_engine_channel_message_send(channel,response);
325 }
326
327 /** Dispatch MRCP request */
demo_recog_channel_request_dispatch(mrcp_engine_channel_t * channel,mrcp_message_t * request)328 static apt_bool_t demo_recog_channel_request_dispatch(mrcp_engine_channel_t *channel, mrcp_message_t *request)
329 {
330 apt_bool_t processed = FALSE;
331 mrcp_message_t *response = mrcp_response_create(request,request->pool);
332 switch(request->start_line.method_id) {
333 case RECOGNIZER_SET_PARAMS:
334 break;
335 case RECOGNIZER_GET_PARAMS:
336 break;
337 case RECOGNIZER_DEFINE_GRAMMAR:
338 break;
339 case RECOGNIZER_RECOGNIZE:
340 processed = demo_recog_channel_recognize(channel,request,response);
341 break;
342 case RECOGNIZER_GET_RESULT:
343 break;
344 case RECOGNIZER_START_INPUT_TIMERS:
345 processed = demo_recog_channel_timers_start(channel,request,response);
346 break;
347 case RECOGNIZER_STOP:
348 processed = demo_recog_channel_stop(channel,request,response);
349 break;
350 default:
351 break;
352 }
353 if(processed == FALSE) {
354 /* send asynchronous response for not handled request */
355 mrcp_engine_channel_message_send(channel,response);
356 }
357 return TRUE;
358 }
359
360 /** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
demo_recog_stream_destroy(mpf_audio_stream_t * stream)361 static apt_bool_t demo_recog_stream_destroy(mpf_audio_stream_t *stream)
362 {
363 return TRUE;
364 }
365
366 /** Callback is called from MPF engine context to perform any action before open */
demo_recog_stream_open(mpf_audio_stream_t * stream,mpf_codec_t * codec)367 static apt_bool_t demo_recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
368 {
369 return TRUE;
370 }
371
372 /** Callback is called from MPF engine context to perform any action after close */
demo_recog_stream_close(mpf_audio_stream_t * stream)373 static apt_bool_t demo_recog_stream_close(mpf_audio_stream_t *stream)
374 {
375 return TRUE;
376 }
377
378 /* Raise demo START-OF-INPUT event */
demo_recog_start_of_input(demo_recog_channel_t * recog_channel)379 static apt_bool_t demo_recog_start_of_input(demo_recog_channel_t *recog_channel)
380 {
381 /* create START-OF-INPUT event */
382 mrcp_message_t *message = mrcp_event_create(
383 recog_channel->recog_request,
384 RECOGNIZER_START_OF_INPUT,
385 recog_channel->recog_request->pool);
386 if(!message) {
387 return FALSE;
388 }
389
390 /* set request state */
391 message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
392 /* send asynch event */
393 return mrcp_engine_channel_message_send(recog_channel->channel,message);
394 }
395
396 /* Load demo recognition result */
demo_recog_result_load(demo_recog_channel_t * recog_channel,mrcp_message_t * message)397 static apt_bool_t demo_recog_result_load(demo_recog_channel_t *recog_channel, mrcp_message_t *message)
398 {
399 FILE *file;
400 mrcp_engine_channel_t *channel = recog_channel->channel;
401 const apt_dir_layout_t *dir_layout = channel->engine->dir_layout;
402 char *file_path = apt_datadir_filepath_get(dir_layout,"result.xml",message->pool);
403 if(!file_path) {
404 return FALSE;
405 }
406
407 /* read the demo result from file */
408 file = fopen(file_path,"r");
409 if(file) {
410 mrcp_generic_header_t *generic_header;
411 char text[1024];
412 apr_size_t size;
413 size = fread(text,1,sizeof(text),file);
414 apt_string_assign_n(&message->body,text,size,message->pool);
415 fclose(file);
416
417 /* get/allocate generic header */
418 generic_header = mrcp_generic_header_prepare(message);
419 if(generic_header) {
420 /* set content types */
421 apt_string_assign(&generic_header->content_type,"application/x-nlsml",message->pool);
422 mrcp_generic_header_property_add(message,GENERIC_HEADER_CONTENT_TYPE);
423 }
424 }
425 return TRUE;
426 }
427
428 /* Raise demo RECOGNITION-COMPLETE event */
demo_recog_recognition_complete(demo_recog_channel_t * recog_channel,mrcp_recog_completion_cause_e cause)429 static apt_bool_t demo_recog_recognition_complete(demo_recog_channel_t *recog_channel, mrcp_recog_completion_cause_e cause)
430 {
431 mrcp_recog_header_t *recog_header;
432 /* create RECOGNITION-COMPLETE event */
433 mrcp_message_t *message = mrcp_event_create(
434 recog_channel->recog_request,
435 RECOGNIZER_RECOGNITION_COMPLETE,
436 recog_channel->recog_request->pool);
437 if(!message) {
438 return FALSE;
439 }
440
441 /* get/allocate recognizer header */
442 recog_header = mrcp_resource_header_prepare(message);
443 if(recog_header) {
444 /* set completion cause */
445 recog_header->completion_cause = cause;
446 mrcp_resource_header_property_add(message,RECOGNIZER_HEADER_COMPLETION_CAUSE);
447 }
448 /* set request state */
449 message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
450
451 if(cause == RECOGNIZER_COMPLETION_CAUSE_SUCCESS) {
452 demo_recog_result_load(recog_channel,message);
453 }
454
455 recog_channel->recog_request = NULL;
456 /* send asynch event */
457 return mrcp_engine_channel_message_send(recog_channel->channel,message);
458 }
459
460 /** Callback is called from MPF engine context to write/send new frame */
demo_recog_stream_write(mpf_audio_stream_t * stream,const mpf_frame_t * frame)461 static apt_bool_t demo_recog_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
462 {
463 demo_recog_channel_t *recog_channel = stream->obj;
464 if(recog_channel->stop_response) {
465 /* send asynchronous response to STOP request */
466 mrcp_engine_channel_message_send(recog_channel->channel,recog_channel->stop_response);
467 recog_channel->stop_response = NULL;
468 recog_channel->recog_request = NULL;
469 return TRUE;
470 }
471
472 if(recog_channel->recog_request) {
473 mpf_detector_event_e det_event = mpf_activity_detector_process(recog_channel->detector,frame);
474 switch(det_event) {
475 case MPF_DETECTOR_EVENT_ACTIVITY:
476 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Activity "APT_SIDRES_FMT,
477 MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
478 demo_recog_start_of_input(recog_channel);
479 break;
480 case MPF_DETECTOR_EVENT_INACTIVITY:
481 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Inactivity "APT_SIDRES_FMT,
482 MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
483 demo_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
484 break;
485 case MPF_DETECTOR_EVENT_NOINPUT:
486 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Noinput "APT_SIDRES_FMT,
487 MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
488 if(recog_channel->timers_started == TRUE) {
489 demo_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
490 }
491 break;
492 default:
493 break;
494 }
495
496 if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
497 if(frame->marker == MPF_MARKER_START_OF_EVENT) {
498 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Start of Event "APT_SIDRES_FMT" id:%d",
499 MRCP_MESSAGE_SIDRES(recog_channel->recog_request),
500 frame->event_frame.event_id);
501 }
502 else if(frame->marker == MPF_MARKER_END_OF_EVENT) {
503 apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected End of Event "APT_SIDRES_FMT" id:%d duration:%d ts",
504 MRCP_MESSAGE_SIDRES(recog_channel->recog_request),
505 frame->event_frame.event_id,
506 frame->event_frame.duration);
507 }
508 }
509
510 if(recog_channel->audio_out) {
511 fwrite(frame->codec_frame.buffer,1,frame->codec_frame.size,recog_channel->audio_out);
512 }
513 }
514 return TRUE;
515 }
516
demo_recog_msg_signal(demo_recog_msg_type_e type,mrcp_engine_channel_t * channel,mrcp_message_t * request)517 static apt_bool_t demo_recog_msg_signal(demo_recog_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request)
518 {
519 apt_bool_t status = FALSE;
520 demo_recog_channel_t *demo_channel = channel->method_obj;
521 demo_recog_engine_t *demo_engine = demo_channel->demo_engine;
522 apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
523 apt_task_msg_t *msg = apt_task_msg_get(task);
524 if(msg) {
525 demo_recog_msg_t *demo_msg;
526 msg->type = TASK_MSG_USER;
527 demo_msg = (demo_recog_msg_t*) msg->data;
528
529 demo_msg->type = type;
530 demo_msg->channel = channel;
531 demo_msg->request = request;
532 status = apt_task_msg_signal(task,msg);
533 }
534 return status;
535 }
536
demo_recog_msg_process(apt_task_t * task,apt_task_msg_t * msg)537 static apt_bool_t demo_recog_msg_process(apt_task_t *task, apt_task_msg_t *msg)
538 {
539 demo_recog_msg_t *demo_msg = (demo_recog_msg_t*)msg->data;
540 switch(demo_msg->type) {
541 case DEMO_RECOG_MSG_OPEN_CHANNEL:
542 /* open channel and send asynch response */
543 mrcp_engine_channel_open_respond(demo_msg->channel,TRUE);
544 break;
545 case DEMO_RECOG_MSG_CLOSE_CHANNEL:
546 {
547 /* close channel, make sure there is no activity and send asynch response */
548 demo_recog_channel_t *recog_channel = demo_msg->channel->method_obj;
549 if(recog_channel->audio_out) {
550 fclose(recog_channel->audio_out);
551 recog_channel->audio_out = NULL;
552 }
553
554 mrcp_engine_channel_close_respond(demo_msg->channel);
555 break;
556 }
557 case DEMO_RECOG_MSG_REQUEST_PROCESS:
558 demo_recog_channel_request_dispatch(demo_msg->channel,demo_msg->request);
559 break;
560 default:
561 break;
562 }
563 return TRUE;
564 }
565