[Freeswitch-branches] [commit] r3326 - in freeswitch/branches/knhor/trunk: . src src/include src/mod/languages/mod_spidermonkey

Freeswitch SVN knhor at freeswitch.org
Sun Nov 12 00:08:42 EST 2006


Author: knhor
Date: Sun Nov 12 00:08:38 2006
New Revision: 3326

Modified:
   freeswitch/branches/knhor/trunk/   (props changed)
   freeswitch/branches/knhor/trunk/src/include/switch_ivr.h
   freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
   freeswitch/branches/knhor/trunk/src/switch_ivr.c

Log:
Merged revisions 3317-3325 via svnmerge from trunk


Modified: freeswitch/branches/knhor/trunk/src/include/switch_ivr.h
==============================================================================
--- freeswitch/branches/knhor/trunk/src/include/switch_ivr.h	(original)
+++ freeswitch/branches/knhor/trunk/src/include/switch_ivr.h	Sun Nov 12 00:08:38 2006
@@ -75,8 +75,8 @@
 SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
 																   switch_input_callback_function_t dtmf_callback,
 																   void *buf,
-																   unsigned int buflen,
-																   unsigned int timeout);
+																   uint32_t buflen,
+																   uint32_t timeout);
 
 /*!
   \brief Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.
@@ -91,11 +91,11 @@
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_session_t *session,
 																char *buf,
-																unsigned int buflen,
-																unsigned int maxdigits,
+																uint32_t buflen,
+																uint32_t maxdigits,
 																const char *terminators,
 																char *terminator,
-																unsigned int timeout);
+																uint32_t timeout);
 
 /*!
   \brief Engage background Speech detection on a session
@@ -187,7 +187,7 @@
 												   char *timer_name,
 												   switch_input_callback_function_t dtmf_callback,
 												   void *buf,
-												   unsigned int buflen);
+												   uint32_t buflen);
 
 
 
@@ -207,7 +207,7 @@
 													 char *file,
 													 switch_input_callback_function_t dtmf_callback,
 													 void *buf,
-													 unsigned int buflen);
+													 uint32_t buflen);
 
 /*!
  \brief Function to evaluate an expression against a string
@@ -234,15 +234,15 @@
   \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,
+                                                           uint32_t min_digits,
+                                                           uint32_t max_digits,
+                                                           uint32_t max_tries,
+                                                           uint32_t timeout,
                                                            char* valid_terminators,
                                                            char* audio_file,
                                                            char* bad_input_audio_file,
                                                            void* digit_buffer,
-                                                           unsigned int digit_buffer_length,
+                                                           uint32_t digit_buffer_length,
                                                            char* digits_regex);
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_speak_text_handle(switch_core_session_t *session,
@@ -252,7 +252,7 @@
                                                              switch_input_callback_function_t dtmf_callback,
                                                              char *text,
                                                              void *buf,
-                                                             unsigned int buflen);
+                                                             uint32_t buflen);
 
 /*!
   \brief Speak given text with given tts engine
@@ -275,7 +275,7 @@
 													  switch_input_callback_function_t dtmf_callback,
 													  char *text,
 													  void *buf,
-													  unsigned int buflen);
+													  uint32_t buflen);
 
 /*!
   \brief Make an outgoing call
@@ -458,6 +458,103 @@
   \return SWITCH_STATUS_SUCCESS if all is well 
 */
 SWITCH_DECLARE(switch_status_t) switch_ivr_digit_stream_parser_set_terminator(switch_ivr_digit_stream_parser_t *parser, char digit);
+
+/** @} */
+
+/**
+ * @defgroup switch_ivr_menu IVR Menu Library
+ * @ingroup switch_ivr
+ *	IVR menu functions
+ *	
+ * @{
+ */
+
+typedef enum {
+	SWITCH_IVR_MENU_FLAG_FALLTOMAIN = (1 << 0),
+	SWITCH_IVR_MENU_FLAG_FREEPOOL = (1 << 1),
+	SWITCH_IVR_MENU_FLAG_STACK = (1 << 2),
+} switch_ivr_menu_flags;
+/* Actions are either set in switch_ivr_menu_bind_function or returned by a callback */
+typedef enum {
+	SWITCH_IVR_ACTION_DIE, 		/* Exit the menu.                  */
+	SWITCH_IVR_ACTION_EXECMENU,	/* Goto another menu in the stack. */
+	SWITCH_IVR_ACTION_EXECAPP,		/* Execute an application.         */
+	SWITCH_IVR_ACTION_PLAYSOUND,	/* Play a sound.                   */
+	SWITCH_IVR_ACTION_BACK,		/* Go back 1 menu.                 */
+	SWITCH_IVR_ACTION_TOMAIN,		/* Go back to the top level menu.  */
+	SWITCH_IVR_ACTION_TRANSFER,	/* Transfer caller to another ext. */
+} switch_ivr_action_t;
+struct switch_ivr_menu;
+typedef switch_ivr_action_t switch_ivr_menu_action_function_t(struct switch_ivr_menu *, char *, size_t, void *);
+typedef struct switch_ivr_menu switch_ivr_menu_t;
+typedef struct switch_ivr_menu_action switch_ivr_menu_action_t;
+/******************************************************************************************************/
+
+/*!
+ *\brief Create a new menu object.
+ *\param new the pointer to the new menu
+ *\param main The top level menu, (NULL if this is the top level one).
+ *\param name A pointer to the name of this menu.
+ *\param greeting_sound Optional pointer to a main sound (press 1 for this 2 for that).
+ *\param short_greeting_sound Optional pointer to a shorter main sound for subsequent loops.
+ *\param invalid_sound Optional pointer to a sound to play after invalid input.
+ *\param timeout A number of milliseconds to pause before looping.
+ *\param max_failures Maximum number of failures to withstand before hangingup This resets everytime you enter the menu.
+ *\param inlen The max len of the input (1 for 1 digit menu opts, 2 for 2 digit etc.)
+ *\param pool memory pool (NULL to create one)
+ *\return SWUTCH_STATUS_SUCCESS if the menu was created
+ */
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_init(switch_ivr_menu_t **new,
+													 switch_ivr_menu_t *main,
+													 char *name, 
+													 char *greeting_sound, 
+													 char *short_greeting_sound,
+													 char *invalid_sound, 
+													 int timeout,
+													 int max_failures, 
+													 int inlen,
+													 switch_memory_pool_t *pool);
+
+/*!
+ *\brief switch_ivr_menu_bind_action: Bind a keystroke to an action.
+ *\param menu The menu obj you wish to bind to.
+ *\param ivr_action switch_ivr_action_t enum of what you want to do.
+ *\param arg Optional (sometimes necessary) string arguement.
+ *\param bind KeyStrokes to bind the action to.
+ *\return SWUTCH_STATUS_SUCCESS if the action was binded
+ */
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_action(switch_ivr_menu_t *menu, switch_ivr_action_t ivr_action, char *arg, char *bind);
+
+
+/*!
+ *\brief Bind a keystroke to a callback function.
+ *\param menu The menu obj you wish to bind to.
+ *\param function The function to call [int proto(struct switch_ivr_menu *, char *, size_t, void *)]
+ *\param bind KeyStrokes to bind the action to.
+ *\note The function is passed a buffer to fill in with any required argument data.
+ *\note The function is also passed an optional void pointer to an object set upon menu execution. (think threads)
+ *\note The function returns an switch_ivr_action_t enum of what you want to do. and looks to your buffer for args.
+ *\return SWUTCH_STATUS_SUCCESS if the function was binded
+ */
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_function(switch_ivr_menu_t *menu, switch_ivr_menu_action_function_t *function, char *bind);
+
+
+/*!
+ *\brief Execute a menu.
+ *\param session The session running the menu.
+ *\param stack The top-level menu object (the first one you created.)
+ *\param name A pointer to the name of the menu.
+ *\param obj A void pointer to an object you want to make avaliable to your callback functions that you may have binded with switch_ivr_menu_bind_function.
+ *\return SWITCH_STATUS_SUCCESS if all is well
+ */
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj);
+
+/*!
+ *\brief free a stack of menu objects.
+ *\param stack The top level menu you wish to destroy.
+ *\return SWITCH_STATUS_SUCCESS if the object was a top level menu and it was freed
+ */
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_free_stack(switch_ivr_menu_t *stack);
 
 /** @} */
 

Modified: freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c
==============================================================================
--- freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	(original)
+++ freeswitch/branches/knhor/trunk/src/mod/languages/mod_spidermonkey/mod_spidermonkey.c	Sun Nov 12 00:08:38 2006
@@ -415,7 +415,7 @@
 	apr_dso_handle_t *dso = NULL;
 	apr_status_t status = SWITCH_STATUS_SUCCESS;
 	apr_dso_handle_sym_t function_handle = NULL;
-	spidermonkey_init_t spidermonkey_init;
+	spidermonkey_init_t spidermonkey_init = NULL;
 	const sm_module_interface_t *module_interface, *mp;
 
 	int loading = 1;

Modified: freeswitch/branches/knhor/trunk/src/switch_ivr.c
==============================================================================
--- freeswitch/branches/knhor/trunk/src/switch_ivr.c	(original)
+++ freeswitch/branches/knhor/trunk/src/switch_ivr.c	Sun Nov 12 00:08:38 2006
@@ -176,13 +176,13 @@
 SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_callback(switch_core_session_t *session,
 																   switch_input_callback_function_t input_callback,
 																   void *buf,
-																   unsigned int buflen,
-																   unsigned int timeout)
+																   uint32_t buflen,
+																   uint32_t timeout)
 {
 	switch_channel_t *channel;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	switch_time_t started = 0;
-	unsigned int elapsed;
+	uint32_t elapsed;
 
 	channel = switch_core_session_get_channel(session);
     assert(channel != NULL);
@@ -201,7 +201,7 @@
 		char dtmf[128];
 
 		if (timeout) {
-			elapsed = (unsigned int)((switch_time_now() - started) / 1000);
+			elapsed = (uint32_t)((switch_time_now() - started) / 1000);
 			if (elapsed >= timeout) {
 				break;
 			}
@@ -243,17 +243,17 @@
 
 SWITCH_DECLARE(switch_status_t) switch_ivr_collect_digits_count(switch_core_session_t *session,
 																char *buf,
-																unsigned int buflen,
-																unsigned int maxdigits,
+																uint32_t buflen,
+																uint32_t maxdigits,
 																const char *terminators,
 																char *terminator,
-																unsigned int timeout)
+																uint32_t timeout)
 {
-	unsigned int i = 0, x =  (unsigned int) strlen(buf);
+	uint32_t i = 0, x =  (uint32_t) strlen(buf);
 	switch_channel_t *channel;
 	switch_status_t status = SWITCH_STATUS_SUCCESS;
 	switch_time_t started = 0;
-	unsigned int elapsed;
+	uint32_t elapsed;
 
 	channel = switch_core_session_get_channel(session);
     assert(channel != NULL);
@@ -278,7 +278,7 @@
 		switch_event_t *event;
 
 		if (timeout) {
-			elapsed = (unsigned int)((switch_time_now() - started) / 1000);
+			elapsed = (uint32_t)((switch_time_now() - started) / 1000);
 			if (elapsed >= timeout) {
 				break;
 			}
@@ -292,7 +292,7 @@
 		if (switch_channel_has_dtmf(channel)) {
 			char dtmf[128];
 			switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
-			for(i =0 ; i < (unsigned int) strlen(dtmf); i++) {
+			for(i =0 ; i < (uint32_t) strlen(dtmf); i++) {
 
 				if (strchr(terminators, dtmf[i])) {
 					*terminator = dtmf[i];
@@ -327,7 +327,7 @@
 													 char *file,
 													 switch_input_callback_function_t input_callback,
 													 void *buf,
-													 unsigned int buflen)
+													 uint32_t buflen)
 {
 	switch_channel_t *channel;
     char dtmf[128];
@@ -911,7 +911,7 @@
 												   char *timer_name,
 												   switch_input_callback_function_t input_callback,
 												   void *buf,
-												   unsigned int buflen)
+												   uint32_t buflen)
 {
 	switch_channel_t *channel;
 	int16_t abuf[FILE_STARTSAMPLES];
@@ -1264,9 +1264,9 @@
 	pcre_prepared = pcre_compile(expression, 0, &error, &error_offset, NULL);
 
 	//See if there was an error in the expression
-	if(error != NULL) {
+	if (error != NULL) {
 		//Clean up after ourselves
-		if(pcre_prepared) {
+		if (pcre_prepared) {
 			pcre_free(pcre_prepared);
 			pcre_prepared = NULL;
 		}	       
@@ -1282,7 +1282,7 @@
 	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) {
+	if (pcre_prepared) {
 		pcre_free(pcre_prepared);
 		pcre_prepared = NULL;
 	}
@@ -1290,7 +1290,7 @@
 	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) {
+	if (match_count > 0) {
 		return SWITCH_STATUS_SUCCESS;
 	} else {
 		return SWITCH_STATUS_FALSE;
@@ -1298,15 +1298,15 @@
 }
 
 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,
+														   uint32_t min_digits,
+														   uint32_t max_digits,
+														   uint32_t max_tries,
+														   uint32_t timeout,
 														   char* valid_terminators,
 														   char* prompt_audio_file,
 														   char* bad_input_audio_file,
 														   void* digit_buffer,
-														   unsigned int digit_buffer_length,
+														   uint32_t digit_buffer_length,
 														   char* digits_regex) 
 {
 
@@ -1341,19 +1341,19 @@
 		}
 
 		//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) {
+		if (max_digits == 1 && status == SWITCH_STATUS_BREAK) {
 			//Check the digit if we have a regex
-			if(digits_regex != NULL) {
+			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) {
+				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) {
+					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
@@ -1375,25 +1375,25 @@
 		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) {
+		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)) {
+		if (min_digits <= strlen(digit_buffer)) {
 			//See if we need to test a regex
-			if(digits_regex != NULL) {
+			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) {
+				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) {
+					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
@@ -1423,7 +1423,7 @@
 															 switch_input_callback_function_t input_callback,
 															 char *text,
 															 void *buf,
-															 unsigned int buflen)
+															 uint32_t buflen)
 {
 	switch_channel_t *channel;
 	short abuf[960];
@@ -1614,7 +1614,7 @@
 													  switch_input_callback_function_t input_callback,
 													  char *text,
 													  void *buf,
-													  unsigned int buflen)
+													  uint32_t buflen)
 {
 	switch_channel_t *channel;
 	int interval = 0;
@@ -1640,7 +1640,7 @@
 	if (switch_core_speech_open(&sh,
 								tts_name,
 								voice_name,
-								(unsigned int)rate,
+								(uint32_t)rate,
 								&flags,
 								switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid TTS module!\n");
@@ -3376,6 +3376,319 @@
 		parser->terminator = digit;
 		status = SWITCH_STATUS_SUCCESS;
 	}
+
+	return status;
+}
+
+struct switch_ivr_menu_action;
+
+struct switch_ivr_menu {
+	char *name;
+	char *greeting_sound;
+	char *short_greeting_sound;
+	char *invalid_sound;
+	int max_failures;
+	int timeout;
+	int inlen;
+	uint32_t flags;
+	struct switch_ivr_menu_action *actions;
+	struct switch_ivr_menu *next;
+	switch_memory_pool_t *pool;
+};
+
+
+struct switch_ivr_menu_action {
+	switch_ivr_menu_action_function_t *function;
+	switch_ivr_action_t ivr_action;
+	char *arg;
+	char *bind;
+	struct switch_ivr_menu_action *next;
+};
+
+static switch_ivr_menu_t *switch_ivr_find_menu(switch_ivr_menu_t *stack, char *name) {
+	switch_ivr_menu_t *ret;
+	for(ret = stack; ret ; ret = ret->next) {
+		if (!name || !strcmp(ret->name, name))
+			break;
+	}
+	return ret;
+}
+
+
+static void switch_ivr_menu_stack(switch_ivr_menu_t **top, switch_ivr_menu_t *bottom) 
+{
+	switch_ivr_menu_t *ptr;
+
+	for(ptr = *top ; ptr && ptr->next ; ptr = ptr->next);
+
+	if (ptr) {
+		ptr->next = bottom;
+	} else {
+		*top = bottom;
+	}
+
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_init(switch_ivr_menu_t **new,
+													 switch_ivr_menu_t *main,
+													 char *name, 
+													 char *greeting_sound, 
+													 char *short_greeting_sound,
+													 char *invalid_sound, 
+													 int timeout,
+													 int max_failures, 
+													 int inlen,
+													 switch_memory_pool_t *pool)
+{
+	switch_ivr_menu_t *menu;
+	uint8_t newpool = 0;
+
+	if (!pool) {
+		if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n");
+			return SWITCH_STATUS_MEMERR;
+		}
+		newpool = 1;
+	}
+	
+	if (!(menu = switch_core_alloc(pool, sizeof(*menu)))) {
+		if (newpool) {
+			switch_core_destroy_memory_pool(&pool);
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n");
+			return SWITCH_STATUS_MEMERR;
+		}
+	}
+	menu->pool = pool;
+
+	menu->name = switch_core_strdup(menu->pool, name);
+	menu->greeting_sound = switch_core_strdup(menu->pool, greeting_sound);
+	menu->short_greeting_sound = switch_core_strdup(menu->pool, short_greeting_sound);
+	menu->invalid_sound = switch_core_strdup(menu->pool, invalid_sound);
+	menu->max_failures = max_failures;
+	menu->timeout = timeout;
+	menu->actions = NULL;
+	menu->inlen = inlen;
+	if (newpool) {
+		menu->flags |= SWITCH_IVR_MENU_FLAG_FREEPOOL;
+	}
+
+	if (menu->timeout <= 0)
+		menu->timeout = 10000;
+	if (menu->inlen <= 0)
+		menu->inlen = 1;
+	
+	if (main) {
+		switch_ivr_menu_stack(&main, menu);
+	} else {
+		menu->flags |= SWITCH_IVR_MENU_FLAG_STACK;
+	}
+	
+	*new = menu;
+	
+	return SWITCH_STATUS_SUCCESS;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_action(switch_ivr_menu_t *menu, switch_ivr_action_t ivr_action, char *arg, char *bind)
+{
+	switch_ivr_menu_action_t *action;
+
+	if ((action = switch_core_alloc(menu->pool, sizeof(*action)))) {
+		action->bind = bind;
+		action->next = menu->actions;
+		action->arg = arg;
+		action->ivr_action = ivr_action;
+		menu->actions = action;
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_MEMERR;
+}
+
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_bind_function(switch_ivr_menu_t *menu, switch_ivr_menu_action_function_t *function, char *bind)
+{
+	switch_ivr_menu_action_t *action;
+
+
+	if ((action = switch_core_alloc(menu->pool, sizeof(*action)))) {
+		action->bind = bind;
+		action->function = function;
+		action->next = menu->actions;
+		menu->actions = action;
+		return SWITCH_STATUS_SUCCESS;
+	}
+
+	return SWITCH_STATUS_MEMERR;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_free_stack(switch_ivr_menu_t *stack) 
+{
+	switch_memory_pool_t *pool;
+
+	if (!switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_STACK) || switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FREEPOOL)) {
+		return SWITCH_STATUS_FALSE;
+	}
+
+	pool = stack->pool;
+	switch_core_destroy_memory_pool(&pool);
+	pool = NULL;
+
+	return SWITCH_STATUS_SUCCESS;
+
+}
+
+SWITCH_DECLARE(switch_status_t) switch_ivr_menu_execute(switch_core_session_t *session, switch_ivr_menu_t *stack, char *name, void *obj)
+{
+	int reps = 0, errs = 0, match = 0, running = 1;
+	char *greeting_sound = NULL, *aptr;
+	char *buf, arg[512];
+	switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE;
+	switch_ivr_menu_action_t *ap;
+	switch_ivr_menu_t *menu;
+	switch_channel_t *channel;
+	switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+	channel = switch_core_session_get_channel(session);
+	assert(channel != NULL);
+
+
+	if (!(menu = switch_ivr_find_menu(stack, name))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Menu!\n");
+		return -1;
+	}
+	
+	if (!(buf = malloc(menu->inlen))) {
+		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Memory!\n");
+		return -1;
+	}
+	
+	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name);
+
+	for (reps = 0 ; (running && status == SWITCH_STATUS_SUCCESS && errs < menu->max_failures) ; reps++) {
+
+		if (!switch_channel_ready(channel)) {
+			break;
+		}
+
+
+		if (reps > 0 && menu->short_greeting_sound) {
+			greeting_sound = menu->short_greeting_sound;
+		} else {
+			greeting_sound = menu->greeting_sound;
+		}
+
+		match = 0;
+		aptr = NULL;
+		memset(buf, 0, menu->inlen);
+		memset(arg, 0, sizeof(arg));
+
+		if (switch_play_and_get_digits(session,
+									   menu->inlen,
+									   menu->inlen,
+									   1,
+									   menu->timeout, "#",
+									   greeting_sound,
+									   NULL,
+									   buf,
+									   menu->inlen,
+									   NULL) != SWITCH_STATUS_SUCCESS) {
+			break;
+		}
+		
+		if (!switch_strlen_zero(buf)) {
+			for(ap = menu->actions; ap ; ap = ap->next) {
+				if (!strcmp(buf, ap->bind)) {
+					char *membuf;
+
+					switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu %s matched %s\n", menu->name, buf);
+					match++;
+					errs = 0;
+					if (ap->function) {
+						todo = ap->function(menu, arg, sizeof(arg), obj);
+						aptr = arg;
+					} else {
+						todo = ap->ivr_action;
+						aptr = ap->arg;
+					}
+
+					switch(todo) {
+					case SWITCH_IVR_ACTION_DIE:
+						status = SWITCH_STATUS_FALSE;
+						break;
+					case SWITCH_IVR_ACTION_PLAYSOUND:
+						status = switch_ivr_play_file(session, NULL, aptr, NULL, NULL, NULL, 0);
+						break;
+					case SWITCH_IVR_ACTION_TRANSFER:
+						switch_ivr_session_transfer(session, aptr, NULL, NULL);
+						running = 0;
+						break;
+					case SWITCH_IVR_ACTION_EXECMENU:
+						reps = -1;
+						status = switch_ivr_menu_execute(session, stack, aptr, obj);
+						break;
+					case SWITCH_IVR_ACTION_EXECAPP: {
+						const switch_application_interface_t *application_interface;
+						if ((membuf = strdup(aptr))) {
+							char *app_name = membuf;
+							char *app_arg = strchr(app_name, ' ');
+
+							if (app_arg) {
+								*app_arg = '\0';
+								app_arg++;
+							}
+						
+							if (app_name && app_arg) {
+								if ((application_interface = switch_loadable_module_get_application_interface(app_name))) {
+									if (application_interface->application_function) {
+										application_interface->application_function(session, app_arg);
+									}
+								}
+							}
+						}
+					}
+						break;
+					case SWITCH_IVR_ACTION_BACK:
+						running = 0;
+						status = SWITCH_STATUS_SUCCESS;
+						break;
+					case SWITCH_IVR_ACTION_TOMAIN:
+						switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
+						status = SWITCH_STATUS_BREAK;
+						break;
+					default:
+						switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid TODO!\n");
+						break;
+					}
+				}
+			}
+
+
+			if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { /* top level */ 
+				if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */
+					switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN);
+					status = SWITCH_STATUS_SUCCESS;
+					running = 1;
+					continue;
+				}
+			}
+		}
+		if (!match) {
+			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu %s caught invalid input %s\n", menu->name, buf);
+
+			if (menu->invalid_sound) {
+				status = switch_ivr_play_file(session, NULL, aptr, NULL, NULL, NULL, 0);
+			}
+			errs++;
+
+			if (status == SWITCH_STATUS_SUCCESS) {
+				status = switch_ivr_sleep(session, 1000);
+			}
+		}
+		
+	}
+
+	switch_safe_free(buf);
 
 	return status;
 }



More information about the Freeswitch-branches mailing list