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;