Collaboration diagram for IVR Menu Library:
| #define switch_ivr_phrase_macro | ( | session, | |||
| macro_name, | |||||
| data, | |||||
| lang, | |||||
| args | ) | switch_ivr_phrase_macro_event(session, macro_name, data, NULL, lang, args) |
Definition at line 872 of file switch_ivr.h.
Referenced by play_and_collect(), CoreSession::sayPhrase(), switch_ivr_eavesdrop_session(), switch_ivr_phrase_macro_event(), and switch_ivr_play_file().
| typedef switch_ivr_action_t switch_ivr_menu_action_function_t(struct switch_ivr_menu *, char *, char *, size_t, void *) |
Definition at line 754 of file switch_ivr.h.
| typedef struct switch_ivr_menu_action switch_ivr_menu_action_t |
Definition at line 756 of file switch_ivr.h.
| typedef struct switch_ivr_menu switch_ivr_menu_t |
Definition at line 755 of file switch_ivr.h.
| typedef struct switch_ivr_menu_xml_ctx switch_ivr_menu_xml_ctx_t |
Definition at line 840 of file switch_ivr.h.
| enum switch_ivr_action_t |
| SWITCH_IVR_ACTION_DIE | |
| SWITCH_IVR_ACTION_EXECMENU | |
| SWITCH_IVR_ACTION_EXECAPP | |
| SWITCH_IVR_ACTION_PLAYSOUND | |
| SWITCH_IVR_ACTION_BACK | |
| SWITCH_IVR_ACTION_TOMAIN | |
| SWITCH_IVR_ACTION_NOOP |
Definition at line 744 of file switch_ivr.h.
00744 { 00745 SWITCH_IVR_ACTION_DIE, /* Exit the menu. */ 00746 SWITCH_IVR_ACTION_EXECMENU, /* Goto another menu in the stack. */ 00747 SWITCH_IVR_ACTION_EXECAPP, /* Execute an application. */ 00748 SWITCH_IVR_ACTION_PLAYSOUND, /* Play a sound. */ 00749 SWITCH_IVR_ACTION_BACK, /* Go back 1 menu. */ 00750 SWITCH_IVR_ACTION_TOMAIN, /* Go back to the top level menu. */ 00751 SWITCH_IVR_ACTION_NOOP /* No operation */ 00752 } switch_ivr_action_t;
| SWITCH_IVR_MENU_FLAG_FALLTOMAIN | |
| SWITCH_IVR_MENU_FLAG_FREEPOOL | |
| SWITCH_IVR_MENU_FLAG_STACK |
Definition at line 738 of file switch_ivr.h.
00738 { 00739 SWITCH_IVR_MENU_FLAG_FALLTOMAIN = (1 << 0), 00740 SWITCH_IVR_MENU_FLAG_FREEPOOL = (1 << 1), 00741 SWITCH_IVR_MENU_FLAG_STACK = (1 << 2) 00742 } switch_ivr_menu_flags;
| switch_status_t switch_ivr_bind_dtmf_meta_session | ( | switch_core_session_t * | session, | |
| uint32_t | key, | |||
| switch_bind_flag_t | bind_flags, | |||
| const char * | app | |||
| ) |
Definition at line 3272 of file switch_ivr_async.c.
References dtmf_meta_app_t::app, dtmf_meta_app_t::bind_flags, dtmf_meta_app_t::flags, is_dtmf, dtmf_meta_settings_t::map, dtmf_meta_settings_t::meta, meta_on_dtmf(), SBF_DIAL_ALEG, SBF_DIAL_BLEG, SMF_HOLD_BLEG, dtmf_meta_data_t::sr, switch_channel_get_private(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_strdup, SWITCH_DTMF_RECV, SWITCH_DTMF_SEND, switch_dtmftoi(), switch_itodtmf(), SWITCH_LOG_ERROR, SWITCH_LOG_INFO, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_META_VAR_KEY, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, dtmf_meta_settings_t::up, and zstr.
03274 { 03275 switch_channel_t *channel = switch_core_session_get_channel(session); 03276 dtmf_meta_data_t *md = switch_channel_get_private(channel, SWITCH_META_VAR_KEY); 03277 const char *meta_var = switch_channel_get_variable(channel, "bind_meta_key"); 03278 char meta = '*'; 03279 char str[2] = ""; 03280 03281 if (meta_var) { 03282 char t_meta = *meta_var; 03283 if (is_dtmf(t_meta)) { 03284 meta = t_meta; 03285 } else { 03286 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid META KEY %c\n", t_meta); 03287 } 03288 } 03289 03290 if (meta != '*' && meta != '#') { 03291 str[0] = meta; 03292 03293 if (switch_dtmftoi(str) == (char)key) { 03294 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid key %u, same as META CHAR\n", key); 03295 return SWITCH_STATUS_FALSE; 03296 } 03297 } 03298 03299 03300 if (key > 13) { 03301 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid key %u\n", key); 03302 return SWITCH_STATUS_FALSE; 03303 } 03304 03305 if (!md) { 03306 md = switch_core_session_alloc(session, sizeof(*md)); 03307 switch_channel_set_private(channel, SWITCH_META_VAR_KEY, md); 03308 switch_core_event_hook_add_send_dtmf(session, meta_on_dtmf); 03309 switch_core_event_hook_add_recv_dtmf(session, meta_on_dtmf); 03310 } 03311 03312 if (!zstr(app)) { 03313 if ((bind_flags & SBF_DIAL_ALEG)) { 03314 md->sr[SWITCH_DTMF_RECV].meta = meta; 03315 md->sr[SWITCH_DTMF_RECV].up = 1; 03316 md->sr[SWITCH_DTMF_RECV].map[key].app = switch_core_session_strdup(session, app); 03317 md->sr[SWITCH_DTMF_RECV].map[key].flags |= SMF_HOLD_BLEG; 03318 md->sr[SWITCH_DTMF_RECV].map[key].bind_flags = bind_flags; 03319 03320 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Bound A-Leg: %c%c %s\n", meta, switch_itodtmf((char)key), app); 03321 } 03322 if ((bind_flags & SBF_DIAL_BLEG)) { 03323 md->sr[SWITCH_DTMF_SEND].meta = meta; 03324 md->sr[SWITCH_DTMF_SEND].up = 1; 03325 md->sr[SWITCH_DTMF_SEND].map[key].app = switch_core_session_strdup(session, app); 03326 md->sr[SWITCH_DTMF_SEND].map[key].flags |= SMF_HOLD_BLEG; 03327 md->sr[SWITCH_DTMF_SEND].map[key].bind_flags = bind_flags; 03328 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Bound B-Leg: %c%c %s\n", meta, switch_itodtmf((char)key), app); 03329 } 03330 03331 } else { 03332 if ((bind_flags & SBF_DIAL_ALEG)) { 03333 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "UnBound A-Leg: %c%c\n", meta, switch_itodtmf((char)key)); 03334 md->sr[SWITCH_DTMF_SEND].map[key].app = NULL; 03335 } else { 03336 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "UnBound: B-Leg %c%d\n", meta, key); 03337 md->sr[SWITCH_DTMF_SEND].map[key].app = NULL; 03338 } 03339 } 03340 03341 return SWITCH_STATUS_SUCCESS; 03342 }
| switch_status_t switch_ivr_blind_transfer_ack | ( | switch_core_session_t * | session, | |
| switch_bool_t | success | |||
| ) |
Definition at line 3504 of file switch_ivr.c.
References CF_CONFIRM_BLIND_TRANSFER, switch_core_session_message::from, switch_core_session_message::message_id, switch_core_session_message::numeric_arg, switch_channel_clear_flag(), switch_channel_get_variable, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_receive_message, switch_core_session_rwunlock(), SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and zstr.
Referenced by switch_core_standard_on_routing().
03505 { 03506 switch_channel_t *channel = switch_core_session_get_channel(session); 03507 switch_status_t status = SWITCH_STATUS_FALSE; 03508 03509 if (switch_channel_test_flag(channel, CF_CONFIRM_BLIND_TRANSFER)) { 03510 switch_core_session_t *other_session; 03511 const char *uuid = switch_channel_get_variable(channel, "blind_transfer_uuid"); 03512 03513 switch_channel_clear_flag(channel, CF_CONFIRM_BLIND_TRANSFER); 03514 03515 if (!zstr(uuid) && (other_session = switch_core_session_locate(uuid))) { 03516 switch_core_session_message_t msg = { 0 }; 03517 msg.message_id = SWITCH_MESSAGE_INDICATE_BLIND_TRANSFER_RESPONSE; 03518 msg.from = __FILE__; 03519 msg.numeric_arg = success; 03520 switch_core_session_receive_message(other_session, &msg); 03521 switch_core_session_rwunlock(other_session); 03522 status = SWITCH_STATUS_SUCCESS; 03523 } 03524 } 03525 03526 return status; 03527 03528 }
| switch_status_t switch_ivr_block_dtmf_session | ( | switch_core_session_t * | session | ) |
Definition at line 3258 of file switch_ivr_async.c.
References block_on_dtmf(), SWITCH_BLOCK_DTMF_KEY, switch_channel_get_private(), switch_channel_set_private(), switch_core_session_get_channel(), and SWITCH_STATUS_SUCCESS.
03259 { 03260 switch_channel_t *channel = switch_core_session_get_channel(session); 03261 uint8_t enabled = (uint8_t)(intptr_t)switch_channel_get_private(channel, SWITCH_BLOCK_DTMF_KEY); 03262 03263 if (!enabled) { 03264 switch_channel_set_private(channel, SWITCH_BLOCK_DTMF_KEY, (void *)(intptr_t)1); 03265 switch_core_event_hook_add_send_dtmf(session, block_on_dtmf); 03266 switch_core_event_hook_add_recv_dtmf(session, block_on_dtmf); 03267 } 03268 03269 return SWITCH_STATUS_SUCCESS; 03270 }
| char* switch_ivr_check_presence_mapping | ( | const char * | exten_name, | |
| const char * | domain_name | |||
| ) |
Definition at line 3426 of file switch_ivr.c.
References switch_xml::next, switch_assert, SWITCH_CHANNEL_LOG, switch_event_add_header_string(), switch_event_create, switch_event_destroy(), SWITCH_EVENT_REQUEST_PARAMS, SWITCH_LOG_DEBUG1, SWITCH_LOG_ERROR, switch_log_printf(), switch_regex_perform(), switch_regex_safe_free, SWITCH_STACK_BOTTOM, switch_xml_attr(), switch_xml_child(), switch_xml_free(), switch_xml_open_cfg(), and zstr.
03427 { 03428 char *cf = "presence_map.conf"; 03429 switch_xml_t cfg, xml, x_domains, x_domain, x_exten; 03430 char *r = NULL; 03431 switch_event_t *params = NULL; 03432 switch_regex_t *re = NULL; 03433 int proceed = 0, ovector[100]; 03434 03435 switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); 03436 switch_assert(params); 03437 03438 if ( !zstr(domain_name) ) { 03439 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "domain", domain_name); 03440 } 03441 03442 if ( !zstr(exten_name) ) { 03443 switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "exten", exten_name); 03444 } 03445 03446 if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { 03447 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf); 03448 goto end; 03449 } 03450 03451 if (!(x_domains = switch_xml_child(cfg, "domains"))) { 03452 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find any domains!\n"); 03453 goto end; 03454 } 03455 03456 for (x_domain = switch_xml_child(x_domains, "domain"); x_domain; x_domain = x_domain->next) { 03457 const char *dname = switch_xml_attr(x_domain, "name"); 03458 if (!dname || (strcasecmp(dname, "*") && strcasecmp(domain_name, dname))) continue; 03459 03460 for (x_exten = switch_xml_child(x_domain, "exten"); x_exten; x_exten = x_exten->next) { 03461 const char *regex = switch_xml_attr(x_exten, "regex"); 03462 const char *proto = switch_xml_attr(x_exten, "proto"); 03463 03464 if (!zstr(regex) && !zstr(proto)) { 03465 proceed = switch_regex_perform(exten_name, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0])); 03466 switch_regex_safe_free(re); 03467 03468 if (proceed) { 03469 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Mapping %s@%s to proto %s matching expression [%s]\n", 03470 exten_name, domain_name, proto, regex); 03471 r = strdup(proto); 03472 goto end; 03473 } 03474 03475 } 03476 } 03477 } 03478 03479 end: 03480 switch_event_destroy(¶ms); 03481 03482 if (xml) { 03483 switch_xml_free(xml); 03484 } 03485 03486 return r; 03487 03488 }
| switch_status_t switch_ivr_create_message_reply | ( | switch_event_t ** | reply, | |
| switch_event_t * | message, | |||
| const char * | new_proto | |||
| ) |
Definition at line 3413 of file switch_ivr.c.
References switch_event_add_header_string(), switch_event_dup_reply(), SWITCH_STACK_BOTTOM, and SWITCH_STATUS_SUCCESS.
03414 { 03415 switch_status_t status = SWITCH_STATUS_SUCCESS; 03416 03417 if ((status = switch_event_dup_reply(reply, message) != SWITCH_STATUS_SUCCESS)) { 03418 abort(); 03419 } 03420 03421 switch_event_add_header_string(*reply, SWITCH_STACK_BOTTOM, "proto", new_proto); 03422 03423 return status; 03424 }
| void switch_ivr_delay_echo | ( | switch_core_session_t * | session, | |
| uint32_t | delay_ms | |||
| ) |
Definition at line 2737 of file switch_ivr.c.
References switch_frame::buflen, switch_frame::codec, switch_frame::data, switch_frame::datalen, switch_codec_implementation::microseconds_per_packet, switch_frame::payload, switch_codec_implementation::samples_per_packet, switch_codec_implementation::samples_per_second, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_core_session_get_channel(), switch_core_session_get_read_codec(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), switch_core_session_write_frame(), SWITCH_IO_FLAG_NONE, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), and SWITCH_READ_ACCEPTABLE.
02738 { 02739 stfu_instance_t *jb; 02740 int qlen = 0; 02741 stfu_frame_t *jb_frame; 02742 switch_frame_t *read_frame, write_frame = { 0 }; 02743 switch_status_t status; 02744 switch_channel_t *channel = switch_core_session_get_channel(session); 02745 uint32_t interval; 02746 uint32_t ts = 0; 02747 switch_codec_implementation_t read_impl = { 0 }; 02748 switch_core_session_get_read_impl(session, &read_impl); 02749 02750 02751 if (delay_ms < 1 || delay_ms > 10000) { 02752 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid delay [%d] must be between 1 and 10000\n", delay_ms); 02753 return; 02754 } 02755 02756 interval = read_impl.microseconds_per_packet / 1000; 02757 //samples = switch_samples_per_packet(read_impl.samples_per_second, interval); 02758 02759 qlen = delay_ms / (interval) / 2; 02760 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Setting delay to %dms (%d frames)\n", delay_ms, qlen); 02761 jb = stfu_n_init(qlen, qlen, read_impl.samples_per_packet, read_impl.samples_per_second, 0); 02762 02763 write_frame.codec = switch_core_session_get_read_codec(session); 02764 02765 while (switch_channel_ready(channel)) { 02766 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); 02767 if (!SWITCH_READ_ACCEPTABLE(status)) { 02768 break; 02769 } 02770 02771 stfu_n_eat(jb, ts, read_frame->payload, read_frame->data, read_frame->datalen, 0); 02772 ts += read_impl.samples_per_packet; 02773 02774 if ((jb_frame = stfu_n_read_a_frame(jb))) { 02775 write_frame.data = jb_frame->data; 02776 write_frame.datalen = (uint32_t) jb_frame->dlen; 02777 write_frame.buflen = (uint32_t) jb_frame->dlen; 02778 status = switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0); 02779 if (!SWITCH_READ_ACCEPTABLE(status)) { 02780 break; 02781 } 02782 } 02783 } 02784 02785 stfu_n_destroy(&jb); 02786 }
| switch_status_t switch_ivr_dmachine_bind | ( | switch_ivr_dmachine_t * | dmachine, | |
| const char * | realm, | |||
| const char * | digits, | |||
| int32_t | key, | |||
| switch_ivr_dmachine_callback_t | callback, | |||
| void * | user_data | |||
| ) |
Definition at line 228 of file switch_ivr_async.c.
References dm_binding_head_t::binding_list, DMACHINE_MAX_DIGIT_LEN, switch_ivr_dmachine_binding::next, SWITCH_CHANNEL_LOG, switch_core_alloc, switch_core_hash_find(), switch_core_hash_insert(), switch_core_strdup, switch_ivr_dmachine_set_realm(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, dm_binding_head_t::tail, and zstr.
00234 { 00235 switch_ivr_dmachine_binding_t *binding; 00236 switch_size_t len; 00237 dm_binding_head_t *headp; 00238 00239 if (strlen(digits) > DMACHINE_MAX_DIGIT_LEN -1) { 00240 return SWITCH_STATUS_FALSE; 00241 } 00242 00243 if (zstr(realm)) { 00244 realm = "default"; 00245 } 00246 00247 if (!(headp = switch_core_hash_find(dmachine->binding_hash, realm))) { 00248 headp = switch_core_alloc(dmachine->pool, sizeof(*headp)); 00249 switch_core_hash_insert(dmachine->binding_hash, realm, headp); 00250 } 00251 00252 binding = switch_core_alloc(dmachine->pool, sizeof(*binding)); 00253 00254 if (*digits == '~') { 00255 binding->is_regex = 1; 00256 digits++; 00257 } 00258 00259 binding->key = key; 00260 binding->digits = switch_core_strdup(dmachine->pool, digits); 00261 binding->callback = callback; 00262 binding->user_data = user_data; 00263 00264 if (headp->tail) { 00265 headp->tail->next = binding; 00266 } else { 00267 headp->binding_list = binding; 00268 } 00269 00270 headp->tail = binding; 00271 00272 len = strlen(digits); 00273 00274 if (dmachine->realm != headp) { 00275 switch_ivr_dmachine_set_realm(dmachine, realm); 00276 } 00277 00278 if (binding->is_regex && dmachine->max_digit_len != DMACHINE_MAX_DIGIT_LEN -1) { 00279 dmachine->max_digit_len = DMACHINE_MAX_DIGIT_LEN -1; 00280 } else if (len > dmachine->max_digit_len) { 00281 dmachine->max_digit_len = (uint32_t) len; 00282 } 00283 00284 if (binding->is_regex) { 00285 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Digit parser %s: binding %s/%s/%d callback: %p data: %p\n", 00286 dmachine->name, digits, realm, key, (void *)(intptr_t) callback, user_data); 00287 } else { 00288 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Digit parser %s: binding %s/%s/%d callback: %p data: %p\n", 00289 dmachine->name, digits, realm, key, (void *)(intptr_t) callback, user_data); 00290 } 00291 00292 return SWITCH_STATUS_SUCCESS; 00293 }
| switch_status_t switch_ivr_dmachine_clear | ( | switch_ivr_dmachine_t * | dmachine | ) |
Definition at line 555 of file switch_ivr_async.c.
References SWITCH_STATUS_SUCCESS.
Referenced by switch_ivr_dmachine_ping().
00556 { 00557 00558 memset(dmachine->digits, 0, sizeof(dmachine->digits)); 00559 dmachine->cur_digit_len = 0; 00560 dmachine->last_digit_time = 0; 00561 return SWITCH_STATUS_SUCCESS; 00562 }
| switch_status_t switch_ivr_dmachine_clear_realm | ( | switch_ivr_dmachine_t * | dmachine, | |
| const char * | realm | |||
| ) |
Definition at line 204 of file switch_ivr_async.c.
References SWITCH_CHANNEL_LOG, switch_core_hash_delete(), switch_core_hash_find(), SWITCH_LOG_ERROR, SWITCH_LOG_INFO, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and zstr.
00205 { 00206 dm_binding_head_t *headp; 00207 00208 if (zstr(realm)) { 00209 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Digit parser %s: Error unknown realm: '%s'\n", dmachine->name, realm); 00210 return SWITCH_STATUS_FALSE; 00211 } 00212 00213 headp = switch_core_hash_find(dmachine->binding_hash, realm); 00214 00215 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Clearing realm '%s'\n", dmachine->name, realm); 00216 00217 if (headp == dmachine->realm) { 00218 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, 00219 "Digit parser %s: '%s' was the active realm, no realm currently selected.\n", dmachine->name, realm); 00220 dmachine->realm = NULL; 00221 } 00222 00223 /* pool alloc'd just ditch it and it will give back the memory when we destroy ourselves */ 00224 switch_core_hash_delete(dmachine->binding_hash, realm); 00225 return SWITCH_STATUS_SUCCESS; 00226 }
| switch_status_t switch_ivr_dmachine_create | ( | switch_ivr_dmachine_t ** | dmachine_p, | |
| const char * | name, | |||
| switch_memory_pool_t * | pool, | |||
| uint32_t | digit_timeout, | |||
| uint32_t | input_timeout, | |||
| switch_ivr_dmachine_callback_t | match_callback, | |||
| switch_ivr_dmachine_callback_t | nonmatch_callback, | |||
| void * | user_data | |||
| ) |
Definition at line 120 of file switch_ivr_async.c.
References switch_core_alloc, switch_core_hash_init, switch_core_new_memory_pool, switch_core_strdup, switch_mutex_init(), SWITCH_MUTEX_NESTED, and SWITCH_STATUS_SUCCESS.
00128 { 00129 switch_byte_t my_pool = 0; 00130 switch_ivr_dmachine_t *dmachine; 00131 00132 if (!pool) { 00133 switch_core_new_memory_pool(&pool); 00134 my_pool = 1; 00135 } 00136 00137 dmachine = switch_core_alloc(pool, sizeof(*dmachine)); 00138 dmachine->pool = pool; 00139 dmachine->my_pool = my_pool; 00140 dmachine->digit_timeout_ms = digit_timeout_ms; 00141 dmachine->input_timeout_ms = input_timeout_ms; 00142 dmachine->match.dmachine = dmachine; 00143 dmachine->name = switch_core_strdup(dmachine->pool, name); 00144 switch_mutex_init(&dmachine->mutex, SWITCH_MUTEX_NESTED, dmachine->pool); 00145 00146 switch_core_hash_init(&dmachine->binding_hash, dmachine->pool); 00147 00148 if (match_callback) { 00149 dmachine->match_callback = match_callback; 00150 } 00151 00152 if (nonmatch_callback) { 00153 dmachine->nonmatch_callback = nonmatch_callback; 00154 } 00155 00156 dmachine->user_data = user_data; 00157 00158 *dmachine_p = dmachine; 00159 00160 return SWITCH_STATUS_SUCCESS; 00161 }
| void switch_ivr_dmachine_destroy | ( | switch_ivr_dmachine_t ** | dmachine | ) |
Definition at line 174 of file switch_ivr_async.c.
References pool, switch_core_destroy_memory_pool, and switch_core_hash_destroy().
Referenced by switch_core_session_perform_destroy().
00175 { 00176 switch_memory_pool_t *pool; 00177 00178 if (!(dmachine && *dmachine)) return; 00179 00180 pool = (*dmachine)->pool; 00181 00182 switch_core_hash_destroy(&(*dmachine)->binding_hash); 00183 00184 if ((*dmachine)->my_pool) { 00185 switch_core_destroy_memory_pool(&pool); 00186 } 00187 }
| switch_status_t switch_ivr_dmachine_feed | ( | switch_ivr_dmachine_t * | dmachine, | |
| const char * | digits, | |||
| switch_ivr_dmachine_match_t ** | match | |||
| ) |
Definition at line 523 of file switch_ivr_async.c.
References SWITCH_CHANNEL_LOG, switch_ivr_dmachine_ping(), SWITCH_LOG_ERROR, switch_log_printf(), switch_mutex_lock(), switch_mutex_unlock(), SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_time_now(), and zstr.
Referenced by switch_core_session_recv_dtmf(), switch_core_session_send_dtmf(), switch_ivr_collect_digits_callback(), switch_ivr_gentones(), switch_ivr_park(), switch_ivr_play_file(), switch_ivr_record_file(), switch_ivr_sleep(), and switch_ivr_speak_text_handle().
00524 { 00525 const char *p; 00526 switch_status_t status = SWITCH_STATUS_BREAK; 00527 00528 if (!zstr(digits)) { 00529 status = SWITCH_STATUS_SUCCESS; 00530 } 00531 00532 for (p = digits; p && *p; p++) { 00533 switch_mutex_lock(dmachine->mutex); 00534 if (dmachine->cur_digit_len < dmachine->max_digit_len) { 00535 switch_status_t istatus; 00536 char *e = dmachine->digits + strlen(dmachine->digits); 00537 00538 *e++ = *p; 00539 *e = '\0'; 00540 dmachine->cur_digit_len++; 00541 switch_mutex_unlock(dmachine->mutex); 00542 dmachine->last_digit_time = switch_time_now(); 00543 if (status == SWITCH_STATUS_SUCCESS && (istatus = switch_ivr_dmachine_ping(dmachine, match)) != SWITCH_STATUS_SUCCESS) { 00544 status = istatus; 00545 } 00546 } else { 00547 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "dmachine overflow error!\n"); 00548 status = SWITCH_STATUS_FALSE; 00549 } 00550 } 00551 00552 return status; 00553 }
| const char* switch_ivr_dmachine_get_failed_digits | ( | switch_ivr_dmachine_t * | dmachine | ) |
Definition at line 407 of file switch_ivr_async.c.
00408 { 00409 00410 return dmachine->last_failed_digits; 00411 }
| switch_ivr_dmachine_match_t* switch_ivr_dmachine_get_match | ( | switch_ivr_dmachine_t * | dmachine | ) |
Definition at line 397 of file switch_ivr_async.c.
00398 { 00399 if (dmachine->is_match) { 00400 dmachine->is_match = 0; 00401 return &dmachine->match; 00402 } 00403 00404 return NULL; 00405 }
| const char* switch_ivr_dmachine_get_name | ( | switch_ivr_dmachine_t * | dmachine | ) |
Definition at line 115 of file switch_ivr_async.c.
00116 { 00117 return (const char *) dmachine->name; 00118 }
| switch_status_t switch_ivr_dmachine_last_ping | ( | switch_ivr_dmachine_t * | dmachine | ) |
Definition at line 81 of file switch_ivr_async.c.
Referenced by switch_ivr_play_and_detect_speech().
00082 { 00083 return dmachine->last_return; 00084 }
| switch_status_t switch_ivr_dmachine_ping | ( | switch_ivr_dmachine_t * | dmachine, | |
| switch_ivr_dmachine_match_t ** | match_p | |||
| ) |
Definition at line 413 of file switch_ivr_async.c.
References DM_MATCH_BOTH, DM_MATCH_EXACT, DM_MATCH_NEGATIVE, DM_MATCH_NEVER, DM_MATCH_NONE, DM_MATCH_POSITIVE, switch_ivr_dmachine_check_match(), switch_ivr_dmachine_check_timeout(), switch_ivr_dmachine_clear(), switch_mutex_lock(), switch_mutex_unlock(), switch_set_string, SWITCH_STATUS_BREAK, SWITCH_STATUS_CONTINUE, SWITCH_STATUS_FALSE, SWITCH_STATUS_FOUND, SWITCH_STATUS_NOTFOUND, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, and zstr.
Referenced by signal_bridge_on_hibernate(), switch_core_session_read_frame(), switch_ivr_collect_digits_callback(), switch_ivr_dmachine_feed(), switch_ivr_gentones(), switch_ivr_park(), switch_ivr_play_file(), switch_ivr_record_file(), switch_ivr_sleep(), and switch_ivr_speak_text_handle().
00414 { 00415 switch_bool_t is_timeout = switch_ivr_dmachine_check_timeout(dmachine); 00416 dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout); 00417 switch_status_t r, s; 00418 int clear = 0; 00419 00420 if (is_match == DM_MATCH_NEVER) { 00421 is_timeout++; 00422 } 00423 00424 switch_mutex_lock(dmachine->mutex); 00425 00426 if (zstr(dmachine->digits) && !is_timeout) { 00427 r = SWITCH_STATUS_SUCCESS; 00428 } else if (dmachine->cur_digit_len > dmachine->max_digit_len) { 00429 r = SWITCH_STATUS_FALSE; 00430 } else if (is_match == DM_MATCH_EXACT || (is_match == DM_MATCH_BOTH && is_timeout)) { 00431 r = SWITCH_STATUS_FOUND; 00432 00433 dmachine->match.match_digits = dmachine->last_matching_digits; 00434 dmachine->match.match_key = dmachine->last_matching_binding->key; 00435 dmachine->match.user_data = dmachine->last_matching_binding->user_data; 00436 00437 if (match_p) { 00438 *match_p = &dmachine->match; 00439 } 00440 00441 dmachine->is_match = 1; 00442 00443 dmachine->match.type = DM_MATCH_POSITIVE; 00444 00445 if (dmachine->last_matching_binding->callback) { 00446 s = dmachine->last_matching_binding->callback(&dmachine->match); 00447 00448 switch(s) { 00449 case SWITCH_STATUS_CONTINUE: 00450 r = SWITCH_STATUS_SUCCESS; 00451 break; 00452 case SWITCH_STATUS_SUCCESS: 00453 break; 00454 default: 00455 r = SWITCH_STATUS_BREAK; 00456 break; 00457 } 00458 } 00459 00460 if (dmachine->match_callback) { 00461 dmachine->match.user_data = dmachine->user_data; 00462 s = dmachine->match_callback(&dmachine->match); 00463 00464 switch(s) { 00465 case SWITCH_STATUS_CONTINUE: 00466 r = SWITCH_STATUS_SUCCESS; 00467 break; 00468 case SWITCH_STATUS_SUCCESS: 00469 break; 00470 default: 00471 r = SWITCH_STATUS_BREAK; 00472 break; 00473 } 00474 00475 } 00476 00477 clear++; 00478 } else if (is_timeout) { 00479 r = SWITCH_STATUS_TIMEOUT; 00480 } else if (is_match == DM_MATCH_NONE && dmachine->cur_digit_len == dmachine->max_digit_len) { 00481 r = SWITCH_STATUS_NOTFOUND; 00482 } else { 00483 r = SWITCH_STATUS_SUCCESS; 00484 } 00485 00486 if (r != SWITCH_STATUS_FOUND && r != SWITCH_STATUS_SUCCESS && r != SWITCH_STATUS_BREAK) { 00487 switch_set_string(dmachine->last_failed_digits, dmachine->digits); 00488 dmachine->match.match_digits = dmachine->last_failed_digits; 00489 00490 dmachine->match.type = DM_MATCH_NEGATIVE; 00491 00492 if (dmachine->nonmatch_callback) { 00493 dmachine->match.user_data = dmachine->user_data; 00494 s = dmachine->nonmatch_callback(&dmachine->match); 00495 00496 switch(s) { 00497 case SWITCH_STATUS_CONTINUE: 00498 r = SWITCH_STATUS_SUCCESS; 00499 break; 00500 case SWITCH_STATUS_SUCCESS: 00501 break; 00502 default: 00503 r = SWITCH_STATUS_BREAK; 00504 break; 00505 } 00506 00507 } 00508 00509 clear++; 00510 } 00511 00512 if (clear) { 00513 switch_ivr_dmachine_clear(dmachine); 00514 } 00515 00516 dmachine->last_return = r; 00517 00518 switch_mutex_unlock(dmachine->mutex); 00519 00520 return r; 00521 }
| void switch_ivr_dmachine_set_digit_timeout_ms | ( | switch_ivr_dmachine_t * | dmachine, | |
| uint32_t | digit_timeout_ms | |||
| ) |
Definition at line 164 of file switch_ivr_async.c.
00165 { 00166 dmachine->digit_timeout_ms = digit_timeout_ms; 00167 }
| void switch_ivr_dmachine_set_input_timeout_ms | ( | switch_ivr_dmachine_t * | dmachine, | |
| uint32_t | input_timeout_ms | |||
| ) |
Definition at line 169 of file switch_ivr_async.c.
00170 { 00171 dmachine->input_timeout_ms = input_timeout_ms; 00172 }
| void switch_ivr_dmachine_set_match_callback | ( | switch_ivr_dmachine_t * | dmachine, | |
| switch_ivr_dmachine_callback_t | match_callback | |||
| ) |
Definition at line 99 of file switch_ivr_async.c.
References switch_assert.
00100 { 00101 00102 switch_assert(dmachine); 00103 dmachine->match_callback = match_callback; 00104 00105 }
| void switch_ivr_dmachine_set_nonmatch_callback | ( | switch_ivr_dmachine_t * | dmachine, | |
| switch_ivr_dmachine_callback_t | nonmatch_callback | |||
| ) |
Definition at line 107 of file switch_ivr_async.c.
References switch_assert.
00108 { 00109 00110 switch_assert(dmachine); 00111 dmachine->nonmatch_callback = nonmatch_callback; 00112 00113 }
| switch_status_t switch_ivr_dmachine_set_realm | ( | switch_ivr_dmachine_t * | dmachine, | |
| const char * | realm | |||
| ) |
Definition at line 189 of file switch_ivr_async.c.
References SWITCH_CHANNEL_LOG, switch_core_hash_find(), SWITCH_LOG_ERROR, SWITCH_LOG_INFO, switch_log_printf(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.
Referenced by switch_ivr_dmachine_bind().
00190 { 00191 dm_binding_head_t *headp = switch_core_hash_find(dmachine->binding_hash, realm); 00192 00193 if (headp) { 00194 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Digit parser %s: Setting realm to '%s'\n", dmachine->name, realm); 00195 dmachine->realm = headp; 00196 return SWITCH_STATUS_SUCCESS; 00197 } 00198 00199 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Digit parser %s: Error Setting realm to '%s'\n", dmachine->name, realm); 00200 00201 return SWITCH_STATUS_FALSE; 00202 }
| switch_status_t switch_ivr_find_bridged_uuid | ( | const char * | uuid, | |
| char * | b_uuid, | |||
| switch_size_t | blen | |||
| ) |
Definition at line 1695 of file switch_ivr_bridge.c.
References switch_assert, switch_channel_get_variable, switch_copy_string(), switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_rwunlock(), SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.
Referenced by switch_ivr_intercept_session().
01696 { 01697 switch_core_session_t *rsession; 01698 switch_status_t status = SWITCH_STATUS_FALSE; 01699 01700 switch_assert(uuid); 01701 01702 if ((rsession = switch_core_session_locate(uuid))) { 01703 switch_channel_t *rchannel = switch_core_session_get_channel(rsession); 01704 const char *brto; 01705 01706 if ((brto = switch_channel_get_variable(rchannel, "orignate_signal_bond")) || 01707 (brto = switch_channel_get_variable(rchannel, SWITCH_SIGNAL_BOND_VARIABLE))) { 01708 switch_copy_string(b_uuid, brto, blen); 01709 status = SWITCH_STATUS_SUCCESS; 01710 } 01711 switch_core_session_rwunlock(rsession); 01712 } 01713 01714 return status; 01715 01716 }
| switch_status_t switch_ivr_get_file_handle | ( | switch_core_session_t * | session, | |
| switch_file_handle_t ** | fh | |||
| ) |
Definition at line 952 of file switch_ivr_play_say.c.
References switch_channel_get_private(), switch_core_session_get_channel(), switch_core_session_io_read_lock(), switch_core_session_io_rwunlock(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.
00953 { 00954 switch_file_handle_t *fhp; 00955 switch_channel_t *channel = switch_core_session_get_channel(session); 00956 00957 *fh = NULL; 00958 switch_core_session_io_read_lock(session); 00959 00960 if ((fhp = switch_channel_get_private(channel, "__fh"))) { 00961 *fh = fhp; 00962 return SWITCH_STATUS_SUCCESS; 00963 } 00964 00965 switch_core_session_io_rwunlock(session); 00966 00967 return SWITCH_STATUS_FALSE; 00968 }
| switch_say_gender_t switch_ivr_get_say_gender_by_name | ( | const char * | name | ) |
Definition at line 74 of file switch_ivr_say.c.
References SAY_GENDER_NAMES.
Referenced by switch_ivr_phrase_macro_event(), switch_ivr_say(), and switch_ivr_say_string().
00075 { 00076 int x = 0; 00077 00078 if (!name) return (switch_say_gender_t)0; 00079 00080 for (x = 0; SAY_GENDER_NAMES[x]; x++) { 00081 if (!strcasecmp(SAY_GENDER_NAMES[x], name)) { 00082 break; 00083 } 00084 } 00085 00086 return (switch_say_gender_t) x; 00087 }
| switch_say_method_t switch_ivr_get_say_method_by_name | ( | const char * | name | ) |
Definition at line 89 of file switch_ivr_say.c.
References SAY_METHOD_NAMES.
Referenced by switch_ivr_phrase_macro_event(), switch_ivr_say(), and switch_ivr_say_string().
00090 { 00091 int x = 0; 00092 00093 if (!name) return (switch_say_method_t)0; 00094 00095 for (x = 0; SAY_METHOD_NAMES[x]; x++) { 00096 if (!strcasecmp(SAY_METHOD_NAMES[x], name)) { 00097 break; 00098 } 00099 } 00100 00101 return (switch_say_method_t) x; 00102 }
| switch_say_type_t switch_ivr_get_say_type_by_name | ( | const char * | name | ) |
Definition at line 104 of file switch_ivr_say.c.
References SAY_TYPE_NAMES.
Referenced by switch_ivr_phrase_macro_event(), switch_ivr_say(), and switch_ivr_say_string().
00105 { 00106 int x = 0; 00107 00108 if (!name) return (switch_say_type_t)0; 00109 00110 for (x = 0; SAY_TYPE_NAMES[x]; x++) { 00111 if (!strcasecmp(SAY_TYPE_NAMES[x], name)) { 00112 break; 00113 } 00114 } 00115 00116 return (switch_say_type_t) x; 00117 }
| switch_status_t switch_ivr_insert_file | ( | switch_core_session_t * | session, | |
| const char * | file, | |||
| const char * | insert_file, | |||
| switch_size_t | sample_point | |||
| ) |
Definition at line 3259 of file switch_ivr.c.
References switch_codec_implementation::actual_samples_per_second, switch_file_handle::channels, switch_file_handle::native_rate, switch_codec_implementation::number_of_channels, START_SAMPLES, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_core_file_close(), switch_core_file_open, switch_core_file_read(), switch_core_file_seek(), switch_core_file_write(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_sprintf(), SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ, SWITCH_FILE_FLAG_WRITE, SWITCH_FILE_NATIVE, SWITCH_FILE_OPEN, switch_file_rename(), SWITCH_GLOBAL_dirs, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_PATH_SEPARATOR, switch_safe_free, SWITCH_STATUS_SUCCESS, switch_test_flag, switch_uuid_format(), SWITCH_UUID_FORMATTED_LENGTH, switch_uuid_get(), switch_zmalloc, and switch_directories::temp_dir.
Referenced by CoreSession::insertFile().
03260 { 03261 switch_file_handle_t orig_fh = { 0 }; 03262 switch_file_handle_t new_fh = { 0 }; 03263 switch_codec_implementation_t read_impl = { 0 }; 03264 char *tmp_file; 03265 switch_uuid_t uuid; 03266 char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; 03267 int16_t *abuf = NULL; 03268 switch_size_t olen = 0; 03269 int asis = 0; 03270 switch_channel_t *channel = switch_core_session_get_channel(session); 03271 switch_size_t sample_count = 0; 03272 uint32_t pos = 0; 03273 char *ext; 03274 03275 switch_uuid_get(&uuid); 03276 switch_uuid_format(uuid_str, &uuid); 03277 03278 if ((ext = strrchr(file, '.'))) { 03279 ext++; 03280 } else { 03281 ext = "wav"; 03282 } 03283 03284 tmp_file = switch_core_session_sprintf(session, "%s%smsg_%s.%s", 03285 SWITCH_GLOBAL_dirs.temp_dir, SWITCH_PATH_SEPARATOR, uuid_str, ext); 03286 03287 switch_core_session_get_read_impl(session, &read_impl); 03288 03289 new_fh.channels = read_impl.number_of_channels; 03290 new_fh.native_rate = read_impl.actual_samples_per_second; 03291 03292 03293 if (switch_core_file_open(&new_fh, 03294 tmp_file, 03295 new_fh.channels, 03296 read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_WRITE | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { 03297 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", tmp_file); 03298 goto end; 03299 } 03300 03301 03302 if (switch_core_file_open(&orig_fh, 03303 file, 03304 new_fh.channels, 03305 read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { 03306 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); 03307 goto end; 03308 } 03309 03310 03311 switch_zmalloc(abuf, START_SAMPLES * sizeof(*abuf)); 03312 03313 if (switch_test_flag((&orig_fh), SWITCH_FILE_NATIVE)) { 03314 asis = 1; 03315 } 03316 03317 while (switch_channel_ready(channel)) { 03318 olen = START_SAMPLES; 03319 03320 if (!asis) { 03321 olen /= 2; 03322 } 03323 03324 if ((sample_count + olen) > sample_point) { 03325 olen = sample_point - sample_count; 03326 } 03327 03328 if (!olen || switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { 03329 break; 03330 } 03331 03332 sample_count += olen; 03333 03334 switch_core_file_write(&new_fh, abuf, &olen); 03335 } 03336 03337 switch_core_file_close(&orig_fh); 03338 03339 03340 if (switch_core_file_open(&orig_fh, 03341 insert_file, 03342 new_fh.channels, 03343 read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { 03344 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); 03345 goto end; 03346 } 03347 03348 03349 while (switch_channel_ready(channel)) { 03350 olen = START_SAMPLES; 03351 03352 if (!asis) { 03353 olen /= 2; 03354 } 03355 03356 if (switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { 03357 break; 03358 } 03359 03360 sample_count += olen; 03361 03362 switch_core_file_write(&new_fh, abuf, &olen); 03363 } 03364 03365 switch_core_file_close(&orig_fh); 03366 03367 if (switch_core_file_open(&orig_fh, 03368 file, 03369 new_fh.channels, 03370 read_impl.actual_samples_per_second, SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { 03371 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Failed to open file %s\n", file); 03372 goto end; 03373 } 03374 03375 pos = 0; 03376 switch_core_file_seek(&orig_fh, &pos, sample_point, SEEK_SET); 03377 03378 while (switch_channel_ready(channel)) { 03379 olen = START_SAMPLES; 03380 03381 if (!asis) { 03382 olen /= 2; 03383 } 03384 03385 if (switch_core_file_read(&orig_fh, abuf, &olen) != SWITCH_STATUS_SUCCESS || !olen) { 03386 break; 03387 } 03388 03389 sample_count += olen; 03390 03391 switch_core_file_write(&new_fh, abuf, &olen); 03392 } 03393 03394 end: 03395 03396 if (switch_test_flag((&orig_fh), SWITCH_FILE_OPEN)) { 03397 switch_core_file_close(&orig_fh); 03398 } 03399 03400 if (switch_test_flag((&new_fh), SWITCH_FILE_OPEN)) { 03401 switch_core_file_close(&new_fh); 03402 } 03403 03404 switch_file_rename(tmp_file, file, switch_core_session_get_pool(session)); 03405 unlink(tmp_file); 03406 03407 switch_safe_free(abuf); 03408 03409 return SWITCH_STATUS_SUCCESS; 03410 }
| void switch_ivr_intercept_session | ( | switch_core_session_t * | session, | |
| const char * | uuid, | |||
| switch_bool_t | bleg | |||
| ) |
Definition at line 1718 of file switch_ivr_bridge.c.
References CF_ANSWERED, CF_BRIDGED, CF_INTERCEPT, CF_INTERCEPTED, CF_TRANSFER, CS_PARK, SWITCH_CAUSE_PICKED_OFF, switch_channel_answer, switch_channel_get_variable, switch_channel_hangup, switch_channel_mark_hold(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_flag, switch_channel_set_state, switch_channel_set_state_flag(), switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_get_uuid(), switch_core_session_locate(), switch_core_session_rwunlock(), switch_core_session_strdup, SWITCH_FALSE, switch_ivr_find_bridged_uuid(), switch_ivr_uuid_bridge(), SWITCH_LOG_DEBUG, switch_log_printf(), SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_STATUS_SUCCESS, switch_true(), SWITCH_UUID_FORMATTED_LENGTH, and zstr.
01719 { 01720 switch_core_session_t *rsession, *bsession = NULL; 01721 switch_channel_t *channel, *rchannel, *bchannel = NULL; 01722 const char *buuid, *var; 01723 char brto[SWITCH_UUID_FORMATTED_LENGTH + 1] = ""; 01724 01725 if (bleg) { 01726 if (switch_ivr_find_bridged_uuid(uuid, brto, sizeof(brto)) == SWITCH_STATUS_SUCCESS) { 01727 uuid = switch_core_session_strdup(session, brto); 01728 } else { 01729 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "no uuid bridged to %s\n", uuid); 01730 return; 01731 } 01732 } 01733 01734 if (zstr(uuid) || !(rsession = switch_core_session_locate(uuid))) { 01735 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "no uuid %s\n", uuid); 01736 return; 01737 } 01738 01739 channel = switch_core_session_get_channel(session); 01740 rchannel = switch_core_session_get_channel(rsession); 01741 buuid = switch_channel_get_variable(rchannel, SWITCH_SIGNAL_BOND_VARIABLE); 01742 01743 if ((var = switch_channel_get_variable(channel, "intercept_unbridged_only")) && switch_true(var)) { 01744 if ((switch_channel_test_flag(rchannel, CF_BRIDGED))) { 01745 switch_core_session_rwunlock(rsession); 01746 return; 01747 } 01748 } 01749 01750 if ((var = switch_channel_get_variable(channel, "intercept_unanswered_only")) && switch_true(var)) { 01751 if ((switch_channel_test_flag(rchannel, CF_ANSWERED))) { 01752 switch_core_session_rwunlock(rsession); 01753 return; 01754 } 01755 } 01756 01757 switch_channel_answer(channel); 01758 01759 if (!zstr(buuid)) { 01760 if ((bsession = switch_core_session_locate(buuid))) { 01761 bchannel = switch_core_session_get_channel(bsession); 01762 switch_channel_set_flag(bchannel, CF_INTERCEPT); 01763 } 01764 } 01765 01766 if (!switch_channel_test_flag(rchannel, CF_ANSWERED)) { 01767 switch_channel_answer(rchannel); 01768 } 01769 01770 switch_channel_mark_hold(rchannel, SWITCH_FALSE); 01771 01772 switch_channel_set_state_flag(rchannel, CF_TRANSFER); 01773 switch_channel_set_state(rchannel, CS_PARK); 01774 01775 if (bchannel) { 01776 switch_channel_set_state_flag(bchannel, CF_TRANSFER); 01777 switch_channel_set_state(bchannel, CS_PARK); 01778 } 01779 01780 switch_channel_set_flag(rchannel, CF_INTERCEPTED); 01781 switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), uuid); 01782 switch_core_session_rwunlock(rsession); 01783 01784 if (bsession) { 01785 switch_channel_hangup(bchannel, SWITCH_CAUSE_PICKED_OFF); 01786 switch_core_session_rwunlock(bsession); 01787 } 01788 01789 01790 01791 }
| switch_status_t switch_ivr_kill_uuid | ( | const char * | uuid, | |
| switch_call_cause_t | cause | |||
| ) |
Definition at line 3490 of file switch_ivr.c.
References switch_channel_hangup, switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_rwunlock(), SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and zstr.
03491 { 03492 switch_core_session_t *session; 03493 03494 if (zstr(uuid) || !(session = switch_core_session_locate(uuid))) { 03495 return SWITCH_STATUS_FALSE; 03496 } else { 03497 switch_channel_t *channel = switch_core_session_get_channel(session); 03498 switch_channel_hangup(channel, cause); 03499 switch_core_session_rwunlock(session); 03500 return SWITCH_STATUS_SUCCESS; 03501 } 03502 }
| switch_status_t switch_ivr_menu_bind_action | ( | switch_ivr_menu_t * | menu, | |
| switch_ivr_action_t | ivr_action, | |||
| const char * | arg, | |||
| const char * | bind | |||
| ) |
switch_ivr_menu_bind_action: Bind a keystroke to an action.
| menu | The menu obj you wish to bind to. | |
| ivr_action | switch_ivr_action_t enum of what you want to do. | |
| arg | Optional (sometimes necessary) string arguement. | |
| bind | KeyStrokes to bind the action to. |
Definition at line 215 of file switch_ivr_menu.c.
References switch_ivr_menu_action::next, switch_core_alloc, switch_core_strdup, SWITCH_STATUS_MEMERR, and SWITCH_STATUS_SUCCESS.
Referenced by IVRMenu::bindAction(), and switch_ivr_menu_stack_xml_build().
00216 { 00217 switch_ivr_menu_action_t *action, *ap; 00218 uint32_t len; 00219 00220 if ((action = switch_core_alloc(menu->pool, sizeof(*action)))) { 00221 action->bind = switch_core_strdup(menu->pool, bind); 00222 action->arg = switch_core_strdup(menu->pool, arg); 00223 if (*action->bind == '/') { 00224 action->re = 1; 00225 } else { 00226 len = (uint32_t) strlen(action->bind); 00227 if (len > menu->inlen) { 00228 menu->inlen = len; 00229 } 00230 } 00231 action->ivr_action = ivr_action; 00232 00233 if (menu->actions) { 00234 for(ap = menu->actions; ap && ap->next; ap = ap->next); 00235 ap->next = action; 00236 } else { 00237 menu->actions = action; 00238 } 00239 00240 return SWITCH_STATUS_SUCCESS; 00241 } 00242 00243 return SWITCH_STATUS_MEMERR; 00244 }
| switch_status_t switch_ivr_menu_bind_function | ( | switch_ivr_menu_t * | menu, | |
| switch_ivr_menu_action_function_t * | function, | |||
| const char * | arg, | |||
| const char * | bind | |||
| ) |
Bind a keystroke to a callback function.
| menu | The menu obj you wish to bind to. | |
| function | The function to call [int proto(struct switch_ivr_menu *, char *, size_t, void *)] | |
| arg | Optional (sometimes necessary) string arguement. | |
| bind | KeyStrokes to bind the action to. |
The function is also passed an optional void pointer to an object set upon menu execution. (think threads)
The function returns an switch_ivr_action_t enum of what you want to do. and looks to your buffer for args.
Definition at line 246 of file switch_ivr_menu.c.
References switch_ivr_menu_action::next, switch_core_alloc, switch_core_strdup, SWITCH_STATUS_MEMERR, and SWITCH_STATUS_SUCCESS.
Referenced by switch_ivr_menu_stack_xml_build().
00248 { 00249 switch_ivr_menu_action_t *action, *ap; 00250 uint32_t len; 00251 00252 if ((action = switch_core_alloc(menu->pool, sizeof(*action)))) { 00253 action->bind = switch_core_strdup(menu->pool, bind); 00254 action->arg = switch_core_strdup(menu->pool, arg); 00255 00256 if (*action->bind == '/') { 00257 action->re = 1; 00258 } else { 00259 len = (uint32_t) strlen(action->bind); 00260 if (len > menu->inlen) { 00261 menu->inlen = len; 00262 } 00263 } 00264 00265 action->function = function; 00266 00267 if (menu->actions) { 00268 for(ap = menu->actions; ap && ap->next; ap = ap->next); 00269 ap->next = action; 00270 } else { 00271 menu->actions = action; 00272 } 00273 00274 return SWITCH_STATUS_SUCCESS; 00275 } 00276 00277 return SWITCH_STATUS_MEMERR; 00278 }
| switch_status_t switch_ivr_menu_execute | ( | switch_core_session_t * | session, | |
| switch_ivr_menu_t * | stack, | |||
| char * | name, | |||
| void * | obj | |||
| ) |
Execute a menu.
| session | The session running the menu. | |
| stack | The top-level menu object (the first one you created.) | |
| name | A pointer to the name of the menu. | |
| 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. |
Definition at line 400 of file switch_ivr_menu.c.
References actions, switch_ivr_menu_action::arg, switch_ivr_menu_action::bind, buf, switch_ivr_menu_action::function, greeting_sound, inlen, invalid_sound, switch_ivr_menu_action::ivr_action, max_failures, max_timeouts, name, switch_ivr_menu_action::next, play_and_collect(), switch_ivr_menu_action::re, running, short_greeting_sound, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_clear_flag, switch_core_session_exec(), switch_core_session_get_channel(), switch_core_session_strdup, SWITCH_FALSE, switch_goto_status, SWITCH_IVR_ACTION_BACK, SWITCH_IVR_ACTION_DIE, SWITCH_IVR_ACTION_EXECAPP, SWITCH_IVR_ACTION_EXECMENU, SWITCH_IVR_ACTION_NOOP, SWITCH_IVR_ACTION_PLAYSOUND, SWITCH_IVR_ACTION_TOMAIN, switch_ivr_menu_execute(), switch_ivr_menu_find(), SWITCH_IVR_MENU_FLAG_FALLTOMAIN, SWITCH_IVR_MENU_FLAG_STACK, switch_ivr_play_file(), switch_ivr_sleep(), switch_loadable_module_get_application_interface(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, switch_perform_substitution(), switch_regex_perform(), switch_regex_safe_free, switch_set_flag, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_IS_BREAK, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, switch_test_flag, tts_engine, tts_voice, UNPROTECT_INTERFACE, and zstr.
Referenced by IVRMenu::execute(), and switch_ivr_menu_execute().
00401 { 00402 int reps = 0, errs = 0, timeouts = 0, match = 0, running = 1; 00403 char *greeting_sound = NULL, *aptr = NULL; 00404 char arg[512]; 00405 switch_ivr_action_t todo = SWITCH_IVR_ACTION_DIE; 00406 switch_ivr_menu_action_t *ap; 00407 switch_ivr_menu_t *menu; 00408 switch_channel_t *channel; 00409 switch_status_t status = SWITCH_STATUS_SUCCESS; 00410 00411 if (++stack->stack_count > 12) { 00412 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Too many levels of recursion.\n"); 00413 switch_goto_status(SWITCH_STATUS_FALSE, end); 00414 } 00415 00416 if (!session || !stack || zstr(name)) { 00417 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid menu context\n"); 00418 switch_goto_status(SWITCH_STATUS_FALSE, end); 00419 } 00420 00421 channel = switch_core_session_get_channel(session); 00422 00423 if (!(menu = switch_ivr_menu_find(stack, name))) { 00424 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Menu!\n"); 00425 switch_goto_status(SWITCH_STATUS_FALSE, end); 00426 } 00427 00428 if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { 00429 switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); 00430 switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); 00431 } 00432 00433 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Executing IVR menu %s\n", menu->name); 00434 switch_channel_set_variable(channel, "ivr_menu_status", "success"); 00435 00436 for (reps = 0; running && status == SWITCH_STATUS_SUCCESS; reps++) { 00437 if (!switch_channel_ready(channel)) { 00438 break; 00439 } 00440 if (errs == menu->max_failures) { 00441 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum failures\n"); 00442 switch_channel_set_variable(channel, "ivr_menu_status", "failure"); 00443 break; 00444 } 00445 if (timeouts == menu->max_timeouts) { 00446 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Maximum timeouts\n"); 00447 switch_channel_set_variable(channel, "ivr_menu_status", "timeout"); 00448 break; 00449 } 00450 00451 if (reps > 0 && menu->short_greeting_sound) { 00452 greeting_sound = menu->short_greeting_sound; 00453 } else { 00454 greeting_sound = menu->greeting_sound; 00455 } 00456 00457 match = 0; 00458 aptr = NULL; 00459 00460 memset(arg, 0, sizeof(arg)); 00461 00462 memset(menu->buf, 0, menu->inlen + 1); 00463 00464 if (play_and_collect(session, menu, greeting_sound, menu->inlen) == SWITCH_STATUS_TIMEOUT && *menu->buf == '\0') { 00465 timeouts++; 00466 continue; 00467 } 00468 00469 if (*menu->buf != '\0') { 00470 00471 for (ap = menu->actions; ap; ap = ap->next) { 00472 int ok = 0; 00473 char substituted[1024]; 00474 char *use_arg = ap->arg; 00475 00476 if (!zstr(menu->tts_engine) && !zstr(menu->tts_voice)) { 00477 switch_channel_set_variable(channel, "tts_engine", menu->tts_engine); 00478 switch_channel_set_variable(channel, "tts_voice", menu->tts_voice); 00479 } 00480 00481 if (ap->re) { 00482 switch_regex_t *re = NULL; 00483 int ovector[30]; 00484 00485 if ((ok = switch_regex_perform(menu->buf, ap->bind, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { 00486 switch_perform_substitution(re, ok, ap->arg, menu->buf, substituted, sizeof(substituted), ovector); 00487 use_arg = substituted; 00488 } 00489 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "action regex [%s] [%s] [%d]\n", menu->buf, ap->bind, ok); 00490 00491 switch_regex_safe_free(re); 00492 } else { 00493 ok = !strcmp(menu->buf, ap->bind); 00494 } 00495 00496 if (ok) { 00497 match++; 00498 errs = 0; 00499 if (ap->function) { 00500 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 00501 "IVR function on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, use_arg); 00502 todo = ap->function(menu, use_arg, arg, sizeof(arg), obj); 00503 aptr = arg; 00504 } else { 00505 todo = ap->ivr_action; 00506 aptr = use_arg; 00507 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 00508 "IVR action on menu '%s' matched '%s' param '%s'\n", menu->name, menu->buf, aptr); 00509 } 00510 00511 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "switch_ivr_menu_execute todo=[%d]\n", todo); 00512 00513 switch (todo) { 00514 case SWITCH_IVR_ACTION_DIE: 00515 status = SWITCH_STATUS_FALSE; 00516 break; 00517 case SWITCH_IVR_ACTION_PLAYSOUND: 00518 status = switch_ivr_play_file(session, NULL, aptr, NULL); 00519 break; 00520 case SWITCH_IVR_ACTION_EXECMENU: 00521 if (!strcmp(aptr, menu->name)) { 00522 status = SWITCH_STATUS_SUCCESS; 00523 } else { 00524 reps = -1; 00525 status = switch_ivr_menu_execute(session, stack, aptr, obj); 00526 } 00527 break; 00528 case SWITCH_IVR_ACTION_EXECAPP: 00529 { 00530 switch_application_interface_t *application_interface; 00531 char *app_name; 00532 char *app_arg = NULL; 00533 00534 status = SWITCH_STATUS_FALSE; 00535 00536 if (!zstr(aptr)) { 00537 app_name = switch_core_session_strdup(session, aptr); 00538 if ((app_arg = strchr(app_name, ' '))) { 00539 *app_arg++ = '\0'; 00540 } 00541 00542 if ((application_interface = switch_loadable_module_get_application_interface(app_name))) { 00543 switch_core_session_exec(session, application_interface, app_arg); 00544 UNPROTECT_INTERFACE(application_interface); 00545 status = SWITCH_STATUS_SUCCESS; 00546 } 00547 } 00548 } 00549 break; 00550 case SWITCH_IVR_ACTION_BACK: 00551 running = 0; 00552 status = SWITCH_STATUS_SUCCESS; 00553 break; 00554 case SWITCH_IVR_ACTION_TOMAIN: 00555 switch_set_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); 00556 status = SWITCH_STATUS_BREAK; 00557 break; 00558 case SWITCH_IVR_ACTION_NOOP: 00559 status = SWITCH_STATUS_SUCCESS; 00560 break; 00561 default: 00562 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Invalid TODO!\n"); 00563 break; 00564 } 00565 } 00566 } 00567 00568 if (switch_test_flag(menu, SWITCH_IVR_MENU_FLAG_STACK)) { /* top level */ 00569 if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN)) { /* catch the fallback and recover */ 00570 switch_clear_flag(stack, SWITCH_IVR_MENU_FLAG_FALLTOMAIN); 00571 status = SWITCH_STATUS_SUCCESS; 00572 running = 1; 00573 continue; 00574 } 00575 } 00576 } 00577 if (!match) { 00578 if (*menu->buf) { 00579 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' caught invalid input '%s'\n", menu->name, 00580 menu->buf); 00581 if (menu->invalid_sound) { 00582 play_and_collect(session, menu, menu->invalid_sound, 0); 00583 } 00584 } else { 00585 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "IVR menu '%s' no input detected\n", menu->name); 00586 } 00587 errs++; 00588 if (status == SWITCH_STATUS_SUCCESS) { 00589 status = switch_ivr_sleep(session, 1000, SWITCH_FALSE, NULL); 00590 } 00591 /* breaks are ok too */ 00592 if (SWITCH_STATUS_IS_BREAK(status)) { 00593 status = SWITCH_STATUS_SUCCESS; 00594 } 00595 } 00596 } 00597 00598 if (stack->stack_count == 1) { 00599 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "exit-sound '%s'\n", menu->exit_sound); 00600 if (!zstr(menu->exit_sound)) { 00601 status = play_and_collect(session, menu, menu->exit_sound, 0); 00602 } 00603 } 00604 00605 end: 00606 00607 stack->stack_count--; 00608 00609 return status; 00610 }
| switch_status_t switch_ivr_menu_init | ( | switch_ivr_menu_t ** | new_menu, | |
| switch_ivr_menu_t * | main, | |||
| const char * | name, | |||
| const char * | greeting_sound, | |||
| const char * | short_greeting_sound, | |||
| const char * | invalid_sound, | |||
| const char * | exit_sound, | |||
| const char * | confirm_macro, | |||
| const char * | confirm_key, | |||
| const char * | tts_engine, | |||
| const char * | tts_voice, | |||
| int | confirm_attempts, | |||
| int | inter_timeout, | |||
| int | digit_len, | |||
| int | timeout, | |||
| int | max_failures, | |||
| int | max_timeouts, | |||
| switch_memory_pool_t * | pool | |||
| ) |
Create a new menu object.
| new_menu | the pointer to the new menu | |
| main | The top level menu, (NULL if this is the top level one). | |
| name | A pointer to the name of this menu. | |
| greeting_sound | Optional pointer to a main sound (press 1 for this 2 for that). | |
| short_greeting_sound | Optional pointer to a shorter main sound for subsequent loops. | |
| invalid_sound | Optional pointer to a sound to play after invalid input. | |
| exit_sound | Optional pointer to a sound to play upon exiting the menu. | |
| confirm_macro | phrase macro name to confirm input | |
| confirm_key | the dtmf key required for positive confirmation | |
| tts_engine | the tts engine to use for this menu | |
| tts_voice | the tts voice to use for this menu | |
| confirm_attempts | number of times to prompt to confirm input before failure | |
| inter_timeout | inter-digit timeout | |
| digit_len | max number of digits | |
| timeout | A number of milliseconds to pause before looping. | |
| max_failures | Maximum number of failures to withstand before hangingup This resets everytime you enter the menu. | |
| pool | memory pool (NULL to create one). |
Definition at line 96 of file switch_ivr_menu.c.
References SWITCH_CHANNEL_LOG, switch_core_alloc, switch_core_destroy_memory_pool, switch_core_new_memory_pool, switch_core_strdup, SWITCH_IVR_MENU_FLAG_FREEPOOL, SWITCH_IVR_MENU_FLAG_STACK, switch_ivr_menu_stack_add(), SWITCH_LOG_CRIT, switch_log_printf(), switch_set_flag, SWITCH_STATUS_MEMERR, SWITCH_STATUS_SUCCESS, and zstr.
Referenced by IVRMenu::IVRMenu(), and switch_ivr_menu_stack_xml_build().
00110 { 00111 switch_ivr_menu_t *menu; 00112 uint8_t newpool = 0; 00113 00114 if (!pool) { 00115 if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { 00116 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "OH OH no pool\n"); 00117 return SWITCH_STATUS_MEMERR; 00118 } 00119 newpool = 1; 00120 } 00121 00122 if (!(menu = switch_core_alloc(pool, sizeof(*menu)))) { 00123 if (newpool) { 00124 switch_core_destroy_memory_pool(&pool); 00125 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); 00126 return SWITCH_STATUS_MEMERR; 00127 } 00128 } 00129 00130 menu->pool = pool; 00131 00132 if (!confirm_attempts) { 00133 confirm_attempts = 3; 00134 } 00135 00136 if (!inter_timeout) { 00137 inter_timeout = timeout / 2; 00138 } 00139 00140 if (!zstr(name)) { 00141 menu->name = switch_core_strdup(menu->pool, name); 00142 } 00143 00144 if (!zstr(greeting_sound)) { 00145 menu->greeting_sound = switch_core_strdup(menu->pool, greeting_sound); 00146 } 00147 00148 if (!zstr(short_greeting_sound)) { 00149 menu->short_greeting_sound = switch_core_strdup(menu->pool, short_greeting_sound); 00150 } 00151 00152 if (!zstr(invalid_sound)) { 00153 menu->invalid_sound = switch_core_strdup(menu->pool, invalid_sound); 00154 } 00155 00156 if (!zstr(exit_sound)) { 00157 menu->exit_sound = switch_core_strdup(menu->pool, exit_sound); 00158 } 00159 00160 if (!zstr(confirm_macro)) { 00161 menu->confirm_macro = switch_core_strdup(menu->pool, confirm_macro); 00162 } 00163 00164 if (!zstr(tts_engine)) { 00165 menu->tts_engine = switch_core_strdup(menu->pool, tts_engine); 00166 } 00167 00168 if (!zstr(tts_voice)) { 00169 menu->tts_voice = switch_core_strdup(menu->pool, tts_voice); 00170 } 00171 00172 menu->confirm_attempts = confirm_attempts; 00173 00174 menu->inlen = digit_len; 00175 00176 if (max_failures > 0) { 00177 menu->max_failures = max_failures; 00178 } else { 00179 menu->max_failures = 3; 00180 } 00181 00182 if (max_timeouts > 0) { 00183 menu->max_timeouts = max_timeouts; 00184 } else { 00185 menu->max_timeouts = 3; 00186 } 00187 00188 menu->timeout = timeout; 00189 00190 menu->inter_timeout = inter_timeout; 00191 00192 menu->actions = NULL; 00193 00194 if (newpool) { 00195 switch_set_flag(menu, SWITCH_IVR_MENU_FLAG_FREEPOOL); 00196 } 00197 00198 if (menu->timeout <= 0) { 00199 menu->timeout = 10000; 00200 } 00201 00202 if (main) { 00203 switch_ivr_menu_stack_add(&main, menu); 00204 } else { 00205 switch_set_flag(menu, SWITCH_IVR_MENU_FLAG_STACK); 00206 } 00207 00208 menu->buf = switch_core_alloc(menu->pool, 1024); 00209 00210 *new_menu = menu; 00211 00212 return SWITCH_STATUS_SUCCESS; 00213 }
| switch_status_t switch_ivr_menu_stack_free | ( | switch_ivr_menu_t * | stack | ) |
free a stack of menu objects.
| stack | The top level menu you wish to destroy. |
Definition at line 280 of file switch_ivr_menu.c.
References pool, switch_core_destroy_memory_pool, SWITCH_IVR_MENU_FLAG_FREEPOOL, SWITCH_IVR_MENU_FLAG_STACK, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_test_flag.
Referenced by IVRMenu::~IVRMenu().
00281 { 00282 switch_status_t status = SWITCH_STATUS_FALSE; 00283 00284 if (stack != NULL && stack->pool != NULL) { 00285 if (switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_STACK) 00286 && switch_test_flag(stack, SWITCH_IVR_MENU_FLAG_FREEPOOL)) { 00287 switch_memory_pool_t *pool = stack->pool; 00288 status = switch_core_destroy_memory_pool(&pool); 00289 } else { 00290 status = SWITCH_STATUS_SUCCESS; 00291 } 00292 } 00293 00294 return status; 00295 }
| switch_status_t switch_ivr_menu_stack_xml_add_custom | ( | switch_ivr_menu_xml_ctx_t * | xml_menu_ctx, | |
| const char * | name, | |||
| switch_ivr_menu_action_function_t * | function | |||
| ) |
| xml_menu_ctx | The XML menu parser context previously created by switch_ivr_menu_stack_xml_init | |
| name | The xml tag name to add to the parser engine | |
| function | The menu function callback that will be executed when menu digits are bound to this name |
Definition at line 762 of file switch_ivr_menu.c.
References switch_ivr_menu_stack_xml_add().
00764 { 00765 return switch_ivr_menu_stack_xml_add(xml_menu_ctx, name, -1, function); 00766 }
| switch_status_t switch_ivr_menu_stack_xml_build | ( | switch_ivr_menu_xml_ctx_t * | xml_menu_ctx, | |
| switch_ivr_menu_t ** | menu_stack, | |||
| switch_xml_t | xml_menus, | |||
| switch_xml_t | xml_menu | |||
| ) |
Build a menu stack from an xml source.
| xml_menu_ctx | The XML menu parser context previously created by switch_ivr_menu_stack_xml_init | |
| menu_stack | The menu stack object that will be created for you | |
| xml_menus | The xml Menus source | |
| xml_menu | The xml Menu source of the menu to be created |
Definition at line 768 of file switch_ivr_menu.c.
References switch_ivr_menu_xml_map::action, switch_ivr_menu_xml_map::function, is_valid_action(), switch_ivr_menu_xml_map::name, switch_xml::next, switch_ivr_menu_xml_map::next, pool, SWITCH_CHANNEL_LOG, SWITCH_IVR_ACTION_EXECMENU, switch_ivr_menu_bind_action(), switch_ivr_menu_bind_function(), switch_ivr_menu_find(), SWITCH_IVR_MENU_FLAG_FREEPOOL, switch_ivr_menu_init(), switch_ivr_menu_stack_xml_build(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_set_flag, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_xml_attr(), switch_xml_attr_soft(), switch_xml_child(), switch_xml_find_child(), and zstr.
Referenced by switch_ivr_menu_stack_xml_build().
00770 { 00771 switch_status_t status = SWITCH_STATUS_FALSE; 00772 00773 if (xml_menu_ctx != NULL && menu_stack != NULL && xml_menu != NULL) { 00774 const char *menu_name = switch_xml_attr_soft(xml_menu, "name"); /* if the attr doesn't exist, return "" */ 00775 const char *greet_long = switch_xml_attr(xml_menu, "greet-long"); /* if the attr doesn't exist, return NULL */ 00776 const char *greet_short = switch_xml_attr(xml_menu, "greet-short"); /* if the attr doesn't exist, return NULL */ 00777 const char *invalid_sound = switch_xml_attr(xml_menu, "invalid-sound"); /* if the attr doesn't exist, return NULL */ 00778 const char *exit_sound = switch_xml_attr(xml_menu, "exit-sound"); /* if the attr doesn't exist, return NULL */ 00779 const char *timeout = switch_xml_attr_soft(xml_menu, "timeout"); /* if the attr doesn't exist, return "" */ 00780 const char *max_failures = switch_xml_attr_soft(xml_menu, "max-failures"); /* if the attr doesn't exist, return "" */ 00781 const char *max_timeouts = switch_xml_attr_soft(xml_menu, "max-timeouts"); 00782 const char *confirm_macro = switch_xml_attr(xml_menu, "confirm-macro"); 00783 const char *confirm_key = switch_xml_attr(xml_menu, "confirm-key"); 00784 const char *tts_engine = switch_xml_attr(xml_menu, "tts-engine"); 00785 const char *tts_voice = switch_xml_attr(xml_menu, "tts-voice"); 00786 const char *confirm_attempts = switch_xml_attr_soft(xml_menu, "confirm-attempts"); 00787 const char *digit_len = switch_xml_attr_soft(xml_menu, "digit-len"); 00788 const char *inter_timeout = switch_xml_attr_soft(xml_menu, "inter-digit-timeout"); 00789 00790 switch_ivr_menu_t *menu = NULL; 00791 00792 if (zstr(max_timeouts)) { 00793 max_timeouts = max_failures; 00794 } 00795 00796 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "building menu '%s'\n", menu_name); 00797 00798 status = switch_ivr_menu_init(&menu, 00799 *menu_stack, 00800 menu_name, 00801 greet_long, 00802 greet_short, 00803 invalid_sound, 00804 exit_sound, 00805 confirm_macro, 00806 confirm_key, 00807 tts_engine, 00808 tts_voice, 00809 atoi(confirm_attempts), 00810 atoi(inter_timeout), 00811 atoi(digit_len), 00812 atoi(timeout), 00813 strlen(max_failures) ? atoi(max_failures) : 0, strlen(max_timeouts) ? atoi(max_timeouts) : 0, xml_menu_ctx->pool); 00814 /* set the menu_stack for the caller */ 00815 if (status == SWITCH_STATUS_SUCCESS && *menu_stack == NULL) { 00816 *menu_stack = menu; 00817 00818 if (xml_menu_ctx->autocreated) { 00819 switch_set_flag(menu, SWITCH_IVR_MENU_FLAG_FREEPOOL); 00820 } 00821 } 00822 00823 if (status == SWITCH_STATUS_SUCCESS && menu != NULL) { 00824 switch_xml_t xml_kvp; 00825 00826 /* build menu entries */ 00827 for (xml_kvp = switch_xml_child(xml_menu, "entry"); xml_kvp != NULL && status == SWITCH_STATUS_SUCCESS; xml_kvp = xml_kvp->next) { 00828 const char *action = switch_xml_attr(xml_kvp, "action"); 00829 const char *digits = switch_xml_attr(xml_kvp, "digits"); 00830 const char *param = switch_xml_attr_soft(xml_kvp, "param"); 00831 00832 if (is_valid_action(action) && !zstr(digits)) { 00833 switch_ivr_menu_xml_map_t *xml_map = xml_menu_ctx->map; 00834 int found = 0; 00835 00836 /* find and appropriate xml handler */ 00837 while (xml_map != NULL && !found) { 00838 if (!(found = (strcasecmp(xml_map->name, action) == 0))) { 00839 xml_map = xml_map->next; 00840 } 00841 } 00842 00843 if (found && xml_map != NULL) { 00844 /* do we need to build a new sub-menu ? */ 00845 if (xml_map->action == SWITCH_IVR_ACTION_EXECMENU && switch_ivr_menu_find(*menu_stack, param) == NULL) { 00846 if ((xml_menu = switch_xml_find_child(xml_menus, "menu", "name", param)) != NULL) { 00847 status = switch_ivr_menu_stack_xml_build(xml_menu_ctx, menu_stack, xml_menus, xml_menu); 00848 } 00849 } 00850 /* finally bind the menu entry */ 00851 if (status == SWITCH_STATUS_SUCCESS) { 00852 if (xml_map->function != NULL) { 00853 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, 00854 "binding menu caller control '%s'/'%s' to '%s'\n", xml_map->name, param, digits); 00855 status = switch_ivr_menu_bind_function(menu, xml_map->function, param, digits); 00856 } else { 00857 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "binding menu action '%s' to '%s'\n", xml_map->name, digits); 00858 status = switch_ivr_menu_bind_action(menu, xml_map->action, param, digits); 00859 } 00860 } 00861 } 00862 } else { 00863 status = SWITCH_STATUS_FALSE; 00864 } 00865 } 00866 } 00867 } 00868 00869 if (status != SWITCH_STATUS_SUCCESS) { 00870 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to build xml menu\n"); 00871 } 00872 00873 return status; 00874 }
| switch_status_t switch_ivr_menu_stack_xml_init | ( | switch_ivr_menu_xml_ctx_t ** | xml_menu_ctx, | |
| switch_memory_pool_t * | pool | |||
| ) |
| xml_menu_ctx | A pointer of a XML menu parser context to be created | |
| pool | memory pool (NULL to create one) |
Definition at line 727 of file switch_ivr_menu.c.
References iam, iam_s::name, SWITCH_CHANNEL_LOG, switch_core_alloc, switch_core_new_memory_pool, switch_ivr_menu_stack_xml_add(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.
00728 { 00729 switch_status_t status = SWITCH_STATUS_FALSE; 00730 int autocreated = 0; 00731 00732 /* build a memory pool ? */ 00733 if (pool == NULL) { 00734 status = switch_core_new_memory_pool(&pool); 00735 autocreated = 1; 00736 } 00737 /* allocate the xml context */ 00738 if (xml_menu_ctx != NULL && pool != NULL) { 00739 *xml_menu_ctx = switch_core_alloc(pool, sizeof(switch_ivr_menu_xml_ctx_t)); 00740 if (*xml_menu_ctx != NULL) { 00741 (*xml_menu_ctx)->pool = pool; 00742 (*xml_menu_ctx)->autocreated = autocreated; 00743 (*xml_menu_ctx)->map = NULL; 00744 status = SWITCH_STATUS_SUCCESS; 00745 } else { 00746 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to alloc xml_ctx\n"); 00747 status = SWITCH_STATUS_FALSE; 00748 } 00749 } 00750 /* build the standard/default xml menu handler mappings */ 00751 if (status == SWITCH_STATUS_SUCCESS && xml_menu_ctx != NULL && *xml_menu_ctx != NULL) { 00752 int i; 00753 00754 for (i = 0; iam[i].name && status == SWITCH_STATUS_SUCCESS; i++) { 00755 status = switch_ivr_menu_stack_xml_add(*xml_menu_ctx, iam[i].name, iam[i].action, NULL); 00756 } 00757 } 00758 00759 return status; 00760 }
| switch_status_t switch_ivr_menu_str2action | ( | const char * | action_name, | |
| switch_ivr_action_t * | action | |||
| ) |
Definition at line 687 of file switch_ivr_menu.c.
References iam, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and zstr.
Referenced by IVRMenu::bindAction().
00688 { 00689 int i; 00690 00691 if (!zstr(action_name)) { 00692 for (i = 0;; i++) { 00693 if (!iam[i].name) { 00694 break; 00695 } 00696 00697 if (!strcasecmp(iam[i].name, action_name)) { 00698 *action = iam[i].action; 00699 return SWITCH_STATUS_SUCCESS; 00700 } 00701 } 00702 } 00703 00704 return SWITCH_STATUS_FALSE; 00705 }
| void switch_ivr_park_session | ( | switch_core_session_t * | session | ) |
Definition at line 2729 of file switch_ivr.c.
References CF_TRANSFER, CS_PARK, switch_channel_set_flag, switch_channel_set_state, and switch_core_session_get_channel().
Referenced by audio_bridge_on_exchange_media(), signal_bridge_on_hangup(), and switch_ivr_multi_threaded_bridge().
02730 { 02731 switch_channel_t *channel = switch_core_session_get_channel(session); 02732 switch_channel_set_state(channel, CS_PARK); 02733 switch_channel_set_flag(channel, CF_TRANSFER); 02734 02735 }
| switch_status_t switch_ivr_phrase_macro_event | ( | switch_core_session_t * | session, | |
| const char * | macro_name, | |||
| const char * | data, | |||
| switch_event_t * | event, | |||
| const char * | lang, | |||
| switch_input_args_t * | args | |||
| ) |
Definition at line 39 of file switch_ivr_play_say.c.
References switch_say_args_t::gender, switch_say_args_t::method, switch_say_interface::say_function, switch_assert, switch_channel_event_set_data(), switch_channel_expand_variables, switch_channel_get_variable, switch_channel_pre_answer, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_exec(), switch_core_session_get_channel(), switch_core_session_strdup, switch_event_add_header_string(), switch_event_create, switch_event_destroy(), switch_event_expand_headers, SWITCH_EVENT_REQUEST_PARAMS, SWITCH_FALSE, switch_ivr_get_say_gender_by_name(), switch_ivr_get_say_method_by_name(), switch_ivr_get_say_type_by_name(), switch_ivr_phrase_macro, switch_ivr_play_file(), switch_ivr_sleep(), switch_ivr_speak_text(), switch_loadable_module_get_application_interface(), switch_loadable_module_get_say_interface(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, switch_perform_substitution(), switch_regex_perform(), switch_regex_safe_free, switch_safe_free, switch_separate_paren_args(), SWITCH_STACK_BOTTOM, SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_GENERR, SWITCH_STATUS_SUCCESS, switch_str_nil, switch_true(), SWITCH_TRUE, switch_xml_attr(), switch_xml_attr_soft(), switch_xml_child(), switch_xml_find_child(), switch_xml_free(), switch_xml_locate_language(), switch_say_args_t::type, UNPROTECT_INTERFACE, and zstr.
00041 { 00042 switch_event_t *hint_data; 00043 switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL, macro, input, action; 00044 switch_status_t status = SWITCH_STATUS_GENERR; 00045 const char *old_sound_prefix = NULL, *sound_path = NULL, *tts_engine = NULL, *tts_voice = NULL; 00046 const char *module_name = NULL, *chan_lang = NULL; 00047 switch_channel_t *channel = switch_core_session_get_channel(session); 00048 uint8_t done = 0; 00049 int matches = 0; 00050 const char *pause_val; 00051 int pause = 100; 00052 const char *group_macro_name = NULL; 00053 const char *local_macro_name = macro_name; 00054 switch_bool_t sound_prefix_enforced = switch_true(switch_channel_get_variable(channel, "sound_prefix_enforced")); 00055 switch_bool_t local_sound_prefix_enforced = SWITCH_FALSE; 00056 00057 if (!macro_name) { 00058 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No phrase macro specified.\n"); 00059 return status; 00060 } 00061 00062 if (!lang) { 00063 chan_lang = switch_channel_get_variable(channel, "default_language"); 00064 if (!chan_lang) { 00065 chan_lang = "en"; 00066 } 00067 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang); 00068 } else { 00069 chan_lang = lang; 00070 } 00071 00072 switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS); 00073 switch_assert(hint_data); 00074 00075 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", macro_name); 00076 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang); 00077 if (data) { 00078 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "data", data); 00079 if (event) { 00080 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "data", data); 00081 } 00082 } else { 00083 data = ""; 00084 } 00085 switch_channel_event_set_data(channel, hint_data); 00086 00087 if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, ¯os, chan_lang) != SWITCH_STATUS_SUCCESS) { 00088 goto done; 00089 } 00090 00091 if ((module_name = switch_xml_attr(language, "say-module"))) { 00092 } else if ((module_name = switch_xml_attr(language, "module"))) { 00093 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute. Use say-module instead\n"); 00094 } else { 00095 module_name = chan_lang; 00096 } 00097 00098 if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) { 00099 if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) { 00100 sound_path = (char *) switch_xml_attr(language, "sound_path"); 00101 } 00102 } 00103 00104 if (!(tts_engine = (char *) switch_xml_attr(language, "tts-engine"))) { 00105 tts_engine = (char *) switch_xml_attr(language, "tts_engine"); 00106 } 00107 00108 if (!(tts_voice = (char *) switch_xml_attr(language, "tts-voice"))) { 00109 tts_voice = (char *) switch_xml_attr(language, "tts_voice"); 00110 } 00111 00112 /* If we use the new structure, check for a group name */ 00113 if (language != macros) { 00114 char *p; 00115 char *macro_name_dup = switch_core_session_strdup(session, macro_name); 00116 const char *group_sound_path; 00117 const char *sound_prefix_enforced_str; 00118 00119 if ((p = strchr(macro_name_dup, '@'))) { 00120 *p++ = '\0'; 00121 local_macro_name = macro_name_dup; 00122 group_macro_name = p; 00123 00124 if (!(macros = switch_xml_find_child(phrases, "macros", "name", group_macro_name))) { 00125 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macros group %s.\n", group_macro_name); 00126 goto done; 00127 } 00128 } 00129 /* Support override of certain language attribute */ 00130 if ((group_sound_path = (char *) switch_xml_attr(macros, "sound-prefix")) || (group_sound_path = (char *) switch_xml_attr(macros, "sound-path")) || (group_sound_path = (char *) switch_xml_attr(macros, "sound_path"))) { 00131 sound_path = group_sound_path; 00132 } 00133 00134 if (sound_prefix_enforced == SWITCH_FALSE && (sound_prefix_enforced_str = switch_xml_attr(macros, "sound-prefix-enforced")) 00135 && (local_sound_prefix_enforced = switch_true(sound_prefix_enforced_str)) == SWITCH_TRUE) { 00136 switch_channel_set_variable(channel, "sound_prefix_enforced", sound_prefix_enforced_str); 00137 } 00138 00139 } 00140 00141 if (!(macro = switch_xml_find_child(macros, "macro", "name", local_macro_name))) { 00142 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find macro %s.\n", macro_name); 00143 goto done; 00144 } 00145 00146 if (sound_path && sound_prefix_enforced == SWITCH_FALSE) { 00147 char *p; 00148 old_sound_prefix = switch_str_nil(switch_channel_get_variable(channel, "sound_prefix")); 00149 p = switch_core_session_strdup(session, old_sound_prefix); 00150 old_sound_prefix = p; 00151 switch_channel_set_variable(channel, "sound_prefix", sound_path); 00152 } 00153 00154 if ((pause_val = switch_xml_attr(macro, "pause"))) { 00155 int tmp = atoi(pause_val); 00156 if (tmp >= 0) { 00157 pause = tmp; 00158 } 00159 } 00160 00161 if (!(input = switch_xml_child(macro, "input"))) { 00162 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Can't find any input tags.\n"); 00163 goto done; 00164 } 00165 00166 if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { 00167 status = SWITCH_STATUS_FALSE; 00168 goto done; 00169 } 00170 00171 while (input && !done) { 00172 char *field = (char *) switch_xml_attr(input, "field"); 00173 char *pattern = (char *) switch_xml_attr(input, "pattern"); 00174 const char *do_break = switch_xml_attr_soft(input, "break_on_match"); 00175 char *field_expanded = NULL; 00176 char *field_expanded_alloc = NULL; 00177 00178 if (!field) { 00179 field = (char *) data; 00180 } 00181 if (event) { 00182 field_expanded_alloc = switch_event_expand_headers(event, field); 00183 } else { 00184 field_expanded_alloc = switch_channel_expand_variables(channel, field); 00185 } 00186 00187 if (field_expanded_alloc == field) { 00188 field_expanded_alloc = NULL; 00189 field_expanded = field; 00190 } else { 00191 field_expanded = field_expanded_alloc; 00192 } 00193 00194 if (pattern) { 00195 switch_regex_t *re = NULL; 00196 int proceed = 0, ovector[100]; 00197 char *substituted = NULL; 00198 uint32_t len = 0; 00199 char *odata = NULL; 00200 char *expanded = NULL; 00201 switch_xml_t match = NULL; 00202 00203 status = SWITCH_STATUS_SUCCESS; 00204 00205 if ((proceed = switch_regex_perform(field_expanded, pattern, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { 00206 match = switch_xml_child(input, "match"); 00207 } else { 00208 match = switch_xml_child(input, "nomatch"); 00209 } 00210 00211 if (match) { 00212 matches++; 00213 for (action = switch_xml_child(match, "action"); action && status == SWITCH_STATUS_SUCCESS; action = action->next) { 00214 char *adata = (char *) switch_xml_attr_soft(action, "data"); 00215 char *func = (char *) switch_xml_attr_soft(action, "function"); 00216 00217 if (strchr(pattern, '(') && strchr(adata, '$') && proceed > 0) { 00218 len = (uint32_t) (strlen(data) + strlen(adata) + 10) * proceed; 00219 if (!(substituted = malloc(len))) { 00220 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error!\n"); 00221 switch_regex_safe_free(re); 00222 switch_safe_free(expanded); 00223 goto done; 00224 } 00225 memset(substituted, 0, len); 00226 switch_perform_substitution(re, proceed, adata, field_expanded, substituted, len, ovector); 00227 odata = substituted; 00228 } else { 00229 odata = adata; 00230 } 00231 00232 if (event) { 00233 expanded = switch_event_expand_headers(event, odata); 00234 } else { 00235 expanded = switch_channel_expand_variables(channel, odata); 00236 } 00237 00238 if (expanded == odata) { 00239 expanded = NULL; 00240 } else { 00241 odata = expanded; 00242 } 00243 00244 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Handle %s:[%s] (%s:%s)\n", func, odata, chan_lang, 00245 module_name); 00246 00247 if (!strcasecmp(func, "play-file")) { 00248 status = switch_ivr_play_file(session, NULL, odata, args); 00249 } else if (!strcasecmp(func, "phrase")) { 00250 char *name = (char *) switch_xml_attr_soft(action, "phrase"); 00251 status = switch_ivr_phrase_macro(session, name, odata, chan_lang, args); 00252 } else if (!strcasecmp(func, "break")) { 00253 done = 1; 00254 /* must allow the switch_safe_free below to execute or we leak - do not break here */ 00255 } else if (!strcasecmp(func, "execute")) { 00256 switch_application_interface_t *app; 00257 char *cmd, *cmd_args; 00258 status = SWITCH_STATUS_FALSE; 00259 00260 cmd = switch_core_session_strdup(session, odata); 00261 cmd_args = switch_separate_paren_args(cmd); 00262 00263 if (!cmd_args) { 00264 cmd_args = ""; 00265 } 00266 00267 if ((app = switch_loadable_module_get_application_interface(cmd)) != NULL) { 00268 status = switch_core_session_exec(session, app, cmd_args); 00269 UNPROTECT_INTERFACE(app); 00270 } else { 00271 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid Application %s\n", cmd); 00272 } 00273 } else if (!strcasecmp(func, "say")) { 00274 switch_say_interface_t *si; 00275 if ((si = switch_loadable_module_get_say_interface(module_name))) { 00276 char *say_type = (char *) switch_xml_attr_soft(action, "type"); 00277 char *say_method = (char *) switch_xml_attr_soft(action, "method"); 00278 char *say_gender = (char *) switch_xml_attr_soft(action, "gender"); 00279 switch_say_args_t say_args = {0}; 00280 00281 say_args.type = switch_ivr_get_say_type_by_name(say_type); 00282 say_args.method = switch_ivr_get_say_method_by_name(say_method); 00283 say_args.gender = switch_ivr_get_say_gender_by_name(say_gender); 00284 00285 status = si->say_function(session, odata, &say_args, args); 00286 } else { 00287 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name); 00288 } 00289 } else if (!strcasecmp(func, "speak-text")) { 00290 const char *my_tts_engine = switch_xml_attr(action, "tts-engine"); 00291 const char *my_tts_voice = switch_xml_attr(action, "tts-voice"); 00292 00293 if (!my_tts_engine) { 00294 my_tts_engine = tts_engine; 00295 } 00296 00297 if (!my_tts_voice) { 00298 my_tts_voice = tts_voice; 00299 } 00300 if (zstr(tts_engine) || zstr(tts_voice)) { 00301 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "TTS is not configured\n"); 00302 } else { 00303 status = switch_ivr_speak_text(session, my_tts_engine, my_tts_voice, odata, args); 00304 } 00305 } 00306 00307 switch_ivr_sleep(session, pause, SWITCH_FALSE, NULL); 00308 switch_safe_free(expanded); 00309 switch_safe_free(substituted); 00310 00311 } 00312 } 00313 00314 switch_regex_safe_free(re); 00315 00316 if ((match && do_break && switch_true(do_break)) || status == SWITCH_STATUS_BREAK) { 00317 break; 00318 } 00319 00320 } 00321 00322 switch_safe_free(field_expanded_alloc); 00323 00324 if (status != SWITCH_STATUS_SUCCESS) { 00325 done = 1; 00326 break; 00327 } 00328 00329 input = input->next; 00330 } 00331 00332 done: 00333 00334 if (hint_data) { 00335 switch_event_destroy(&hint_data); 00336 } 00337 00338 if (!matches) { 00339 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Macro [%s]: '%s' did not match any patterns\n", macro_name, data); 00340 } 00341 00342 if (old_sound_prefix) { 00343 switch_channel_set_variable(channel, "sound_prefix", old_sound_prefix); 00344 } 00345 if (local_sound_prefix_enforced == SWITCH_TRUE) { 00346 switch_channel_set_variable(channel, "sound_prefix_enforced", NULL); 00347 } 00348 00349 if (xml) { 00350 switch_xml_free(xml); 00351 } 00352 00353 return status; 00354 }
| switch_status_t switch_ivr_process_fh | ( | switch_core_session_t * | session, | |
| const char * | cmd, | |||
| switch_file_handle_t * | fhp | |||
| ) |
Definition at line 3141 of file switch_ivr.c.
References switch_codec::implementation, switch_codec_implementation::samples_per_second, switch_atoui(), SWITCH_CHANNEL_SESSION_LOG, switch_clear_flag, switch_core_file_seek(), switch_core_file_truncate(), switch_core_session_get_read_codec(), SWITCH_FILE_DONE, SWITCH_FILE_OPEN, SWITCH_FILE_PAUSE, SWITCH_LOG_DEBUG, switch_log_printf(), switch_normalize_volume, switch_set_flag, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_test_flag, and zstr.
Referenced by CoreSession::process_callback_result().
03142 { 03143 if (zstr(cmd)) { 03144 return SWITCH_STATUS_SUCCESS; 03145 } 03146 03147 if (fhp) { 03148 if (!switch_test_flag(fhp, SWITCH_FILE_OPEN)) { 03149 return SWITCH_STATUS_FALSE; 03150 } 03151 03152 if (!strncasecmp(cmd, "speed", 5)) { 03153 char *p; 03154 03155 if ((p = strchr(cmd, ':'))) { 03156 p++; 03157 if (*p == '+' || *p == '-') { 03158 int step; 03159 if (!(step = atoi(p))) { 03160 step = 1; 03161 } 03162 fhp->speed += step; 03163 } else { 03164 int speed = atoi(p); 03165 fhp->speed = speed; 03166 } 03167 return SWITCH_STATUS_SUCCESS; 03168 } 03169 03170 return SWITCH_STATUS_FALSE; 03171 03172 } else if (!strncasecmp(cmd, "volume", 6)) { 03173 char *p; 03174 03175 if ((p = strchr(cmd, ':'))) { 03176 p++; 03177 if (*p == '+' || *p == '-') { 03178 int step; 03179 if (!(step = atoi(p))) { 03180 step = 1; 03181 } 03182 fhp->vol += step; 03183 } else { 03184 int vol = atoi(p); 03185 fhp->vol = vol; 03186 } 03187 return SWITCH_STATUS_SUCCESS; 03188 } 03189 03190 if (fhp->vol) { 03191 switch_normalize_volume(fhp->vol); 03192 } 03193 03194 return SWITCH_STATUS_FALSE; 03195 } else if (!strcasecmp(cmd, "pause")) { 03196 if (switch_test_flag(fhp, SWITCH_FILE_PAUSE)) { 03197 switch_clear_flag(fhp, SWITCH_FILE_PAUSE); 03198 } else { 03199 switch_set_flag(fhp, SWITCH_FILE_PAUSE); 03200 } 03201 return SWITCH_STATUS_SUCCESS; 03202 } else if (!strcasecmp(cmd, "stop")) { 03203 switch_set_flag(fhp, SWITCH_FILE_DONE); 03204 return SWITCH_STATUS_FALSE; 03205 } else if (!strcasecmp(cmd, "truncate")) { 03206 switch_core_file_truncate(fhp, 0); 03207 } else if (!strcasecmp(cmd, "restart")) { 03208 unsigned int pos = 0; 03209 fhp->speed = 0; 03210 switch_core_file_seek(fhp, &pos, 0, SEEK_SET); 03211 return SWITCH_STATUS_SUCCESS; 03212 } else if (!strncasecmp(cmd, "seek", 4)) { 03213 switch_codec_t *codec; 03214 unsigned int samps = 0; 03215 unsigned int pos = 0; 03216 char *p; 03217 codec = switch_core_session_get_read_codec(session); 03218 03219 if ((p = strchr(cmd, ':'))) { 03220 p++; 03221 if (*p == '+' || *p == '-') { 03222 int step; 03223 int32_t target; 03224 if (!(step = atoi(p))) { 03225 step = 1000; 03226 } 03227 03228 samps = step * (codec->implementation->samples_per_second / 1000); 03229 target = (int32_t)fhp->pos + samps; 03230 03231 if (target < 0) { 03232 target = 0; 03233 } 03234 03235 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", target); 03236 switch_core_file_seek(fhp, &pos, target, SEEK_SET); 03237 03238 } else { 03239 samps = switch_atoui(p) * (codec->implementation->samples_per_second / 1000); 03240 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "seek to position %d\n", samps); 03241 switch_core_file_seek(fhp, &pos, samps, SEEK_SET); 03242 } 03243 } 03244 03245 return SWITCH_STATUS_SUCCESS; 03246 } 03247 } 03248 03249 if (!strcmp(cmd, "true") || !strcmp(cmd, "undefined")) { 03250 return SWITCH_STATUS_SUCCESS; 03251 } 03252 03253 return SWITCH_STATUS_FALSE; 03254 03255 }
| switch_status_t switch_ivr_read | ( | switch_core_session_t * | session, | |
| uint32_t | min_digits, | |||
| uint32_t | max_digits, | |||
| const char * | prompt_audio_file, | |||
| const char * | var_name, | |||
| char * | digit_buffer, | |||
| switch_size_t | digit_buffer_length, | |||
| uint32_t | timeout, | |||
| const char * | valid_terminators, | |||
| uint32_t | digit_timeout | |||
| ) |
Definition at line 1865 of file switch_ivr_play_say.c.
References switch_input_args_t::buf, switch_input_args_t::buflen, switch_assert, switch_channel_pre_answer, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_get_channel(), switch_ivr_collect_digits_count(), switch_ivr_play_file(), SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_READ_RESULT_VARIABLE, SWITCH_READ_TERMINATOR_USED_VARIABLE, switch_snprintf(), SWITCH_STATUS_BREAK, SWITCH_STATUS_FALSE, SWITCH_STATUS_RESTART, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, SWITCH_STATUS_TOO_SMALL, and zstr.
Referenced by collect_thread_run(), CoreSession::read(), and switch_play_and_get_digits().
01876 { 01877 switch_channel_t *channel; 01878 switch_input_args_t args = { 0 }; 01879 switch_status_t status = SWITCH_STATUS_SUCCESS; 01880 size_t len = 0; 01881 char tb[2] = ""; 01882 01883 switch_assert(session); 01884 01885 if (!digit_timeout) { 01886 digit_timeout = timeout; 01887 } 01888 01889 if (max_digits < min_digits) { 01890 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, 01891 "Max digits %u is less than Min %u, forcing Max to %u\n", max_digits, min_digits, min_digits); 01892 max_digits = min_digits; 01893 } 01894 01895 channel = switch_core_session_get_channel(session); 01896 switch_channel_set_variable(channel, SWITCH_READ_RESULT_VARIABLE, NULL); 01897 01898 if (var_name) { 01899 switch_channel_set_variable(channel, var_name, NULL); 01900 } 01901 01902 if ((min_digits && digit_buffer_length < min_digits) || digit_buffer_length < max_digits) { 01903 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Buffer too small!\n"); 01904 return SWITCH_STATUS_FALSE; 01905 } 01906 01907 if (switch_channel_pre_answer(channel) != SWITCH_STATUS_SUCCESS) { 01908 return SWITCH_STATUS_FALSE; 01909 } 01910 01911 memset(digit_buffer, 0, digit_buffer_length); 01912 args.buf = digit_buffer; 01913 args.buflen = (uint32_t) digit_buffer_length; 01914 01915 if (!zstr(prompt_audio_file) && strcasecmp(prompt_audio_file, "silence")) { 01916 if ((status = switch_ivr_play_file(session, NULL, prompt_audio_file, &args)) == SWITCH_STATUS_BREAK) { 01917 status = SWITCH_STATUS_SUCCESS; 01918 } 01919 } 01920 01921 if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) { 01922 goto end; 01923 } 01924 01925 len = strlen(digit_buffer); 01926 01927 if ((min_digits && len < min_digits) || len < max_digits) { 01928 args.buf = digit_buffer + len; 01929 args.buflen = (uint32_t) (digit_buffer_length - len); 01930 status = switch_ivr_collect_digits_count(session, digit_buffer, digit_buffer_length, max_digits, valid_terminators, &tb[0], 01931 len ? digit_timeout : timeout, digit_timeout, 0); 01932 } 01933 01934 01935 if (tb[0]) { 01936 char *p; 01937 01938 switch_channel_set_variable(channel, SWITCH_READ_TERMINATOR_USED_VARIABLE, tb); 01939 01940 if ((p = strchr(valid_terminators, tb[0]))) { 01941 if (p >= (valid_terminators + 1) && (*(p - 1) == '+' || *(p - 1) == 'x')) { 01942 switch_snprintf(digit_buffer + strlen(digit_buffer), digit_buffer_length - strlen(digit_buffer), "%s", tb); 01943 if (*(p - 1) == 'x') { 01944 status = SWITCH_STATUS_RESTART; 01945 } 01946 } 01947 } 01948 } 01949 01950 len = strlen(digit_buffer); 01951 if ((min_digits && len < min_digits)) { 01952 status = SWITCH_STATUS_TOO_SMALL; 01953 } 01954 01955 switch (status) { 01956 case SWITCH_STATUS_SUCCESS: 01957 switch_channel_set_variable(channel, SWITCH_READ_RESULT_VARIABLE, "success"); 01958 break; 01959 case SWITCH_STATUS_TIMEOUT: 01960 switch_channel_set_variable(channel, SWITCH_READ_RESULT_VARIABLE, "timeout"); 01961 break; 01962 default: 01963 switch_channel_set_variable(channel, SWITCH_READ_RESULT_VARIABLE, "failure"); 01964 break; 01965 01966 } 01967 01968 end: 01969 01970 if (status != SWITCH_STATUS_RESTART && max_digits == 1 && len == 1 && valid_terminators && strchr(valid_terminators, *digit_buffer)) { 01971 *digit_buffer = '\0'; 01972 } 01973 01974 if (var_name && !zstr(digit_buffer)) { 01975 switch_channel_set_variable(channel, var_name, digit_buffer); 01976 } 01977 01978 return status; 01979 01980 }
| switch_status_t switch_ivr_release_file_handle | ( | switch_core_session_t * | session, | |
| switch_file_handle_t ** | fh | |||
| ) |
Definition at line 970 of file switch_ivr_play_say.c.
References switch_core_session_io_rwunlock(), and SWITCH_STATUS_SUCCESS.
00971 { 00972 *fh = NULL; 00973 switch_core_session_io_rwunlock(session); 00974 00975 return SWITCH_STATUS_SUCCESS; 00976 }
| switch_status_t switch_ivr_say | ( | switch_core_session_t * | session, | |
| const char * | tosay, | |||
| const char * | module_name, | |||
| const char * | say_type, | |||
| const char * | say_method, | |||
| const char * | say_gender, | |||
| switch_input_args_t * | args | |||
| ) |
Definition at line 2788 of file switch_ivr.c.
References switch_say_args_t::gender, switch_say_args_t::method, switch_say_interface::say_function, switch_assert, switch_channel_event_set_data(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_get_channel(), switch_core_session_strdup, switch_event_add_header_string(), switch_event_create, switch_event_destroy(), SWITCH_EVENT_REQUEST_PARAMS, switch_ivr_get_say_gender_by_name(), switch_ivr_get_say_method_by_name(), switch_ivr_get_say_type_by_name(), switch_loadable_module_get_say_interface(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_true(), switch_xml_attr(), switch_xml_free(), switch_xml_locate_language(), switch_say_args_t::type, and zstr.
Referenced by CoreSession::say().
02795 { 02796 switch_say_interface_t *si; 02797 switch_channel_t *channel; 02798 switch_status_t status = SWITCH_STATUS_FALSE; 02799 const char *save_path = NULL, *chan_lang = NULL, *lang = NULL, *sound_path = NULL; 02800 switch_event_t *hint_data; 02801 switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL; 02802 char *p; 02803 02804 switch_assert(session); 02805 channel = switch_core_session_get_channel(session); 02806 switch_assert(channel); 02807 02808 if (zstr(module_name)) { 02809 module_name = "en"; 02810 } 02811 02812 if (module_name) { 02813 char *p; 02814 p = switch_core_session_strdup(session, module_name); 02815 module_name = p; 02816 02817 if ((p = strchr(module_name, ':'))) { 02818 *p++ = '\0'; 02819 chan_lang = p; 02820 } 02821 } 02822 02823 if (!chan_lang) { 02824 lang = switch_channel_get_variable(channel, "language"); 02825 02826 if (!lang) { 02827 chan_lang = switch_channel_get_variable(channel, "default_language"); 02828 if (!chan_lang) { 02829 chan_lang = module_name; 02830 } 02831 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang); 02832 } else { 02833 chan_lang = lang; 02834 } 02835 } 02836 02837 switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS); 02838 switch_assert(hint_data); 02839 02840 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app"); 02841 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang); 02842 switch_channel_event_set_data(channel, hint_data); 02843 02844 if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, ¯os, chan_lang) != SWITCH_STATUS_SUCCESS) { 02845 goto done; 02846 } 02847 02848 if ((p = (char *) switch_xml_attr(language, "say-module"))) { 02849 module_name = switch_core_session_strdup(session, p); 02850 } else if ((p = (char *) switch_xml_attr(language, "module"))) { 02851 module_name = switch_core_session_strdup(session, p); 02852 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n"); 02853 } else { 02854 module_name = chan_lang; 02855 } 02856 02857 if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) { 02858 if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) { 02859 sound_path = (char *) switch_xml_attr(language, "sound_path"); 02860 } 02861 } 02862 02863 if (channel) { 02864 const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced"); 02865 if (!switch_true(p)) { 02866 save_path = switch_channel_get_variable(channel, "sound_prefix"); 02867 if (sound_path) { 02868 switch_channel_set_variable(channel, "sound_prefix", sound_path); 02869 } 02870 } 02871 } 02872 02873 if ((si = switch_loadable_module_get_say_interface(module_name))) { 02874 /* should go back and proto all the say mods to const.... */ 02875 switch_say_args_t say_args = {0}; 02876 02877 say_args.type = switch_ivr_get_say_type_by_name(say_type); 02878 say_args.method = switch_ivr_get_say_method_by_name(say_method); 02879 say_args.gender = switch_ivr_get_say_gender_by_name(say_gender); 02880 02881 status = si->say_function(session, (char *) tosay, &say_args, args); 02882 } else { 02883 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name); 02884 status = SWITCH_STATUS_FALSE; 02885 } 02886 02887 done: 02888 02889 if (hint_data) { 02890 switch_event_destroy(&hint_data); 02891 } 02892 02893 if (save_path) { 02894 switch_channel_set_variable(channel, "sound_prefix", save_path); 02895 } 02896 02897 if (xml) { 02898 switch_xml_free(xml); 02899 } 02900 02901 return status; 02902 }
| switch_status_t switch_ivr_say_ip | ( | switch_core_session_t * | session, | |
| char * | tosay, | |||
| switch_say_callback_t | number_func, | |||
| switch_say_args_t * | say_args, | |||
| switch_input_args_t * | args | |||
| ) |
Definition at line 168 of file switch_ivr_say.c.
References say_file, say_num, switch_core_session_strdup, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.
00173 { 00174 char *a, *b, *c, *d; 00175 if (!(a = switch_core_session_strdup(session, tosay))) { 00176 return SWITCH_STATUS_FALSE; 00177 } 00178 00179 if (!(b = strchr(a, '.'))) { 00180 return SWITCH_STATUS_FALSE; 00181 } 00182 00183 *b++ = '\0'; 00184 00185 if (!(c = strchr(b, '.'))) { 00186 return SWITCH_STATUS_FALSE; 00187 } 00188 00189 *c++ = '\0'; 00190 00191 if (!(d = strchr(c, '.'))) { 00192 return SWITCH_STATUS_FALSE; 00193 } 00194 00195 *d++ = '\0'; 00196 00197 say_num(atoi(a), say_args->method); 00198 say_file("digits/dot.wav"); 00199 say_num(atoi(b), say_args->method); 00200 say_file("digits/dot.wav"); 00201 say_num(atoi(c), say_args->method); 00202 say_file("digits/dot.wav"); 00203 say_num(atoi(d), say_args->method); 00204 00205 return SWITCH_STATUS_SUCCESS; 00206 }
| switch_status_t switch_ivr_say_spell | ( | switch_core_session_t * | session, | |
| char * | tosay, | |||
| switch_say_args_t * | say_args, | |||
| switch_input_args_t * | args | |||
| ) |
Definition at line 133 of file switch_ivr_say.c.
References say_file, SST_NAME_PHONETIC, and SST_NAME_SPELLED.
00134 { 00135 char *p; 00136 00137 for (p = tosay; p && *p; p++) { 00138 int a = tolower((int) *p); 00139 if (a >= '0' && a <= '9') { 00140 say_file("digits/%d.wav", a - '0'); 00141 } else { 00142 if (say_args->type == SST_NAME_SPELLED) { 00143 say_file("ascii/%d.wav", a); 00144 } else if (say_args->type == SST_NAME_PHONETIC) { 00145 say_file("phonetic-ascii/%d.wav", a); 00146 } 00147 } 00148 } 00149 00150 return SWITCH_STATUS_SUCCESS; 00151 }
| switch_status_t switch_ivr_say_string | ( | switch_core_session_t * | session, | |
| const char * | lang, | |||
| const char * | ext, | |||
| const char * | tosay, | |||
| const char * | module_name, | |||
| const char * | say_type, | |||
| const char * | say_method, | |||
| const char * | say_gender, | |||
| char ** | rstr | |||
| ) |
Definition at line 2904 of file switch_ivr.c.
References switch_say_args_t::ext, switch_say_args_t::gender, switch_say_args_t::method, switch_say_interface::say_string_function, switch_assert, switch_channel_event_set_data(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_get_channel(), switch_event_add_header_string(), switch_event_create, switch_event_destroy(), SWITCH_EVENT_REQUEST_PARAMS, switch_ivr_get_say_gender_by_name(), switch_ivr_get_say_method_by_name(), switch_ivr_get_say_type_by_name(), switch_loadable_module_get_say_interface(), SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_STACK_BOTTOM, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_true(), switch_xml_attr(), switch_xml_free(), switch_xml_locate_language(), and switch_say_args_t::type.
02913 { 02914 switch_say_interface_t *si; 02915 switch_channel_t *channel = NULL; 02916 switch_status_t status = SWITCH_STATUS_FALSE; 02917 const char *save_path = NULL, *chan_lang = NULL, *sound_path = NULL; 02918 switch_event_t *hint_data; 02919 switch_xml_t cfg, xml = NULL, language = NULL, macros = NULL, phrases = NULL; 02920 02921 if (session) { 02922 channel = switch_core_session_get_channel(session); 02923 02924 if (!lang) { 02925 lang = switch_channel_get_variable(channel, "language"); 02926 02927 if (!lang) { 02928 chan_lang = switch_channel_get_variable(channel, "default_language"); 02929 if (!chan_lang) { 02930 chan_lang = "en"; 02931 } 02932 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "No language specified - Using [%s]\n", chan_lang); 02933 } else { 02934 chan_lang = lang; 02935 } 02936 } 02937 } 02938 02939 if (!lang) lang = "en"; 02940 if (!chan_lang) chan_lang = lang; 02941 02942 switch_event_create(&hint_data, SWITCH_EVENT_REQUEST_PARAMS); 02943 switch_assert(hint_data); 02944 02945 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "macro_name", "say_app"); 02946 switch_event_add_header_string(hint_data, SWITCH_STACK_BOTTOM, "lang", chan_lang); 02947 02948 if (channel) { 02949 switch_channel_event_set_data(channel, hint_data); 02950 } 02951 02952 if (switch_xml_locate_language(&xml, &cfg, hint_data, &language, &phrases, ¯os, chan_lang) != SWITCH_STATUS_SUCCESS) { 02953 goto done; 02954 } 02955 02956 if ((module_name = switch_xml_attr(language, "say-module"))) { 02957 } else if ((module_name = switch_xml_attr(language, "module"))) { 02958 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Deprecated usage of module attribute\n"); 02959 } else { 02960 module_name = chan_lang; 02961 } 02962 02963 if (!(sound_path = (char *) switch_xml_attr(language, "sound-prefix"))) { 02964 if (!(sound_path = (char *) switch_xml_attr(language, "sound-path"))) { 02965 sound_path = (char *) switch_xml_attr(language, "sound_path"); 02966 } 02967 } 02968 02969 if (channel) { 02970 const char *p = switch_channel_get_variable(channel, "sound_prefix_enforced"); 02971 if (!switch_true(p)) { 02972 save_path = switch_channel_get_variable(channel, "sound_prefix"); 02973 if (sound_path) { 02974 switch_channel_set_variable(channel, "sound_prefix", sound_path); 02975 } 02976 } 02977 } 02978 02979 if ((si = switch_loadable_module_get_say_interface(module_name))) { 02980 /* should go back and proto all the say mods to const.... */ 02981 switch_say_args_t say_args = {0}; 02982 02983 say_args.type = switch_ivr_get_say_type_by_name(say_type); 02984 say_args.method = switch_ivr_get_say_method_by_name(say_method); 02985 say_args.gender = switch_ivr_get_say_gender_by_name(say_gender); 02986 say_args.ext = ext; 02987 status = si->say_string_function(session, (char *) tosay, &say_args, rstr); 02988 } else { 02989 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid SAY Interface [%s]!\n", module_name); 02990 status = SWITCH_STATUS_FALSE; 02991 } 02992 02993 done: 02994 02995 if (hint_data) { 02996 switch_event_destroy(&hint_data); 02997 } 02998 02999 if (save_path && channel) { 03000 switch_channel_set_variable(channel, "sound_prefix", save_path); 03001 } 03002 03003 if (xml) { 03004 switch_xml_free(xml); 03005 } 03006 03007 return status; 03008 }
| switch_status_t switch_ivr_set_user | ( | switch_core_session_t * | session, | |
| const char * | data | |||
| ) |
Definition at line 3036 of file switch_ivr.c.
References get_prefixed_str(), switch_xml::next, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_variable, switch_core_session_alloc, switch_core_session_get_channel(), switch_core_session_strdup, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, switch_xml_attr(), switch_xml_child(), switch_xml_free(), switch_xml_locate_user(), and zstr.
03037 { 03038 switch_xml_t x_domain, xml = NULL, x_user, x_param, x_params, x_group = NULL; 03039 char *user, *number_alias, *domain; 03040 switch_channel_t *channel = switch_core_session_get_channel(session); 03041 switch_status_t status = SWITCH_STATUS_FALSE; 03042 03043 char *prefix_buffer = NULL, *prefix; 03044 size_t buffer_size = 0; 03045 size_t prefix_size = 0; 03046 if (zstr(data)) { 03047 goto error; 03048 } 03049 03050 user = switch_core_session_strdup(session, data); 03051 03052 if ((prefix = strchr(user, ' '))) { 03053 *prefix++ = 0; 03054 } 03055 03056 if (!(domain = strchr(user, '@'))) { 03057 goto error; 03058 } 03059 03060 *domain++ = '\0'; 03061 03062 if (switch_xml_locate_user("id", user, domain, NULL, &xml, &x_domain, &x_user, &x_group, NULL) != SWITCH_STATUS_SUCCESS) { 03063 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "can't find user [%s@%s]\n", user, domain); 03064 goto done; 03065 } 03066 03067 status = SWITCH_STATUS_SUCCESS; 03068 03069 if (!zstr(prefix)) { 03070 prefix_size = strlen(prefix); 03071 buffer_size = 1024 + prefix_size + 1; 03072 prefix_buffer = switch_core_session_alloc(session, buffer_size); 03073 } 03074 03075 if ((number_alias = (char *) switch_xml_attr(x_user, "number-alias"))) { 03076 switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "number_alias"), number_alias); 03077 } 03078 03079 if ((x_params = switch_xml_child(x_domain, "variables"))) { 03080 for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { 03081 const char *var = switch_xml_attr(x_param, "name"); 03082 const char *val = switch_xml_attr(x_param, "value"); 03083 03084 if (var && val) { 03085 switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val); 03086 } 03087 } 03088 } 03089 03090 if (x_group && (x_params = switch_xml_child(x_group, "variables"))) { 03091 for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { 03092 const char *var = switch_xml_attr(x_param, "name"); 03093 const char *val = switch_xml_attr(x_param, "value"); 03094 03095 if (var && val) { 03096 switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val); 03097 } 03098 } 03099 } 03100 03101 if ((x_params = switch_xml_child(x_user, "variables"))) { 03102 for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { 03103 const char *var = switch_xml_attr(x_param, "name"); 03104 const char *val = switch_xml_attr(x_param, "value"); 03105 03106 if (var && val) { 03107 switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, var), val); 03108 } 03109 } 03110 } 03111 03112 switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "user_name"), user); 03113 switch_channel_set_variable(channel, get_prefixed_str(prefix_buffer, buffer_size, prefix, prefix_size, "domain_name"), domain); 03114 03115 goto done; 03116 03117 error: 03118 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No user@domain specified.\n"); 03119 03120 done: 03121 if (xml) { 03122 switch_xml_free(xml); 03123 } 03124 03125 return status; 03126 }
| switch_status_t switch_ivr_soft_hold | ( | switch_core_session_t * | session, | |
| const char * | unhold_key, | |||
| const char * | moh_a, | |||
| const char * | moh_b | |||
| ) |
Definition at line 2558 of file switch_ivr_play_say.c.
References switch_input_args_t::buf, switch_input_args_t::buflen, CF_BROADCAST, hold_on_dtmf(), switch_input_args_t::input_callback, SMF_ECHO_ALEG, SMF_LOOP, switch_assert, switch_channel_get_hold_music(), switch_channel_get_name(), switch_channel_get_variable, SWITCH_CHANNEL_SESSION_LOG, switch_channel_stop_broadcast, switch_channel_test_flag(), switch_core_session_get_channel(), switch_core_session_locate(), switch_core_session_rwunlock(), switch_ivr_broadcast(), switch_ivr_collect_digits_callback(), switch_ivr_play_file(), switch_log_printf(), SWITCH_LOG_WARNING, SWITCH_SIGNAL_BOND_VARIABLE, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and zstr.
02559 { 02560 switch_channel_t *channel, *other_channel; 02561 switch_core_session_t *other_session; 02562 const char *other_uuid, *moh = NULL; 02563 int moh_br = 0; 02564 switch_input_args_t args = { 0 }; 02565 args.input_callback = hold_on_dtmf; 02566 args.buf = (void *) unhold_key; 02567 args.buflen = (uint32_t) strlen(unhold_key); 02568 02569 switch_assert(session != NULL); 02570 channel = switch_core_session_get_channel(session); 02571 switch_assert(channel != NULL); 02572 02573 if ((other_uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE))) { 02574 if ((other_session = switch_core_session_locate(other_uuid))) { 02575 other_channel = switch_core_session_get_channel(other_session); 02576 02577 if (moh_b) { 02578 moh = moh_b; 02579 } else { 02580 moh = switch_channel_get_hold_music(other_channel); 02581 } 02582 02583 if (!zstr(moh) && strcasecmp(moh, "silence") && !switch_channel_test_flag(other_channel, CF_BROADCAST)) { 02584 switch_ivr_broadcast(other_uuid, moh, SMF_ECHO_ALEG | SMF_LOOP); 02585 moh_br++; 02586 } 02587 02588 if (moh_a) { 02589 moh = moh_a; 02590 } else { 02591 moh = switch_channel_get_hold_music(channel); 02592 } 02593 02594 if (!zstr(moh) && strcasecmp(moh, "silence")) { 02595 switch_ivr_play_file(session, NULL, moh, &args); 02596 } else { 02597 switch_ivr_collect_digits_callback(session, &args, 0, 0); 02598 } 02599 02600 if (moh_br) { 02601 switch_channel_stop_broadcast(other_channel); 02602 } 02603 02604 switch_core_session_rwunlock(other_session); 02605 02606 02607 return SWITCH_STATUS_SUCCESS; 02608 } 02609 02610 } 02611 02612 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Channel %s is not in a bridge\n", switch_channel_get_name(channel)); 02613 return SWITCH_STATUS_FALSE; 02614 02615 }
| switch_status_t switch_ivr_sound_test | ( | switch_core_session_t * | session | ) |
Definition at line 42 of file switch_ivr.c.
References switch_codec_implementation::actual_samples_per_second, switch_frame::data, switch_codec_implementation::microseconds_per_packet, switch_codec_implementation::number_of_channels, switch_frame::samples, switch_codec_implementation::samples_per_packet, switch_codec_implementation::samples_per_second, SFF_CNG, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, switch_core_codec_destroy(), switch_core_codec_init, switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_impl(), switch_core_session_read_frame(), SWITCH_IO_FLAG_NONE, SWITCH_LOG_CONSOLE, SWITCH_LOG_ERROR, switch_log_printf(), SWITCH_READ_ACCEPTABLE, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, and switch_test_flag.
00043 { 00044 00045 switch_codec_implementation_t imp = { 0 }; 00046 switch_codec_t codec = { 0 }; 00047 int16_t peak = 0; 00048 int16_t *data; 00049 switch_frame_t *read_frame = NULL; 00050 uint32_t i; 00051 switch_channel_t *channel = switch_core_session_get_channel(session); 00052 switch_status_t status = SWITCH_STATUS_SUCCESS; 00053 int64_t global_total = 0, global_sum = 0, period_sum = 0; 00054 int period_total = 0; 00055 int period_avg = 0, global_avg = 0; 00056 int avg = 0; 00057 int period_len; 00058 00059 switch_core_session_get_read_impl(session, &imp); 00060 00061 period_len = imp.actual_samples_per_second / imp.samples_per_packet; 00062 00063 if (switch_core_codec_init(&codec, 00064 "L16", 00065 NULL, 00066 imp.samples_per_second, 00067 imp.microseconds_per_packet / 1000, 00068 imp.number_of_channels, 00069 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, 00070 switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { 00071 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error L16@%uhz %u channels %dms\n", 00072 imp.samples_per_second, imp.number_of_channels, imp.microseconds_per_packet / 1000); 00073 return SWITCH_STATUS_FALSE; 00074 } 00075 00076 while (switch_channel_ready(channel)) { 00077 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); 00078 00079 if (!SWITCH_READ_ACCEPTABLE(status)) { 00080 break; 00081 } 00082 00083 if (switch_test_flag(read_frame, SFF_CNG) || !read_frame->samples) { 00084 continue; 00085 } 00086 00087 00088 data = (int16_t *) read_frame->data; 00089 peak = 0; 00090 avg = 0; 00091 for (i = 0; i < read_frame->samples; i++) { 00092 const int16_t s = (int16_t) abs(data[i]); 00093 if (s > peak) { 00094 peak = s; 00095 } 00096 avg += s; 00097 } 00098 00099 avg /= read_frame->samples; 00100 00101 period_sum += peak; 00102 global_sum += peak; 00103 00104 global_total++; 00105 period_total++; 00106 00107 period_avg = (int) (period_sum / period_total); 00108 00109 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CONSOLE, 00110 "\npacket_avg=%d packet_peak=%d period_avg=%d global_avg=%d\n\n", avg, peak, period_avg, global_avg); 00111 00112 if (period_total >= period_len) { 00113 global_avg = (int) (global_sum / global_total); 00114 period_total = 0; 00115 period_sum = 0; 00116 } 00117 00118 } 00119 00120 00121 switch_core_codec_destroy(&codec); 00122 00123 return SWITCH_STATUS_SUCCESS; 00124 00125 }
| switch_status_t switch_ivr_unbind_dtmf_meta_session | ( | switch_core_session_t * | session, | |
| uint32_t | key | |||
| ) |
Definition at line 3210 of file switch_ivr_async.c.
References dtmf_meta_data_t::sr, switch_channel_get_private(), SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_private(), switch_core_session_get_channel(), SWITCH_DTMF_RECV, SWITCH_DTMF_SEND, SWITCH_LOG_ERROR, SWITCH_LOG_INFO, switch_log_printf(), SWITCH_META_VAR_KEY, SWITCH_STATUS_FALSE, and SWITCH_STATUS_SUCCESS.
03211 { 03212 switch_channel_t *channel = switch_core_session_get_channel(session); 03213 03214 if (key) { 03215 dtmf_meta_data_t *md = switch_channel_get_private(channel, SWITCH_META_VAR_KEY); 03216 03217 if (!md || key > 9) { 03218 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Invalid key %u\n", key); 03219 return SWITCH_STATUS_FALSE; 03220 } 03221 03222 memset(&md->sr[SWITCH_DTMF_RECV].map[key], 0, sizeof(md->sr[SWITCH_DTMF_RECV].map[key])); 03223 memset(&md->sr[SWITCH_DTMF_SEND].map[key], 0, sizeof(md->sr[SWITCH_DTMF_SEND].map[key])); 03224 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "UnBound A-Leg: %d\n", key); 03225 03226 } else { 03227 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "UnBound A-Leg: ALL\n"); 03228 switch_channel_set_private(channel, SWITCH_META_VAR_KEY, NULL); 03229 } 03230 03231 return SWITCH_STATUS_SUCCESS; 03232 }
| switch_status_t switch_ivr_unblock_dtmf_session | ( | switch_core_session_t * | session | ) |
Definition at line 3246 of file switch_ivr_async.c.
References SWITCH_BLOCK_DTMF_KEY, switch_channel_get_private(), switch_channel_set_private(), switch_core_session_get_channel(), and SWITCH_STATUS_SUCCESS.
03247 { 03248 switch_channel_t *channel = switch_core_session_get_channel(session); 03249 uint8_t enabled = (uint8_t)(intptr_t)switch_channel_get_private(channel, SWITCH_BLOCK_DTMF_KEY); 03250 03251 if (enabled) { 03252 switch_channel_set_private(channel, SWITCH_BLOCK_DTMF_KEY, NULL); 03253 } 03254 03255 return SWITCH_STATUS_SUCCESS; 03256 }
| switch_bool_t switch_ivr_uuid_exists | ( | const char * | uuid | ) |
Definition at line 3128 of file switch_ivr.c.
References switch_core_session_locate(), switch_core_session_rwunlock(), and SWITCH_FALSE.
03129 { 03130 switch_bool_t exists = SWITCH_FALSE; 03131 switch_core_session_t *psession = NULL; 03132 03133 if ((psession = switch_core_session_locate(uuid))) { 03134 switch_core_session_rwunlock(psession); 03135 exists = 1; 03136 } 03137 03138 return exists; 03139 }
| switch_status_t switch_ivr_wait_for_answer | ( | switch_core_session_t * | session, | |
| switch_core_session_t * | peer_session | |||
| ) |
Definition at line 801 of file switch_ivr_originate.c.
References switch_codec_implementation::actual_samples_per_second, ringback::asis, ringback::audio_buffer, switch_frame::buflen, CF_ANSWERED, CF_DISABLE_RINGBACK, CF_EARLY_MEDIA, CF_PROXY_MEDIA, CF_PROXY_MODE, CF_XFER_ZOMBIE, switch_file_handle::channels, switch_frame::codec, CS_RESET, CS_SOFT_EXECUTE, switch_frame::data, switch_frame::datalen, switch_codec_implementation::decoded_bytes_per_packet, switch_dtmf_t::digit, switch_codec_implementation::encoded_bytes_per_packet, ringback::fh, ringback::fhb, switch_file_handle::file_path, switch_codec_implementation::iananame, switch_codec::implementation, switch_codec_implementation::number_of_channels, teletone_generation_session::rate, switch_file_handle::samplerate, switch_frame::samples, switch_codec_implementation::samples_per_packet, ringback::silence, switch_file_handle::speed, switch_assert, switch_buffer_create_dynamic(), switch_buffer_destroy(), switch_buffer_read_loop(), switch_buffer_set_loops(), SWITCH_CALL_TIMEOUT_VARIABLE, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE, SWITCH_CHANNEL_CHANNEL_LOG, switch_channel_dequeue_dtmf(), switch_channel_get_state(), switch_channel_get_variable, switch_channel_hangup, switch_channel_has_dtmf(), switch_channel_media_ready, switch_channel_ready, SWITCH_CHANNEL_SESSION_LOG, switch_channel_set_state, switch_channel_test_flag(), switch_channel_up_nosig, SWITCH_CODEC_FLAG_DECODE, SWITCH_CODEC_FLAG_ENCODE, SWITCH_CODEC_FLAG_PASSTHROUGH, switch_cond_next(), switch_core_codec_destroy(), switch_core_codec_init, switch_core_codec_ready(), switch_core_file_close(), switch_core_file_open, switch_core_file_read(), switch_core_file_seek(), switch_core_session_get_channel(), switch_core_session_get_pool(), switch_core_session_get_read_codec(), switch_core_session_read_frame(), switch_core_session_reset(), switch_core_session_set_read_codec(), switch_core_session_sprintf(), switch_core_session_write_frame(), SWITCH_FILE_DATA_SHORT, SWITCH_FILE_FLAG_READ, switch_generate_sln_silence(), SWITCH_IO_FLAG_NONE, switch_is_file_path(), switch_ivr_parse_all_events(), switch_ivr_parse_all_messages(), SWITCH_IVR_VERIFY_SILENCE_DIVISOR, SWITCH_LOG_DEBUG, SWITCH_LOG_ERROR, switch_log_printf(), switch_micro_time_now(), switch_mprintf(), SWITCH_READ_ACCEPTABLE, SWITCH_RECOMMENDED_BUFFER_SIZE, switch_safe_free, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE, SWITCH_STATUS_FALSE, SWITCH_STATUS_SUCCESS, SWITCH_STATUS_TIMEOUT, switch_test_flag, SWITCH_TRUE, SWITCH_URL_SEPARATOR, switch_yield, switch_zmalloc, teletone_destroy_session(), teletone_handler(), teletone_init_session(), teletone_run(), ringback::ts, and zstr.
Referenced by switch_ivr_multi_threaded_bridge(), uuid_bridge_on_soft_execute(), and CoreSession::waitForAnswer().
00802 { 00803 switch_channel_t *caller_channel = NULL; 00804 switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session); 00805 const char *ringback_data = NULL; 00806 switch_frame_t write_frame = { 0 }; 00807 switch_codec_t write_codec = { 0 }; 00808 switch_codec_t *read_codec = switch_core_session_get_read_codec(session); 00809 uint8_t pass = 0; 00810 ringback_t ringback = { 0 }; 00811 switch_frame_t *read_frame = NULL; 00812 switch_status_t status = SWITCH_STATUS_SUCCESS; 00813 int timelimit = 60; 00814 const char *var; 00815 switch_time_t start = 0; 00816 const char *cancel_key = NULL; 00817 switch_channel_state_t wait_state = 0; 00818 00819 switch_assert(peer_channel); 00820 00821 if (switch_channel_get_state(peer_channel) == CS_RESET) { 00822 switch_channel_set_state(peer_channel, CS_SOFT_EXECUTE); 00823 } 00824 00825 if (session) { 00826 caller_channel = switch_core_session_get_channel(session); 00827 } 00828 00829 if ((switch_channel_test_flag(peer_channel, CF_ANSWERED) || switch_channel_test_flag(peer_channel, CF_EARLY_MEDIA))) { 00830 goto end; 00831 } 00832 00833 switch_zmalloc(write_frame.data, SWITCH_RECOMMENDED_BUFFER_SIZE); 00834 write_frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE; 00835 00836 if (caller_channel && (var = switch_channel_get_variable(caller_channel, SWITCH_CALL_TIMEOUT_VARIABLE))) { 00837 timelimit = atoi(var); 00838 if (timelimit < 0) { 00839 timelimit = 60; 00840 } 00841 } 00842 00843 timelimit *= 1000000; 00844 start = switch_micro_time_now(); 00845 00846 if (caller_channel) { 00847 cancel_key = switch_channel_get_variable(caller_channel, "origination_cancel_key"); 00848 00849 if (switch_channel_test_flag(caller_channel, CF_ANSWERED)) { 00850 ringback_data = switch_channel_get_variable(caller_channel, "transfer_ringback"); 00851 } 00852 00853 if (!ringback_data) { 00854 ringback_data = switch_channel_get_variable(caller_channel, "ringback"); 00855 } 00856 00857 if (switch_channel_test_flag(caller_channel, CF_PROXY_MODE) || switch_channel_test_flag(caller_channel, CF_PROXY_MEDIA)) { 00858 ringback_data = NULL; 00859 } else if (zstr(ringback_data)) { 00860 if ((var = switch_channel_get_variable(caller_channel, SWITCH_SEND_SILENCE_WHEN_IDLE_VARIABLE))) { 00861 int sval = atoi(var); 00862 00863 if (sval) { 00864 ringback_data = switch_core_session_sprintf(session, "silence:%d", sval); 00865 } 00866 } 00867 } 00868 } 00869 00870 00871 if (read_codec && ringback_data) { 00872 if (switch_is_file_path(ringback_data)) { 00873 if (!(strrchr(ringback_data, '.') || strstr(ringback_data, SWITCH_URL_SEPARATOR))) { 00874 ringback.asis++; 00875 } 00876 } 00877 00878 00879 00880 if (!ringback.asis) { 00881 if ((pass = (uint8_t) switch_test_flag(read_codec, SWITCH_CODEC_FLAG_PASSTHROUGH))) { 00882 goto no_ringback; 00883 } 00884 00885 if (switch_core_codec_init(&write_codec, 00886 "L16", 00887 NULL, 00888 read_codec->implementation->actual_samples_per_second, 00889 read_codec->implementation->microseconds_per_packet / 1000, 00890 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, 00891 switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) { 00892 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Codec Error!\n"); 00893 if (caller_channel) { 00894 switch_channel_hangup(caller_channel, SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE); 00895 } 00896 read_codec = NULL; 00897 goto done; 00898 } else { 00899 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, 00900 "Raw Codec Activation Success L16@%uhz 1 channel %dms\n", 00901 read_codec->implementation->actual_samples_per_second, read_codec->implementation->microseconds_per_packet / 1000); 00902 00903 write_frame.codec = &write_codec; 00904 write_frame.datalen = read_codec->implementation->decoded_bytes_per_packet; 00905 write_frame.samples = write_frame.datalen / 2; 00906 memset(write_frame.data, 255, write_frame.datalen); 00907 switch_core_session_set_read_codec(session, &write_codec); 00908 } 00909 } 00910 00911 if (switch_channel_test_flag(caller_channel, CF_DISABLE_RINGBACK)) { 00912 ringback_data = NULL; 00913 } 00914 00915 if (ringback_data) { 00916 char *tmp_data = NULL; 00917 00918 if (switch_is_file_path(ringback_data)) { 00919 char *ext; 00920 00921 if (ringback.asis) { 00922 write_frame.codec = read_codec; 00923 ext = read_codec->implementation->iananame; 00924 tmp_data = switch_mprintf("%s.%s", ringback_data, ext); 00925 ringback_data = tmp_data; 00926 } 00927 00928 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Play Ringback File [%s]\n", ringback_data); 00929 00930 ringback.fhb.channels = read_codec->implementation->number_of_channels; 00931 ringback.fhb.samplerate = read_codec->implementation->actual_samples_per_second; 00932 if (switch_core_file_open(&ringback.fhb, 00933 ringback_data, 00934 read_codec->implementation->number_of_channels, 00935 read_codec->implementation->actual_samples_per_second, 00936 SWITCH_FILE_FLAG_READ | SWITCH_FILE_DATA_SHORT, NULL) != SWITCH_STATUS_SUCCESS) { 00937 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error Playing File\n"); 00938 switch_safe_free(tmp_data); 00939 goto done; 00940 } 00941 ringback.fh = &ringback.fhb; 00942 } else { 00943 if (!strncasecmp(ringback_data, "silence", 7)) { 00944 const char *p = ringback_data + 7; 00945 if (*p == ':') { 00946 p++; 00947 if (p) { 00948 ringback.silence = atoi(p); 00949 } 00950 } 00951 SWITCH_IVR_VERIFY_SILENCE_DIVISOR(ringback.silence); 00952 } else { 00953 switch_buffer_create_dynamic(&ringback.audio_buffer, 512, 1024, 0); 00954 switch_buffer_set_loops(ringback.audio_buffer, -1); 00955 00956 teletone_init_session(&ringback.ts, 0, teletone_handler, &ringback); 00957 ringback.ts.rate = read_codec->implementation->actual_samples_per_second; 00958 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Play Ringback Tone [%s]\n", ringback_data); 00959 if (teletone_run(&ringback.ts, ringback_data)) { 00960 switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Error Playing Tone\n"); 00961 teletone_destroy_session(&ringback.ts); 00962 switch_buffer_destroy(&ringback.audio_buffer); 00963 ringback_data = NULL; 00964 } 00965 } 00966 } 00967 switch_safe_free(tmp_data); 00968 } 00969 } 00970 00971 no_ringback: 00972 00973 if (caller_channel) { 00974 wait_state = switch_channel_get_state(caller_channel); 00975 } 00976 00977 while (switch_channel_ready(peer_channel) && !switch_channel_media_ready(peer_channel)) { 00978 int diff = (int) (switch_micro_time_now() - start); 00979 00980 switch_ivr_parse_all_messages(session); 00981 00982 if (caller_channel && cancel_key) { 00983 if (switch_channel_has_dtmf(caller_channel)) { 00984 switch_dtmf_t dtmf = { 0, 0 }; 00985 if (switch_channel_dequeue_dtmf(caller_channel, &dtmf) == SWITCH_STATUS_SUCCESS) { 00986 if (dtmf.digit == *cancel_key) { 00987 status = SWITCH_STATUS_FALSE; 00988 goto done; 00989 } 00990 } 00991 } 00992 } 00993 00994 if (caller_channel && switch_channel_get_state(caller_channel) != wait_state) { 00995 goto done; 00996 } 00997 00998 if (diff > timelimit) { 00999 status = SWITCH_STATUS_TIMEOUT; 01000 goto done; 01001 } 01002 01003 if (switch_channel_media_ready(caller_channel)) { 01004 status = switch_core_session_read_frame(session, &read_frame, SWITCH_IO_FLAG_NONE, 0); 01005 if (!SWITCH_READ_ACCEPTABLE(status)) { 01006 break; 01007 } 01008 } else { 01009 read_frame = NULL; 01010 } 01011 01012 if (read_frame && !pass) { 01013 01014 if (ringback.fh) { 01015 switch_size_t mlen, olen; 01016 unsigned int pos = 0; 01017 01018 if (ringback.asis) { 01019 mlen = write_frame.codec->implementation->encoded_bytes_per_packet; 01020 } else { 01021 mlen = write_frame.codec->implementation->samples_per_packet; 01022 } 01023 01024 olen = mlen; 01025 //if (ringback.fh->resampler && ringback.fh->resampler->rfactor > 1) { 01026 //olen = (switch_size_t) (olen * ringback.fh->resampler->rfactor); 01027 //} 01028 switch_core_file_read(ringback.fh, write_frame.data, &olen); 01029 01030 if (olen == 0) { 01031 olen = mlen; 01032 ringback.fh->speed = 0; 01033 switch_core_file_seek(ringback.fh, &pos, 0, SEEK_SET); 01034 switch_core_file_read(ringback.fh, write_frame.data, &olen); 01035 if (olen == 0) { 01036 switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(caller_channel), SWITCH_LOG_ERROR, 01037 "Failure to read or re-read after seeking to beginning on file [%s]\n", ringback.fh->file_path); 01038 break; 01039 } 01040 } 01041 write_frame.datalen = (uint32_t) (ringback.asis ? olen : olen * 2); 01042 } else if (ringback.audio_buffer) { 01043 if ((write_frame.datalen = (uint32_t) switch_buffer_read_loop(ringback.audio_buffer, 01044 write_frame.data, 01045 write_frame.codec->implementation->decoded_bytes_per_packet)) <= 0) { 01046 break; 01047 } 01048 } else if (ringback.silence) { 01049 write_frame.datalen = write_frame.codec->implementation->decoded_bytes_per_packet; 01050 switch_generate_sln_silence((int16_t *) write_frame.data, write_frame.datalen / 2, ringback.silence); 01051 } 01052 01053 if ((ringback.fh || ringback.silence || ringback.audio_buffer) && write_frame.codec && write_frame.datalen) { 01054 if (switch_core_session_write_frame(session, &write_frame, SWITCH_IO_FLAG_NONE, 0) != SWITCH_STATUS_SUCCESS) { 01055 break; 01056 } 01057 } 01058 } else { 01059 switch_cond_next(); 01060 } 01061 } 01062 01063 done: 01064 01065 if (ringback.fh) { 01066 switch_core_file_close(ringback.fh); 01067 ringback.fh = NULL; 01068 } else if (ringback.audio_buffer) { 01069 teletone_destroy_session(&ringback.ts); 01070 switch_buffer_destroy(&ringback.audio_buffer); 01071 } 01072 01073 01074 switch_ivr_parse_all_events(session); 01075 01076 switch_core_session_reset(session, SWITCH_TRUE, SWITCH_TRUE); 01077 01078 if (switch_core_codec_ready(&write_codec)) { 01079 switch_core_codec_destroy(&write_codec); 01080 } 01081 01082 switch_safe_free(write_frame.data); 01083 01084 end: 01085 01086 if (!switch_channel_media_ready(peer_channel)) { 01087 if (switch_channel_up_nosig(peer_channel)) { 01088 switch_channel_hangup(peer_channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); 01089 } 01090 status = SWITCH_STATUS_FALSE; 01091 } 01092 01093 if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) { 01094 switch_channel_state_t peer_state = switch_channel_get_state(peer_channel); 01095 01096 while (switch_channel_ready(peer_channel) && switch_channel_get_state(peer_channel) == peer_state) { 01097 switch_ivr_parse_all_messages(session); 01098 switch_channel_ready(caller_channel); 01099 switch_yield(20000); 01100 } 01101 } 01102 01103 if (caller_channel && !switch_channel_up_nosig(caller_channel)) { 01104 status = SWITCH_STATUS_FALSE; 01105 } 01106 01107 return status; 01108 }
| void switch_process_import | ( | switch_core_session_t * | session, | |
| switch_channel_t * | peer_channel, | |||
| const char * | varname, | |||
| const char * | prefix | |||
| ) |
Definition at line 1110 of file switch_ivr_originate.c.
References switch_assert, switch_channel_get_variable, switch_channel_set_variable, switch_core_session_get_channel(), switch_core_session_strdup, switch_mprintf(), and switch_separate_string().
01111 { 01112 const char *import, *val; 01113 switch_channel_t *caller_channel; 01114 01115 switch_assert(session && peer_channel); 01116 caller_channel = switch_core_session_get_channel(session); 01117 01118 if ((import = switch_channel_get_variable(caller_channel, varname))) { 01119 char *mydata = switch_core_session_strdup(session, import); 01120 int i, argc; 01121 char *argv[64] = { 0 }; 01122 01123 if ((argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))))) { 01124 for (i = 0; i < argc; i++) { 01125 if ((val = switch_channel_get_variable(peer_channel, argv[i]))) { 01126 if (prefix) { 01127 char *var = switch_mprintf("%s%s", prefix, argv[i]); 01128 switch_channel_set_variable(caller_channel, var, val); 01129 free(var); 01130 } else { 01131 switch_channel_set_variable(caller_channel, argv[i], val); 01132 } 01133 } 01134 } 01135 } 01136 } 01137 }
1.4.7