04280 { 04281 int reps = 0, errs = 0, match = 0, running = 1; 04282 char *greeting_sound = NULL, *aptr = NULL; 04283 char arg[512]; 04284 switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; 04285 switch_ivr_menu_action_t *ap; 04286 switch_ivr_menu_t *menu; 04287 switch_channel_t *channel; 04288 switch_status_t status = SWITCH_STATUS_SUCCESS; 04289 04290 if (session == NULL || stack == NULL || switch_strlen_zero(name)) { 04291 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid menu context\n"); 04292 return SWITCH_STATUS_FALSE; 04293 } 04294 04295 channel = switch_core_session_get_channel(session); 04296 assert(channel != NULL); 04297 04298 if (!(menu = switch_ivr_menu_find(stack, name))) { 04299 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Menu!\n"); 04300 return SWITCH_STATUS_FALSE; 04301 } 04302 04303 if (!(menu->buf = malloc(menu->inlen))) { 04304 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Memory!\n"); 04305 return SWITCH_STATUS_FALSE; 04306 } 04307 04308 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); 04309 04310 for (reps = 0 ; (running && status == SWITCH_STATUS_SUCCESS && errs < menu->max_failures) ; reps++) { 04311 if (!switch_channel_ready(channel)) { 04312 break; 04313 } 04314 04315 if (reps > 0 && menu->short_greeting_sound) { 04316 greeting_sound = menu->short_greeting_sound; 04317 } else { 04318 greeting_sound = menu->greeting_sound; 04319 } 04320 04321 match = 0; 04322 aptr = NULL; 04323 04324 memset(arg, 0, sizeof(arg)); 04325 04326 memset(menu->buf, 0, menu->inlen); 04327 status = play_or_say(session, menu, greeting_sound, menu->inlen - 1); 04328 04329 if (!switch_strlen_zero(menu->buf)) { 04330 for(ap = menu->actions; ap ; ap = ap->next) { 04331 if (!strcmp(menu->buf, ap->bind)) { 04332 char *membuf; 04333 04334 match++; 04335 errs = 0; 04336 if (ap->function) { 04337 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, ap->arg); 04338 todo = ap->function(menu, ap->arg, arg, sizeof(arg), obj); 04339 aptr = arg; 04340 } else { 04341 todo = ap->ivr_action; 04342 aptr = ap->arg; 04343 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf,aptr); 04344 } 04345 04346 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo); 04347 04348 switch(todo) { 04349 case SWITCH_IVR_ACTION_DIE: 04350 status = SWITCH_STATUS_FALSE; 04351 break; 04352 case SWITCH_IVR_ACTION_PLAYSOUND: 04353 status = switch_ivr_play_file(session, NULL, aptr, NULL); 04354 break; 04355 case SWITCH_IVR_ACTION_SAYTEXT: 04356 status = switch_ivr_speak_text(session, menu->tts_engine, menu->tts_voice, 0, aptr, NULL); 04357 break; 04358 case SWITCH_IVR_ACTION_SAYPHRASE: 04359 status = switch_ivr_phrase_macro(session, aptr, "", menu->phrase_lang, NULL); 04360 break; 04361 case SWITCH_IVR_ACTION_TRANSFER: 04362 switch_ivr_session_transfer(session, aptr, NULL, NULL); 04363 running = 0; 04364 break; 04365 case SWITCH_IVR_ACTION_EXECMENU: 04366 reps = -1; 04367 status = switch_ivr_menu_execute(session, stack, aptr, obj); 04368 break; 04369 case SWITCH_IVR_ACTION_EXECAPP: { 04370 const switch_application_interface_t *application_interface; 04371 04372 if ((membuf = strdup(aptr))) { 04373 char *app_name = membuf; 04374 char *app_arg = strchr(app_name, ' '); 04375 04376 if (app_arg) { 04377 *app_arg = '\0'; 04378 app_arg++; 04379 } 04380 04381 if (app_name && app_arg) { 04382 if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { 04383 if (application_interface->application_function) { 04384 application_interface->application_function(session, app_arg); 04385 } 04386 } 04387 } 04388 } 04389 } 04390 break; 04391 case SWITCH_IVR_ACTION_BACK: 04392 running = 0; 04393 status = SWITCH_STATUS_SUCCESS; 04394 break; 04395 case SWITCH_IVR_ACTION_TOMAIN: 04396 switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); 04397 status = SWITCH_STATUS_BREAK; 04398 break; 04399 case SWITCH_IVR_ACTION_NOOP: 04400 status = SWITCH_STATUS_SUCCESS; 04401 break; 04402 default: 04403 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid TODO!\n"); 04404 break; 04405 } 04406 } 04407 } 04408 04409 04410 if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { // top level 04411 if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { // catch the fallback and recover 04412 switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); 04413 status = SWITCH_STATUS_SUCCESS; 04414 running = 1; 04415 continue; 04416 } 04417 } 04418 } 04419 if (!match) { 04420 if (*menu->buf) { 04421 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, menu->buf); 04422 if (menu->invalid_sound) { 04423 play_or_say(session, menu, menu->invalid_sound, 0); 04424 } 04425 } 04426 else { 04427 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name); 04428 } 04429 errs++; 04430 if (status == SWITCH_STATUS_SUCCESS) { 04431 status = switch_ivr_sleep(session, 1000); 04432 } 04433 /* breaks are ok too */ 04434 if (SWITCH_STATUS_IS_BREAK(status)) { 04435 status = SWITCH_STATUS_SUCCESS; 04436 } 04437 } 04438 } 04439 04440 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "exit-sound '%s'\n",menu->exit_sound); 04441 if (!switch_strlen_zero(menu->exit_sound)) { 04442 play_or_say(session, menu, menu->exit_sound, 0); 04443 } 04444 04445 switch_safe_free(menu->buf); 04446 04447 return status; 04448 }