static switch_status_t listen_entry(switch_core_session_t *session, dir_profile_t *profile, listing_callback_t *cbt) { char buf[2] = ""; char macro[256] = ""; char recorded_name[256] = ""; /* Try to use the recorded name from voicemail if it exist */ if (switch_loadable_module_exists("mod_voicemail") == SWITCH_STATUS_SUCCESS) { char *cmd = NULL; switch_stream_handle_t stream = { 0 }; SWITCH_STANDARD_STREAM(stream); cmd = switch_core_session_sprintf(session, "%s/%s@%s|name_path", cbt->params->profile, cbt->extension, cbt->params->domain); switch_api_execute("vm_prefs", cmd, session, &stream); if (strncmp("-ERR", stream.data, 4)) { switch_copy_string(recorded_name, (char *) stream.data, sizeof(recorded_name)); } switch_safe_free(stream.data); } if (zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%d", DIR_RESULT_ITEM, cbt->want + 1); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (!zstr_buf(recorded_name) && zstr_buf(buf)) { switch_ivr_read(session, 0, 1, recorded_name, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (zstr_buf(recorded_name) && zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", DIR_RESULT_SAY_NAME, cbt->fullname); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (cbt->exten_visible && zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%s", DIR_RESULT_AT, cbt->extension); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), 1, profile->terminator_key, 0); } if (zstr_buf(buf)) { switch_snprintf(macro, sizeof(macro), "phrase:%s:%c,%c,%c,%c", DIR_RESULT_MENU, *profile->select_name_key, *profile->next_key, *profile->prev_key, *profile->new_search_key); switch_ivr_read(session, 0, 1, macro, NULL, buf, sizeof(buf), profile->digit_timeout, profile->terminator_key, 0); } if (!zstr_buf(buf)) { if (buf[0] == *profile->select_name_key) { switch_copy_string(cbt->transfer_to, cbt->extension, 255); } if (buf[0] == *profile->new_search_key) { cbt->new_search = 1; } if (buf[0] == *profile->prev_key) { cbt->move = ENTRY_MOVE_PREV; } } else { return SWITCH_STATUS_TIMEOUT; } return SWITCH_STATUS_SUCCESS; }
void mtvm_menu_purge(switch_core_session_t *session, vmivr_profile_t *profile) { if (profile->id && profile->authorized) { if (1==1 /* TODO make Purge email on exit optional ??? */) { const char *cmd = switch_core_session_sprintf(session, "%s %s %s", profile->api_profile, profile->domain, profile->id); mt_api_execute(session, profile->api_msg_purge, cmd); } } }
static switch_status_t do_snap(switch_core_session_t *session) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_media_bug_t *bug = switch_channel_get_private(channel, "snapshot"); char *file; switch_file_handle_t fh = { 0 }; switch_codec_implementation_t read_impl = { 0 }; switch_size_t bytes_read; int16_t pdata[4096] = { 0 }; if (bug) { switch_time_exp_t tm; switch_size_t retsize; char date[80] = ""; struct cap_cb *cb = (struct cap_cb *) switch_core_media_bug_get_user_data(bug); if (!cb) { return SWITCH_STATUS_FALSE; } switch_time_exp_lt(&tm, switch_time_make(switch_epoch_time_now(NULL), 0)); switch_strftime(date, &retsize, sizeof(date), "%Y_%m_%d_%H_%M_%S", &tm); file = switch_core_session_sprintf(session, "%s%s%s_%s.wav", SWITCH_GLOBAL_dirs.sounds_dir, SWITCH_PATH_SEPARATOR, cb->base, date); switch_core_session_get_read_impl(session, &read_impl); fh.channels = 0; fh.native_rate = read_impl.actual_samples_per_second; if (switch_core_file_open(&fh, file, 0, read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error opening %s\n", file); switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE); return SWITCH_STATUS_FALSE; } switch_mutex_lock(cb->mutex); while ((bytes_read = switch_buffer_read(cb->buffer, pdata, sizeof(pdata)))) { switch_size_t samples = bytes_read / 2; if (switch_core_file_write(&fh, pdata, &samples) != SWITCH_STATUS_SUCCESS) { break; } } switch_mutex_unlock(cb->mutex); switch_core_file_close(&fh); switch_core_set_variable("file", file); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Wrote %s\n", file); return SWITCH_STATUS_SUCCESS; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s Bug is not attached.\n", switch_channel_get_name(channel)); return SWITCH_STATUS_FALSE; }
void vmivr_menu_record_greeting_with_slot(switch_core_session_t *session, vmivr_profile_t *profile) { vmivr_menu_t menu = { "std_record_greeting_with_slot" }; const char *result; int gnum = -1; /* Initialize Menu Configs */ menu_init(profile, &menu); result = vmivr_menu_get_input_set(session, profile, &menu, "X"); if (result) gnum = atoi(result); /* If user entered 0, we don't accept it */ if (gnum > 0) { vmivr_menu_t sub_menu = { "std_record_greeting" }; char *tmp_filepath = NULL; const char *record_format = NULL; switch_status_t status; /* Initialize Menu Configs */ menu_init(profile, &sub_menu); record_format = switch_event_get_header(menu.event_settings, "Record-Format"); tmp_filepath = generate_random_file_name(session, "voicemail_ivr", record_format); status = vmivr_menu_record(session, profile, &sub_menu, tmp_filepath); if (status == SWITCH_STATUS_SUCCESS) { char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath); char *str_num = switch_core_session_sprintf(session, "%d", gnum); vmivr_api_execute(session, profile->api_pref_greeting_set, cmd); ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); } menu_free(&sub_menu); } menu_free(&menu); }
char *generate_random_file_name(switch_core_session_t *session, const char *mod_name, const char *file_extension) { char rand_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1] = ""; switch_uuid_t srand_uuid; switch_uuid_get(&srand_uuid); switch_uuid_format(rand_uuid, &srand_uuid); return switch_core_session_sprintf(session, "%s%s%s_%s.%s", SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, mod_name, rand_uuid, file_extension); }
void mtvm_menu_record_greeting_with_slot(switch_core_session_t *session, vmivr_profile_t *profile) { vmivr_menu_profile_t menu = { "std_record_greeting_with_slot" }; const char *result; int gnum = -1; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &menu); result = mtvm_menu_get_input_set(session, profile, menu, "X", NULL); if (result) gnum = atoi(result); /* If user entered 0, we don't accept it */ if (gnum > 0) { vmivr_menu_profile_t sub_menu = { "std_record_greeting" }; char *tmp_filepath = generate_random_file_name(session, "protovm", "wav" /* TODO make it configurable */); switch_status_t status; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &sub_menu); status = mtvm_menu_record(session, profile, sub_menu, tmp_filepath); if (status == SWITCH_STATUS_SUCCESS) { char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath); char *str_num = switch_core_session_sprintf(session, "%d", gnum); mt_api_execute(session, profile->api_pref_greeting_set, cmd); playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); } free_profile_menu_event(&sub_menu); } free_profile_menu_event(&menu); }
void mtvm_menu_set_password(switch_core_session_t *session, vmivr_profile_t *profile) { char *password; vmivr_menu_profile_t menu = { "std_set_password" }; password = mtvm_menu_get_input_set(session, profile, menu, "XXX." /* TODO Conf Min 3 Digit */, "#" /* TODO Conf terminate input key */); /* TODO Add Prompts to tell if password was set and if it was not */ if (password) { char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, password); mt_api_execute(session, profile->api_pref_password_set, cmd); } free_profile_menu_event(&menu); }
void vmivr_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profile_t *profile) { vmivr_menu_t menu = { "std_select_greeting_slot" }; const char *result; int gnum = -1; /* Initialize Menu Configs */ menu_init(profile, &menu); result = vmivr_menu_get_input_set(session, profile, &menu, "X"); if (result) gnum = atoi(result); if (gnum != -1) { char * cmd = switch_core_session_sprintf(session, "%s %s %s %d", profile->api_profile, profile->domain, profile->id, gnum); if (vmivr_api_execute(session, profile->api_pref_greeting_set, cmd) == SWITCH_STATUS_SUCCESS) { char *str_num = switch_core_session_sprintf(session, "%d", gnum); char *cmd = switch_core_session_sprintf(session, "json %s %s %s %d %s", profile->api_profile, profile->domain, profile->id); switch_event_t *phrases = jsonapi2event(session, profile->api_pref_greeting_get, cmd); ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, phrases, NULL, 0); if (switch_true(switch_event_get_header(phrases, "VM-Message-Private-Local-Copy"))) { const char *file_path = switch_event_get_header(phrases, "VM-Preference-Greeting-File-Path"); if (file_path && unlink(file_path) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete temp file [%s]\n", file_path); } } switch_event_destroy(&phrases); } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid_slot"), NULL, NULL, NULL, 0); } } menu_free(&menu); }
void mtvm_menu_select_greeting_slot(switch_core_session_t *session, vmivr_profile_t *profile) { vmivr_menu_profile_t menu = { "std_select_greeting_slot" }; const char *result; int gnum = -1; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &menu); result = mtvm_menu_get_input_set(session, profile, menu, "X", NULL); if (result) gnum = atoi(result); if (gnum != -1) { char * cmd = switch_core_session_sprintf(session, "%s %s %s %d", profile->api_profile, profile->domain, profile->id, gnum); if (mt_api_execute(session, profile->api_pref_greeting_set, cmd) == SWITCH_STATUS_SUCCESS) { char *str_num = switch_core_session_sprintf(session, "%d", gnum); playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); } else { playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "invalid_slot"), NULL, NULL, NULL, 0); } } free_profile_menu_event(&menu); }
void vmivr_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); vmivr_menu_t menu = { "std_authenticate" }; int retry; const char *auth_var = NULL; /* Initialize Menu Configs */ menu_init(profile, &menu); if (profile->id && (auth_var = switch_channel_get_variable(channel, "voicemail_authorized")) && switch_true(auth_var)) { profile->authorized = SWITCH_TRUE; } for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0 && profile->authorized == SWITCH_FALSE; retry--) { const char *id = profile->id, *password = NULL; char *cmd = NULL; const char *password_mask = switch_event_get_header(menu.event_settings, "Password-Mask"); const char *user_mask = switch_event_get_header(menu.event_settings, "User-Mask"); if (!id) { vmivr_menu_t sub_menu = { "std_authenticate_ask_user" }; /* Initialize Menu Configs */ menu_init(profile, &sub_menu); switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); id = vmivr_menu_get_input_set(session, profile, &sub_menu, user_mask); menu_free(&sub_menu); } if (!password) { vmivr_menu_t sub_menu = { "std_authenticate_ask_password" }; /* Initialize Menu Configs */ menu_init(profile, &sub_menu); switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); password = vmivr_menu_get_input_set(session, profile, &sub_menu, password_mask); menu_free(&sub_menu); } cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, id, password); if (vmivr_api_execute(session, profile->api_auth_login, cmd) == SWITCH_STATUS_SUCCESS) { profile->id = id; profile->authorized = SWITCH_TRUE; } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "fail_auth"), NULL, NULL, NULL, 0); } } menu_free(&menu); }
void mtvm_menu_record_name(switch_core_session_t *session, vmivr_profile_t *profile) { switch_status_t status; vmivr_menu_profile_t menu = { "std_record_name" }; char *tmp_filepath = generate_random_file_name(session, "protovm", "wav" /* TODO make it configurable */); /* Initialize Menu Configs */ populate_profile_menu_event(profile, &menu); status = mtvm_menu_record(session, profile, menu, tmp_filepath); if (status == SWITCH_STATUS_SUCCESS) { char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, tmp_filepath); mt_api_execute(session, profile->api_pref_recname_set, cmd); } }
void vmivr_menu_purge(switch_core_session_t *session, vmivr_profile_t *profile) { vmivr_menu_t menu = { "std_menu_purge" }; /* Initialize Menu Configs */ menu_init(profile, &menu); if (profile->id && profile->authorized) { const char *exit_purge = switch_event_get_header(menu.event_settings, "Exit-Purge"); if (switch_true(exit_purge)) { const char *cmd = switch_core_session_sprintf(session, "%s %s %s", profile->api_profile, profile->domain, profile->id); vmivr_api_execute(session, profile->api_msg_purge, cmd); } } menu_free(&menu); }
char *sofia_media_get_multipart(switch_core_session_t *session, const char *prefix, const char *sdp, char **mp_type) { char *extra_headers = NULL; switch_stream_handle_t stream = { 0 }; switch_event_header_t *hi = NULL; int x = 0; switch_channel_t *channel = switch_core_session_get_channel(session); const char *boundary = switch_core_session_get_uuid(session); SWITCH_STANDARD_STREAM(stream); if ((hi = switch_channel_variable_first(channel))) { for (; hi; hi = hi->next) { const char *name = (char *) hi->name; char *value = (char *) hi->value; if (!strncasecmp(name, prefix, strlen(prefix))) { const char *hname = name + strlen(prefix); if (*value == '~') { stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n%s\n", boundary, hname, strlen(value), value + 1); } else { stream.write_function(&stream, "--%s\nContent-Type: %s\nContent-Length: %d\n\n%s\n", boundary, hname, strlen(value) + 1, value); } x++; } } switch_channel_variable_last(channel); } if (x) { *mp_type = switch_core_session_sprintf(session, "multipart/mixed; boundary=%s", boundary); if (sdp) { stream.write_function(&stream, "--%s\nContent-Type: application/sdp\nContent-Length: %d\n\n%s\n", boundary, strlen(sdp) + 1, sdp); } stream.write_function(&stream, "--%s--\n", boundary); } if (!zstr((char *) stream.data)) { extra_headers = stream.data; } else { switch_safe_free(stream.data); } return extra_headers; }
void mtvm_menu_authenticate(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); vmivr_menu_profile_t menu = { "std_authenticate" }; int retry; const char *auth_var = NULL; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &menu); if (profile->id && (auth_var = switch_channel_get_variable(channel, "voicemail_authorized")) && switch_true(auth_var)) { profile->authorized = SWITCH_TRUE; } for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0 && profile->authorized == SWITCH_FALSE; retry--) { const char *id = profile->id, *password = NULL; char *cmd = NULL; if (!id) { vmivr_menu_profile_t sub_menu = { "std_authenticate_ask_user" }; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &sub_menu); id = mtvm_menu_get_input_set(session, profile, sub_menu, "X." /* TODO Conf Min 3 Digit */, "#" /* TODO Conf terminate input key */); free_profile_menu_event(&sub_menu); } if (!password) { vmivr_menu_profile_t sub_menu = { "std_authenticate_ask_password" }; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &sub_menu); password = mtvm_menu_get_input_set(session, profile, sub_menu, "X." /* TODO Conf Min 3 Digit */, "#" /* TODO Conf terminate input key */); free_profile_menu_event(&sub_menu); } cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, id, password); if (mt_api_execute(session, profile->api_auth_login, cmd) == SWITCH_STATUS_SUCCESS) { profile->id = id; profile->authorized = SWITCH_TRUE; } else { playbackBufferDTMF(session, switch_event_get_header(menu.event_phrases, "fail_auth"), NULL, NULL, NULL, 0); } } free_profile_menu_event(&menu); }
void vmivr_menu_record_name(switch_core_session_t *session, vmivr_profile_t *profile) { switch_status_t status; vmivr_menu_t menu = { "std_record_name" }; const char *tmp_filepath = NULL; const char *record_format = NULL; /* Initialize Menu Configs */ menu_init(profile, &menu); record_format = switch_event_get_header(menu.event_settings, "Record-Format"); tmp_filepath = generate_random_file_name(session, "voicemail_ivr", record_format); status = vmivr_menu_record(session, profile, &menu, tmp_filepath); if (status == SWITCH_STATUS_SUCCESS) { char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, tmp_filepath); vmivr_api_execute(session, profile->api_pref_recname_set, cmd); } }
void vmivr_menu_set_password(switch_core_session_t *session, vmivr_profile_t *profile) { char *password; vmivr_menu_t menu = { "std_set_password" }; const char *password_mask = NULL; /* Initialize Menu Configs */ menu_init(profile, &menu); password_mask = switch_event_get_header(menu.event_settings, "Password-Mask"); password = vmivr_menu_get_input_set(session, profile, &menu, password_mask); if (password) { char *cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, password); if (vmivr_api_execute(session, profile->api_pref_password_set, cmd)) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "password_set"), NULL, NULL, NULL, 0); } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "password_not_set"), NULL, NULL, NULL, 0); } } menu_free(&menu); }
WSChannel* WSClientParser::CreateCall( switch_core_session_t *session, const char *profileName, const char *profileContext, const char *profileDialplan, const char* ip ) { WSChannel *wsChannel = NULL; switch_memory_pool_t *pool = NULL; switch_channel_t* channel = NULL; switch_caller_profile_t *caller_profile = NULL; char *user = mpUser; char *domain = mpDomain; const char *destNumber = mpDestNumber; const char *context = NULL; const char *dialplan = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateCall( " "this : %p, " "profileName : '%s', " "profileContext : '%s', " "profileDialplan : '%s', " "ip : '%s' " ") \n", this, profileName, profileContext, profileDialplan, ip ); // 参数不能为空 if ( !user || !domain || !destNumber ) { status = SWITCH_STATUS_FALSE; } // 不允许一个连接创建多个会话 if( status == SWITCH_STATUS_SUCCESS && mpChannel ) { status = SWITCH_STATUS_FALSE; } if( status == SWITCH_STATUS_SUCCESS ) { pool = switch_core_session_get_pool(session); channel = switch_core_session_get_channel(session); switch_channel_set_name( channel, switch_core_session_sprintf(session, "ws/%s/%s/%s", profileName, user, destNumber) ); } // if ( status == SWITCH_STATUS_SUCCESS && !zstr(user) && !zstr(domain)) { // // 拨号不做验证 // const char *ivrUser = switch_core_session_sprintf(session, "%s@%s", user, domain); // status = switch_ivr_set_user(session, ivrUser); // } if( status == SWITCH_STATUS_SUCCESS ) { if (!(context = switch_channel_get_variable(channel, "user_context"))) { if (!(context = profileContext)) { context = "public"; } } if (!(dialplan = switch_channel_get_variable(channel, "inbound_dialplan"))) { if (!(dialplan = profileDialplan)) { dialplan = "LUA"; } } // switch_log_printf( // SWITCH_CHANNEL_SESSION_LOG(session), // SWITCH_LOG_NOTICE, // "WSClientParser::CreateCall( " // "context : %s, " // "dialplan : %s " // ") \n", // context, // dialplan // ); // 设置主叫 caller_profile = switch_caller_profile_new( pool, switch_str_nil(user), dialplan, SWITCH_DEFAULT_CLID_NAME, !zstr(user) ? user : SWITCH_DEFAULT_CLID_NUMBER, ip /* net addr */, NULL /* ani */, NULL /* anii */, NULL /* rdnis */, "mod_ws", context, destNumber ); switch_channel_set_caller_profile(channel, caller_profile); switch_core_session_add_stream(session, NULL); switch_channel_set_variable(channel, "caller", user); switch_channel_set_state(channel, CS_INIT); wsChannel = CreateChannel(session); } if( wsChannel ) { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_INFO, "WSClientParser::CreateCall( " "[Success], " "this : %p, " "wsChannel : %p, " "profileName : '%s', " "profileContext : '%s', " "profileDialplan : '%s', " "ip : '%s' " ") \n", this, wsChannel, profileName, profileContext, profileDialplan, ip ); } else { switch_log_printf( SWITCH_CHANNEL_UUID_LOG(this->GetUUID()), SWITCH_LOG_ERROR, "WSClientParser::CreateCall( " "[Fail], " "this : %p " ") \n", this, profileName, profileContext, profileDialplan, ip ); } return wsChannel; }
void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); vmivr_menu_t menu = { "std_main_menu" }; int retry; switch_bool_t action_on_new_message_occured = SWITCH_FALSE; /* Initialize Menu Configs */ menu_init(profile, &menu); if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name); goto end; } for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) { char *cmd = NULL; const char *action = NULL; const char *action_on_new_message = switch_event_get_header(menu.event_settings, "Action-On-New-Message"); menu_instance_init(&menu); switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); ivre_init(&menu.ivre_d, menu.dtmfa); cmd = switch_core_session_sprintf(session, "json %s %s %s %s", profile->api_profile, profile->domain, profile->id, profile->folder_name); jsonapi_populate_event(session, menu.phrase_params, profile->api_msg_count, cmd); /* Verify that phrases returned values, if not, exit */ if (!switch_event_get_header(menu.phrase_params, "VM-Total-New-Messages")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Return from API is invalid. Check that the context exist on your DB backend\n"); menu_instance_free(&menu); break; } ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, menu.phrase_params, NULL, 0); if (atoi(switch_event_get_header(menu.phrase_params, "VM-Total-New-Messages")) > 0 && menu.ivre_d.result == RES_WAITFORMORE && !action_on_new_message_occured && action_on_new_message) { menu.ivre_d.result = RES_FOUND; action = action_on_new_message; action_on_new_message_occured = SWITCH_TRUE; } else { ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout); } if (menu.ivre_d.result == RES_TIMEOUT) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_INVALID) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */ if (!action) { action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored); } /* Reset the try count */ retry = menu.ivr_maximum_attempts; if (action) { if (!strncasecmp(action, "new_msg:", 8)) { void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+8); profile->folder_filter = VM_MSG_NEW; if (fPtr) { fPtr(session, profile); } } else if (!strncasecmp(action, "saved_msg:", 10)) { void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+10); profile->folder_filter = VM_MSG_SAVED; if (fPtr) { fPtr(session, profile); } } else if (!strcasecmp(action, "return")) { /* Return to the previous menu */ retry = -1; } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } } } menu_instance_free(&menu); } end: menu_free(&menu); }
void mtvm_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_event_t *msg_list_params = NULL; size_t msg_count = 0; size_t current_msg = 1; size_t next_msg = current_msg; size_t previous_msg = current_msg; char *cmd = NULL; int retry; /* Different switch to control playback of phrases */ switch_bool_t initial_count_played = SWITCH_FALSE; switch_bool_t skip_header = SWITCH_FALSE; switch_bool_t msg_deleted = SWITCH_FALSE; switch_bool_t msg_undeleted = SWITCH_FALSE; switch_bool_t msg_saved = SWITCH_FALSE; vmivr_menu_profile_t menu = { "std_navigator" }; /* Initialize Menu Configs */ populate_profile_menu_event(profile, &menu); if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases and Keys\n"); return; } /* Get VoiceMail List And update msg count */ cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); msg_list_params = jsonapi2event(session, NULL, profile->api_msg_list, cmd); msg_count = atol(switch_event_get_header(msg_list_params,"VM-List-Count")); /* TODO Add Detection of new message and notify the user */ for (retry = MAX_ATTEMPT; switch_channel_ready(channel) && retry > 0; retry--) { dtmf_ss_t loc; char *dtmfa[16] = { 0 }; switch_event_t *phrase_params = NULL; switch_event_create(&phrase_params, SWITCH_EVENT_REQUEST_PARAMS); append_event_profile(phrase_params, profile, menu); populate_dtmfa_from_event(phrase_params, profile, menu, dtmfa); previous_msg = current_msg; /* Simple Protection to not go out of msg list scope */ /* TODO: Add Prompt to notify they reached the begining or the end */ if (next_msg == 0) { next_msg = 1; } else if (next_msg > msg_count) { next_msg = msg_count; } current_msg = next_msg; captureMenuInitialize(&loc, dtmfa); /* Prompt related to previous Message here */ append_event_message(session, profile, phrase_params, msg_list_params, previous_msg); if (msg_deleted) { msg_deleted = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "deleted", phrase_params, NULL, 0); } if (msg_undeleted) { msg_undeleted = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "undeleted", phrase_params, NULL, 0); } if (msg_saved) { msg_saved = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "ack"), "saved", phrase_params, NULL, 0); } /* Prompt related the current message */ append_event_message(session, profile, phrase_params, msg_list_params, current_msg); /* TODO check if msg is gone (purged by another session, notify user and auto jump to next message or something) */ if (!skip_header) { if (!initial_count_played) { cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); jsonapi2event(session, phrase_params, profile->api_msg_count, cmd); initial_count_played = SWITCH_TRUE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, phrase_params, NULL, 0); } if (msg_count > 0) { captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "say_msg_number"), NULL, phrase_params, NULL, 0); captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "say_date"), NULL, phrase_params, NULL, 0); } } if (msg_count > 0) { /* TODO Update the Read date of a message (When msg start, or when it listen compleatly ??? To be determined */ captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "play_message"), NULL, phrase_params, NULL, 0); } skip_header = SWITCH_FALSE; captureMenu(session, &loc, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, phrase_params, NULL, DEFAULT_IVR_TIMEOUT); if (loc.result == RES_TIMEOUT) { /* TODO Ask for the prompt Again IF retry != 0 */ } else if (loc.result == RES_INVALID) { /* TODO Say invalid option, and ask for the prompt again IF retry != 0 */ } else if (loc.result == RES_FOUND) { /* Matching DTMF Key Pressed */ const char *action = switch_event_get_header(menu.event_keys_dtmf, loc.dtmf_stored); /* Reset the try count */ retry = MAX_ATTEMPT; if (action) { if (!strcasecmp(action, "skip_intro")) { /* Skip Header / Play the recording again */ skip_header = SWITCH_TRUE; } else if (!strcasecmp(action, "next_msg")) { /* Next Message */ next_msg++; } else if (!strcasecmp(action, "prev_msg")) { /* Previous Message */ next_msg--; } else if (!strcasecmp(action, "delete_msg")) { /* Delete / Undelete Message */ if (strncasecmp(switch_event_get_header(phrase_params, "VM-Message-Flags"), "delete", 6)) { cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); mt_api_execute(session, profile->api_msg_delete, cmd); msg_deleted = SWITCH_TRUE; /* TODO Option for auto going to next message or just return to the menu (So user used to do 76 to delete and next message wont be confused) */ next_msg++; } else { cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); mt_api_execute(session, profile->api_msg_undelete, cmd); msg_undeleted = SWITCH_TRUE; } } else if (!strcasecmp(action, "save_msg")) { /* Save Message */ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(phrase_params, "VM-Message-UUID")); mt_api_execute(session, profile->api_msg_save, cmd); msg_saved = SWITCH_TRUE; } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = mtvm_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } else if (!strcasecmp(action, "return")) { /* Return */ retry = -1; } } } /* IF the API to get the message returned us a COPY of the file locally (temp file create from a DB or from a web server), delete it */ if (switch_true(switch_event_get_header(phrase_params, "VM-Message-Private-Local-Copy"))) { const char *file_path = switch_event_get_header(phrase_params, "VM-Message-File-Path"); if (file_path && unlink(file_path) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete temp file [%s]\n", file_path); } } switch_event_destroy(&phrase_params); } switch_event_destroy(&msg_list_params); free_profile_menu_event(&menu); return; }
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, timeouts = 0, match = 0, running = 1; char *greeting_sound = NULL, *aptr = NULL; char 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; if (++stack->stack_count > 12) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!session || !stack || zstr(name)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } channel = switch_core_session_get_channel(session); if (!(menu = switch_ivr_menu_find(stack, name))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n"); switch_goto_status(SWITCH_STATUS_FALSE, end); } if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); switch_channel_set_variable(channel, "ivr_menu_status", "success"); if (!zstr(menu->pin)) { char digit_buffer[128] = ""; char *digits_regex = switch_core_session_sprintf(session, "^%s$", menu->pin); if (switch_play_and_get_digits(session, strlen(menu->pin), strlen(menu->pin), 3, 3000, "#", menu->prompt_pin_file, menu->bad_pin_file, NULL, digit_buffer, sizeof(digit_buffer), digits_regex, 10000, NULL) != SWITCH_STATUS_SUCCESS) { switch_goto_status(SWITCH_STATUS_FALSE, end); } } for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) { if (!switch_channel_ready(channel)) { break; } if (errs == menu->max_failures) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n"); switch_channel_set_variable(channel, "ivr_menu_status", "failure"); if (!zstr(menu->exec_on_max_fail)) { exec_app(session, menu->exec_on_max_fail); } break; } if (timeouts == menu->max_timeouts) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n"); switch_channel_set_variable(channel, "ivr_menu_status", "timeout"); if (!zstr(menu->exec_on_max_timeout)) { exec_app(session, menu->exec_on_max_timeout); } 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(arg, 0, sizeof(arg)); memset(menu->buf, 0, menu->inlen + 1); if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') { timeouts++; continue; } if (*menu->buf != '\0') { for (ap = menu->actions; ap; ap = ap->next) { int ok = 0; char substituted[1024]; char *use_arg = ap->arg; if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); } if (ap->re) { switch_regex_t *re = NULL; int ovector[30]; if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector); use_arg = substituted; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok); switch_regex_safe_free(re); } else { ok = !strcmp(menu->buf, ap->bind); } if (ok) { match++; errs = 0; if (ap->function) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg); todo = ap->function(menu, use_arg, arg, sizeof(arg), obj); aptr = arg; } else { todo = ap->ivr_action; aptr = use_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr); } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo); 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); break; case SWITCH_IVR_ACTION_EXECMENU: if (!strcmp(aptr, menu->name)) { status = SWITCH_STATUS_SUCCESS; } else { reps = -1; status = switch_ivr_menu_execute(session, stack, aptr, obj); } break; case SWITCH_IVR_ACTION_EXECAPP: { switch_application_interface_t *application_interface; char *app_name; char *app_arg = NULL; status = SWITCH_STATUS_FALSE; if (!zstr(aptr)) { app_name = switch_core_session_strdup(session, aptr); if ((app_arg = strchr(app_name, ' '))) { *app_arg++ = '\0'; } if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { if (!zstr(menu->transfer_sound) && !strcmp(app_name, "transfer")) { status = play_and_collect(session, menu, menu->transfer_sound, 0); } switch_core_session_exec(session, application_interface, app_arg); UNPROTECT_INTERFACE(application_interface); status = SWITCH_STATUS_SUCCESS; } } } 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; case SWITCH_IVR_ACTION_NOOP: status = SWITCH_STATUS_SUCCESS; break; default: switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), 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) { if (*menu->buf) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, menu->buf); if (menu->invalid_sound) { play_and_collect(session, menu, menu->invalid_sound, 0); } } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name); } errs++; /* breaks are ok too */ if (SWITCH_STATUS_IS_BREAK(status)) { status = SWITCH_STATUS_SUCCESS; } } } if (stack->stack_count == 1) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound); if (!zstr(menu->exit_sound)) { status = play_and_collect(session, menu, menu->exit_sound, 0); } } end: stack->stack_count--; return status; }
switch_status_t ladspa_session(switch_core_session_t *session, const char *flags, const char *plugin_name, const char *label, const char *params) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_media_bug_t *bug; switch_status_t status; switch_ladspa_t *pvt = { 0 }; switch_codec_implementation_t read_impl = { 0 }; int i, bflags = SMBF_READ_REPLACE | SMBF_ANSWER_REQ; char *pstr; int argc; char *argv[50]; char *dparams = NULL; if (zstr(plugin_name)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "%s INVALID PLUGIN\n", switch_channel_get_name(channel)); return SWITCH_STATUS_FALSE; } if (zstr(flags)) { flags = "r"; } if (strchr(flags, 'w')) { bflags = SMBF_WRITE_REPLACE; } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "FLAGS: %s PLUGIN: %s LABEL: %s PARAMS: %s\n", flags, plugin_name, label, params); switch_core_session_get_read_impl(session, &read_impl); pvt = switch_core_session_alloc(session, sizeof(*pvt)); pvt->session = session; if (!zstr(label)) { pvt->label_name = switch_core_session_strdup(session, label); } else { char *p; pvt->label_name = switch_core_session_strdup(session, plugin_name); if ((p = strrchr(pvt->label_name, '.'))) { *p = '\0'; } } if (strstr(plugin_name, ".so")) { pvt->plugin_name = switch_core_session_strdup(session, plugin_name); } else { pvt->plugin_name = switch_core_session_sprintf(session, "%s.so", plugin_name); } dparams = switch_core_session_strdup(session, params); argc = switch_split(dparams, ' ', argv); for (i = 0; i < argc; i++) { if (switch_is_number(argv[i])) { if (pvt->num_idx < MAX_INDEX) { pvt->config[pvt->num_idx] = atof(argv[i]); pvt->has_config[pvt->num_idx] = 1; pvt->num_idx++; } } else { if (pvt->str_idx < MAX_INDEX) { pvt->str_config[pvt->str_idx++] = switch_core_session_strdup(session, argv[i]); } } } if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_FALSE; } pstr = switch_core_session_sprintf(session, "%s|%s|%s|%s", flags, plugin_name, label, params); if ((status = switch_core_media_bug_add(session, "ladspa", pstr, ladspa_callback, pvt, 0, bflags | SMBF_NO_PAUSE, &bug)) != SWITCH_STATUS_SUCCESS) { return status; } switch_channel_set_private(channel, "ladspa", bug); return SWITCH_STATUS_SUCCESS; }
static switch_bool_t fsk_detect_callback(switch_media_bug_t *bug, void *user_data, switch_abc_type_t type) { switch_fsk_detect_t *pvt = (switch_fsk_detect_t *) user_data; //switch_frame_t *frame = NULL; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); switch (type) { case SWITCH_ABC_TYPE_INIT: { switch_codec_implementation_t read_impl = { 0 }; switch_core_session_get_read_impl(pvt->session, &read_impl); if (fsk_demod_init(&pvt->fsk_data, read_impl.actual_samples_per_second, pvt->fbuf, sizeof(pvt->fbuf))) { return SWITCH_FALSE; } break; } case SWITCH_ABC_TYPE_CLOSE: { fsk_demod_destroy(&pvt->fsk_data); } break; case SWITCH_ABC_TYPE_WRITE_REPLACE: case SWITCH_ABC_TYPE_READ_REPLACE: { switch_frame_t *rframe; if (type == SWITCH_ABC_TYPE_READ_REPLACE) { rframe = switch_core_media_bug_get_read_replace_frame(bug); } else { rframe = switch_core_media_bug_get_write_replace_frame(bug); } if (!pvt->skip && fsk_demod_feed(&pvt->fsk_data, rframe->data, rframe->datalen / 2) != SWITCH_STATUS_SUCCESS) { char str[1024] = ""; size_t type, mlen; char *sp; switch_event_t *event; const char *app_var; int total = 0; switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA); while(fsk_data_parse(&pvt->fsk_data, &type, &sp, &mlen) == SWITCH_STATUS_SUCCESS) { char *varname = NULL, *val, *p; switch_copy_string(str, sp, mlen+1); *(str+mlen) = '\0'; switch_clean_string(str); //printf("TYPE %u LEN %u VAL [%s]\n", (unsigned)type, (unsigned)mlen, str); val = str; switch(type) { case MDMF_DATETIME: varname = "fsk_datetime"; break; case MDMF_PHONE_NAME: varname = "fsk_phone_name"; break; case MDMF_PHONE_NUM: varname = "fsk_phone_num"; break; case MDMF_NAME_VALUE: varname = switch_core_session_sprintf(pvt->session, "fsk_%s", val); if ((p = strchr(varname, ':'))) { *p++ = '\0'; val = p; } break; default: break; } if (varname && val) { total++; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s setting FSK var [%s][%s]\n", switch_channel_get_name(channel), varname, val); switch_channel_set_variable(channel, varname, val); if (event) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, varname, val); } } } if (event) { if (switch_core_session_queue_event(pvt->session, &event) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); } } if (total && (app_var = switch_channel_get_variable(channel, "execute_on_fsk"))) { char *app_arg; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "%s processing execute_on_fsk [%s]\n", switch_channel_get_name(channel), app_var); if ((app_arg = strchr(app_var, ' '))) { *app_arg++ = '\0'; } switch_core_session_execute_application(pvt->session, app_var, app_arg); } pvt->skip = 10; } memset(rframe->data, 255, rframe->datalen); if (type == SWITCH_ABC_TYPE_READ_REPLACE) { switch_core_media_bug_set_read_replace_frame(bug, rframe); } else { switch_core_media_bug_set_write_replace_frame(bug, rframe); } if (pvt->skip && !--pvt->skip) { return SWITCH_FALSE; } } break; case SWITCH_ABC_TYPE_WRITE: default: break; } return SWITCH_TRUE; }
void vmivr_menu_navigator(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_event_t *msg_list_params = NULL; size_t msg_count = 0; size_t current_msg = 1; size_t next_msg = current_msg; size_t previous_msg = current_msg; char *cmd = NULL; int retry; /* Different switch to control playback of phrases */ switch_bool_t initial_count_played = SWITCH_FALSE; switch_bool_t skip_header = SWITCH_FALSE; switch_bool_t skip_playback = SWITCH_FALSE; switch_bool_t msg_deleted = SWITCH_FALSE; switch_bool_t msg_undeleted = SWITCH_FALSE; switch_bool_t msg_saved = SWITCH_FALSE; vmivr_menu_t menu = { "std_navigator" }; /* Initialize Menu Configs */ menu_init(profile, &menu); if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name); goto done; } /* Get VoiceMail List And update msg count */ cmd = switch_core_session_sprintf(session, "json %s %s %s %s %s", profile->api_profile, profile->domain, profile->id, profile->folder_name, profile->folder_filter); msg_list_params = jsonapi2event(session, profile->api_msg_list, cmd); if (msg_list_params) { msg_count = atol(switch_event_get_header(msg_list_params,"VM-List-Count")); if (msg_count == 0) { goto done; } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "API message list return invalid result : %s(%s)\n", profile->api_msg_list, cmd); goto done; } /* TODO Add Detection of new message and notify the user */ for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) { switch_core_session_message_t msg = { 0 }; char cid_buf[1024] = ""; menu_instance_init(&menu); switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); previous_msg = current_msg; ivre_init(&menu.ivre_d, menu.dtmfa); /* Prompt related to previous Message here */ append_event_message(session, profile, menu.phrase_params, msg_list_params, previous_msg); if (msg_deleted) { msg_deleted = SWITCH_FALSE; ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "ack"), "deleted", menu.phrase_params, NULL, 0); } if (msg_undeleted) { msg_undeleted = SWITCH_FALSE; ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "ack"), "undeleted", menu.phrase_params, NULL, 0); } if (msg_saved) { msg_saved = SWITCH_FALSE; ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "ack"), "saved", menu.phrase_params, NULL, 0); } switch_event_del_header(menu.phrase_params, "VM-Message-Flags"); /* Simple Protection to not go out of msg list scope */ if (next_msg == 0) { next_msg = 1; } else if (next_msg > msg_count) { next_msg = msg_count; ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "no_more_messages"), NULL, NULL, NULL, 0); } current_msg = next_msg; /* Prompt related the current message */ append_event_message(session, profile, menu.phrase_params, msg_list_params, current_msg); /* Used for extra control in phrases */ switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "VM-List-Count", "%"SWITCH_SIZE_T_FMT, msg_count); /* Display MSG CID/Name to caller */ switch_snprintf(cid_buf, sizeof(cid_buf), "%s|%s", switch_str_nil(switch_event_get_header(menu.phrase_params, "VM-Message-Caller-Number")), switch_str_nil(switch_event_get_header(menu.phrase_params, "VM-Message-Caller-Name"))); msg.from = __FILE__; msg.string_arg = cid_buf; msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY; switch_core_session_receive_message(session, &msg); /* Save in profile the current msg info for other menu processing AND restoration of our current position */ profile->current_msg = current_msg; profile->current_msg_uuid = switch_core_session_strdup(session, switch_event_get_header(menu.phrase_params, "VM-Message-UUID")); /* TODO check if msg is gone (purged by another session, notify user and auto jump to next message or something) */ if (!skip_header) { if (!initial_count_played) { cmd = switch_core_session_sprintf(session, "json %s %s %s", profile->api_profile, profile->domain, profile->id); jsonapi_populate_event(session, menu.phrase_params, profile->api_msg_count, cmd); initial_count_played = SWITCH_TRUE; // TODO ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, menu.phrase_params, NULL, 0); } if (msg_count > 0) { ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "say_msg_number"), NULL, menu.phrase_params, NULL, 0); ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "say_date"), NULL, menu.phrase_params, NULL, 0); } } if (msg_count > 0 && !skip_playback) { /* TODO Update the Read date of a message (When msg start, or when it listen compleatly ??? To be determined */ ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "play_message"), NULL, menu.phrase_params, NULL, 0); } skip_header = SWITCH_FALSE; skip_playback = SWITCH_FALSE; ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout); if (menu.ivre_d.result == RES_TIMEOUT) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_INVALID) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored); /* Reset the try count */ retry = menu.ivr_maximum_attempts; action: if (action) { if (!strcasecmp(action, "skip_intro")) { /* Skip Header / Play the recording again */ skip_header = SWITCH_TRUE; } else if (!strcasecmp(action, "next_msg")) { /* Next Message */ next_msg++; } else if (!strcasecmp(action, "prev_msg")) { /* Previous Message */ next_msg--; } else if (!strcasecmp(action, "delete_msg")) { /* Delete / Undelete Message */ const char *msg_flags = switch_event_get_header(menu.phrase_params, "VM-Message-Flags"); if (!msg_flags || strncasecmp(msg_flags, "delete", 6)) { const char *action_on_delete = switch_event_get_header(menu.event_settings, "Nav-Action-On-Delete"); cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(menu.phrase_params, "VM-Message-UUID")); vmivr_api_execute(session, profile->api_msg_delete, cmd); msg_deleted = SWITCH_TRUE; if (action_on_delete) { action = action_on_delete; goto action; } else { skip_header = skip_playback = SWITCH_TRUE; } } else { cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(menu.phrase_params, "VM-Message-UUID")); vmivr_api_execute(session, profile->api_msg_undelete, cmd); msg_undeleted = SWITCH_TRUE; } } else if (!strcasecmp(action, "save_msg")) { /* Save Message */ cmd = switch_core_session_sprintf(session, "%s %s %s %s", profile->api_profile, profile->domain, profile->id, switch_event_get_header(menu.phrase_params, "VM-Message-UUID")); vmivr_api_execute(session, profile->api_msg_save, cmd); msg_saved = SWITCH_TRUE; } else if (!strcasecmp(action, "callback")) { /* CallBack caller */ const char *cid_num = switch_event_get_header(menu.phrase_params, "VM-Message-Caller-Number"); if (cid_num) { /* TODO add detection for private number */ switch_core_session_execute_exten(session, cid_num, "XML", profile->domain); } else { /* TODO Some error msg that the msg doesn't contain a caller number */ } } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } else if (!strcasecmp(action, "return")) { /* Return */ retry = -1; } } } /* IF the API to get the message returned us a COPY of the file menu.ivre_dally (temp file create from a DB or from a web server), delete it */ if (switch_true(switch_event_get_header(menu.phrase_params, "VM-Message-Private-Local-Copy"))) { const char *file_path = switch_event_get_header(menu.phrase_params, "VM-Message-File-Path"); if (file_path && unlink(file_path) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete temp file [%s]\n", file_path); } } menu_instance_free(&menu); } done: switch_event_destroy(&msg_list_params); menu_free(&menu); return; }
void vmivr_menu_forward(switch_core_session_t *session, vmivr_profile_t *profile) { vmivr_menu_t menu = { "std_forward_ask_prepend" }; switch_channel_t *channel = switch_core_session_get_channel(session); const char *prepend_filepath = NULL; int retry; switch_bool_t forward_msg = SWITCH_FALSE; /* Initialize Menu Configs */ menu_init(profile, &menu); if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name); goto end; } for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) { menu_instance_init(&menu); switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); ivre_init(&menu.ivre_d, menu.dtmfa); ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout); if (menu.ivre_d.result == RES_TIMEOUT) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_INVALID) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored); /* Reset the try count */ retry = menu.ivr_maximum_attempts; if (action) { if (!strcasecmp(action, "return")) { /* Return to the previous menu */ retry = -1; forward_msg = SWITCH_FALSE; } else if (!strcasecmp(action, "prepend")) { /* Prepend record msg */ vmivr_menu_t sub_menu = { "std_record_message" }; const char *tmp_filepath = NULL; const char *record_format = NULL; switch_status_t status; /* Initialize Menu Configs */ menu_init(profile, &sub_menu); record_format = switch_event_get_header(sub_menu.event_settings, "Record-Format"); tmp_filepath = generate_random_file_name(session, "voicemail_ivr", record_format); status = vmivr_menu_record(session, profile, &sub_menu, tmp_filepath); if (status == SWITCH_STATUS_SUCCESS) { //char *cmd = switch_core_session_sprintf(session, "%s %s %s %d %s", profile->api_profile, profile->domain, profile->id, gnum, tmp_filepath); //char *str_num = switch_core_session_sprintf(session, "%d", gnum); //vmivr_api_execute(session, profile->api_pref_greeting_set, cmd); //ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "selected_slot"), str_num, NULL, NULL, 0); prepend_filepath = tmp_filepath; retry = -1; forward_msg = SWITCH_TRUE; } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "record_failed"), NULL, NULL, NULL, 0); } menu_free(&sub_menu); } else if (!strcasecmp(action, "forward")) { /* Forward without prepend msg */ retry = -1; forward_msg = SWITCH_TRUE; } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } } } menu_instance_free(&menu); } /* Ask Extension to Forward */ if (forward_msg) { for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) { const char *id = NULL; vmivr_menu_t sub_menu = { "std_forward_ask_extension" }; /* Initialize Menu Configs */ menu_init(profile, &sub_menu); switch_event_add_header(sub_menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); id = vmivr_menu_get_input_set(session, profile, &sub_menu, "X."); if (id) { const char *cmd = switch_core_session_sprintf(session, "%s %s %s %s %s %s %s%s%s", profile->api_profile, profile->domain, profile->id, profile->current_msg_uuid, profile->domain, id, prepend_filepath?" ":"", prepend_filepath?prepend_filepath:"" ); if (vmivr_api_execute(session, profile->api_msg_forward, cmd) == SWITCH_STATUS_SUCCESS) { ivre_playback_dtmf_buffered(session, switch_event_get_header(sub_menu.event_phrases, "ack"), "saved", NULL, NULL, 0); retry = -1; } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(sub_menu.event_phrases, "invalid_extension"), NULL, NULL, NULL, 0); } } else { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid_input"), NULL, NULL, NULL, 0); } menu_free(&sub_menu); /* TODO add Confirmation of the transfered number */ } /* TODO Ask if we want to transfer the msg to more person */ } end: menu_free(&menu); }
void vmivr_menu_main(switch_core_session_t *session, vmivr_profile_t *profile) { switch_channel_t *channel = switch_core_session_get_channel(session); vmivr_menu_t menu = { "std_main_menu" }; int retry; /* Initialize Menu Configs */ menu_init(profile, &menu); if (!menu.event_keys_dtmf || !menu.event_phrases) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing Menu Phrases or Keys in menu '%s'\n", menu.name); goto end; } for (retry = menu.ivr_maximum_attempts; switch_channel_ready(channel) && retry > 0; retry--) { char *cmd = NULL; menu_instance_init(&menu); switch_event_add_header(menu.phrase_params, SWITCH_STACK_BOTTOM, "IVR-Retry-Left", "%d", retry); ivre_init(&menu.ivre_d, menu.dtmfa); cmd = switch_core_session_sprintf(session, "json %s %s %s %s", profile->api_profile, profile->domain, profile->id, profile->folder_name); jsonapi2event(session, menu.phrase_params, profile->api_msg_count, cmd); //initial_count_played = SWITCH_TRUE; ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "msg_count"), NULL, menu.phrase_params, NULL, 0); ivre_playback(session, &menu.ivre_d, switch_event_get_header(menu.event_phrases, "menu_options"), NULL, menu.phrase_params, NULL, menu.ivr_entry_timeout); if (menu.ivre_d.result == RES_TIMEOUT) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "timeout"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_INVALID) { ivre_playback_dtmf_buffered(session, switch_event_get_header(menu.event_phrases, "invalid"), NULL, NULL, NULL, 0); } else if (menu.ivre_d.result == RES_FOUND) { /* Matching DTMF Key Pressed */ const char *action = switch_event_get_header(menu.event_keys_dtmf, menu.ivre_d.dtmf_stored); /* Reset the try count */ retry = menu.ivr_maximum_attempts; if (action) { if (!strncasecmp(action, "new_msg:", 8)) { void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+8); profile->folder_filter = VM_MSG_NEW; if (fPtr) { fPtr(session, profile); } } else if (!strncasecmp(action, "saved_msg:", 10)) { void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+10); profile->folder_filter = VM_MSG_SAVED; if (fPtr) { fPtr(session, profile); } } else if (!strcasecmp(action, "return")) { /* Return to the previous menu */ retry = -1; } else if (!strncasecmp(action, "menu:", 5)) { /* Sub Menu */ void (*fPtr)(switch_core_session_t *session, vmivr_profile_t *profile) = vmivr_get_menu_function(action+5); if (fPtr) { fPtr(session, profile); } } } } menu_instance_free(&menu); } end: menu_free(&menu); }