[Freeswitch-trunk] [GIT]FreeSWITCH branch master updated. v1.0.6-1129-g15e65cf
git at svn.freeswitch.org
git at svn.freeswitch.org
Mon Jan 31 23:16:30 MSK 2011
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "FreeSWITCH".
The branch, master has been updated
via 15e65cfafb8a46caca8bb8a63d55edf817f17f2d (commit)
from 92a9bacc44576e7b1d41c48752af597801e41d21 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 15e65cfafb8a46caca8bb8a63d55edf817f17f2d
Author: Luke Dashjr <luke at openmethods.com>
Date: Wed Jan 26 14:40:35 2011 -0600
MERGE: DTMF recognition via ASR modules (implemented in UniMRCP)
diff --git a/src/include/switch_core.h b/src/include/switch_core.h
index 26a048c..a3d74e9 100644
--- a/src/include/switch_core.h
+++ b/src/include/switch_core.h
@@ -1715,6 +1715,15 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, s
SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
/*!
+ \brief Feed DTMF to an asr handle
+ \param ah the handle to feed data to
+ \param dtmf a string of DTMF digits
+ \param flags flags to influence behaviour
+ \return SWITCH_STATUS_SUCCESS
+*/
+SWITCH_DECLARE(switch_status_t) switch_core_asr_feed_dtmf(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags);
+
+/*!
\brief Check an asr handle for results
\param ah the handle to check
\param flags flags to influence behaviour
diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h
index e0119b4..8303af7 100644
--- a/src/include/switch_module_interfaces.h
+++ b/src/include/switch_module_interfaces.h
@@ -400,6 +400,8 @@ struct switch_asr_interface {
switch_status_t (*asr_disable_grammar) (switch_asr_handle_t *ah, const char *name);
/*! function to disable all grammars to the asr interface */
switch_status_t (*asr_disable_all_grammars) (switch_asr_handle_t *ah);
+ /*! function to feed DTMF to the ASR */
+ switch_status_t (*asr_feed_dtmf) (switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags);
};
/*! an abstract representation of an asr speech interface. */
diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
index b9cecd1..b3679cf 100644
--- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
+++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c
@@ -49,6 +49,7 @@
#include "mrcp_resource_loader.h"
#include "mpf_engine.h"
#include "mpf_codec_manager.h"
+#include "mpf_dtmf_generator.h"
#include "mpf_rtp_termination_factory.h"
#include "mrcp_sofiasip_client_agent.h"
#include "mrcp_unirtsp_client_agent.h"
@@ -442,6 +443,12 @@ struct recognizer_data {
int start_of_input;
/** true, if input timers have started */
int timers_started;
+ /** UniMRCP mpf stream */
+ mpf_audio_stream_t *unimrcp_stream;
+ /** DTMF generator */
+ mpf_dtmf_generator_t *dtmf_generator;
+ /** true, if presently transmitting DTMF */
+ char dtmf_generator_active;
};
typedef struct recognizer_data recognizer_data_t;
@@ -457,6 +464,7 @@ static switch_status_t recog_asr_disable_grammar(switch_asr_handle_t *ah, const
static switch_status_t recog_asr_disable_all_grammars(switch_asr_handle_t *ah);
static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_t *flags);
static switch_status_t recog_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags);
+static switch_status_t recog_asr_feed_dtmf(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags);
#if 0
static switch_status_t recog_asr_start(switch_asr_handle_t *ah, const char *name);
#endif
@@ -472,6 +480,7 @@ static void recog_asr_float_param(switch_asr_handle_t *ah, char *param, double v
/* recognizer's interface for UniMRCP */
static apt_bool_t recog_message_handler(const mrcp_app_message_t *app_message);
static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message);
+static apt_bool_t recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
static apt_bool_t recog_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
/* recognizer specific speech_channel_funcs */
@@ -3114,6 +3123,9 @@ static switch_status_t recog_asr_close(switch_asr_handle_t *ah, switch_asr_flag_
speech_channel_destroy(schannel);
switch_core_hash_destroy(&r->grammars);
switch_core_hash_destroy(&r->enabled_grammars);
+ if (r->dtmf_generator) {
+ mpf_dtmf_generator_destroy(r->dtmf_generator);
+ }
/* this lets FreeSWITCH's speech_thread know the handle is closed */
switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED);
@@ -3134,6 +3146,39 @@ static switch_status_t recog_asr_feed(switch_asr_handle_t *ah, void *data, unsig
return speech_channel_write(schannel, data, &slen);
}
+/**
+ * Process asr_feed_dtmf request from FreeSWITCH
+ *
+ * @param ah the FreeSWITCH speech recognition handle
+ * @return SWITCH_STATUS_SUCCESS if successful
+ */
+static switch_status_t recog_asr_feed_dtmf(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags)
+{
+ speech_channel_t *schannel = (speech_channel_t *) ah->private_info;
+ recognizer_data_t *r = (recognizer_data_t *) schannel->data;
+ char digits[2];
+
+ if (!r->dtmf_generator) {
+ if (!r->unimrcp_stream) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Cannot queue DTMF: No UniMRCP stream object open\n", schannel->name);
+ return SWITCH_STATUS_FALSE;
+ }
+ r->dtmf_generator = mpf_dtmf_generator_create(r->unimrcp_stream, schannel->unimrcp_session->pool);
+ if (!r->dtmf_generator) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) Cannot queue DTMF: Failed to create DTMF generator\n", schannel->name);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ digits[0] = dtmf->digit;
+ digits[1] = '\0';
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) Queued DTMF: %s\n", schannel->name, digits);
+ mpf_dtmf_generator_enqueue(r->dtmf_generator, digits);
+ r->dtmf_generator_active = 1;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
#if 0
/**
* Process asr_start request from FreeSWITCH
@@ -3380,6 +3425,23 @@ static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp
}
/**
+ * UniMRCP callback requesting open for speech recognition
+ *
+ * @param stream the UniMRCP stream
+ * @param codec the codec
+ * @return TRUE
+ */
+static apt_bool_t recog_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
+{
+ speech_channel_t *schannel = (speech_channel_t *) stream->obj;
+ recognizer_data_t *r = (recognizer_data_t *) schannel->data;
+
+ r->unimrcp_stream = stream;
+
+ return TRUE;
+}
+
+/**
* UniMRCP callback requesting next frame for speech recognition
*
* @param stream the UniMRCP stream
@@ -3389,6 +3451,7 @@ static apt_bool_t recog_on_message_receive(mrcp_application_t *application, mrcp
static apt_bool_t recog_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
{
speech_channel_t *schannel = (speech_channel_t *) stream->obj;
+ recognizer_data_t *r = (recognizer_data_t *) schannel->data;
switch_size_t to_read = frame->codec_frame.size;
/* grab the data. pad it if there isn't enough */
@@ -3398,6 +3461,13 @@ static apt_bool_t recog_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *fra
}
frame->type |= MEDIA_FRAME_TYPE_AUDIO;
}
+
+ if (r->dtmf_generator_active) {
+ if (!mpf_dtmf_generator_put_frame(r->dtmf_generator, frame)) {
+ if (!mpf_dtmf_generator_sending(r->dtmf_generator))
+ r->dtmf_generator_active = 0;
+ }
+ }
return TRUE;
}
@@ -3421,6 +3491,7 @@ static switch_status_t recog_load(switch_loadable_module_interface_t *module_int
asr_interface->asr_disable_all_grammars = recog_asr_disable_all_grammars;
asr_interface->asr_close = recog_asr_close;
asr_interface->asr_feed = recog_asr_feed;
+ asr_interface->asr_feed_dtmf = recog_asr_feed_dtmf;
#if 0
asr_interface->asr_start = recog_asr_start;
#endif
@@ -3443,7 +3514,7 @@ static switch_status_t recog_load(switch_loadable_module_interface_t *module_int
globals.recog.dispatcher.on_channel_remove = speech_on_channel_remove;
globals.recog.dispatcher.on_message_receive = recog_on_message_receive;
globals.recog.audio_stream_vtable.destroy = NULL;
- globals.recog.audio_stream_vtable.open_rx = NULL;
+ globals.recog.audio_stream_vtable.open_rx = recog_stream_open;
globals.recog.audio_stream_vtable.close_rx = NULL;
globals.recog.audio_stream_vtable.read_frame = recog_stream_read;
globals.recog.audio_stream_vtable.open_tx = NULL;
diff --git a/src/switch_core_asr.c b/src/switch_core_asr.c
index 691011a..7f231ef 100644
--- a/src/switch_core_asr.c
+++ b/src/switch_core_asr.c
@@ -239,6 +239,19 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, vo
return ah->asr_interface->asr_feed(ah, data, len, flags);
}
+SWITCH_DECLARE(switch_status_t) switch_core_asr_feed_dtmf(switch_asr_handle_t *ah, const switch_dtmf_t *dtmf, switch_asr_flag_t *flags)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+ switch_assert(ah != NULL);
+
+ if (ah->asr_interface->asr_feed_dtmf) {
+ status = ah->asr_interface->asr_feed_dtmf(ah, dtmf, flags);
+ }
+
+ return status;
+}
+
SWITCH_DECLARE(switch_status_t) switch_core_asr_check_results(switch_asr_handle_t *ah, switch_asr_flag_t *flags)
{
switch_assert(ah != NULL);
diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c
index 66cd369..5df7af3 100644
--- a/src/switch_ivr_async.c
+++ b/src/switch_ivr_async.c
@@ -2660,6 +2660,20 @@ static switch_bool_t speech_callback(switch_media_bug_t *bug, void *user_data, s
return SWITCH_TRUE;
}
+static switch_status_t speech_on_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf, switch_dtmf_direction_t direction)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ struct speech_thread_handle *sth = switch_channel_get_private(channel, SWITCH_SPEECH_KEY);
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_asr_flag_t flags = SWITCH_ASR_FLAG_NONE;
+
+ if (switch_core_asr_feed_dtmf(sth->ah, dtmf, &flags) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error Feeding DTMF\n");
+ }
+
+ return status;
+}
+
SWITCH_DECLARE(switch_status_t) switch_ivr_stop_detect_speech(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -2875,6 +2889,11 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_detect_speech(switch_core_session_t *
return status;
}
+ if ((status = switch_core_event_hook_add_recv_dtmf(session, speech_on_dtmf)) != SWITCH_STATUS_SUCCESS) {
+ switch_ivr_stop_detect_speech(session);
+ return status;
+ }
+
switch_channel_set_private(channel, SWITCH_SPEECH_KEY, sth);
return SWITCH_STATUS_SUCCESS;
-----------------------------------------------------------------------
Summary of changes:
src/include/switch_core.h | 9 ++++
src/include/switch_module_interfaces.h | 2 +
src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c | 73 ++++++++++++++++++++++++++++-
src/switch_core_asr.c | 13 +++++
src/switch_ivr_async.c | 19 ++++++++
5 files changed, 115 insertions(+), 1 deletions(-)
hooks/post-receive
--
FreeSWITCH
More information about the Freeswitch-trunk
mailing list