diff --git a/libs/unimrcp/build/pkgconfig/unimrcpclient.pc.in b/libs/unimrcp/build/pkgconfig/unimrcpclient.pc.in index 7fe3f1c130..f95c6822f7 100644 --- a/libs/unimrcp/build/pkgconfig/unimrcpclient.pc.in +++ b/libs/unimrcp/build/pkgconfig/unimrcpclient.pc.in @@ -1,7 +1,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=@includedir@ @UNIMRCP_APR_INCLUDES@ +includedir=@includedir@ @UNIMRCP_APR_INCLUDES@ @UNIMRCP_APU_INCLUDES@ Name: unimrcpclient Description: UniMRCP Client Stack diff --git a/libs/unimrcp/build/pkgconfig/unimrcpplugin.pc.in b/libs/unimrcp/build/pkgconfig/unimrcpplugin.pc.in index df78b8ea7f..e0d93cc005 100644 --- a/libs/unimrcp/build/pkgconfig/unimrcpplugin.pc.in +++ b/libs/unimrcp/build/pkgconfig/unimrcpplugin.pc.in @@ -1,7 +1,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=@includedir@ @UNIMRCP_APR_INCLUDES@ +includedir=@includedir@ @UNIMRCP_APR_INCLUDES@ @UNIMRCP_APU_INCLUDES@ Name: unimrcpplugin Description: UniMRCP Server Plugin diff --git a/libs/unimrcp/build/pkgconfig/unimrcpserver.pc.in b/libs/unimrcp/build/pkgconfig/unimrcpserver.pc.in index 3ed91ecd02..fcb221302e 100644 --- a/libs/unimrcp/build/pkgconfig/unimrcpserver.pc.in +++ b/libs/unimrcp/build/pkgconfig/unimrcpserver.pc.in @@ -1,7 +1,7 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -includedir=@includedir@ @UNIMRCP_APR_INCLUDES@ +includedir=@includedir@ @UNIMRCP_APR_INCLUDES@ @UNIMRCP_APU_INCLUDES@ Name: unimrcpserver Description: UniMRCP Server Stack diff --git a/libs/unimrcp/libs/apr-toolkit/Makefile.am b/libs/unimrcp/libs/apr-toolkit/Makefile.am index e2a065beec..e887e398c2 100644 --- a/libs/unimrcp/libs/apr-toolkit/Makefile.am +++ b/libs/unimrcp/libs/apr-toolkit/Makefile.am @@ -21,6 +21,7 @@ include_HEADERS = include/apt.h \ include/apt_string_table.h \ include/apt_text_stream.h \ include/apt_net.h \ + include/apt_nlsml_doc.h \ include/apt_dir_layout.h \ include/apt_test_suite.h @@ -38,6 +39,7 @@ libaprtoolkit_la_SOURCES = src/apt_obj_list.c \ src/apt_string_table.c \ src/apt_text_stream.c \ src/apt_net.c \ + src/apt_nlsml_doc.c \ src/apt_dir_layout.c \ src/apt_test_suite.c diff --git a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj index 1687f81af7..66d8386294 100644 --- a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj +++ b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj @@ -161,6 +161,10 @@ RelativePath=".\include\apt_net_server_task.h" > + + @@ -234,6 +238,10 @@ RelativePath=".\src\apt_net_server_task.c" > + + diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h b/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h new file mode 100644 index 0000000000..85f8476db4 --- /dev/null +++ b/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h @@ -0,0 +1,48 @@ +/* + * Copyright 2008 Arsen Chaloyan + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __APT_NLSML_DOC_H__ +#define __APT_NLSML_DOC_H__ + +/** + * @file apt_nlsml_doc.h + * @brief Basic NLSML Routine + */ + +#include "apr_xml.h" +#include "apt_string.h" + +APT_BEGIN_EXTERN_C + +/** Load NLSML document */ +APT_DECLARE(apr_xml_doc*) nlsml_doc_load(const apt_str_t *data, apr_pool_t *pool); + +/** Get the first element */ +APT_DECLARE(apr_xml_elem*) nlsml_first_interpret_get(const apr_xml_doc *doc); + +/** Get the next element */ +APT_DECLARE(apr_xml_elem*) nlsml_next_interpret_get(const apr_xml_elem *interpret); + +/** Get and elements of element */ +APT_DECLARE(apt_bool_t) nlsml_interpret_results_get(const apr_xml_elem *interpret, apr_xml_elem **instance, apr_xml_elem **input); + +/** Get specified atrribute of */ +APT_DECLARE(const char *) nlsml_input_attrib_get(const apr_xml_elem *input, const char *attrib, apt_bool_t recursive); + + +APT_END_EXTERN_C + +#endif /*__APT_NLSML_DOC_H__*/ diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c b/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c new file mode 100644 index 0000000000..4e4ae82124 --- /dev/null +++ b/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c @@ -0,0 +1,108 @@ +/* + * 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 "apt_nlsml_doc.h" + +/** Load NLSML document */ +APT_DECLARE(apr_xml_doc*) nlsml_doc_load(const apt_str_t *data, apr_pool_t *pool) +{ + apr_xml_parser *parser; + apr_xml_doc *doc = NULL; + const apr_xml_elem *root; + + /* create XML parser */ + parser = apr_xml_parser_create(pool); + if(apr_xml_parser_feed(parser,data->buf,data->length) != APR_SUCCESS) { + return NULL; + } + + /* done with XML tree creation */ + if(apr_xml_parser_done(parser,&doc) != APR_SUCCESS) { + return NULL; + } + + if(!doc || !doc->root) { + return NULL; + } + root = doc->root; + + /* NLSML validity check: root element must be */ + if(strcmp(root->name,"result") != 0) { + return NULL; + } + + return doc; +} + +/** Get the first element */ +APT_DECLARE(apr_xml_elem*) nlsml_first_interpret_get(const apr_xml_doc *doc) +{ + apr_xml_elem *child_elem; + for(child_elem = doc->root->first_child; child_elem; child_elem = child_elem->next) { + if(strcmp(child_elem->name,"interpretation") == 0) { + return child_elem; + } + } + + return NULL; +} + +/** Get the next element */ +APT_DECLARE(apr_xml_elem*) nlsml_next_interpret_get(const apr_xml_elem *elem) +{ + apr_xml_elem *child_elem; + for(child_elem = elem->next; child_elem; child_elem = child_elem->next) { + if(strcmp(child_elem->name,"interpretation") == 0) { + return child_elem; + } + } + + return NULL; +} + +/** Get and elements of element */ +APT_DECLARE(apt_bool_t) nlsml_interpret_results_get(const apr_xml_elem *interpret, apr_xml_elem **instance, apr_xml_elem **input) +{ + apr_xml_elem *child_elem; + *input = NULL; + *instance = NULL; + for(child_elem = interpret->first_child; child_elem; child_elem = child_elem->next) { + if(strcmp(child_elem->name,"input") == 0) { + *input = child_elem; + } + else if(strcmp(child_elem->name,"instance") == 0) { + *instance = child_elem; + } + } + return TRUE; +} + +/** Get specified atrribute of */ +APT_DECLARE(const char *) nlsml_input_attrib_get(const apr_xml_elem *input, const char *attrib, apt_bool_t recursive) +{ + const apr_xml_attr *xml_attr; + for(xml_attr = input->attr; xml_attr; xml_attr = xml_attr->next) { + if(strcasecmp(xml_attr->name,attrib) == 0) { + return xml_attr->value; + } + } + + if(recursive && input->parent) { + return nlsml_input_attrib_get(input->parent,attrib,recursive); + } + + return NULL; +} diff --git a/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h b/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h index dcc0544198..7af9884e5d 100644 --- a/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h +++ b/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h @@ -93,6 +93,8 @@ struct mrcp_server_session_t { apr_size_t answer_flag_count; /** Number of in-progress terminate requests (flags) */ apr_size_t terminate_flag_count; + /** Number of in-progress deactivare requests (flags) */ + apr_size_t deactivate_flag_count; }; /** MRCP profile */ diff --git a/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c b/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c index 6ef74b2c5b..01d03c8d87 100644 --- a/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c +++ b/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c @@ -595,7 +595,7 @@ MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(mrcp_server_t *server) void mrcp_server_session_add(mrcp_server_session_t *session) { if(session->base.id.buf) { - apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Add Session "APT_SID_FMT,session->base.id.buf); + apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Add Session "APT_SID_FMT,MRCP_SESSION_SID(&session->base)); apr_hash_set(session->server->session_table,session->base.id.buf,session->base.id.length,session); } } @@ -603,7 +603,7 @@ void mrcp_server_session_add(mrcp_server_session_t *session) void mrcp_server_session_remove(mrcp_server_session_t *session) { if(session->base.id.buf) { - apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Remove Session "APT_SID_FMT,session->base.id.buf); + apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Remove Session "APT_SID_FMT,MRCP_SESSION_SID(&session->base)); apr_hash_set(session->server->session_table,session->base.id.buf,session->base.id.length,NULL); } } @@ -820,7 +820,7 @@ static mrcp_profile_t* mrcp_server_profile_get_by_agent(mrcp_server_t *server, m return profile; } } - apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Find Profile by Agent "APT_SID_FMT,session->base.id.buf); + apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Find Profile by Agent "APT_SID_FMT,MRCP_SESSION_SID(&session->base)); return NULL; } diff --git a/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c b/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c index 65ab8bcc6e..7269ddf60f 100644 --- a/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c +++ b/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c @@ -93,6 +93,9 @@ static apt_bool_t mrcp_server_mpf_request_send( mpf_termination_t *termination, void *descriptor); +static apt_bool_t state_machine_on_message_dispatch(mrcp_state_machine_t *state_machine, mrcp_message_t *message); +static apt_bool_t state_machine_on_deactivate(mrcp_state_machine_t *state_machine); + mrcp_server_session_t* mrcp_server_session_create() { @@ -106,6 +109,7 @@ mrcp_server_session_t* mrcp_server_session_create() session->answer = NULL; session->answer_flag_count = 0; session->terminate_flag_count = 0; + session->deactivate_flag_count = 0; return session; } @@ -123,47 +127,6 @@ static mrcp_engine_channel_t* mrcp_server_engine_channel_create(mrcp_server_sess return resource_engine->method_vtable->create_channel(resource_engine,session->base.pool); } -static apt_bool_t mrcp_server_message_dispatch(mrcp_state_machine_t *state_machine, mrcp_message_t *message) -{ - mrcp_channel_t *channel = state_machine->obj; - - if(message->start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) { - /* send request message to resource engine for actual processing */ - if(channel->engine_channel) { - mrcp_engine_channel_request_process(channel->engine_channel,message); - } - } - else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) { - mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session; - /* send response message to client */ - if(channel->control_channel) { - /* MRCPv2 */ - mrcp_server_control_message_send(channel->control_channel,message); - } - else { - /* MRCPv1 */ - mrcp_session_control_response(channel->session,message); - } - - session->active_request = apt_list_pop_front(session->request_queue); - if(session->active_request) { - mrcp_server_signaling_message_dispatch(session,session->active_request); - } - } - else { - /* send event message to client */ - if(channel->control_channel) { - /* MRCPv2 */ - mrcp_server_control_message_send(channel->control_channel,message); - } - else { - /* MRCPv1 */ - mrcp_session_control_response(channel->session,message); - } - } - return TRUE; -} - static mrcp_channel_t* mrcp_server_channel_create(mrcp_server_session_t *session, const apt_str_t *resource_name, apr_size_t id) { mrcp_channel_t *channel; @@ -200,9 +163,12 @@ static mrcp_channel_t* mrcp_server_channel_create(mrcp_server_session_t *session } channel->state_machine = resource->create_server_state_machine( channel, - mrcp_server_message_dispatch, session->base.signaling_agent->mrcp_version, pool); + if(channel->state_machine) { + channel->state_machine->on_dispatch = state_machine_on_message_dispatch; + channel->state_machine->on_deactivate = state_machine_on_deactivate; + } engine_channel = mrcp_server_engine_channel_create(session,resource_name); if(engine_channel) { @@ -413,7 +379,7 @@ static apt_bool_t mrcp_server_session_offer_process(mrcp_server_session_t *sessi session->context = mpf_context_create(session,5,session->base.pool); } apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Offer "APT_SID_FMT" [c:%d a:%d v:%d]", - session->base.id.buf, + MRCP_SESSION_SID(&session->base), descriptor->control_media_arr->nelts, descriptor->audio_media_arr->nelts, descriptor->video_media_arr->nelts); @@ -447,7 +413,7 @@ static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *s mrcp_channel_t *channel; mrcp_termination_slot_t *slot; int i; - apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Terminate Request "APT_SID_FMT,session->base.id.buf); + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Terminate Request "APT_SID_FMT,MRCP_SESSION_SID(&session->base)); for(i=0; ichannels->nelts; i++) { channel = ((mrcp_channel_t**)session->channels->elts)[i]; if(!channel) continue; @@ -499,6 +465,27 @@ static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *s return TRUE; } +static apt_bool_t mrcp_server_session_deactivate(mrcp_server_session_t *session) +{ + mrcp_channel_t *channel; + int i; + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Deactivate Session "APT_SID_FMT,MRCP_SESSION_SID(&session->base)); + for(i=0; ichannels->nelts; i++) { + channel = ((mrcp_channel_t**)session->channels->elts)[i]; + if(!channel || !channel->state_machine) continue; + + if(mrcp_state_machine_deactivate(channel->state_machine) == TRUE) { + session->deactivate_flag_count++; + } + } + + if(!session->deactivate_flag_count) { + mrcp_server_session_terminate_process(session); + } + + return TRUE; +} + static apt_bool_t mrcp_server_on_message_receive(mrcp_server_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message) { if(!channel) { @@ -528,7 +515,7 @@ static apt_bool_t mrcp_server_signaling_message_dispatch(mrcp_server_session_t * mrcp_server_on_message_receive(signaling_message->session,signaling_message->channel,signaling_message->message); break; case SIGNALING_MESSAGE_TERMINATE: - mrcp_server_session_terminate_process(signaling_message->session); + mrcp_server_session_deactivate(signaling_message->session); break; default: break; @@ -749,7 +736,7 @@ static apt_bool_t mrcp_server_session_answer_send(mrcp_server_session_t *session apt_bool_t status; mrcp_session_descriptor_t *descriptor = session->answer; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Answer "APT_SID_FMT" [c:%d a:%d v:%d] Status %s", - session->base.id.buf, + MRCP_SESSION_SID(&session->base), descriptor->control_media_arr->nelts, descriptor->audio_media_arr->nelts, descriptor->video_media_arr->nelts, @@ -782,7 +769,7 @@ static apt_bool_t mrcp_server_session_terminate_send(mrcp_server_session_t *sess channel->engine_channel = NULL; } } - apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Terminate Response "APT_SID_FMT,session->base.id.buf); + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Terminate Response "APT_SID_FMT,MRCP_SESSION_SID(&session->base)); mrcp_session_terminate_response(&session->base); return TRUE; } @@ -912,6 +899,60 @@ static apt_bool_t mrcp_server_on_termination_subtract(mrcp_server_session_t *ses return TRUE; } +static apt_bool_t state_machine_on_message_dispatch(mrcp_state_machine_t *state_machine, mrcp_message_t *message) +{ + mrcp_channel_t *channel = state_machine->obj; + + if(message->start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) { + /* send request message to resource engine for actual processing */ + if(channel->engine_channel) { + mrcp_engine_channel_request_process(channel->engine_channel,message); + } + } + else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) { + mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session; + /* send response message to client */ + if(channel->control_channel) { + /* MRCPv2 */ + mrcp_server_control_message_send(channel->control_channel,message); + } + else { + /* MRCPv1 */ + mrcp_session_control_response(channel->session,message); + } + + session->active_request = apt_list_pop_front(session->request_queue); + if(session->active_request) { + mrcp_server_signaling_message_dispatch(session,session->active_request); + } + } + else { + /* send event message to client */ + if(channel->control_channel) { + /* MRCPv2 */ + mrcp_server_control_message_send(channel->control_channel,message); + } + else { + /* MRCPv1 */ + mrcp_session_control_response(channel->session,message); + } + } + return TRUE; +} + +static apt_bool_t state_machine_on_deactivate(mrcp_state_machine_t *state_machine) +{ + mrcp_channel_t *channel = state_machine->obj; + mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session; + if(session->deactivate_flag_count) { + session->deactivate_flag_count --; + if(!session->deactivate_flag_count) { + mrcp_server_session_terminate_process(session); + } + } + return TRUE; +} + static apt_bool_t mrcp_server_mpf_request_send( mrcp_server_session_t *session, mpf_command_type_e command_id, diff --git a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h index c85af89991..b46851b2ac 100644 --- a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h +++ b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h @@ -40,9 +40,9 @@ struct mrcp_resource_t { apt_bool_t (*resourcify_message_by_name)(mrcp_resource_t *resource, mrcp_message_t *message); /** Create client side state machine */ - mrcp_state_machine_t* (*create_client_state_machine)(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool); + mrcp_state_machine_t* (*create_client_state_machine)(void *obj, mrcp_version_e version, apr_pool_t *pool); /** Create server side state machine */ - mrcp_state_machine_t* (*create_server_state_machine)(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool); + mrcp_state_machine_t* (*create_server_state_machine)(void *obj, mrcp_version_e version, apr_pool_t *pool); }; /** Initialize MRCP resource */ diff --git a/libs/unimrcp/libs/mrcp/control/include/mrcp_state_machine.h b/libs/unimrcp/libs/mrcp/control/include/mrcp_state_machine.h index 52ec2ddf32..4089a8bd07 100644 --- a/libs/unimrcp/libs/mrcp/control/include/mrcp_state_machine.h +++ b/libs/unimrcp/libs/mrcp/control/include/mrcp_state_machine.h @@ -29,32 +29,54 @@ APT_BEGIN_EXTERN_C /** MRCP state machine declaration */ typedef struct mrcp_state_machine_t mrcp_state_machine_t; -/** MRCP message dispatcher */ -typedef apt_bool_t (*mrcp_message_dispatcher_f)(mrcp_state_machine_t *state_machine, mrcp_message_t *message); - /** MRCP state machine */ struct mrcp_state_machine_t { /** External object associated with state machine */ void *obj; - /** Message dispatcher */ - mrcp_message_dispatcher_f dispatcher; + /** State either active or deactivating */ + apt_bool_t active; /** Virtual update */ apt_bool_t (*update)(mrcp_state_machine_t *state_machine, mrcp_message_t *message); + /** Deactivate */ + apt_bool_t (*deactivate)(mrcp_state_machine_t *state_machine); + + + /** Message dispatcher */ + apt_bool_t (*on_dispatch)(mrcp_state_machine_t *state_machine, mrcp_message_t *message); + /** Deactivated */ + apt_bool_t (*on_deactivate)(mrcp_state_machine_t *state_machine); }; /** Initialize MRCP state machine */ -static APR_INLINE void mrcp_state_machine_init(mrcp_state_machine_t *state_machine, void *obj, mrcp_message_dispatcher_f dispatcher) +static APR_INLINE void mrcp_state_machine_init(mrcp_state_machine_t *state_machine, void *obj) { state_machine->obj = obj; - state_machine->dispatcher = dispatcher; + state_machine->active = TRUE; + state_machine->on_dispatch = NULL; + state_machine->on_deactivate = NULL; + state_machine->update = NULL; + state_machine->deactivate = NULL; } /** Update MRCP state machine */ static APR_INLINE apt_bool_t mrcp_state_machine_update(mrcp_state_machine_t *state_machine, mrcp_message_t *message) { - return state_machine->update(state_machine,message); + if(state_machine->update) { + return state_machine->update(state_machine,message); + } + return FALSE; +} + +/** Deactivate MRCP state machine */ +static APR_INLINE apt_bool_t mrcp_state_machine_deactivate(mrcp_state_machine_t *state_machine) +{ + if(state_machine->deactivate) { + state_machine->active = FALSE; + return state_machine->deactivate(state_machine); + } + return FALSE; } APT_END_EXTERN_C diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_state_machine.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_state_machine.h index 0fcbd5e5f1..ee04601c22 100644 --- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_state_machine.h +++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_state_machine.h @@ -27,10 +27,10 @@ APT_BEGIN_EXTERN_C /** Create MRCP recognizer server state machine */ -mrcp_state_machine_t* mrcp_recog_server_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool); +mrcp_state_machine_t* mrcp_recog_server_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool); /** Create MRCP recognizer client state machine */ -mrcp_state_machine_t* mrcp_recog_client_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool); +mrcp_state_machine_t* mrcp_recog_client_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool); APT_END_EXTERN_C diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_state_machine.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_state_machine.h index 524fd29271..eed266e2a4 100644 --- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_state_machine.h +++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_state_machine.h @@ -27,10 +27,10 @@ APT_BEGIN_EXTERN_C /** Create MRCP synthesizer server state machine */ -mrcp_state_machine_t* mrcp_synth_server_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool); +mrcp_state_machine_t* mrcp_synth_server_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool); /** Create MRCP synthesizer client state machine */ -mrcp_state_machine_t* mrcp_synth_client_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool); +mrcp_state_machine_t* mrcp_synth_client_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool); APT_END_EXTERN_C diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_client_state_machine.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_client_state_machine.c index 3e313d7202..358f5ee64e 100644 --- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_client_state_machine.c +++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_client_state_machine.c @@ -23,14 +23,14 @@ static apt_bool_t recog_state_update(mrcp_state_machine_t *state_machine, mrcp_message_t *message) { /* no actual state machine processing yet, dispatch whatever received */ - return state_machine->dispatcher(state_machine,message); + return state_machine->on_dispatch(state_machine,message); } /** Create MRCP recognizer client state machine */ -mrcp_state_machine_t* mrcp_recog_client_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool) +mrcp_state_machine_t* mrcp_recog_client_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool) { mrcp_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_state_machine_t)); - mrcp_state_machine_init(state_machine,obj,dispatcher); + mrcp_state_machine_init(state_machine,obj); state_machine->update = recog_state_update; return state_machine; } diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c index 70691a5a31..1d1a997014 100644 --- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c +++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "mrcp_recog_header.h" /** String table of MRCPv1 recognizer headers (mrcp_recog_header_id) */ diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_server_state_machine.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_server_state_machine.c index 13828ce572..206512967a 100644 --- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_server_state_machine.c +++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_server_state_machine.c @@ -61,18 +61,26 @@ typedef apt_bool_t (*recog_method_f)(mrcp_recog_state_machine_t *state_machine, static APR_INLINE apt_bool_t recog_request_dispatch(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message) { state_machine->active_request = message; - return state_machine->base.dispatcher(&state_machine->base,message); + return state_machine->base.on_dispatch(&state_machine->base,message); } static APR_INLINE apt_bool_t recog_response_dispatch(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message) { state_machine->active_request = NULL; - return state_machine->base.dispatcher(&state_machine->base,message); + if(state_machine->base.active == FALSE) { + /* this is the response to deactivation (STOP) request */ + return state_machine->base.on_deactivate(&state_machine->base); + } + return state_machine->base.on_dispatch(&state_machine->base,message); } static APR_INLINE apt_bool_t recog_event_dispatch(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message) { - return state_machine->base.dispatcher(&state_machine->base,message); + if(state_machine->base.active == FALSE) { + /* do nothing, state machine has already been deactivated */ + return FALSE; + } + return state_machine->base.on_dispatch(&state_machine->base,message); } static APR_INLINE void recog_state_change(mrcp_recog_state_machine_t *state_machine, mrcp_recog_state_e state) @@ -286,10 +294,10 @@ static apt_bool_t recog_response_stop(mrcp_recog_state_machine_t *state_machine, mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST); recog_pending_requests_remove(state_machine,state_machine->active_request,message); recog_state_change(state_machine,RECOGNIZER_STATE_IDLE); + pending_request = apt_list_pop_front(state_machine->queue); recog_response_dispatch(state_machine,message); /* process pending RECOGNIZE requests / if any */ - pending_request = apt_list_pop_front(state_machine->queue); if(pending_request) { apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending RECOGNIZE Request [%d]",pending_request->start_line.request_id); state_machine->is_pending = TRUE; @@ -432,19 +440,19 @@ static apt_bool_t recog_event_state_update(mrcp_recog_state_machine_t *state_mac } /** Update state according to request received from MRCP client or response/event received from recognition engine */ -static apt_bool_t recog_state_update(mrcp_state_machine_t *state_machine, mrcp_message_t *message) +static apt_bool_t recog_state_update(mrcp_state_machine_t *base, mrcp_message_t *message) { - mrcp_recog_state_machine_t *recog_state_machine = (mrcp_recog_state_machine_t*)state_machine; + mrcp_recog_state_machine_t *state_machine = (mrcp_recog_state_machine_t*)base; apt_bool_t status = TRUE; switch(message->start_line.message_type) { case MRCP_MESSAGE_TYPE_REQUEST: - status = recog_request_state_update(recog_state_machine,message); + status = recog_request_state_update(state_machine,message); break; case MRCP_MESSAGE_TYPE_RESPONSE: - status = recog_response_state_update(recog_state_machine,message); + status = recog_response_state_update(state_machine,message); break; case MRCP_MESSAGE_TYPE_EVENT: - status = recog_event_state_update(recog_state_machine,message); + status = recog_event_state_update(state_machine,message); break; default: status = FALSE; @@ -453,13 +461,42 @@ static apt_bool_t recog_state_update(mrcp_state_machine_t *state_machine, mrcp_m return status; } +/** Deactivate state machine */ +static apt_bool_t recog_state_deactivate(mrcp_state_machine_t *base) +{ + mrcp_recog_state_machine_t *state_machine = (mrcp_recog_state_machine_t*)base; + mrcp_message_t *message; + mrcp_message_t *source; + if(state_machine->state != RECOGNIZER_STATE_RECOGNIZING) { + /* no in-progress RECOGNIZE request to deactivate */ + return FALSE; + } + source = state_machine->recog; + if(!source) { + return FALSE; + } + + /* create internal STOP request */ + message = mrcp_request_create( + source->channel_id.resource_id, + RECOGNIZER_STOP, + source->pool); + message->channel_id = source->channel_id; + message->start_line.request_id = source->start_line.request_id + 1; + apt_string_set(&message->start_line.method_name,"DEACTIVATE"); /* informative only */ + message->header = source->header; + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request [%d]",message->start_line.request_id); + return recog_request_dispatch(state_machine,message); +} + /** Create MRCP recognizer server state machine */ -mrcp_state_machine_t* mrcp_recog_server_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool) +mrcp_state_machine_t* mrcp_recog_server_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool) { mrcp_message_header_t *properties; mrcp_recog_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_recog_state_machine_t)); - mrcp_state_machine_init(&state_machine->base,obj,dispatcher); + mrcp_state_machine_init(&state_machine->base,obj); state_machine->base.update = recog_state_update; + state_machine->base.deactivate = recog_state_deactivate; state_machine->state = RECOGNIZER_STATE_IDLE; state_machine->is_pending = FALSE; state_machine->active_request = NULL; diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_client_state_machine.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_client_state_machine.c index 6dd4da2dd9..b34378d176 100644 --- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_client_state_machine.c +++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_client_state_machine.c @@ -23,14 +23,14 @@ static apt_bool_t synth_state_update(mrcp_state_machine_t *state_machine, mrcp_message_t *message) { /* no actual state machine processing yet, dispatch whatever received */ - return state_machine->dispatcher(state_machine,message); + return state_machine->on_dispatch(state_machine,message); } /** Create MRCP synthesizer client state machine */ -mrcp_state_machine_t* mrcp_synth_client_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool) +mrcp_state_machine_t* mrcp_synth_client_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool) { mrcp_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_state_machine_t)); - mrcp_state_machine_init(state_machine,obj,dispatcher); + mrcp_state_machine_init(state_machine,obj); state_machine->update = synth_state_update; return state_machine; } diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c index e7c467f85d..0a84904da3 100644 --- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c +++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "mrcp_synth_header.h" /** String table of MRCP synthesizer headers (mrcp_synthesizer_header_id) */ diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_server_state_machine.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_server_state_machine.c index d569bf952c..73ed63e953 100644 --- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_server_state_machine.c +++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_server_state_machine.c @@ -61,18 +61,26 @@ typedef apt_bool_t (*synth_method_f)(mrcp_synth_state_machine_t *state_machine, static APR_INLINE apt_bool_t synth_request_dispatch(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message) { state_machine->active_request = message; - return state_machine->base.dispatcher(&state_machine->base,message); + return state_machine->base.on_dispatch(&state_machine->base,message); } static APR_INLINE apt_bool_t synth_response_dispatch(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message) { state_machine->active_request = NULL; - return state_machine->base.dispatcher(&state_machine->base,message); + if(state_machine->base.active == FALSE) { + /* this is the response to deactivation (STOP) request */ + return state_machine->base.on_deactivate(&state_machine->base); + } + return state_machine->base.on_dispatch(&state_machine->base,message); } static APR_INLINE apt_bool_t synth_event_dispatch(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message) { - return state_machine->base.dispatcher(&state_machine->base,message); + if(state_machine->base.active == FALSE) { + /* do nothing, state machine has already been deactivated */ + return FALSE; + } + return state_machine->base.on_dispatch(&state_machine->base,message); } static APR_INLINE void synth_state_change(mrcp_synth_state_machine_t *state_machine, mrcp_synth_state_e state) @@ -220,10 +228,10 @@ static apt_bool_t synth_response_stop(mrcp_synth_state_machine_t *state_machine, mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST); synth_pending_requests_remove(state_machine,state_machine->active_request,message); synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE); + pending_request = apt_list_pop_front(state_machine->queue); synth_response_dispatch(state_machine,message); /* process pending SPEAK requests / if any */ - pending_request = apt_list_pop_front(state_machine->queue); if(pending_request) { apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending SPEAK Request [%d]",pending_request->start_line.request_id); state_machine->is_pending = TRUE; @@ -522,9 +530,9 @@ static apt_bool_t synth_event_state_update(mrcp_synth_state_machine_t *state_mac } /** Update state according to request received from MRCP client or response/event received from synthesizer engine */ -static apt_bool_t synth_state_update(mrcp_state_machine_t *state_machine, mrcp_message_t *message) +static apt_bool_t synth_state_update(mrcp_state_machine_t *base, mrcp_message_t *message) { - mrcp_synth_state_machine_t *synth_state_machine = (mrcp_synth_state_machine_t*)state_machine; + mrcp_synth_state_machine_t *synth_state_machine = (mrcp_synth_state_machine_t*)base; apt_bool_t status = TRUE; switch(message->start_line.message_type) { case MRCP_MESSAGE_TYPE_REQUEST: @@ -543,13 +551,39 @@ static apt_bool_t synth_state_update(mrcp_state_machine_t *state_machine, mrcp_m return status; } +/** Deactivate state machine */ +static apt_bool_t synth_state_deactivate(mrcp_state_machine_t *base) +{ + mrcp_synth_state_machine_t *state_machine = (mrcp_synth_state_machine_t*)base; + mrcp_message_t *message; + mrcp_message_t *source; + if(!state_machine->speaker) { + /* no in-progress SPEAK request to deactivate */ + return FALSE; + } + source = state_machine->speaker; + + /* create internal STOP request */ + message = mrcp_request_create( + source->channel_id.resource_id, + SYNTHESIZER_STOP, + source->pool); + message->channel_id = source->channel_id; + message->start_line.request_id = source->start_line.request_id + 1; + apt_string_set(&message->start_line.method_name,"DEACTIVATE"); /* informative only */ + message->header = source->header; + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request [%d]",message->start_line.request_id); + return synth_request_dispatch(state_machine,message); +} + /** Create MRCP synthesizer server state machine */ -mrcp_state_machine_t* mrcp_synth_server_state_machine_create(void *obj, mrcp_message_dispatcher_f dispatcher, mrcp_version_e version, apr_pool_t *pool) +mrcp_state_machine_t* mrcp_synth_server_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool) { mrcp_message_header_t *properties; mrcp_synth_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_synth_state_machine_t)); - mrcp_state_machine_init(&state_machine->base,obj,dispatcher); + mrcp_state_machine_init(&state_machine->base,obj); state_machine->base.update = synth_state_update; + state_machine->base.deactivate = synth_state_deactivate; state_machine->state = SYNTHESIZER_STATE_IDLE; state_machine->is_pending = FALSE; state_machine->active_request = NULL; diff --git a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c index 1cfed93e01..d5e36525fe 100644 --- a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c +++ b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c @@ -14,7 +14,7 @@ * limitations under the License. */ - +#include #include #include #include "mrcp_sdp.h" diff --git a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c index fc33c9477d..f1ea89185a 100644 --- a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c +++ b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include "rtsp_message.h" diff --git a/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c b/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c index 5844f5c55c..e3f945a5dd 100644 --- a/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c +++ b/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include "unimrcp_client.h" #include "uni_version.h" diff --git a/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c b/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c index f95e62ff32..46d3ef4059 100644 --- a/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c +++ b/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include "unimrcp_server.h" #include "uni_version.h" diff --git a/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h b/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h index 78f8ef0b1c..c3d6e793d9 100644 --- a/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h +++ b/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h @@ -34,6 +34,8 @@ mrcp_message_t* demo_define_grammar_message_create(mrcp_session_t *session, mrcp /** 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); +/** Parse NLSML result */ +apt_bool_t demo_nlsml_result_parse(mrcp_message_t *message); /** Create demo RTP termination descriptor */ mpf_rtp_termination_descriptor_t* demo_rtp_descriptor_create(apr_pool_t *pool); diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c index 6c45bc17cb..2f4815af97 100644 --- a/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c +++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c @@ -291,6 +291,7 @@ static apt_bool_t recog_application_on_message_receive(mrcp_application_t *appli } else if(message->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT) { if(message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) { + demo_nlsml_result_parse(message); if(recog_channel) { recog_channel->streaming = FALSE; } diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c index d281885e8d..75812a125f 100644 --- a/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c +++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c @@ -25,6 +25,10 @@ /* recognizer includes */ #include "mrcp_recog_header.h" #include "mrcp_recog_resource.h" +/* NLSML doc include */ +#include "apt_nlsml_doc.h" +/* logger include */ +#include "apt_log.h" static void demo_message_body_set(mrcp_message_t *mrcp_message, const apt_dir_layout_t *dir_layout, const char *file_name) { @@ -127,6 +131,8 @@ mrcp_message_t* demo_recognize_message_create(mrcp_session_t *session, mrcp_chan 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); + recog_header->confidence_threshold = 0.87f; + mrcp_resource_header_property_add(mrcp_message,RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD); } /* set message body */ apt_string_assign(&mrcp_message->body,text,mrcp_message->pool); @@ -134,6 +140,37 @@ mrcp_message_t* demo_recognize_message_create(mrcp_session_t *session, mrcp_chan return mrcp_message; } +/** Parse NLSML result */ +apt_bool_t demo_nlsml_result_parse(mrcp_message_t *message) +{ + apr_xml_elem *interpret; + apr_xml_elem *instance; + apr_xml_elem *input; + apr_xml_doc *doc = nlsml_doc_load(&message->body,message->pool); + if(!doc) { + return FALSE; + } + + /* walk through interpreted results */ + interpret = nlsml_first_interpret_get(doc); + for(; interpret; interpret = nlsml_next_interpret_get(interpret)) { + /* get instance and input */ + nlsml_interpret_results_get(interpret,&instance,&input); + if(instance) { + /* process instance */ + if(instance->first_cdata.first) { + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpreted Instance [%s]",instance->first_cdata.first->text); + } + } + if(input) { + /* process input */ + if(input->first_cdata.first) { + apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Interpreted Input [%s]",input->first_cdata.first->text); + } + } + } + return TRUE; +} /** Create demo RTP termination descriptor */ mpf_rtp_termination_descriptor_t* demo_rtp_descriptor_create(apr_pool_t *pool) diff --git a/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c b/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c index a8b8a803aa..4d9c4ad6ed 100644 --- a/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c +++ b/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c @@ -119,6 +119,8 @@ typedef struct flite_speak_msg_t flite_speak_msg_t; /* we have a special task for the actual synthesis - the task is created when a mrcp speak message is received */ static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg); +static apt_bool_t flite_on_start(apt_task_t *task); +static apt_bool_t flite_on_terminate(apt_task_t *task); /** Declare this macro to use log routine of the server where the plugin is loaded from */ MRCP_PLUGIN_LOGGER_IMPLEMENT @@ -184,14 +186,16 @@ static apt_bool_t flite_synth_task_create(flite_synth_channel_t *synth_channel) } task_vtable = apt_consumer_task_vtable_get(consumer_task); - if(!task_vtable) { - apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak cannot use flite speak task vtable - channel:%d", synth_channel->iId); - return FALSE; + if(task_vtable) { + task_vtable->process_msg = flite_speak; + task_vtable->on_pre_run = flite_on_start; + task_vtable->on_post_run = flite_on_terminate; } - - task_vtable->process_msg = flite_speak; synth_channel->msg_pool = msg_pool; synth_channel->task = apt_consumer_task_base_get(consumer_task); + if(synth_channel->task) { + apt_task_name_set(synth_channel->task,"Flite Task"); + } return TRUE; } @@ -199,19 +203,10 @@ static apt_bool_t flite_synth_task_create(flite_synth_channel_t *synth_channel) static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool) { /* create flite synth channel */ - flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) apr_palloc(pool,sizeof(flite_synth_channel_t)); mpf_codec_descriptor_t *codec_descriptor = NULL; + flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) apr_palloc(pool,sizeof(flite_synth_channel_t)); apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_channel_create"); -#if 0 - codec_descriptor = (mpf_codec_descriptor_t *) apr_palloc(pool,sizeof(mpf_codec_descriptor_t)); - mpf_codec_descriptor_init(codec_descriptor); - codec_descriptor->channel_count = 1; - codec_descriptor->payload_type = 96; - apt_string_set(&codec_descriptor->name,"LPCM"); - codec_descriptor->sampling_rate = 16000; -#endif - synth_channel->flite_engine = (flite_synth_engine_t *) engine->obj; synth_channel->speak_request = NULL; // no active speak request in progress synth_channel->speak_response = NULL; @@ -228,6 +223,15 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en return NULL; } +#if 0 + codec_descriptor = (mpf_codec_descriptor_t *) apr_palloc(pool,sizeof(mpf_codec_descriptor_t)); + mpf_codec_descriptor_init(codec_descriptor); + codec_descriptor->channel_count = 1; + codec_descriptor->payload_type = 96; + apt_string_set(&codec_descriptor->name,"LPCM"); + codec_descriptor->sampling_rate = 16000; +#endif + /* create engine channel base */ synth_channel->channel = mrcp_engine_source_channel_create( engine, /* resource engine */ @@ -272,14 +276,15 @@ static apt_bool_t flite_synth_channel_open(mrcp_engine_channel_t *channel) if(synth_channel->task) { if(apt_task_start(synth_channel->task) == TRUE) { - apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task started - channel %d", synth_channel->iId); + /* async response will be sent */ + return TRUE; } else { apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task start failed - channel %d", synth_channel->iId); } } - return mrcp_engine_channel_open_respond(channel,TRUE); + return mrcp_engine_channel_open_respond(channel,FALSE); } /** Close engine channel (asynchronous response MUST be sent)*/ @@ -289,15 +294,15 @@ static apt_bool_t flite_synth_channel_close(mrcp_engine_channel_t *channel) apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_close - channel %d", synth_channel->iId); if(synth_channel->task) { - if(apt_task_terminate(synth_channel->task,TRUE) == TRUE) { - apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task terminated - channel %d", synth_channel->iId); + if(apt_task_terminate(synth_channel->task,FALSE) == TRUE) { + /* async response will be sent */ + return TRUE; } else { apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task terminate failed - channel %d", synth_channel->iId); } } - mrcp_engine_channel_close_respond(channel); - return TRUE; + return mrcp_engine_channel_close_respond(channel); } /** Process MRCP channel request (asynchronous response MUST be sent)*/ @@ -428,7 +433,7 @@ static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg) apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "< flite_speak_msg_process speak - channel %d", synth_channel->iId); /* just sequential stuff */ - start = apr_time_now(); // in microsec + start = apr_time_now(); /* in microsec */ if(!body->length) { synth_channel->speak_request = NULL; synth_response_construct(response,MRCP_STATUS_CODE_MISSING_PARAM,SYNTHESIZER_COMPLETION_CAUSE_ERROR); @@ -479,7 +484,7 @@ static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg) delete_wave(wave); } - // this will notify the callback that feeds the client that synthesis is complete + /* this will notify the callback that feeds the client that synthesis is complete */ mpf_buffer_event_write(synth_channel->audio_buffer, MEDIA_FRAME_TYPE_EVENT); synth_channel->synthesizing = FALSE; @@ -487,6 +492,26 @@ static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg) return TRUE; } +static APR_INLINE flite_synth_channel_t* flite_synth_channel_get(apt_task_t *task) +{ + apt_consumer_task_t *consumer_task = apt_task_object_get(task); + return apt_consumer_task_object_get(consumer_task); +} + +static apt_bool_t flite_on_start(apt_task_t *task) +{ + flite_synth_channel_t *synth_channel = flite_synth_channel_get(task); + apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task started - channel %d", synth_channel->iId); + return mrcp_engine_channel_open_respond(synth_channel->channel,TRUE); +} + +static apt_bool_t flite_on_terminate(apt_task_t *task) +{ + flite_synth_channel_t *synth_channel = flite_synth_channel_get(task); + apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task terminated - channel %d", synth_channel->iId); + return mrcp_engine_channel_close_respond(synth_channel->channel); +} + /** Process STOP request */ static apt_bool_t flite_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { diff --git a/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c b/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c index 3a16fb7579..14e241d5b5 100644 --- a/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c +++ b/libs/unimrcp/plugins/mrcp-pocketsphinx/src/mrcp_pocketsphinx.c @@ -237,7 +237,10 @@ static mrcp_engine_channel_t* pocketsphinx_engine_recognizer_create(mrcp_resourc recognizer, /* object to associate */ NULL, /* codec descriptor might be NULL by default */ pool); /* pool to allocate memory from */ - + + apr_thread_mutex_create(&recognizer->mutex,APR_THREAD_MUTEX_DEFAULT,channel->pool); + apr_thread_cond_create(&recognizer->wait_object,channel->pool); + recognizer->channel = channel; return channel; } @@ -245,6 +248,15 @@ static mrcp_engine_channel_t* pocketsphinx_engine_recognizer_create(mrcp_resourc /** Destroy pocketsphinx recognizer */ static apt_bool_t pocketsphinx_recognizer_destroy(mrcp_engine_channel_t *channel) { + pocketsphinx_recognizer_t *recognizer = channel->method_obj; + if(recognizer->mutex) { + apr_thread_mutex_destroy(recognizer->mutex); + recognizer->mutex = NULL; + } + if(recognizer->wait_object) { + apr_thread_cond_destroy(recognizer->wait_object); + recognizer->wait_object = NULL; + } return TRUE; } @@ -256,17 +268,10 @@ static apt_bool_t pocketsphinx_recognizer_open(mrcp_engine_channel_t *channel) apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Channel "APT_SIDRES_FMT,RECOGNIZER_SIDRES(recognizer)); - apr_thread_mutex_create(&recognizer->mutex,APR_THREAD_MUTEX_DEFAULT,channel->pool); - apr_thread_cond_create(&recognizer->wait_object,channel->pool); - /* Launch a thread to run recognition in */ rv = apr_thread_create(&recognizer->thread,NULL,pocketsphinx_recognizer_run,recognizer,channel->pool); if(rv != APR_SUCCESS) { apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Failed to Launch Thread "APT_SIDRES_FMT,RECOGNIZER_SIDRES(recognizer)); - apr_thread_mutex_destroy(recognizer->mutex); - recognizer->mutex = NULL; - apr_thread_cond_destroy(recognizer->wait_object); - recognizer->wait_object = NULL; return mrcp_engine_channel_open_respond(channel,FALSE); } @@ -278,25 +283,16 @@ static apt_bool_t pocketsphinx_recognizer_close(mrcp_engine_channel_t *channel) { pocketsphinx_recognizer_t *recognizer = channel->method_obj; apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close Channel "APT_SIDRES_FMT,RECOGNIZER_SIDRES(recognizer)); - if(recognizer->thread) { - apr_status_t rv; - - /* Signal recognition thread to terminate */ - apr_thread_mutex_lock(recognizer->mutex); - recognizer->close_requested = TRUE; - apr_thread_cond_signal(recognizer->wait_object); - apr_thread_mutex_unlock(recognizer->mutex); - - apr_thread_join(&rv,recognizer->thread); - recognizer->thread = NULL; - - apr_thread_mutex_destroy(recognizer->mutex); - recognizer->mutex = NULL; - apr_thread_cond_destroy(recognizer->wait_object); - recognizer->wait_object = NULL; + if(!recognizer->thread) { + return mrcp_engine_channel_close_respond(channel); } - return mrcp_engine_channel_close_respond(channel); + /* Signal recognition thread to terminate */ + apr_thread_mutex_lock(recognizer->mutex); + recognizer->close_requested = TRUE; + apr_thread_cond_signal(recognizer->wait_object); + apr_thread_mutex_unlock(recognizer->mutex); + return TRUE; } /** Process MRCP request (asynchronous response MUST be sent)*/ @@ -533,12 +529,10 @@ static apt_bool_t pocketsphinx_recognize(pocketsphinx_recognizer_t *recognizer, return FALSE; } - response_recog_header->completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS; - mrcp_resource_header_property_add(response,RECOGNIZER_HEADER_COMPLETION_CAUSE); - if(!recognizer->decoder || ps_start_utt(recognizer->decoder, NULL) < 0) { response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED; response_recog_header->completion_cause = RECOGNIZER_COMPLETION_CAUSE_ERROR; + mrcp_resource_header_property_add(response,RECOGNIZER_HEADER_COMPLETION_CAUSE); return FALSE; } @@ -755,17 +749,6 @@ static void* APR_THREAD_FUNC pocketsphinx_recognizer_run(apr_thread_t *thread, v } while(recognizer->close_requested == FALSE); - /* check if recognition is still active */ - if(recognizer->inprogress_recog) { - apr_thread_mutex_lock(recognizer->mutex); - recognizer->stop_response = recognizer->inprogress_recog; - apr_thread_cond_wait(recognizer->wait_object,recognizer->mutex); - apr_thread_mutex_unlock(recognizer->mutex); - if(recognizer->complete_event) { - pocketsphinx_recognition_complete(recognizer,recognizer->complete_event); - } - } - /** Clear all the defined grammars */ pocketsphinx_grammars_clear(recognizer); @@ -776,6 +759,10 @@ static void* APR_THREAD_FUNC pocketsphinx_recognizer_run(apr_thread_t *thread, v recognizer->decoder = NULL; } + recognizer->thread = NULL; + /** Finally send response to channel_close request */ + mrcp_engine_channel_close_respond(recognizer->channel); + /** Exit thread */ apr_thread_exit(thread,APR_SUCCESS); return NULL;