[Freeswitch-svn] [commit] r3223 - in freeswitch/trunk/src: . include
Freeswitch SVN
mikej at freeswitch.org
Sat Oct 28 00:41:00 EDT 2006
Author: mikej
Date: Sat Oct 28 00:40:59 2006
New Revision: 3223
Modified:
freeswitch/trunk/src/include/switch_ivr.h
freeswitch/trunk/src/switch_ivr.c
Log:
Add new higher level ivr functions from Paul Tinsley. Thanks Paul.
Modified: freeswitch/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/trunk/src/include/switch_ivr.h (original)
+++ freeswitch/trunk/src/include/switch_ivr.h Sat Oct 28 00:40:59 2006
@@ -152,6 +152,40 @@
void *buf,
unsigned int buflen);
+/*!
+ \brief Function to evaluate an expression against a string
+ \param target The string to find a match in
+ \param expression The regular expression to run against the string
+ \return Boolean if a match was found or not
+*/
+SWITCH_DECLARE(switch_status_t) switch_regex_match(char *target, char *expression);
+
+/*!
+ \brief Play a sound and gather digits with the number of retries specified if the user doesn't give digits in the set time
+ \param session the current session to play sound to and collect digits
+ \param min_digits the fewest digits allowed for the response to be valid
+ \param max_digits the max number of digits to accept
+ \param max_tries number of times to replay the sound and capture digits
+ \param timeout time to wait for input (this is per iteration, so total possible time = max_tries * (timeout + audio playback length)
+ \param valid_terminators for input that can include # or * (useful for variable length prompts)
+ \param audio_file file to play
+ \param bad_input_audio_file file to play if the input from the user was invalid
+ \param digit_buffer variable digits captured will be put back into (empty if capture failed)
+ \param digit_buffer_length length of the buffer for digits (should be the same or larger than max_digits)
+ \return switch status, used to note status of channel (will still return success if digit capture failed)
+ \note to test for digit capture failure look for \0 in the first position of the buffer
+*/
+SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t *session,
+ unsigned int min_digits,
+ unsigned int max_digits,
+ unsigned int max_tries,
+ unsigned int timeout,
+ char* valid_terminators,
+ char* audio_file,
+ char* bad_input_audio_file,
+ void* digit_buffer,
+ unsigned int digit_buffer_length,
+ char* digits_regex);
SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
switch_speech_handle_t *sh,
Modified: freeswitch/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/trunk/src/switch_ivr.c (original)
+++ freeswitch/trunk/src/switch_ivr.c Sat Oct 28 00:40:59 2006
@@ -24,8 +24,8 @@
* Contributor(s):
*
* Anthony Minessale II <anthmct at yahoo.com>
+ * Paul D. Tinsley <pdt at jackhammer.org>
*
- *
* switch_ivr_api.c -- IVR Library
*
*/
@@ -938,9 +938,169 @@
return status;
}
+SWITCH_DECLARE(switch_status_t) switch_regex_match(char *target, char *expression) {
+ const char* error = NULL; //Used to hold any errors
+ int error_offset = 0; //Holds the offset of an error
+ pcre* pcre_prepared = NULL; //Holds the compiled regex
+ int match_count = 0; //Number of times the regex was matched
+ int offset_vectors[2]; //not used, but has to exist or pcre won't even try to find a match
+
+ //Compile the expression
+ pcre_prepared = pcre_compile(expression, 0, &error, &error_offset, NULL);
+ //See if there was an error in the expression
+ if(error != NULL) {
+ //Clean up after ourselves
+ if(pcre_prepared) {
+ pcre_free(pcre_prepared);
+ pcre_prepared = NULL;
+ }
+ //Note our error
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Regular Expression Error expression[%s] error[%s] location[%d]\n", expression, error, error_offset);
+ //We definitely didn't match anything
+ return SWITCH_STATUS_FALSE;
+ }
+
+ //So far so good, run the regex
+ match_count = pcre_exec(pcre_prepared, NULL, target, (int) strlen(target), 0, 0, offset_vectors, sizeof(offset_vectors) / sizeof(offset_vectors[0]));
+
+ //Clean up
+ if(pcre_prepared) {
+ pcre_free(pcre_prepared);
+ pcre_prepared = NULL;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "number of matches: %d\n", match_count);
+
+ //Was it a match made in heaven?
+ if(match_count > 0) {
+ return SWITCH_STATUS_SUCCESS;
+ } else {
+ return SWITCH_STATUS_FALSE;
+ }
+}
+
+SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t *session,
+ unsigned int min_digits,
+ unsigned int max_digits,
+ unsigned int max_tries,
+ unsigned int timeout,
+ char* valid_terminators,
+ char* prompt_audio_file,
+ char* bad_input_audio_file,
+ void* digit_buffer,
+ unsigned int digit_buffer_length,
+ char* digits_regex)
+{
+
+ char terminator; //used to hold terminator recieved from
+ switch_channel_t *channel; //the channel contained in session
+ switch_status_t status; //used to recieve state out of called functions
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "switch_play_and_get_digits(session, %d, %d, %d, %d, %s, %s, %s, digit_buffer, %d, %s)\n", min_digits, max_digits, max_tries, timeout, valid_terminators, prompt_audio_file, bad_input_audio_file, digit_buffer_length, digits_regex);
+
+ //Get the channel
+ channel = switch_core_session_get_channel(session);
+
+ //Make sure somebody is home
+ assert(channel != NULL);
+
+ //Answer the channel if it hasn't already been answered
+ switch_channel_answer(channel);
+
+ //Start pestering the user for input
+ for(;(switch_channel_get_state(channel) == CS_EXECUTE) && max_tries > 0; max_tries--) {
+ //make the buffer so fresh and so clean clean
+ memset(digit_buffer, 0, digit_buffer_length);
+
+ //Play the file
+ status = switch_ivr_play_file(session, NULL, prompt_audio_file, NULL, NULL, digit_buffer, digit_buffer_length);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "play gave up %s", digit_buffer);
+
+ //Make sure we made it out alive
+ if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ }
+
+ //we only get one digit out of playback, see if thats all we needed and what we got
+ if(max_digits == 1 && status == SWITCH_STATUS_BREAK) {
+ //Check the digit if we have a regex
+ if(digits_regex != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking regex [%s] on [%s]\n", digits_regex, digit_buffer);
+
+ //Make sure the digit is allowed
+ if(switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Match found!\n");
+ //jobs done
+ break;
+ } else {
+ //See if a bad input prompt was specified, if so, play it
+ if(strlen(bad_input_audio_file) > 0) {
+ status = switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL, NULL, NULL, 0);
+
+ //Make sure we made it out alive
+ if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ }
+ }
+ }
+ } else {
+ //jobs done
+ break;
+ }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Calling more digits try %d\n", max_tries);
+
+ //Try to grab some more digits for the timeout period
+ status = switch_ivr_collect_digits_count(session, digit_buffer, digit_buffer_length, max_digits, valid_terminators, &terminator, timeout);
+
+ //Make sure we made it out alive
+ if(status != SWITCH_STATUS_SUCCESS) {
+ //Bail
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ }
+
+ //see if we got enough
+ if(min_digits <= strlen(digit_buffer)) {
+ //See if we need to test a regex
+ if(digits_regex != NULL) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking regex [%s] on [%s]\n", digits_regex, digit_buffer);
+ //Test the regex
+ if(switch_regex_match(digit_buffer, digits_regex) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Match found!\n");
+ //Jobs done
+ return switch_channel_get_state(channel);
+ } else {
+ //See if a bad input prompt was specified, if so, play it
+ if(strlen(bad_input_audio_file) > 0) {
+ status = switch_ivr_play_file(session, NULL, bad_input_audio_file, NULL, NULL, NULL, 0);
+
+ //Make sure we made it out alive
+ if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ }
+ }
+ }
+ } else {
+ //Jobs done
+ return switch_channel_get_state(channel);
+ }
+ }
+ }
+
+ //if we got here, we got no digits or lost the channel
+ digit_buffer = "\0";
+ return switch_channel_get_state(channel);
+}
+
+
SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
switch_speech_handle_t *sh,
switch_codec_t *codec,
@@ -970,14 +1130,14 @@
if (!sh) {
return SWITCH_STATUS_FALSE;
}
-
+
switch_channel_answer(channel);
write_frame.data = abuf;
write_frame.buflen = sizeof(abuf);
- samples = (uint32_t)(sh->rate / 50);
- len = samples * 2;
+ samples = (uint32_t)(sh->rate / 50);
+ len = samples * 2;
flags = 0;
switch_sleep(200000);
@@ -1012,8 +1172,8 @@
if (input_callback || buf) {
/*
- dtmf handler function you can hook up to be executed when a digit is dialed during playback
- if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+ dtmf handler function you can hook up to be executed when a digit is dialed during playback
+ if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
if (switch_channel_has_dtmf(channel)) {
if (buf && !strcasecmp(buf, "_break_")) {
@@ -1041,7 +1201,7 @@
break;
}
}
-
+
if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_PAUSE)) {
if (timer) {
if ((x = switch_core_timer_next(timer)) < 0) {
@@ -1054,7 +1214,7 @@
while (switch_channel_test_flag(channel, CF_HOLD)) {
switch_yield(10000);
}
-
+
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
@@ -1064,10 +1224,10 @@
flags = SWITCH_SPEECH_FLAG_BLOCKING;
status = switch_core_speech_read_tts(sh,
- abuf,
- &ilen,
- &rate,
- &flags);
+ abuf,
+ &ilen,
+ &rate,
+ &flags);
if (status != SWITCH_STATUS_SUCCESS) {
for( x = 0; !done && x < lead_in_out; x++) {
@@ -1084,7 +1244,7 @@
}
done = 1;
}
-
+
if (done) {
break;
}
@@ -1115,15 +1275,15 @@
while (switch_channel_test_flag(channel, CF_HOLD)) {
switch_yield(10000);
}
-
+
if (!SWITCH_READ_ACCEPTABLE(status)) {
break;
}
}
}
-
-
+
+
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "done speaking text\n");
flags = 0;
switch_core_speech_flush_tts(sh);
More information about the Freeswitch-svn
mailing list