From e4d473190d66efc9171576132596bd63f5aa0607 Mon Sep 17 00:00:00 2001
From: Michael S Collins <msc@freeswitch.org>
Date: Thu, 18 Aug 2011 20:29:52 -0700
Subject: [PATCH] mod_dptools: add transfer_on_failure ext/dp/context to
 play_and_get_digits 	     If max tries is reach and user has not made a
 valid entry then system transfers the call leg to the specified destination.

---
 src/include/switch_cpp.h                      |  3 +-
 src/include/switch_ivr.h                      |  3 +-
 .../applications/mod_dptools/mod_dptools.c    | 12 ++++--
 src/switch_cpp.cpp                            |  6 ++-
 src/switch_ivr_play_say.c                     | 43 ++++++++++++++++++-
 5 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/src/include/switch_cpp.h b/src/include/switch_cpp.h
index f4a0922e58..e9f5c29d92 100644
--- a/src/include/switch_cpp.h
+++ b/src/include/switch_cpp.h
@@ -312,7 +312,8 @@ SWITCH_DECLARE(bool) email(char *to, char *from, char *headers = NULL, char *bod
 												 int max_digits,
 												 int max_tries,
 												 int timeout, char *terminators, char *audio_files, char *bad_input_audio_files,
-												 char *digits_regex, const char *var_name = NULL, int digit_timeout = 0);
+												 char *digits_regex, const char *var_name = NULL, int digit_timeout = 0,
+												 const char *transfer_on_failure = NULL);
 
 	/** \brief Play a file that resides on disk into the channel
 	 *
diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h
index 37940daf90..76ce542429 100644
--- a/src/include/switch_ivr.h
+++ b/src/include/switch_ivr.h
@@ -407,7 +407,8 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
 														   const char *bad_input_audio_file,
 														   const char *var_name, char *digit_buffer, uint32_t digit_buffer_length,
 														   const char *digits_regex,
-														   uint32_t digit_timeout);
+														   uint32_t digit_timeout,
+														   const char *transfer_on_failure);
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
 															 switch_speech_handle_t *sh,
diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c
index 8c260ddf7f..271421a9d3 100755
--- a/src/mod/applications/mod_dptools/mod_dptools.c
+++ b/src/mod/applications/mod_dptools/mod_dptools.c
@@ -2022,7 +2022,7 @@ SWITCH_STANDARD_APP(read_function)
 SWITCH_STANDARD_APP(play_and_get_digits_function)
 {
 	char *mydata;
-	char *argv[10] = { 0 };
+	char *argv[11] = { 0 };
 	int argc;
 	int32_t min_digits = 0;
 	int32_t max_digits = 0;
@@ -2035,6 +2035,7 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
 	const char *var_name = NULL;
 	const char *valid_terminators = NULL;
 	const char *digits_regex = NULL;
+	const char *transfer_on_failure = NULL;
 
 	if (!zstr(data) && (mydata = switch_core_session_strdup(session, data))) {
 		argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
@@ -2084,6 +2085,10 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
 		}
 	}
 
+	if (argc > 10) {
+		transfer_on_failure = argv[10];
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Transfer on failure = [%s].\n", transfer_on_failure);
+	}
 
 	if (min_digits <= 1) {
 		min_digits = 1;
@@ -2102,7 +2107,8 @@ SWITCH_STANDARD_APP(play_and_get_digits_function)
 	}
 
 	switch_play_and_get_digits(session, min_digits, max_digits, max_tries, timeout, valid_terminators,
-							   prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), digits_regex, digit_timeout);
+							   prompt_audio_file, bad_input_audio_file, var_name, digit_buffer, sizeof(digit_buffer), 
+							   digits_regex, digit_timeout, transfer_on_failure);
 }
 
 #define SAY_SYNTAX "<module_name>[:<lang>] <say_type> <say_method> [<say_gender>] <text>"
@@ -3904,7 +3910,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
 				   "<min> <max> <file> <var_name> <timeout> <terminators> <digit_timeout>", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "play_and_get_digits", "Play and get Digits", "Play and get Digits",
 				   play_and_get_digits_function, 
-				   "<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> [<digit_timeout>]", SAF_NONE);
+				   "\n\t<min> <max> <tries> <timeout> <terminators> <file> <invalid_file> <var_name> <regexp> [<digit_timeout>] ['<failure_ext> [failure_dp [failure_context]]']", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "stop_record_session", "Stop Record Session", STOP_SESS_REC_DESC, stop_record_session_function, "<path>", SAF_NONE);
 	SWITCH_ADD_APP(app_interface, "record_session", "Record Session", SESS_REC_DESC, record_session_function, "<path> [+<timeout>]", SAF_MEDIA_TAP);
 	SWITCH_ADD_APP(app_interface, "record", "Record File", "Record a file from the channels input", record_function,
diff --git a/src/switch_cpp.cpp b/src/switch_cpp.cpp
index 3ffc6a3a9d..044612792b 100644
--- a/src/switch_cpp.cpp
+++ b/src/switch_cpp.cpp
@@ -825,7 +825,8 @@ SWITCH_DECLARE(char *) CoreSession::playAndGetDigits(int min_digits,
 													 char *bad_input_audio_files,
 													 char *digits_regex,
 													 const char *var_name,
-													 int digit_timeout)
+													 int digit_timeout,
+													 const char *transfer_on_failure)
 {
     switch_status_t status;
 	sanity_check((char *)"");
@@ -844,7 +845,8 @@ SWITCH_DECLARE(char *) CoreSession::playAndGetDigits(int min_digits,
 										 dtmf_buf, 
 										 sizeof(dtmf_buf), 
 										 digits_regex,
-										 (uint32_t) digit_timeout);
+										 (uint32_t) digit_timeout,
+										 transfer_on_failure);
 
 	end_allow_threads();
 	return dtmf_buf;
diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c
index c5200d0e0e..f941ff85c8 100644
--- a/src/switch_ivr_play_say.c
+++ b/src/switch_ivr_play_say.c
@@ -1981,7 +1981,8 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
 														   char *digit_buffer, 
 														   uint32_t digit_buffer_length, 
 														   const char *digits_regex,
-														   uint32_t digit_timeout)
+														   uint32_t digit_timeout,
+														   const char *transfer_on_failure)
 {
 	switch_channel_t *channel = switch_core_session_get_channel(session);
 
@@ -2031,7 +2032,45 @@ SWITCH_DECLARE(switch_status_t) switch_play_and_get_digits(switch_core_session_t
 	}
 
 	memset(digit_buffer, 0, digit_buffer_length);
-	return SWITCH_STATUS_FALSE;
+	
+	/* If we get here then check for transfer-on-failure ext/dp/context */
+	/* split this arg on spaces to get ext, dp, and context */
+		
+	if (!zstr(transfer_on_failure)) {
+		const char *failure_ext = NULL;
+		const char *failure_dialplan = NULL;
+		const char *failure_context = NULL;
+		char *target[4];
+		char *mydata = switch_core_session_strdup(session, transfer_on_failure);
+		int argc;
+		
+		argc = switch_separate_string(mydata, ' ', target, (sizeof(target) / sizeof(target[0])));
+		
+		if ( argc < 1 ) {
+			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR,"Bad target for PAGD failure: [%s]\n", transfer_on_failure);
+			return SWITCH_STATUS_FALSE;
+		}
+		
+		if ( argc > 0 ) {
+			failure_ext = target[0];
+		}
+		
+		if ( argc > 1 ) {
+			failure_dialplan = target[1];
+		}
+
+		if ( argc > 2 ) {
+			failure_context = target[2];
+		}
+
+		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, 
+			"PAGD failure! Transfer to: %s / %s / %s\n", failure_ext, failure_dialplan, failure_context);
+			
+		switch_ivr_session_transfer(session,failure_ext, failure_dialplan, failure_context);
+		return SWITCH_STATUS_FALSE;
+	} 
+	
+	return SWITCH_STATUS_FALSE;	
 }
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,