Add new higher level ivr functions from Paul Tinsley. Thanks Paul.
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@3223 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
18f51bee7b
commit
6b457ddce3
|
@ -152,6 +152,40 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se
|
|||
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,
|
||||
|
|
192
src/switch_ivr.c
192
src/switch_ivr.c
|
@ -24,7 +24,7 @@
|
|||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthmct@yahoo.com>
|
||||
*
|
||||
* Paul D. Tinsley <pdt at jackhammer.org>
|
||||
*
|
||||
* switch_ivr_api.c -- IVR Library
|
||||
*
|
||||
|
@ -938,7 +938,167 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_play_file(switch_core_session_t *sess
|
|||
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,
|
||||
|
@ -970,14 +1130,14 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
|
||||
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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (switch_test_flag(sh, SWITCH_SPEECH_FLAG_PAUSE)) {
|
||||
if (timer) {
|
||||
if ((x = switch_core_timer_next(timer)) < 0) {
|
||||
|
@ -1054,7 +1214,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
while (switch_channel_test_flag(channel, CF_HOLD)) {
|
||||
switch_yield(10000);
|
||||
}
|
||||
|
||||
|
||||
if (!SWITCH_READ_ACCEPTABLE(status)) {
|
||||
break;
|
||||
}
|
||||
|
@ -1064,10 +1224,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
|
||||
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 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
}
|
||||
done = 1;
|
||||
}
|
||||
|
||||
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
|
@ -1115,15 +1275,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue